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

Commit

Permalink
Declare metrics locally and use MetricsRegister
Browse files Browse the repository at this point in the history
  • Loading branch information
dapplion committed Oct 28, 2022
1 parent fffffe4 commit 183f741
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 23 deletions.
10 changes: 4 additions & 6 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,10 @@ import { CreateListenerOptions, DialOptions, Listener, symbol, Transport } from
import type { AbortOptions, Multiaddr } from '@multiformats/multiaddr'
import type { Socket, IpcSocketConnectOpts, TcpSocketConnectOpts } from 'net'
import type { Connection } from '@libp2p/interface-connection'
import type { TcpMetrics } from './metrics.js'
import { getMetrics, Metrics, MetricsRegister } from './metrics.js'

const log = logger('libp2p:tcp')

export { TcpMetrics }

export interface TCPOptions {
/**
* An optional number in ms that is used as an inactivity timeout after which the socket will be closed
Expand Down Expand Up @@ -60,11 +58,11 @@ export interface TCPCreateListenerOptions extends CreateListenerOptions, TCPSock

class TCP implements Transport {
private readonly opts: TCPOptions
private readonly metrics: TcpMetrics | null
private readonly metrics: Metrics | null

constructor (options: TCPOptions = {}, metrics?: TcpMetrics | null) {
constructor (options: TCPOptions = {}, metricsRegistry?: MetricsRegister | null) {
this.opts = options
this.metrics = metrics ?? null
this.metrics = metricsRegistry != null ? getMetrics(metricsRegistry) : null
}

get [symbol] (): true {
Expand Down
6 changes: 3 additions & 3 deletions src/listener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import type { MultiaddrConnection, Connection } from '@libp2p/interface-connecti
import type { Upgrader, Listener, ListenerEvents } from '@libp2p/interface-transport'
import type { Multiaddr } from '@multiformats/multiaddr'
import type { TCPCreateListenerOptions } from './index.js'
import { ServerStatusMetric, TcpMetrics } from './metrics.js'
import { ServerStatusMetric, Metrics } from './metrics.js'

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

Expand All @@ -32,7 +32,7 @@ interface Context extends TCPCreateListenerOptions {
socketInactivityTimeout?: number
socketCloseTimeout?: number
maxConnections?: number
metrics: TcpMetrics | null
metrics: Metrics | null
}

type Status = {started: false} | {started: true, listeningAddr: Multiaddr, peerId: string | null }
Expand All @@ -41,7 +41,7 @@ export class TCPListener extends EventEmitter<ListenerEvents> implements Listene
private readonly server: net.Server
/** Keep track of open connections to destroy in case of timeout */
private readonly connections = new Set<MultiaddrConnection>()
private readonly metrics: TcpMetrics | null
private readonly metrics: Metrics | null

private status: Status = { started: false }

Expand Down
58 changes: 44 additions & 14 deletions src/metrics.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,53 @@
export enum ServerStatusMetric {
stopped = 0,
started = 1
}

export function getMetrics (register: MetricsRegister) {
return {
serverStatus: register.gauge({
name: 'libp2p_tcp_server_status',
help: 'Current status of the TCP server'
}),

connections: register.gauge({
name: 'libp2p_tcp_connections_count',
help: 'Current active connections in TCP listener'
}),

listenerErrors: register.gauge<{ error: string }>({
name: 'libp2p_tcp_listener_errors_total',
help: 'Total count of TCP listener errors by error type',
labelNames: ['error']
}),

socketEvents: register.gauge<{ event: string }>({
name: 'libp2p_tcp_socket_events',
help: 'Total count of TCP socket events by event',
labelNames: ['event']
})
}
}

export type Metrics = ReturnType<typeof getMetrics>

/* eslint-disable etc/prefer-interface, @typescript-eslint/method-signature-style */

export interface MetricsRegister {
gauge<T extends LabelsGeneric>(config: GaugeConfig<T>): Gauge<T>
}

interface GaugeConfig<Labels extends LabelsGeneric> {
name: string
help: string
labelNames?: keyof Labels extends string ? Array<keyof Labels> : undefined
}

type LabelsGeneric = Record<string, string | undefined>
type CollectFn<Labels extends LabelsGeneric> = (metric: Gauge<Labels>) => void

interface Gauge<Labels extends LabelsGeneric = never> {
// Sorry for this mess, `prom-client` API choices are not great
// If the function signature was `inc(value: number, labels?: Labels)`, this would be simpler
// Follows `prom-client` API choices, to require less middleware on consumer
inc(value?: number): void
inc(labels: Labels, value?: number): void
inc(arg1?: Labels | number, arg2?: number): void
Expand All @@ -20,15 +62,3 @@ interface Gauge<Labels extends LabelsGeneric = never> {

addCollect(collectFn: CollectFn<Labels>): void
}

export enum ServerStatusMetric {
stopped = 0,
started = 1
}

export interface TcpMetrics {
serverStatus: Gauge
connections: Gauge
listenerErrors: Gauge<{error: string}>
socketEvents: Gauge<{event: string}>
}

0 comments on commit 183f741

Please sign in to comment.