Skip to content
This repository was archived by the owner on Aug 29, 2023. It is now read-only.

Commit 6c4c316

Browse files
authored
fix: use labels to differentiate interfaces for metrics (#230)
Instead of inserting the interface address into the metric name, use the metric address as a label prefix for the value being reported. This allows our metric names to be stable even if you don't know the ip/port combo that will be used ahead of time. The tradeoff is the label names may change between restarts if the port number changes, but we have to apply a disambguator somewhere. Depends on: - [ ] libp2p/js-libp2p-prometheus-metrics#6
1 parent 6568f81 commit 6c4c316

File tree

3 files changed

+43
-36
lines changed

3 files changed

+43
-36
lines changed

src/index.ts

+3-8
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ export interface TCPComponents {
6262

6363
export interface TCPMetrics {
6464
dialerEvents: CounterGroup
65-
listenerEvents: CounterGroup
6665
}
6766

6867
class TCP implements Transport {
@@ -76,13 +75,9 @@ class TCP implements Transport {
7675

7776
if (components.metrics != null) {
7877
this.metrics = {
79-
dialerEvents: components.metrics.registerCounterGroup('libp2p_tcp_dialer_errors_total', {
78+
dialerEvents: components.metrics.registerCounterGroup('libp2p_tcp_dialer_events_total', {
8079
label: 'event',
81-
help: 'Total count of TCP dialer errors by error type'
82-
}),
83-
listenerEvents: components.metrics.registerCounterGroup('libp2p_tcp_listener_errors_total', {
84-
label: 'event',
85-
help: 'Total count of TCP listener errors by error type'
80+
help: 'Total count of TCP dialer events by type'
8681
})
8782
}
8883
}
@@ -115,7 +110,7 @@ class TCP implements Transport {
115110
})
116111
log('new outbound connection %s', maConn.remoteAddr)
117112
const conn = await options.upgrader.upgradeOutbound(maConn)
118-
log('outbound connection %s upgraded', maConn.remoteAddr)
113+
log('outbound connection upgraded %s', maConn.remoteAddr)
119114
return conn
120115
}
121116

src/listener.ts

+35-25
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import type { MultiaddrConnection, Connection } from '@libp2p/interface-connecti
1111
import type { Upgrader, Listener, ListenerEvents } from '@libp2p/interface-transport'
1212
import type { Multiaddr } from '@multiformats/multiaddr'
1313
import type { TCPCreateListenerOptions } from './index.js'
14-
import type { CounterGroup, Metric, Metrics } from '@libp2p/interface-metrics'
14+
import type { CounterGroup, MetricGroup, Metrics } from '@libp2p/interface-metrics'
1515

1616
const log = logger('libp2p:tcp:listener')
1717

@@ -39,7 +39,7 @@ const SERVER_STATUS_UP = 1
3939
const SERVER_STATUS_DOWN = 0
4040

4141
export interface TCPListenerMetrics {
42-
status: Metric
42+
status: MetricGroup
4343
errors: CounterGroup
4444
events: CounterGroup
4545
}
@@ -52,12 +52,14 @@ export class TCPListener extends EventEmitter<ListenerEvents> implements Listene
5252
private readonly connections = new Set<MultiaddrConnection>()
5353
private status: Status = { started: false }
5454
private metrics?: TCPListenerMetrics
55+
private addr: string
5556

5657
constructor (private readonly context: Context) {
5758
super()
5859

5960
context.keepAlive = context.keepAlive ?? true
6061

62+
this.addr = 'unknown'
6163
this.server = net.createServer(context, this.onSocket.bind(this))
6264

6365
// https://nodejs.org/api/net.html#servermaxconnections
@@ -72,49 +74,56 @@ export class TCPListener extends EventEmitter<ListenerEvents> implements Listene
7274
if (context.metrics != null) {
7375
// we are listening, register metrics for our port
7476
const address = this.server.address()
75-
let addr: string
7677

7778
if (address == null) {
78-
addr = 'unknown'
79+
this.addr = 'unknown'
7980
} else if (typeof address === 'string') {
8081
// unix socket
81-
addr = address
82+
this.addr = address
8283
} else {
83-
addr = `${address.address}:${address.port}`
84+
this.addr = `${address.address}:${address.port}`
8485
}
8586

86-
context.metrics?.registerMetric(`libp2p_tcp_connections_${addr}_total`, {
87+
context.metrics?.registerMetricGroup('libp2p_tcp_inbound_connections_total', {
88+
label: 'address',
8789
help: 'Current active connections in TCP listener',
8890
calculate: () => {
89-
return this.connections.size
91+
return {
92+
[this.addr]: this.connections.size
93+
}
9094
}
9195
})
9296

9397
this.metrics = {
94-
status: context.metrics.registerMetric(`libp2p_tcp_${addr}_server_status_info`, {
95-
help: 'Current status of the TCP server'
98+
status: context.metrics.registerMetricGroup('libp2p_tcp_listener_status_info', {
99+
label: 'address',
100+
help: 'Current status of the TCP listener socket'
96101
}),
97-
errors: context.metrics.registerCounterGroup(`libp2p_tcp_${addr}_server_errors_total`, {
98-
label: 'error',
99-
help: 'Total count of TCP listener errors by error type'
102+
errors: context.metrics.registerMetricGroup('libp2p_tcp_listener_errors_total', {
103+
label: 'address',
104+
help: 'Total count of TCP listener errors by type'
100105
}),
101-
events: context.metrics.registerCounterGroup(`libp2p_tcp_${addr}_socket_events_total`, {
102-
label: 'event',
103-
help: 'Total count of TCP socket events by event'
106+
events: context.metrics.registerMetricGroup('libp2p_tcp_listener_events_total', {
107+
label: 'address',
108+
help: 'Total count of TCP listener events by type'
104109
})
105110
}
106111

107-
this.metrics?.status.update(SERVER_STATUS_UP)
112+
this.metrics?.status.update({
113+
[this.addr]: SERVER_STATUS_UP
114+
})
108115
}
109116

110117
this.dispatchEvent(new CustomEvent('listening'))
111118
})
112119
.on('error', err => {
113-
this.metrics?.errors.increment({ listen_error: true })
120+
this.metrics?.errors.increment({ [`${this.addr} listen_error`]: true })
114121
this.dispatchEvent(new CustomEvent<Error>('error', { detail: err }))
115122
})
116123
.on('close', () => {
117-
this.metrics?.status.update(SERVER_STATUS_DOWN)
124+
this.metrics?.status.update({
125+
[this.addr]: SERVER_STATUS_DOWN
126+
})
118127
this.dispatchEvent(new CustomEvent('close'))
119128
})
120129
}
@@ -123,7 +132,7 @@ export class TCPListener extends EventEmitter<ListenerEvents> implements Listene
123132
// Avoid uncaught errors caused by unstable connections
124133
socket.on('error', err => {
125134
log('socket error', err)
126-
this.metrics?.events.increment({ error: true })
135+
this.metrics?.events.increment({ [`${this.addr} error`]: true })
127136
})
128137

129138
let maConn: MultiaddrConnection
@@ -132,19 +141,20 @@ export class TCPListener extends EventEmitter<ListenerEvents> implements Listene
132141
listeningAddr: this.status.started ? this.status.listeningAddr : undefined,
133142
socketInactivityTimeout: this.context.socketInactivityTimeout,
134143
socketCloseTimeout: this.context.socketCloseTimeout,
135-
metrics: this.metrics?.events
144+
metrics: this.metrics?.events,
145+
metricPrefix: `${this.addr} `
136146
})
137147
} catch (err) {
138148
log.error('inbound connection failed', err)
139-
this.metrics?.errors.increment({ inbound_to_connection: true })
149+
this.metrics?.errors.increment({ [`${this.addr} inbound_to_connection`]: true })
140150
return
141151
}
142152

143153
log('new inbound connection %s', maConn.remoteAddr)
144154
try {
145155
this.context.upgrader.upgradeInbound(maConn)
146156
.then((conn) => {
147-
log('inbound connection %s upgraded', maConn.remoteAddr)
157+
log('inbound connection upgraded %s', maConn.remoteAddr)
148158
this.connections.add(maConn)
149159

150160
socket.once('close', () => {
@@ -159,7 +169,7 @@ export class TCPListener extends EventEmitter<ListenerEvents> implements Listene
159169
})
160170
.catch(async err => {
161171
log.error('inbound connection failed', err)
162-
this.metrics?.errors.increment({ inbound_upgrade: true })
172+
this.metrics?.errors.increment({ [`${this.addr} inbound_upgrade`]: true })
163173

164174
await attemptClose(maConn)
165175
})
@@ -172,7 +182,7 @@ export class TCPListener extends EventEmitter<ListenerEvents> implements Listene
172182
attemptClose(maConn)
173183
.catch(err => {
174184
log.error('closing inbound connection failed', err)
175-
this.metrics?.errors.increment({ inbound_closing_failed: true })
185+
this.metrics?.errors.increment({ [`${this.addr} inbound_closing_failed`]: true })
176186
})
177187
}
178188
}

src/socket-to-conn.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ interface ToConnectionOptions {
2121
socketInactivityTimeout?: number
2222
socketCloseTimeout?: number
2323
metrics?: CounterGroup
24+
metricPrefix?: string
2425
}
2526

2627
/**
@@ -29,6 +30,7 @@ interface ToConnectionOptions {
2930
*/
3031
export const toMultiaddrConnection = (socket: Socket, options: ToConnectionOptions) => {
3132
const metrics = options.metrics
33+
const metricPrefix = options.metricPrefix ?? ''
3234
const inactivityTimeout = options.socketInactivityTimeout ?? SOCKET_TIMEOUT
3335
const closeTimeout = options.socketCloseTimeout ?? CLOSE_TIMEOUT
3436

@@ -63,7 +65,7 @@ export const toMultiaddrConnection = (socket: Socket, options: ToConnectionOptio
6365
// https://nodejs.org/dist/latest-v16.x/docs/api/net.html#socketsettimeouttimeout-callback
6466
socket.setTimeout(inactivityTimeout, () => {
6567
log('%s socket read timeout', lOptsStr)
66-
metrics?.increment({ timeout: true })
68+
metrics?.increment({ [`${metricPrefix}timeout`]: true })
6769

6870
// only destroy with an error if the remote has not sent the FIN message
6971
let err: Error | undefined
@@ -78,7 +80,7 @@ export const toMultiaddrConnection = (socket: Socket, options: ToConnectionOptio
7880

7981
socket.once('close', () => {
8082
log('%s socket read timeout', lOptsStr)
81-
metrics?.increment({ close: true })
83+
metrics?.increment({ [`${metricPrefix}close`]: true })
8284

8385
// In instances where `close` was not explicitly called,
8486
// such as an iterable stream ending, ensure we have set the close
@@ -92,7 +94,7 @@ export const toMultiaddrConnection = (socket: Socket, options: ToConnectionOptio
9294
// the remote sent a FIN packet which means no more data will be sent
9395
// https://nodejs.org/dist/latest-v16.x/docs/api/net.html#event-end
9496
log('socket ended', maConn.remoteAddr.toString())
95-
metrics?.increment({ end: true })
97+
metrics?.increment({ [`${metricPrefix}end`]: true })
9698
})
9799

98100
const maConn: MultiaddrConnection = {

0 commit comments

Comments
 (0)