Logging with charm colorful logger

This commit is contained in:
Maciej Krzyżanowski 2024-03-24 17:10:02 +01:00
parent 361b84aac4
commit 4da29dc45b
7 changed files with 119 additions and 40 deletions

View File

@ -1,100 +1,116 @@
package client
import (
"log"
"net/url"
"os"
"time"
"github.com/charmbracelet/log"
"github.com/gorilla/websocket"
cm "krzyzanowski.dev/p2pchat/common"
)
var logger = log.NewWithOptions(os.Stdout, log.Options{
ReportTimestamp: true,
TimeFormat: time.TimeOnly,
Prefix: "👤 Client",
})
func init() {
if cm.IsProd {
logger.SetLevel(log.InfoLevel)
} else {
logger.SetLevel(log.DebugLevel)
}
}
func RunClient() {
u := url.URL{Scheme: "ws", Host: ":8080", Path: "/wsapi"}
c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
if err != nil {
log.Println("[Client] could not connect to websocket")
logger.Error("could not connect to websocket")
return
}
defer c.Close()
log.Println("[Client] authenticating...")
logger.Info("authenticating...")
rf, _ := cm.RequestFrameFrom(cm.AuthRequest{Nickname: "krzmaciek", Password: "9maciek1"})
err = c.WriteJSON(rf)
if err != nil {
log.Fatalln(err)
logger.Fatal(err)
}
var authResFrame cm.ResponseFrame
err = c.ReadJSON(&authResFrame)
if err != nil {
log.Fatalln(err)
logger.Fatal(err)
}
authRes, err := cm.ResponseFromFrame[cm.AuthResponse](authResFrame)
if err != nil {
log.Fatalln(err)
logger.Fatal(err)
}
log.Printf("[Client] authentication result: %t\n", authRes.IsSuccess)
logger.Infof("authentication result: %t", authRes.IsSuccess)
time.Sleep(time.Second * 1)
log.Println("[Client] sending echo...")
logger.Info("sending echo...")
echoByte := 123
rf, err = cm.RequestFrameFrom(cm.EchoRequest{EchoByte: byte(echoByte)})
if err != nil {
log.Fatalln(err)
logger.Fatal(err)
}
err = c.WriteJSON(rf)
if err != nil {
log.Fatalln(err)
logger.Fatal(err)
}
var echoResFrame cm.ResponseFrame
err = c.ReadJSON(&echoResFrame)
if err != nil {
log.Fatalln(err)
logger.Fatal(err)
}
echoRes, err := cm.ResponseFromFrame[cm.EchoResponse](echoResFrame)
if err != nil {
log.Fatalln(err)
logger.Fatal(err)
}
log.Printf("[Client] sent echo of %d, got %d in return\n", echoByte, echoRes.EchoByte)
logger.Infof("sent echo of %d, got %d in return", echoByte, echoRes.EchoByte)
time.Sleep(time.Second)
log.Println("[Client] i want list of peers...")
logger.Infof("i want list of peers...")
rf, err = cm.RequestFrameFrom(cm.ListPeersRequest{})
if err != nil {
log.Fatalln(err)
logger.Fatal(err)
}
err = c.WriteJSON(rf)
if err != nil {
log.Fatalln(err)
logger.Fatal(err)
}
var listPeersResFrame cm.ResponseFrame
err = c.ReadJSON(&listPeersResFrame)
if err != nil {
log.Fatalln(err)
logger.Fatal(err)
}
listPeersRes, err := cm.ResponseFromFrame[cm.ListPeersResponse](listPeersResFrame)
if err != nil {
log.Fatalln(err)
logger.Fatal(err)
}
log.Println("[Client] printing list of peers:")
logger.Info("printing list of peers:")
for _, p := range listPeersRes.PeersInfo {
log.Printf("[Client] %+v\n", p)
logger.Infof("%+v", p)
}
time.Sleep(time.Second * 5)
logger.Info("closing connection...")
c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
}

View File

@ -4,7 +4,7 @@ import (
"encoding/json"
)
// Constants:
// Constants
const (
EchoRID = 1

3
common/settings.go Normal file
View File

@ -0,0 +1,3 @@
package common
const IsProd = false

16
go.mod
View File

@ -7,4 +7,18 @@ require (
golang.org/x/crypto v0.21.0
)
require golang.org/x/net v0.21.0 // indirect
require (
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/charmbracelet/lipgloss v0.10.0 // indirect
github.com/charmbracelet/log v0.4.0 // indirect
github.com/go-logfmt/logfmt v0.6.0 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mattn/go-isatty v0.0.18 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/muesli/reflow v0.3.0 // indirect
github.com/muesli/termenv v0.15.2 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
golang.org/x/net v0.21.0 // indirect
golang.org/x/sys v0.18.0 // indirect
)

28
go.sum
View File

@ -1,6 +1,34 @@
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/charmbracelet/lipgloss v0.10.0 h1:KWeXFSexGcfahHX+54URiZGkBFazf70JNMtwg/AFW3s=
github.com/charmbracelet/lipgloss v0.10.0/go.mod h1:Wig9DSfvANsxqkRsqj6x87irdy123SR4dOXlKa91ciE=
github.com/charmbracelet/log v0.4.0 h1:G9bQAcx8rWA2T3pWvx7YtPTPwgqpk7D68BX21IRW8ZM=
github.com/charmbracelet/log v0.4.0/go.mod h1:63bXt/djrizTec0l11H20t8FDSvA4CRZJ1KH22MdptM=
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=

View File

@ -8,6 +8,8 @@ import (
"krzyzanowski.dev/p2pchat/server"
)
const IsProd = false
func main() {
args := os.Args[1:]

View File

@ -2,12 +2,13 @@ package server
import (
"encoding/json"
"log"
"net/http"
"os"
"strings"
"sync"
"time"
"github.com/charmbracelet/log"
"github.com/gorilla/websocket"
"golang.org/x/crypto/bcrypt"
"krzyzanowski.dev/p2pchat/common"
@ -39,6 +40,20 @@ type Peer struct {
account *Account
}
var logger = log.NewWithOptions(os.Stdout, log.Options{
ReportTimestamp: true,
TimeFormat: time.TimeOnly,
Prefix: "⚙️ Server",
})
func init() {
if common.IsProd {
logger.SetLevel(log.InfoLevel)
} else {
logger.SetLevel(log.DebugLevel)
}
}
func NewPeer(conn *websocket.Conn) *Peer {
return &Peer{-1, conn, false, nil}
}
@ -67,13 +82,13 @@ func (srvCtx *ServerContext) removePeer(peer *Peer) {
func handleDisconnection(handlerCtx *HandlerContext) {
handlerCtx.removePeer(handlerCtx.peer)
log.Printf("[Server] %s disconnected\n", handlerCtx.peer.conn.RemoteAddr())
logger.Infof("%s disconnected", handlerCtx.peer.conn.RemoteAddr())
}
func (hdlCtx *HandlerContext) handleEcho(reqFrame *common.RequestFrame) (res common.Response, err error) {
echoReq, err := common.RequestFromFrame[common.EchoRequest](*reqFrame)
if err != nil {
log.Println("[Server] could not read request from frame")
logger.Error("could not read request from frame")
return nil, err
}
@ -85,7 +100,7 @@ func (hdlCtx *HandlerContext) handleListPeers(reqFrame *common.RequestFrame) (re
// Currently list peers request is empty, so we can ignore it - we won't use it
_, err = common.RequestFromFrame[common.ListPeersRequest](*reqFrame)
if err != nil {
log.Println("[Server] could not read request from frame")
logger.Error("could not read request from frame")
return nil, err
}
@ -113,7 +128,7 @@ func (hdlCtx *HandlerContext) handleListPeers(reqFrame *common.RequestFrame) (re
func (hdlCtx *HandlerContext) handleAuth(reqFrame *common.RequestFrame) (res common.Response, err error) {
authReq, err := common.RequestFromFrame[common.AuthRequest](*reqFrame)
if err != nil {
log.Println("[Server] could not read request from frame")
logger.Error("could not read request from frame")
return nil, err
}
@ -157,7 +172,7 @@ func (hdlCtx *HandlerContext) handleAuth(reqFrame *common.RequestFrame) (res com
func (srvCtx *ServerContext) printConnectedPeers() {
srvCtx.peersListLock.RLock()
log.Println("[Server] displaying all connections:")
logger.Debug("displaying all connections:")
for _, p := range srvCtx.peersList {
nick := "-"
@ -166,17 +181,17 @@ func (srvCtx *ServerContext) printConnectedPeers() {
nick = p.account.nickname
}
log.Printf("[Server] ID#%d, Addr:%s, Auth:%t, Nick:%s\n", p.id, p.conn.RemoteAddr(), p.hasAccount, nick)
log.Debugf("ID#%d, Addr:%s, Auth:%t, Nick:%s", p.id, p.conn.RemoteAddr(), p.hasAccount, nick)
}
srvCtx.peersListLock.RUnlock()
}
func (hdlCtx *HandlerContext) handleRequest(reqJsonBytes []byte) error {
log.Printf("[Server] got message text: %s\n", strings.Trim(string(reqJsonBytes), "\n"))
logger.Debugf("got message text: %s", strings.Trim(string(reqJsonBytes), "\n"))
var reqFrame common.RequestFrame
json.Unmarshal(reqJsonBytes, &reqFrame)
log.Printf("[Server] unmarshalled request frame (ID=%d)\n", reqFrame.ID)
log.Debugf("unmarshalled request frame (ID=%d)", reqFrame.ID)
var res common.Response
var err error
@ -189,26 +204,26 @@ func (hdlCtx *HandlerContext) handleRequest(reqJsonBytes []byte) error {
}
if err != nil {
log.Printf("[Server] could not handle request ID=%d\n", reqFrame.ID)
logger.Errorf("could not handle request ID=%d", reqFrame.ID)
return err
}
resFrame, err := common.ResponseFrameFrom(res)
if err != nil {
log.Println("[Server] could not create frame from response")
logger.Errorf("could not create frame from response")
return err
}
resJsonBytes, err := json.Marshal(resFrame)
if err != nil {
log.Println("[Server] error marshalling frame to json")
logger.Errorf("error marshalling frame to json")
return err
}
log.Printf("[Server] sending %s\n", string(resJsonBytes))
logger.Debugf("sending %s", string(resJsonBytes))
err = hdlCtx.peer.conn.WriteMessage(websocket.TextMessage, resJsonBytes)
if err != nil {
log.Println("[Server] error writing response frame")
logger.Errorf("error writing response frame")
return err
}
@ -229,7 +244,7 @@ func (srvCtx *ServerContext) wsapiHandler(w http.ResponseWriter, r *http.Request
upgrader := websocket.Upgrader{}
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Println("[Server] upgrade failed")
logger.Errorf("upgrade failed")
return
}
@ -238,7 +253,7 @@ func (srvCtx *ServerContext) wsapiHandler(w http.ResponseWriter, r *http.Request
handlerCtx := &HandlerContext{peer, srvCtx}
defer handleDisconnection(handlerCtx)
defer conn.Close()
log.Printf("[Server] %s connected\n", conn.RemoteAddr())
logger.Infof("%s connected", conn.RemoteAddr())
for {
messType, messBytes, err := conn.ReadMessage()
@ -249,7 +264,7 @@ func (srvCtx *ServerContext) wsapiHandler(w http.ResponseWriter, r *http.Request
if messType != 1 {
err := conn.WriteMessage(websocket.CloseUnsupportedData, []byte("Only JSON text is supported"))
if err != nil {
log.Println("[Server] error sending close message due to unsupported data")
logger.Debugf("[Server] error sending close message due to unsupported data")
}
return
@ -257,7 +272,7 @@ func (srvCtx *ServerContext) wsapiHandler(w http.ResponseWriter, r *http.Request
err = handlerCtx.handleRequest(messBytes)
if err != nil {
log.Println(err)
logger.Debug(err)
break
}
}
@ -274,5 +289,6 @@ func RunServer() {
}()
http.HandleFunc("/wsapi", srvCtx.wsapiHandler)
logger.Info("Starting server...")
http.ListenAndServe(":8080", nil)
}