From 7423c72f8463625e6b2f1e7e2ceeb8a5d734436f Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 7 Jun 2021 15:37:06 -0700 Subject: [PATCH] Add basic metric for recording use after N seconds Signed-off-by: julianknodt --- derp/derp_server.go | 22 ++++++++++++++++++++++ derp/derp_test.go | 19 +++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/derp/derp_server.go b/derp/derp_server.go index 104dc11bf..64828d58f 100644 --- a/derp/derp_server.go +++ b/derp/derp_server.go @@ -120,6 +120,8 @@ type Server struct { multiForwarderCreated expvar.Int multiForwarderDeleted expvar.Int removePktForwardOther expvar.Int + clientsInUse5Sec expvar.Int // Number of clients using Derp after 5 seconds. + clientsInUse10Sec expvar.Int mu sync.Mutex closed bool @@ -457,6 +459,7 @@ func (s *Server) accept(nc Conn, brw *bufio.ReadWriter, remoteAddr string, connN done: ctx.Done(), remoteAddr: remoteAddr, connectedAt: time.Now(), + lastPktAt: time.Now(), sendQueue: make(chan pkt, perClientSendQueueDepth), peerGone: make(chan key.Public), canMesh: clientInfo.MeshKey != "" && clientInfo.MeshKey == s.meshKey, @@ -663,6 +666,7 @@ func (c *sclient) handleFrameSendPacket(ft frameType, fl uint32) error { } return nil } + c.markLastPktAt() p := pkt{ bs: contents, @@ -901,6 +905,7 @@ type sclient struct { // Owned by run, not thread-safe. br *bufio.Reader connectedAt time.Time + lastPktAt time.Time preferred bool // Owned by sender, not thread-safe. @@ -1062,6 +1067,21 @@ func (c *sclient) sendPeerPresent(peer key.Public) error { return err } +func (c *sclient) markLastPktAt() { + old := c.lastPktAt + curr := time.Now() + c.lastPktAt = curr + // If we've been connected for over 5 seconds and haven't previously + since_old := old.Sub(c.connectedAt) + since_now := curr.Sub(c.connectedAt) + if since_old <= 5*time.Second && since_now > 5*time.Second { + c.s.clientsInUse5Sec.Add(1) + } + if since_old <= 10*time.Second && since_now > 10*time.Second { + c.s.clientsInUse10Sec.Add(1) + } +} + // sendMeshUpdates drains as many mesh peerStateChange entries as // possible into the write buffer WITHOUT flushing or otherwise // blocking (as it holds c.s.mu while working). If it can't drain them @@ -1290,6 +1310,8 @@ func (s *Server) ExpVar() expvar.Var { m.Set("multiforwarder_created", &s.multiForwarderCreated) m.Set("multiforwarder_deleted", &s.multiForwarderDeleted) m.Set("packet_forwarder_delete_other_value", &s.removePktForwardOther) + m.Set("clients_inuse_after_5_sec", &s.clientsInUse5Sec) + m.Set("clients_inuse_after_10_sec", &s.clientsInUse10Sec) var expvarVersion expvar.String expvarVersion.Set(version.Long) m.Set("version", &expvarVersion) diff --git a/derp/derp_test.go b/derp/derp_test.go index db3586170..1c4d186ff 100644 --- a/derp/derp_test.go +++ b/derp/derp_test.go @@ -774,6 +774,25 @@ func TestForwarderRegistration(t *testing.T) { }) } +func TestLastAliveCounter(t *testing.T) { + ts := newTestServer(t) + defer ts.close(t) + wantCounter := func(c *expvar.Int, want int) { + t.Helper() + if got := c.Value(); got != int64(want) { + t.Errorf("counter = %v; want %v", got, want) + } + } + wantCounter(&ts.s.clientsInUse5Sec, 0) + tc0 := newRegularClient(t, ts, "c0") + time.Sleep(6 * time.Second) + for _, sc := range ts.s.clients { + sc.markLastPktAt() + } + wantCounter(&ts.s.clientsInUse5Sec, 1) + tc0.close(t) +} + func TestMetaCert(t *testing.T) { priv := newPrivateKey(t) pub := priv.Public()