├── go.mod ├── .gitignore ├── README.md └── cmd └── main.go /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/nats-logger 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Dependency directories (remove the comment below to include it) 15 | # vendor/ 16 | 17 | # Tools 18 | .idea 19 | .vscode 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NATS Logger 2 | 3 | NATS uses a simple publish/subscribe style plain-text protocol to communicate between a NATS Server and its clients. Whilst this connection should remain opaque to the user, it can be quite handy to see the data being passed from time to time - this tool does just that (it also saves me loading Wireshark and filtering the NATS traffic). 4 | 5 | More information on NATS connection protocol can be found [here](https://docs.nats.io/reference/reference-protocols/nats-protocol). 6 | 7 | screenshot 8 | 9 | ## Next step... 10 | 11 | Next step is to add support for printing a pretty print version to a web UI over websockets. 12 | -------------------------------------------------------------------------------- /cmd/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "io" 7 | "log" 8 | "net" 9 | ) 10 | 11 | var ( 12 | localAddr = flag.String("l", "localhost:9999", "Local address") 13 | remoteAddr = flag.String("r", "localhost:5222", "NATS Server address") 14 | ) 15 | 16 | func main() { 17 | 18 | flag.Parse() 19 | fmt.Printf("Listening: %v\nProxying: %v\n\n", *localAddr, *remoteAddr) 20 | 21 | listener, err := net.Listen("tcp", *localAddr) 22 | if err != nil { 23 | panic(err) 24 | } 25 | for { 26 | localConn, err := listener.Accept() 27 | log.Println("New connection", localConn.RemoteAddr()) 28 | if err != nil { 29 | log.Println("error accepting connection", err) 30 | continue 31 | } 32 | go func() { 33 | defer localConn.Close() 34 | natsConn, err := net.Dial("tcp", *remoteAddr) 35 | if err != nil { 36 | log.Println("error dialing remote addr", err) 37 | return 38 | } 39 | defer natsConn.Close() 40 | closer := make(chan struct{}, 2) 41 | 42 | go copy(closer, natsConn, io.TeeReader(localConn, logger("server"))) 43 | go copy(closer, localConn, io.TeeReader(localConn, logger("client"))) 44 | 45 | //go copy(closer, natsConn, localConn) 46 | //go copy(closer, localConn, natsConn) 47 | 48 | <-closer 49 | log.Println("Connection complete", localConn.RemoteAddr()) 50 | }() 51 | 52 | } 53 | 54 | } 55 | 56 | type logger string 57 | 58 | func (lh logger) Write(b []byte) (int, error) { 59 | fmt.Printf(string(b)) 60 | return len(b), nil 61 | } 62 | 63 | func copy(closer chan struct{}, dst io.Writer, src io.Reader) { 64 | _, _ = io.Copy(dst, src) 65 | closer <- struct{}{} // connection is closed, send signal to stop proxy 66 | } 67 | --------------------------------------------------------------------------------