@@ -11,6 +11,7 @@ import type { MultiaddrConnection, Connection } from '@libp2p/interface-connecti
11
11
import type { Upgrader , Listener } from '@libp2p/interface-transport'
12
12
import type { Multiaddr } from '@multiformats/multiaddr'
13
13
import type { TCPCreateListenerOptions } from './index.js'
14
+ import { ServerStatusMetric , TcpMetrics } from './metrics.js'
14
15
15
16
const log = logger ( 'libp2p:tcp:listener' )
16
17
@@ -30,6 +31,7 @@ interface Context extends TCPCreateListenerOptions {
30
31
upgrader : Upgrader
31
32
socketInactivityTimeout ?: number
32
33
socketCloseTimeout ?: number
34
+ metrics : TcpMetrics | null
33
35
}
34
36
35
37
type Status = { started : false } | { started : true , listeningAddr : Multiaddr , peerId : string | null }
@@ -38,6 +40,7 @@ export class TcpListener extends EventEmitter<any> implements Listener {
38
40
private readonly server : net . Server
39
41
/** Keep track of open connections to destroy in case of timeout */
40
42
private readonly connections = new Set < MultiaddrConnection > ( )
43
+ private readonly metrics : TcpMetrics | null
41
44
42
45
private status : Status = { started : false }
43
46
@@ -46,64 +49,66 @@ export class TcpListener extends EventEmitter<any> implements Listener {
46
49
47
50
context . keepAlive = context . keepAlive ?? true
48
51
49
- this . server = net . createServer ( context , this . onSocket . bind ( this ) )
52
+ this . server = net . createServer ( context , socket => {
53
+ this . onSocket ( socket ) . catch ( e => log ( 'onSocket error' , e ) )
54
+ } )
50
55
51
56
this . server
52
57
. on ( 'listening' , ( ) => this . dispatchEvent ( new CustomEvent ( 'listening' ) ) )
53
58
. on ( 'error' , err => this . dispatchEvent ( new CustomEvent < Error > ( 'error' , { detail : err } ) ) )
54
59
. on ( 'close' , ( ) => this . dispatchEvent ( new CustomEvent ( 'close' ) ) )
60
+
61
+ this . metrics = context . metrics
62
+ this . metrics ?. connections . addCollect ( ( ) => {
63
+ this . metrics ?. connections . set ( this . connections . size )
64
+ this . metrics ?. serverStatus . set ( this . status . started ? ServerStatusMetric . started : ServerStatusMetric . stopped )
65
+ } )
55
66
}
56
67
57
- private onSocket ( socket : net . Socket ) {
68
+ private async onSocket ( socket : net . Socket ) {
58
69
// Avoid uncaught errors caused by unstable connections
59
70
socket . on ( 'error' , err => {
60
71
log ( 'socket error' , err )
72
+ this . metrics ?. socketEvents . inc ( { event : 'error' } )
61
73
} )
62
74
63
75
let maConn : MultiaddrConnection
64
76
try {
65
77
maConn = toMultiaddrConnection ( socket , {
66
78
listeningAddr : this . status . started ? this . status . listeningAddr : undefined ,
67
79
socketInactivityTimeout : this . context . socketInactivityTimeout ,
68
- socketCloseTimeout : this . context . socketCloseTimeout
80
+ socketCloseTimeout : this . context . socketCloseTimeout ,
81
+ metrics : this . metrics
69
82
} )
70
83
} catch ( err ) {
71
84
log . error ( 'inbound connection failed' , err )
85
+ this . metrics ?. listenerErrors . inc ( { error : 'inbound_to_connection' } )
72
86
return
73
87
}
74
88
75
89
log ( 'new inbound connection %s' , maConn . remoteAddr )
76
90
try {
77
- this . context . upgrader . upgradeInbound ( maConn )
78
- . then ( ( conn ) => {
79
- log ( 'inbound connection %s upgraded' , maConn . remoteAddr )
80
- this . connections . add ( maConn )
81
-
82
- socket . once ( 'close' , ( ) => {
83
- this . connections . delete ( maConn )
84
- } )
85
-
86
- if ( this . context . handler != null ) {
87
- this . context . handler ( conn )
88
- }
89
-
90
- this . dispatchEvent ( new CustomEvent < Connection > ( 'connection' , { detail : conn } ) )
91
- } )
92
- . catch ( async err => {
93
- log . error ( 'inbound connection failed' , err )
94
-
95
- await attemptClose ( maConn )
96
- } )
97
- . catch ( err => {
98
- log . error ( 'closing inbound connection failed' , err )
99
- } )
91
+ const conn = await this . context . upgrader . upgradeInbound ( maConn )
92
+ log ( 'inbound connection %s upgraded' , maConn . remoteAddr )
93
+ this . connections . add ( maConn )
94
+
95
+ socket . once ( 'close' , ( ) => {
96
+ this . connections . delete ( maConn )
97
+ } )
98
+
99
+ if ( this . context . handler != null ) {
100
+ this . context . handler ( conn )
101
+ }
102
+
103
+ this . dispatchEvent ( new CustomEvent < Connection > ( 'connection' , { detail : conn } ) )
100
104
} catch ( err ) {
101
105
log . error ( 'inbound connection failed' , err )
106
+ this . metrics ?. listenerErrors . inc ( { error : 'inbound_upgrade' } )
102
107
103
- attemptClose ( maConn )
104
- . catch ( err => {
105
- log . error ( 'closing inbound connection failed' , err )
106
- } )
108
+ attemptClose ( maConn ) . catch ( err => {
109
+ log . error ( 'closing inbound connection failed' , err )
110
+ this . metrics ?. listenerErrors . inc ( { error : 'inbound_closing_failed' } )
111
+ } )
107
112
}
108
113
}
109
114
0 commit comments