Skip to content

Commit 3f127b6

Browse files
authored
feat: add metrics to tls encrypter (#3025)
Adds metrics for events and errors
1 parent dd71d8a commit 3f127b6

File tree

2 files changed

+71
-13
lines changed

2 files changed

+71
-13
lines changed

packages/connection-encrypter-tls/src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,14 @@
1919
*/
2020

2121
import { TLS } from './tls.js'
22-
import type { ComponentLogger, ConnectionEncrypter, PrivateKey } from '@libp2p/interface'
22+
import type { ComponentLogger, ConnectionEncrypter, Metrics, PrivateKey } from '@libp2p/interface'
2323

2424
export const PROTOCOL = '/tls/1.0.0'
2525

2626
export interface TLSComponents {
2727
privateKey: PrivateKey
2828
logger: ComponentLogger
29+
metrics?: Metrics
2930
}
3031

3132
export function tls (): (components: TLSComponents) => ConnectionEncrypter {

packages/connection-encrypter-tls/src/tls.ts

Lines changed: 69 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,50 @@ import { HandshakeTimeoutError } from './errors.js'
2424
import { generateCertificate, verifyPeerCertificate, itToStream, streamToIt } from './utils.js'
2525
import { PROTOCOL } from './index.js'
2626
import type { TLSComponents } from './index.js'
27-
import type { MultiaddrConnection, ConnectionEncrypter, SecuredConnection, Logger, SecureConnectionOptions, PrivateKey } from '@libp2p/interface'
27+
import type { MultiaddrConnection, ConnectionEncrypter, SecuredConnection, Logger, SecureConnectionOptions, CounterGroup } from '@libp2p/interface'
2828
import type { Duplex } from 'it-stream-types'
2929
import type { Uint8ArrayList } from 'uint8arraylist'
3030

3131
export class TLS implements ConnectionEncrypter {
3232
public protocol: string = PROTOCOL
3333
private readonly log: Logger
34-
private readonly privateKey: PrivateKey
34+
private readonly components: TLSComponents
35+
private readonly metrics: {
36+
server: {
37+
events?: CounterGroup
38+
errors?: CounterGroup
39+
}
40+
client: {
41+
events?: CounterGroup
42+
errors?: CounterGroup
43+
}
44+
}
3545

3646
constructor (components: TLSComponents) {
3747
this.log = components.logger.forComponent('libp2p:tls')
38-
this.privateKey = components.privateKey
48+
this.components = components
49+
this.metrics = {
50+
server: {
51+
events: components.metrics?.registerCounterGroup('libp2p_tls_server_events_total', {
52+
label: 'event',
53+
help: 'Total count of TLS connection encryption events by type'
54+
}),
55+
errors: components.metrics?.registerCounterGroup('libp2p_tls_server_errors_total', {
56+
label: 'event',
57+
help: 'Total count of TLS connection encryption errors by type'
58+
})
59+
},
60+
client: {
61+
events: components.metrics?.registerCounterGroup('libp2p_tls_server_events_total', {
62+
label: 'event',
63+
help: 'Total count of TLS connection encryption events by type'
64+
}),
65+
errors: components.metrics?.registerCounterGroup('libp2p_tls_server_errors_total', {
66+
label: 'event',
67+
help: 'Total count of TLS connection encryption errors by type'
68+
})
69+
}
70+
}
3971
}
4072

4173
readonly [Symbol.toStringTag] = '@libp2p/tls'
@@ -57,7 +89,7 @@ export class TLS implements ConnectionEncrypter {
5789
*/
5890
async _encrypt <Stream extends Duplex<AsyncGenerator<Uint8Array | Uint8ArrayList>> = MultiaddrConnection> (conn: Stream, isServer: boolean, options?: SecureConnectionOptions): Promise<SecuredConnection<Stream>> {
5991
const opts: TLSSocketOptions = {
60-
...await generateCertificate(this.privateKey),
92+
...await generateCertificate(this.components.privateKey),
6193
isServer,
6294
// require TLS 1.3 or later
6395
minVersion: 'TLSv1.3',
@@ -83,9 +115,13 @@ export class TLS implements ConnectionEncrypter {
83115

84116
return new Promise<SecuredConnection<Stream>>((resolve, reject) => {
85117
options?.signal?.addEventListener('abort', () => {
86-
const err = new HandshakeTimeoutError()
87-
socket.destroy(err)
88-
reject(err)
118+
this.metrics[isServer ? 'server' : 'client'].events?.increment({
119+
abort: true
120+
})
121+
this.metrics[isServer ? 'server' : 'client'].errors?.increment({
122+
encrypt_abort: true
123+
})
124+
socket.emit('error', new HandshakeTimeoutError())
89125
})
90126

91127
const verifyRemote = (): void => {
@@ -104,21 +140,42 @@ export class TLS implements ConnectionEncrypter {
104140
})
105141
})
106142
.catch((err: Error) => {
107-
reject(err)
143+
this.metrics[isServer ? 'server' : 'client'].errors?.increment({
144+
verify_peer_certificate: true
145+
})
146+
socket.emit('error', err)
108147
})
109148
}
110149

111150
socket.on('error', (err: Error) => {
151+
this.log.error('error encrypting %s connection - %e', isServer ? 'server' : 'client', err)
152+
153+
if (err.name !== 'HandshakeTimeoutError') {
154+
this.metrics[isServer ? 'server' : 'client'].events?.increment({
155+
error: true
156+
})
157+
}
158+
159+
socket.destroy(err)
112160
reject(err)
113161
})
114162
socket.once('secure', () => {
115163
this.log('verifying remote certificate')
164+
this.metrics[isServer ? 'server' : 'client'].events?.increment({
165+
secure: true
166+
})
116167
verifyRemote()
117168
})
118-
})
119-
.catch(err => {
120-
socket.destroy(err)
121-
throw err
169+
socket.on('connect', () => {
170+
this.metrics[isServer ? 'server' : 'client'].events?.increment({
171+
connect: true
172+
})
122173
})
174+
socket.on('close', () => {
175+
this.metrics[isServer ? 'server' : 'client'].events?.increment({
176+
close: true
177+
})
178+
})
179+
})
123180
}
124181
}

0 commit comments

Comments
 (0)