From 17caa2a6046ea7c10a552375ae2c34aba65cf1f8 Mon Sep 17 00:00:00 2001 From: Adam Chen Date: Sun, 9 Nov 2025 22:34:44 +0000 Subject: [PATCH 1/3] feat: basic metric monitoring --- cmd/run.go | 2 +- core/entrypoint.go | 4 +++- go.mod | 1 + go.sum | 2 ++ perf/vars.go | 34 ++++++++++++++++++++++++++++++++++ polyamide/conn/bind_std.go | 7 +++++++ polyamide/device/peer.go | 3 +++ polyamide/device/receive.go | 5 +++++ state/debug.go | 2 +- 9 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 perf/vars.go diff --git a/cmd/run.go b/cmd/run.go index 4f51c7d..dae1dad 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -35,7 +35,7 @@ func init() { runCmd.Flags().BoolVarP(&state.DBG_log_probe, "dbg-probe", "p", false, "Write probes to console") runCmd.Flags().BoolVarP(&state.DBG_log_wireguard, "dbg-wg", "w", false, "Outputs wireguard logs to the console") runCmd.Flags().BoolVarP(&state.DBG_log_repo_updates, "dbg-repo", "", false, "Outputs repo updates to the console") - runCmd.Flags().BoolVarP(&state.DBG_pprof, "dbg-pprof", "", false, "Enables pprof on port 6060") + runCmd.Flags().BoolVarP(&state.DBG_debug, "dbg-perf", "", false, "Enables performance debugging server on port 6060") runCmd.Flags().BoolVarP(&state.DBG_trace, "dbg-trace", "", false, "Enables trace to trace.out") runCmd.Flags().StringP("config", "c", DefaultConfigPath, "Path to the config file") runCmd.Flags().StringP("node", "n", DefaultNodeConfigPath, "Path to the node config file") diff --git a/core/entrypoint.go b/core/entrypoint.go index 8869151..01ac085 100644 --- a/core/entrypoint.go +++ b/core/entrypoint.go @@ -16,6 +16,7 @@ import ( "syscall" "time" + "github.com/encodeous/nylon/perf" "github.com/encodeous/nylon/state" "github.com/encodeous/tint" slogmulti "github.com/samber/slog-multi" @@ -35,7 +36,7 @@ func setupDebugging() { } log.Println("Started tracing") } - if state.DBG_pprof { + if state.DBG_debug { go func() { log.Println(http.ListenAndServe("0.0.0.0:6060", nil)) }() @@ -262,6 +263,7 @@ func MainLoop(s *state.State, dispatch <-chan func(*state.State) error) error { s.Cancel(err) } elapsed := time.Since(start) + perf.DispatchLatency.Add(float64(elapsed.Microseconds())) if elapsed > time.Millisecond*4 { s.Log.Warn("dispatch took a long time!", "fun", runtime.FuncForPC(reflect.ValueOf(fun).Pointer()).Name(), "elapsed", elapsed, "len", len(dispatch)) } diff --git a/go.mod b/go.mod index 4c87cc1..8411e37 100644 --- a/go.mod +++ b/go.mod @@ -25,6 +25,7 @@ require ( require ( filippo.io/edwards25519 v1.1.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/encodeous/metric v0.0.0-20251109204822-7c14a5a4eedb // indirect github.com/google/btree v1.1.2 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/kr/pretty v0.3.1 // indirect diff --git a/go.sum b/go.sum index abf1933..4c6638a 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6N github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/encodeous/metric v0.0.0-20251109204822-7c14a5a4eedb h1:BxbznDom+oSwmJzMg3pfsBuL1UjGPQaGssn3Y22hChM= +github.com/encodeous/metric v0.0.0-20251109204822-7c14a5a4eedb/go.mod h1:oXvYSICtw2XX/BBUbzuMfTpu+GrPX1RV7a+vfoOKQ6A= github.com/encodeous/tint v1.2.0 h1:1Y+32Iu+C8MXBoNjsM4YDf6iAkcks7csAI9f7b4fr8k= github.com/encodeous/tint v1.2.0/go.mod h1:pyfyH+fKmtmIuWVWeMcSJjJKVJSb9sVlIfVsW3jkP+Q= github.com/gaissmai/bart v0.25.0 h1:eqiokVPqM3F94vJ0bTHXHtH91S8zkKL+bKh+BsGOsJM= diff --git a/perf/vars.go b/perf/vars.go new file mode 100644 index 0000000..8114dab --- /dev/null +++ b/perf/vars.go @@ -0,0 +1,34 @@ +package perf + +import ( + "expvar" + "net/http" + + "github.com/encodeous/metric" +) + +var ( + DispatchLatency = metric.NewHistogram("1m1s") + SendBatchSize = metric.NewHistogram("10s1s") + RecvBatchSize = metric.NewHistogram("10s1s") + SendsPerSecond = metric.NewCounter("10s1s") + RecvsPerSecond = metric.NewCounter("10s1s") + SentPacketPerSecond = metric.NewCounter("10s1s") + RecvPacketPerSecond = metric.NewCounter("10s1s") + SentBytesPerSecond = metric.NewCounter("10s1s") + RecvBytesPerSecond = metric.NewCounter("10s1s") +) + +func init() { + http.Handle("/debug/metrics", metric.Handler(metric.Exposed)) + expvar.Publish("nylon:SendBatchSize", SendBatchSize) + expvar.Publish("nylon:RecvBatchSize", RecvBatchSize) + + expvar.Publish("nylon:SentPacket/s", SentPacketPerSecond) + expvar.Publish("nylon:RecvPacket/s", RecvPacketPerSecond) + expvar.Publish("nylon:Sends/s", SendsPerSecond) + expvar.Publish("nylon:Recvs/s", RecvsPerSecond) + expvar.Publish("nylon:SentBytes/s", SentBytesPerSecond) + expvar.Publish("nylon:RecvBytes/s", RecvBytesPerSecond) + expvar.Publish("nylon:DispatchLatency (µs)", DispatchLatency) +} diff --git a/polyamide/conn/bind_std.go b/polyamide/conn/bind_std.go index 3e6ba51..27f5fe8 100644 --- a/polyamide/conn/bind_std.go +++ b/polyamide/conn/bind_std.go @@ -16,6 +16,7 @@ import ( "sync" "syscall" + "github.com/encodeous/nylon/perf" "golang.org/x/net/ipv4" "golang.org/x/net/ipv6" ) @@ -259,6 +260,7 @@ func (s *StdNetBind) receiveIP( return 0, err } } + perf.RecvBatchSize.Add(float64(numMsgs)) } else { msg := &(*msgs)[0] msg.N, msg.NN, _, msg.Addr, err = conn.ReadMsgUDP(msg.Buffers[0], msg.OOB) @@ -267,6 +269,7 @@ func (s *StdNetBind) receiveIP( } numMsgs = 1 } + perf.RecvsPerSecond.Add(1) for i := 0; i < numMsgs; i++ { msg := &(*msgs)[i] sizes[i] = msg.N @@ -422,6 +425,8 @@ func (s *StdNetBind) send(conn *net.UDPConn, pc batchWriter, msgs []ipv6.Message if runtime.GOOS == "linux" || runtime.GOOS == "android" { for { n, err = pc.WriteBatch(msgs[start:], 0) + perf.SendBatchSize.Add(float64(n)) + perf.SendsPerSecond.Add(1) if err != nil || n == len(msgs[start:]) { break } @@ -434,6 +439,8 @@ func (s *StdNetBind) send(conn *net.UDPConn, pc batchWriter, msgs []ipv6.Message break } } + perf.SendsPerSecond.Add(float64(len(msgs))) + perf.SendBatchSize.Add(1) } return err } diff --git a/polyamide/device/peer.go b/polyamide/device/peer.go index 1c090ca..9d1afc7 100644 --- a/polyamide/device/peer.go +++ b/polyamide/device/peer.go @@ -13,6 +13,7 @@ import ( "sync/atomic" "time" + "github.com/encodeous/nylon/perf" "github.com/encodeous/nylon/polyamide/conn" ) @@ -170,6 +171,8 @@ func (peer *Peer) SendBuffers(buffers [][]byte, eps []conn.Endpoint) error { for _, b := range buffers { totalLen += uint64(len(b)) } + perf.SentPacketPerSecond.Add(float64(len(buffers))) + perf.SentBytesPerSecond.Add(float64(totalLen)) peer.txBytes.Add(totalLen) return anyError } diff --git a/polyamide/device/receive.go b/polyamide/device/receive.go index f2bad19..b6d1d39 100644 --- a/polyamide/device/receive.go +++ b/polyamide/device/receive.go @@ -12,6 +12,7 @@ import ( "sync" "time" + "github.com/encodeous/nylon/perf" "github.com/encodeous/nylon/polyamide/conn" "golang.org/x/crypto/chacha20poly1305" ) @@ -445,6 +446,7 @@ func (peer *Peer) RoutineSequentialReceiver(maxBatchSize int) { validTailPacket := -1 dataPacketReceived := false rxBytesLen := uint64(0) + rxPkts := 0 for i, elem := range elemsContainer.elems { if elem.packet == nil { @@ -463,6 +465,7 @@ func (peer *Peer) RoutineSequentialReceiver(maxBatchSize int) { peer.SendStagedPackets() } rxBytesLen += uint64(len(elem.packet) + MinMessageSize) + rxPkts++ if len(elem.packet) == 0 { device.Log.Verbosef("%v - Receiving keepalive packet", peer) @@ -487,6 +490,8 @@ func (peer *Peer) RoutineSequentialReceiver(maxBatchSize int) { tcBufs = tcBufs[:0] peer.rxBytes.Add(rxBytesLen) + perf.RecvBytesPerSecond.Add(float64(rxBytesLen)) + perf.RecvPacketPerSecond.Add(float64(rxPkts)) if validTailPacket >= 0 { peer.SetEndpointFromPacket(elemsContainer.elems[validTailPacket].endpoint) peer.keepKeyFreshReceiving() diff --git a/state/debug.go b/state/debug.go index bad5a4f..c7ff52f 100644 --- a/state/debug.go +++ b/state/debug.go @@ -3,5 +3,5 @@ package state var DBG_log_probe = false var DBG_log_wireguard = false var DBG_log_repo_updates = false -var DBG_pprof = false +var DBG_debug = false var DBG_trace = false From 8fcb5324674bbb6d90be22b8f660d27941495708 Mon Sep 17 00:00:00 2001 From: Adam Chen Date: Tue, 11 Nov 2025 18:03:33 +0000 Subject: [PATCH 2/3] use improved metric library --- go.mod | 4 ++-- go.sum | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 8411e37..39938bf 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/encodeous/nylon -go 1.24.4 +go 1.25.1 require ( github.com/encodeous/tint v1.2.0 @@ -25,7 +25,7 @@ require ( require ( filippo.io/edwards25519 v1.1.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/encodeous/metric v0.0.0-20251109204822-7c14a5a4eedb // indirect + github.com/encodeous/metric v0.0.0-20251111175231-f339c2f7c4bd // indirect github.com/google/btree v1.1.2 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/kr/pretty v0.3.1 // indirect diff --git a/go.sum b/go.sum index 4c6638a..91c4abc 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,10 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/encodeous/metric v0.0.0-20251109204822-7c14a5a4eedb h1:BxbznDom+oSwmJzMg3pfsBuL1UjGPQaGssn3Y22hChM= github.com/encodeous/metric v0.0.0-20251109204822-7c14a5a4eedb/go.mod h1:oXvYSICtw2XX/BBUbzuMfTpu+GrPX1RV7a+vfoOKQ6A= +github.com/encodeous/metric v0.0.0-20251111174141-71b1b8e039ef h1:I3MT+fvVHyBDqWsNjo0IoRu5mESMO52feooiGLL+ffY= +github.com/encodeous/metric v0.0.0-20251111174141-71b1b8e039ef/go.mod h1:gXUFQ+MZ+DHHvwRDrNE0NtcjzgplXRF0+shb+NSCsdE= +github.com/encodeous/metric v0.0.0-20251111175231-f339c2f7c4bd h1:B32Ob80QTv5MomcVt709TsiWyD0QrpUYtnwW1jQFNlE= +github.com/encodeous/metric v0.0.0-20251111175231-f339c2f7c4bd/go.mod h1:DiXCPJtfZYioejF9zv9wfs3TXqWWglKGQ20DsBNVWVw= github.com/encodeous/tint v1.2.0 h1:1Y+32Iu+C8MXBoNjsM4YDf6iAkcks7csAI9f7b4fr8k= github.com/encodeous/tint v1.2.0/go.mod h1:pyfyH+fKmtmIuWVWeMcSJjJKVJSb9sVlIfVsW3jkP+Q= github.com/gaissmai/bart v0.25.0 h1:eqiokVPqM3F94vJ0bTHXHtH91S8zkKL+bKh+BsGOsJM= From 4996c7bbf1a4f20a68bdbd059688961b51d1b6bd Mon Sep 17 00:00:00 2001 From: Adam Chen Date: Tue, 11 Nov 2025 18:07:36 +0000 Subject: [PATCH 3/3] bump go version --- .github/workflows/go-test.yml | 2 +- go.mod | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/go-test.yml b/.github/workflows/go-test.yml index 8b1ce36..f5ea208 100644 --- a/.github/workflows/go-test.yml +++ b/.github/workflows/go-test.yml @@ -16,7 +16,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v4 with: - go-version: '1.24.0' + go-version: '1.25.4' - name: Install Dependencies run: go install diff --git a/go.mod b/go.mod index 39938bf..bb80ebd 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/encodeous/nylon -go 1.25.1 +go 1.25.4 require ( github.com/encodeous/tint v1.2.0