Skip to content

Commit ea3c26f

Browse files
committed
agent: add ConnStats
1 parent 9bd83e5 commit ea3c26f

File tree

2 files changed

+99
-0
lines changed

2 files changed

+99
-0
lines changed

agent/stats.go

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package agent
2+
3+
import (
4+
"net"
5+
"time"
6+
)
7+
8+
// ConnStats wraps a net.Conn with statistics.
9+
type ConnStats struct {
10+
CreatedAt time.Time `json:"created_at,omitempty"`
11+
Protocol string `json:"protocol,omitempty"`
12+
RxBytes uint64 `json:"rx_bytes,omitempty"`
13+
TxBytes uint64 `json:"tx_bytes,omitempty"`
14+
15+
net.Conn `json:"-"`
16+
}
17+
18+
var _ net.Conn = new(ConnStats)
19+
20+
func (c *ConnStats) Read(b []byte) (n int, err error) {
21+
n, err = c.Conn.Read(b)
22+
c.RxBytes += uint64(n)
23+
return n, err
24+
}
25+
26+
func (c *ConnStats) Write(b []byte) (n int, err error) {
27+
n, err = c.Conn.Write(b)
28+
c.TxBytes += uint64(n)
29+
return n, err
30+
}
31+
32+
var _ net.Conn = new(ConnStats)
33+
34+
// Stats records the Agent's network connection statistics for use in
35+
// user-facing metrics and debugging.
36+
type Stats struct {
37+
Conns []ConnStats `json:"conns,omitempty"`
38+
}

agent/stats_test.go

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package agent_test
2+
3+
import (
4+
"io"
5+
"net"
6+
"testing"
7+
8+
"github.com/stretchr/testify/assert"
9+
"github.com/stretchr/testify/require"
10+
11+
"github.com/coder/coder/agent"
12+
)
13+
14+
func TestConnStats(t *testing.T) {
15+
t.Parallel()
16+
17+
t.Run("Write", func(t *testing.T) {
18+
t.Parallel()
19+
20+
c1, c2 := net.Pipe()
21+
22+
payload := []byte("dogs & cats")
23+
statsConn := &agent.ConnStats{Conn: c1}
24+
25+
got := make(chan []byte)
26+
go func() {
27+
b, _ := io.ReadAll(c2)
28+
got <- b
29+
}()
30+
n, err := statsConn.Write(payload)
31+
require.NoError(t, err)
32+
assert.Equal(t, len(payload), n)
33+
statsConn.Close()
34+
35+
require.Equal(t, payload, <-got)
36+
37+
require.EqualValues(t, statsConn.TxBytes, len(payload))
38+
require.EqualValues(t, statsConn.RxBytes, 0)
39+
})
40+
41+
t.Run("Read", func(t *testing.T) {
42+
t.Parallel()
43+
44+
c1, c2 := net.Pipe()
45+
46+
payload := []byte("cats & dogs")
47+
statsConn := &agent.ConnStats{Conn: c1}
48+
49+
go func() {
50+
c2.Write(payload)
51+
c2.Close()
52+
}()
53+
54+
got, err := io.ReadAll(statsConn)
55+
require.NoError(t, err)
56+
assert.Equal(t, len(payload), len(got))
57+
58+
require.EqualValues(t, statsConn.RxBytes, len(payload))
59+
require.EqualValues(t, statsConn.TxBytes, 0)
60+
})
61+
}

0 commit comments

Comments
 (0)