Skip to content

Commit fb7bc2e

Browse files
committed
Add tests for metrics.
1 parent 7f3d9d0 commit fb7bc2e

File tree

2 files changed

+79
-1
lines changed

2 files changed

+79
-1
lines changed

cmd/outline-ss-server/metrics.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ const (
3131
activeIPKeyTrackerReportingInterval = 5 * time.Second
3232
)
3333

34+
var since = time.Since
35+
3436
type outlineMetrics struct {
3537
ipinfo.IPInfoMap
3638
activeIPKeyTracker
@@ -93,7 +95,7 @@ func (t *activeIPKeyTracker) reportAll() {
9395

9496
// Reports time connected for a given active client.
9597
func (t *activeIPKeyTracker) reportDuration(c activeClient) {
96-
connDuration := time.Since(c.startTime)
98+
connDuration := since(c.startTime)
9799
logger.Debugf("Reporting activity for key `%v`, duration: %v", c.IPKey.accessKey, connDuration)
98100
t.metricsCallback(c.IPKey, connDuration)
99101

cmd/outline-ss-server/metrics_test.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@
1515
package main
1616

1717
import (
18+
"strings"
1819
"testing"
1920
"time"
2021

2122
"github.com/Jigsaw-Code/outline-ss-server/ipinfo"
2223
"github.com/Jigsaw-Code/outline-ss-server/service/metrics"
2324
"github.com/prometheus/client_golang/prometheus"
25+
promtest "github.com/prometheus/client_golang/prometheus/testutil"
2426
"github.com/stretchr/testify/require"
2527
)
2628

@@ -40,6 +42,7 @@ func TestMethodsDontPanic(t *testing.T) {
4042
ssMetrics.SetBuildInfo("0.0.0-test")
4143
ssMetrics.SetNumAccessKeys(20, 2)
4244
ssMetrics.AddOpenTCPConnection(fakeAddr("127.0.0.1:9"))
45+
ssMetrics.AddAuthenticatedTCPConnection(fakeAddr("127.0.0.1:9"), "key-1")
4346
ssMetrics.AddClosedTCPConnection(fakeAddr("127.0.0.1:9"), "1", "OK", proxyMetrics, 10*time.Millisecond)
4447
ssMetrics.AddUDPPacketFromClient(ipinfo.IPInfo{CountryCode: "US", ASN: 100}, "2", "OK", 10, 20)
4548
ssMetrics.AddUDPPacketFromTarget(ipinfo.IPInfo{CountryCode: "US", ASN: 100}, "3", "OK", 10, 20)
@@ -55,6 +58,79 @@ func TestASNLabel(t *testing.T) {
5558
require.Equal(t, "100", asnLabel(100))
5659
}
5760

61+
func TestIPKeyActivityPerKeyDoesNotReportUnlessAllConnectionsClosed(t *testing.T) {
62+
since = func(time.Time) time.Duration { return 3 * time.Second }
63+
reg := prometheus.NewPedanticRegistry()
64+
ssMetrics := newPrometheusOutlineMetrics(nil, reg)
65+
accessKey := "key-1"
66+
status := "OK"
67+
data := metrics.ProxyMetrics{}
68+
duration := time.Minute
69+
70+
ssMetrics.AddAuthenticatedTCPConnection(fakeAddr("127.0.0.1:9"), accessKey)
71+
ssMetrics.AddAuthenticatedTCPConnection(fakeAddr("127.0.0.1:1"), accessKey)
72+
ssMetrics.AddClosedTCPConnection(fakeAddr("127.0.0.1:9"), accessKey, status, data, duration)
73+
74+
err := promtest.GatherAndCompare(
75+
reg,
76+
strings.NewReader(""),
77+
"shadowsocks_ip_key_connectivity_seconds",
78+
)
79+
require.NoError(t, err, "unexpectedly found metric value")
80+
}
81+
82+
func TestIPKeyActivityPerKey(t *testing.T) {
83+
since = func(time.Time) time.Duration { return 3 * time.Second }
84+
reg := prometheus.NewPedanticRegistry()
85+
ssMetrics := newPrometheusOutlineMetrics(nil, reg)
86+
accessKey := "key-1"
87+
status := "OK"
88+
data := metrics.ProxyMetrics{}
89+
duration := time.Minute
90+
91+
ssMetrics.AddAuthenticatedTCPConnection(fakeAddr("127.0.0.1:9"), accessKey)
92+
ssMetrics.AddAuthenticatedTCPConnection(fakeAddr("127.0.0.1:1"), accessKey)
93+
ssMetrics.AddClosedTCPConnection(fakeAddr("127.0.0.1:9"), accessKey, status, data, duration)
94+
ssMetrics.AddClosedTCPConnection(fakeAddr("127.0.0.1:1"), accessKey, status, data, duration)
95+
96+
expected := strings.NewReader(`
97+
# HELP shadowsocks_ip_key_connectivity_seconds Time at least 1 connection was open for a (IP, access key) pair, per key
98+
# TYPE shadowsocks_ip_key_connectivity_seconds counter
99+
shadowsocks_ip_key_connectivity_seconds{access_key="key-1"} 3
100+
`)
101+
err := promtest.GatherAndCompare(
102+
reg,
103+
expected,
104+
"shadowsocks_ip_key_connectivity_seconds",
105+
)
106+
require.NoError(t, err, "unexpected metric value found")
107+
}
108+
109+
func TestIPKeyActivityPerLocation(t *testing.T) {
110+
since = func(time.Time) time.Duration { return 5 * time.Second }
111+
reg := prometheus.NewPedanticRegistry()
112+
ssMetrics := newPrometheusOutlineMetrics(nil, reg)
113+
accessKey := "key-1"
114+
status := "OK"
115+
data := metrics.ProxyMetrics{}
116+
duration := time.Minute
117+
118+
ssMetrics.AddAuthenticatedTCPConnection(fakeAddr("127.0.0.1:9"), accessKey)
119+
ssMetrics.AddClosedTCPConnection(fakeAddr("127.0.0.1:9"), accessKey, status, data, duration)
120+
121+
expected := strings.NewReader(`
122+
# HELP shadowsocks_ip_key_connectivity_seconds_per_location Time at least 1 connection was open for a (IP, access key) pair, per location
123+
# TYPE shadowsocks_ip_key_connectivity_seconds_per_location counter
124+
shadowsocks_ip_key_connectivity_seconds_per_location{asn="",location=""} 5
125+
`)
126+
err := promtest.GatherAndCompare(
127+
reg,
128+
expected,
129+
"shadowsocks_ip_key_connectivity_seconds_per_location",
130+
)
131+
require.NoError(t, err, "unexpected metric value found")
132+
}
133+
58134
func BenchmarkOpenTCP(b *testing.B) {
59135
ssMetrics := newPrometheusOutlineMetrics(nil, prometheus.NewRegistry())
60136
b.ResetTimer()

0 commit comments

Comments
 (0)