Skip to content

Commit 55e8d0c

Browse files
authored
feat: add AS organization name to metrics (#204)
* feat: add AS organization name to metrics * Revert to pass `int` to `asnLabel()`.
1 parent fa651d3 commit 55e8d0c

File tree

5 files changed

+28
-20
lines changed

5 files changed

+28
-20
lines changed

cmd/outline-ss-server/metrics.go

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ func newProxyCollector(proto string) (*proxyCollector, error) {
6060
prometheus.CounterOpts{
6161
Name: "data_bytes_per_location",
6262
Help: "Bytes transferred by the proxy, per location",
63-
}, []string{"proto", "dir", "location", "asn"}).CurryWith(map[string]string{"proto": proto})
63+
}, []string{"proto", "dir", "location", "asn", "asorg"}).CurryWith(map[string]string{"proto": proto})
6464
if err != nil {
6565
return nil, err
6666
}
@@ -82,16 +82,16 @@ func (c *proxyCollector) Collect(ch chan<- prometheus.Metric) {
8282

8383
func (c *proxyCollector) addClientTarget(clientProxyBytes, proxyTargetBytes int64, accessKey string, clientInfo ipinfo.IPInfo) {
8484
addIfNonZero(clientProxyBytes, c.dataBytesPerKey, "c>p", accessKey)
85-
addIfNonZero(clientProxyBytes, c.dataBytesPerLocation, "c>p", clientInfo.CountryCode.String(), asnLabel(clientInfo.ASN))
85+
addIfNonZero(clientProxyBytes, c.dataBytesPerLocation, "c>p", clientInfo.CountryCode.String(), asnLabel(clientInfo.ASN.Number), clientInfo.ASN.Organization)
8686
addIfNonZero(proxyTargetBytes, c.dataBytesPerKey, "p>t", accessKey)
87-
addIfNonZero(proxyTargetBytes, c.dataBytesPerLocation, "p>t", clientInfo.CountryCode.String(), asnLabel(clientInfo.ASN))
87+
addIfNonZero(proxyTargetBytes, c.dataBytesPerLocation, "p>t", clientInfo.CountryCode.String(), asnLabel(clientInfo.ASN.Number), clientInfo.ASN.Organization)
8888
}
8989

9090
func (c *proxyCollector) addTargetClient(targetProxyBytes, proxyClientBytes int64, accessKey string, clientInfo ipinfo.IPInfo) {
9191
addIfNonZero(targetProxyBytes, c.dataBytesPerKey, "p<t", accessKey)
92-
addIfNonZero(targetProxyBytes, c.dataBytesPerLocation, "p<t", clientInfo.CountryCode.String(), asnLabel(clientInfo.ASN))
92+
addIfNonZero(targetProxyBytes, c.dataBytesPerLocation, "p<t", clientInfo.CountryCode.String(), asnLabel(clientInfo.ASN.Number), clientInfo.ASN.Organization)
9393
addIfNonZero(proxyClientBytes, c.dataBytesPerKey, "c<p", accessKey)
94-
addIfNonZero(proxyClientBytes, c.dataBytesPerLocation, "c<p", clientInfo.CountryCode.String(), asnLabel(clientInfo.ASN))
94+
addIfNonZero(proxyClientBytes, c.dataBytesPerLocation, "c<p", clientInfo.CountryCode.String(), asnLabel(clientInfo.ASN.Number), clientInfo.ASN.Organization)
9595
}
9696

9797
type tcpConnMetrics struct {
@@ -175,12 +175,12 @@ func newTCPCollector() (*tcpServiceMetrics, error) {
175175
Namespace: namespace,
176176
Name: "connections_opened",
177177
Help: "Count of open TCP connections",
178-
}, []string{"location", "asn"}),
178+
}, []string{"location", "asn", "asorg"}),
179179
closedConnections: prometheus.NewCounterVec(prometheus.CounterOpts{
180180
Namespace: namespace,
181181
Name: "connections_closed",
182182
Help: "Count of closed TCP connections",
183-
}, []string{"location", "asn", "status", "access_key"}),
183+
}, []string{"location", "asn", "asorg", "status", "access_key"}),
184184
connectionDurationMs: prometheus.NewHistogramVec(
185185
prometheus.HistogramOpts{
186186
Namespace: namespace,
@@ -217,11 +217,11 @@ func (c *tcpServiceMetrics) Collect(ch chan<- prometheus.Metric) {
217217
}
218218

219219
func (c *tcpServiceMetrics) openConnection(clientInfo ipinfo.IPInfo) {
220-
c.openConnections.WithLabelValues(clientInfo.CountryCode.String(), asnLabel(clientInfo.ASN)).Inc()
220+
c.openConnections.WithLabelValues(clientInfo.CountryCode.String(), asnLabel(clientInfo.ASN.Number), clientInfo.ASN.Organization).Inc()
221221
}
222222

223223
func (c *tcpServiceMetrics) closeConnection(status string, duration time.Duration, accessKey string, clientInfo ipinfo.IPInfo) {
224-
c.closedConnections.WithLabelValues(clientInfo.CountryCode.String(), asnLabel(clientInfo.ASN), status, accessKey).Inc()
224+
c.closedConnections.WithLabelValues(clientInfo.CountryCode.String(), asnLabel(clientInfo.ASN.Number), clientInfo.ASN.Organization, status, accessKey).Inc()
225225
c.connectionDurationMs.WithLabelValues(status).Observe(duration.Seconds() * 1000)
226226
}
227227

@@ -310,7 +310,7 @@ func newUDPCollector() (*udpServiceMetrics, error) {
310310
Namespace: namespace,
311311
Name: "packets_from_client_per_location",
312312
Help: "Packets received from the client, per location and status",
313-
}, []string{"location", "asn", "status"}),
313+
}, []string{"location", "asn", "asorg", "status"}),
314314
addedNatEntries: prometheus.NewCounter(
315315
prometheus.CounterOpts{
316316
Namespace: namespace,
@@ -351,7 +351,7 @@ func (c *udpServiceMetrics) removeNatEntry() {
351351
}
352352

353353
func (c *udpServiceMetrics) addPacketFromClient(status string, clientProxyBytes, proxyTargetBytes int64, accessKey string, clientInfo ipinfo.IPInfo) {
354-
c.packetsFromClientPerLocation.WithLabelValues(clientInfo.CountryCode.String(), asnLabel(clientInfo.ASN), status).Inc()
354+
c.packetsFromClientPerLocation.WithLabelValues(clientInfo.CountryCode.String(), asnLabel(clientInfo.ASN.Number), clientInfo.ASN.Organization, status).Inc()
355355
c.proxyCollector.addClientTarget(clientProxyBytes, proxyTargetBytes, accessKey, clientInfo)
356356
}
357357

@@ -408,7 +408,7 @@ func newTunnelTimeMetrics(ip2info ipinfo.IPInfoMap) *tunnelTimeMetrics {
408408
Namespace: namespace,
409409
Name: "seconds_per_location",
410410
Help: "Tunnel time, per location.",
411-
}, []string{"location", "asn"}),
411+
}, []string{"location", "asn", "asorg"}),
412412
}
413413
}
414414

@@ -433,7 +433,7 @@ func (c *tunnelTimeMetrics) reportTunnelTime(ipKey IPKey, client *activeClient,
433433
tunnelTime := tNow.Sub(client.startTime)
434434
slog.LogAttrs(nil, slog.LevelDebug, "Reporting tunnel time.", slog.String("key", ipKey.accessKey), slog.Duration("duration", tunnelTime))
435435
c.tunnelTimePerKey.WithLabelValues(ipKey.accessKey).Add(tunnelTime.Seconds())
436-
c.tunnelTimePerLocation.WithLabelValues(client.info.CountryCode.String(), asnLabel(client.info.ASN)).Add(tunnelTime.Seconds())
436+
c.tunnelTimePerLocation.WithLabelValues(client.info.CountryCode.String(), asnLabel(client.info.ASN.Number), client.info.ASN.Organization).Add(tunnelTime.Seconds())
437437
// Reset the start time now that the tunnel time has been reported.
438438
client.startTime = tNow
439439
}

cmd/outline-ss-server/metrics_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ func TestTunnelTime(t *testing.T) {
130130
expected := strings.NewReader(`
131131
# HELP tunnel_time_seconds_per_location Tunnel time, per location.
132132
# TYPE tunnel_time_seconds_per_location counter
133-
tunnel_time_seconds_per_location{asn="",location="XL"} 5
133+
tunnel_time_seconds_per_location{asn="",asorg="",location="XL"} 5
134134
`)
135135
err := promtest.GatherAndCompare(
136136
reg,

ipinfo/ipinfo.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ type IPInfoMap interface {
2626

2727
type IPInfo struct {
2828
CountryCode CountryCode
29-
ASN int
29+
ASN ASN
3030
}
3131

3232
type CountryCode string
@@ -35,6 +35,11 @@ func (cc CountryCode) String() string {
3535
return string(cc)
3636
}
3737

38+
type ASN struct {
39+
Number int
40+
Organization string
41+
}
42+
3843
const (
3944
// Codes in the X* range are reserved to be user-assigned.
4045
// See https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Decoding_table

ipinfo/mmdb.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,10 @@ func (ip2info *MMDBIPInfoMap) GetIPInfo(ip net.IP) (IPInfo, error) {
7979
if asnErr != nil {
8080
asnErr = fmt.Errorf("asn lookup failed: %w", asnErr)
8181
} else if record != nil {
82-
info.ASN = int(record.AutonomousSystemNumber)
82+
info.ASN = ASN{
83+
Number: int(record.AutonomousSystemNumber),
84+
Organization: record.AutonomousSystemOrganization,
85+
}
8386
}
8487
}
8588
return info, errors.Join(countryErr, asnErr)

ipinfo/mmdb_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,11 @@ func TestIPInfoMapASNOnly(t *testing.T) {
7878
// For examples, see https://github.com/maxmind/MaxMind-DB/blob/main/source-data/GeoLite2-ASN-Test.json
7979
info, err := ip2info.GetIPInfo(net.ParseIP("38.108.80.24"))
8080
require.NoError(t, err)
81-
assert.Equal(t, IPInfo{ASN: 174}, info)
81+
assert.Equal(t, IPInfo{ASN: ASN{Number: 174, Organization: "Cogent Communications"}}, info)
8282

8383
info, err = ip2info.GetIPInfo(net.ParseIP("2400::1"))
8484
require.NoError(t, err)
85-
assert.Equal(t, IPInfo{ASN: 4766}, info)
85+
assert.Equal(t, IPInfo{ASN: ASN{Number: 4766, Organization: "Korea Telecom"}}, info)
8686

8787
info, err = ip2info.GetIPInfo(net.ParseIP("10.0.0.1"))
8888
require.NoError(t, err)
@@ -104,15 +104,15 @@ func TestIPInfoMap(t *testing.T) {
104104

105105
info, err := ip2info.GetIPInfo(net.ParseIP("67.43.156.0"))
106106
require.NoError(t, err)
107-
assert.Equal(t, IPInfo{CountryCode: "BT", ASN: 35908}, info)
107+
assert.Equal(t, IPInfo{CountryCode: "BT", ASN: ASN{Number: 35908, Organization: ""}}, info)
108108

109109
info, err = ip2info.GetIPInfo(net.ParseIP("2a02:d280::"))
110110
require.NoError(t, err)
111111
assert.Equal(t, IPInfo{CountryCode: "CZ"}, info)
112112

113113
info, err = ip2info.GetIPInfo(net.ParseIP("2400::1"))
114114
require.NoError(t, err)
115-
assert.Equal(t, IPInfo{ASN: 4766}, info)
115+
assert.Equal(t, IPInfo{ASN: ASN{Number: 4766, Organization: "Korea Telecom"}}, info)
116116

117117
info, err = ip2info.GetIPInfo(net.ParseIP("10.0.0.1"))
118118
require.NoError(t, err)

0 commit comments

Comments
 (0)