Closed hajsf closed 2 years ago
Just implement the interface and set your implementation as the logger, basic Go. https://github.com/tulir/whatsmeow/blob/main/util/log/log.go#L16-L23
Just implement the interface and set your implementation as the logger
Thanks, I got it done as:
package main
import (
"fmt"
"strings"
"time"
waLog "go.mau.fi/whatsmeow/util/log"
)
type customLogger struct {
Mod string
Color bool
Min int
}
var levelToInt = map[string]int{
"": -1,
"DEBUG": 0,
"INFO": 1,
"WARN": 2,
"ERROR": 3,
}
func (c *customLogger) outputf(level, msg string, args ...interface{}) {
if levelToInt[level] < c.Min {
return
}
if strings.Compare(level, "ERROR") == 0 {
passer.data <- sseData{
event: "notification",
message: fmt.Sprintf("%s [%s %s] %s", time.Now().Format("15:04:05.000"), c.Mod, level, fmt.Sprintf(msg, args...)),
}
}
}
func (c *customLogger) Errorf(msg string, args ...interface{}) { c.outputf("ERROR", msg, args...) }
func (c *customLogger) Warnf(msg string, args ...interface{}) { c.outputf("WARN", msg, args...) }
func (c *customLogger) Infof(msg string, args ...interface{}) { c.outputf("INFO", msg, args...) }
func (c *customLogger) Debugf(msg string, args ...interface{}) { c.outputf("DEBUG", msg, args...) }
func (c *customLogger) Sub(mod string) waLog.Logger {
return &customLogger{Mod: fmt.Sprintf("%s/%s", c.Mod, mod), Color: c.Color, Min: c.Min}
}
func LogText(module string, minLevel string, color bool) waLog.Logger {
return &customLogger{Mod: module, Color: color, Min: levelToInt[strings.ToUpper(minLevel)]}
}
Where passer
is defined as:
type sseData struct {
event, message string
}
type DataPasser struct {
data chan sseData
logs chan string
connection chan struct{} // To control maximum allowed clients connections
}
const maxClients = 1
func init() {
passer = &DataPasser{
data: make(chan sseData),
logs: make(chan string),
connection: make(chan struct{}, maxClients),
}
}
Now I can analyze the ERROR (or log) message at func (c *customLogger) outputf(level, msg string, args ...interface{}) { ... }
or send it to the browser as Server Sent Event as:
package main
import (
"fmt"
"net/http"
)
type sseData struct {
event, message string
}
type DataPasser struct {
data chan sseData
logs chan string
connection chan struct{} // To control maximum allowed clients connections
}
func (p *DataPasser) HandleSignal(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/event-stream; charset=utf-8")
w.Header().Set("Cache-Control", "no-cache")
w.Header().Set("Connection", "keep-alive")
setupCORS(&w, r)
flusher, ok := w.(http.Flusher)
if !ok {
http.Error(w, "Internal error", 500)
return
}
fmt.Println("Client connected from IP:", r.RemoteAddr)
if len(p.connection) > 0 {
fmt.Fprint(w, "event: notification\ndata: Connection is opened in another browser/tap ...\n\n")
flusher.Flush()
}
p.connection <- struct{}{}
fmt.Fprint(w, "event: notification\ndata: Connecting to WhatsApp server ...\n\n")
flusher.Flush()
// Connect to the WhatsApp client
go Connect()
for {
select {
case data := <-p.data:
switch {
case len(data.event) > 0:
fmt.Fprintf(w, "event: %v\ndata: %v\n\n", data.event, data.message)
case len(data.event) == 0:
fmt.Fprintf(w, "data: %v\n\n", data.message)
}
flusher.Flush()
case <-r.Context().Done():
<-p.connection
fmt.Println("Connection closed from IP:", r.RemoteAddr)
return
}
}
}
func setupCORS(w *http.ResponseWriter, req *http.Request) {
(*w).Header().Set("Cache-Control", "no-cache")
(*w).Header().Set("Access-Control-Allow-Origin", "*")
(*w).Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
(*w).Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
}
I'm interested in having a custom logger, so I can read the log result from inside my code, so I can analyze it and take the required action, same as explained at #200
Any thought or support please.