UNPKG

@libp2p/interface

Version:
549 lines (491 loc) 15.7 kB
import type { MultiaddrConnection, Stream } from './index.js' /** * Create tracked metrics with these options. Loosely based on the * interfaces exposed by the prom-client module */ export interface MetricOptions { /** * Optional label for the metric */ label?: string /** * Optional help for the metric */ help?: string } /** * A function that returns a tracked metric which may be expensive * to calculate so it is only invoked when metrics are being scraped */ export type CalculateMetric<T = number> = (() => T) | (() => Promise<T>) /** * Create tracked metrics that are expensive to calculate by passing * a function that is only invoked when metrics are being scraped */ export interface CalculatedMetricOptions<T = number> extends MetricOptions { /** * An optional function invoked to calculate the component metric instead of * using `.update`, `.increment`, and `.decrement` */ calculate: CalculateMetric<T> } /** * Call this function to stop the timer returned from the `.timer` method * on the metric */ export interface StopTimer { (): void } /** * A tracked metric loosely based on the interfaces exposed by the * prom-client module */ export interface Metric { /** * Update the stored metric to the passed value */ update(value: number): void /** * Increment the metric by the passed value or 1 */ increment(value?: number): void /** * Decrement the metric by the passed value or 1 */ decrement(value?: number): void /** * Reset this metric to its default value */ reset(): void /** * Start a timed metric, call the returned function to * stop the timer */ timer(): StopTimer } /** * A group of related metrics loosely based on the interfaces exposed by the * prom-client module */ export interface MetricGroup<T extends string = any> { /** * Update the stored metric group to the passed value */ update(values: Partial<Record<T, number>>): void /** * Increment the metric group keys by the passed number or * `true` to increment by 1 */ increment(values: Partial<Record<T, number | true>>): void /** * Decrement the metric group keys by the passed number or * `true` to decrement by 1 */ decrement(values: Partial<Record<T, number | true>>): void /** * Reset the passed key in this metric group to its default value * or all keys if no key is passed */ reset(): void /** * Start a timed metric for the named key in the group, call * the returned function to stop the timer */ timer(key: string): StopTimer } /** * A tracked counter loosely based on the Counter interface exposed * by the prom-client module - counters are metrics that only go up */ export interface Counter { /** * Increment the metric by the passed value or 1 */ increment(value?: number): void /** * Reset this metric to its default value */ reset(): void } /** * A group of tracked counters loosely based on the Counter interface * exposed by the prom-client module - counters are metrics that only * go up */ export interface CounterGroup<T extends string = any> { /** * Increment the metric group keys by the passed number or * any non-numeric value to increment by 1 */ increment(values: Partial<Record<T, number | true>>): void /** * Reset the passed key in this metric group to its default value * or all keys if no key is passed */ reset(): void } export interface HistogramOptions extends MetricOptions { /** * Buckets for the histogram */ buckets?: number[] } /** * Create tracked metrics that are expensive to calculate by passing * a function that is only invoked when metrics are being scraped */ export interface CalculatedHistogramOptions<T = number> extends HistogramOptions { /** * An optional function invoked to calculate the component metric instead of * using `.observe` */ calculate: CalculateMetric<T> } export interface Histogram { /** * Observe the passed value */ observe(value: number): void /** * Reset this histogram to its default value */ reset(): void /** * Start a timed metric, call the returned function to * stop the timer */ timer(): StopTimer } export interface HistogramGroup<T extends string = any> { /** * Observe the passed value for the named key in the group */ observe(values: Partial<Record<T, number>>): void /** * Reset the passed key in this histogram group to its default value * or all keys if no key is passed */ reset(): void /** * Start a timed metric for the named key in the group, call * the returned function to stop the timer */ timer(key: string): StopTimer } export interface SummaryOptions extends MetricOptions { /** * Percentiles for the summary */ percentiles?: number[] /** * Configure how old a bucket can be before it is reset for sliding window */ maxAgeSeconds?: number /** * Configure how many buckets in the sliding window */ ageBuckets?: number /** * Remove entries without any new values in the last `maxAgeSeconds` */ pruneAgedBuckets?: boolean /** * Control compression of data in t-digest */ compressCount?: number } /** * Create tracked metrics that are expensive to calculate by passing * a function that is only invoked when metrics are being scraped */ export interface CalculatedSummaryOptions<T = number> extends SummaryOptions { /** * An optional function invoked to calculate the component metric instead of * using `.observe` */ calculate: CalculateMetric<T> } /** * A tracked summary loosely based on the Summary interface exposed * by the prom-client module */ export interface Summary { /** * Observe the passed value */ observe(value: number): void /** * Reset this summary to its default value */ reset(): void /** * Start a timed metric, call the returned function to * stop the timer */ timer(): StopTimer } /** * A group of tracked summaries loosely based on the Summary interface * exposed by the prom-client module */ export interface SummaryGroup<T extends string = any> { /** * Observe the passed value for the named key in the group */ observe(values: Partial<Record<T, number>>): void /** * Reset the passed key in this summary group to its default value * or all keys if no key is passed */ reset(): void /** * Start a timed metric for the named key in the group, call * the returned function to stop the timer */ timer(key: string): StopTimer } /** * The libp2p metrics tracking object. This interface is only concerned * with the collection of metrics, please see the individual implementations * for how to extract metrics for viewing. * * @example How to register a simple metric * * ```typescript * import { Metrics, Metric } from '@libp2p/interface/metrics' * * interface MyServiceComponents { * metrics: Metrics * } * * class MyService { * private readonly myMetric: Metric * * constructor (components: MyServiceComponents) { * this.myMetric = components.metrics.registerMetric({ * name: 'my_metric', * label: 'my_label', * help: 'my help text' * }) * } * * // later * doSomething () { * this.myMetric.update(1) * } * } * ``` * * @example How to register a dynamically calculated metric * * A metric that is expensive to calculate can be created by passing a `calculate` function that will only be invoked when metrics are being scraped: * * ```typescript * import { Metrics, Metric } from '@libp2p/interface/metrics' * * interface MyServiceComponents { * metrics: Metrics * } * * class MyService { * private readonly myMetric: Metric * * constructor (components: MyServiceComponents) { * this.myMetric = components.metrics.registerMetric({ * name: 'my_metric', * label: 'my_label', * help: 'my help text', * calculate: async () => { * // do something expensive * return 1 * } * }) * } * } * ``` * * @example How to register a group of metrics * * If several metrics should be grouped together (e.g. for graphing purposes) `registerMetricGroup` can be used instead: * * ```typescript * import { Metrics, MetricGroup } from '@libp2p/interface/metrics' * * interface MyServiceComponents { * metrics: Metrics * } * * class MyService { * private readonly myMetricGroup: MetricGroup * * constructor (components: MyServiceComponents) { * this.myMetricGroup = components.metrics.registerMetricGroup({ * name: 'my_metric_group', * label: 'my_label', * help: 'my help text' * }) * } * * // later * doSomething () { * this.myMetricGroup.increment({ my_label: 'my_value' }) * } * } * ``` * * There are specific metric groups for tracking libp2p connections and streams: * * @example How to track multiaddr connections * * This is something only libp2p transports need to do. * * ```typescript * import { Metrics } from '@libp2p/interface/metrics' * * interface MyServiceComponents { * metrics: Metrics * } * * class MyService { * private readonly metrics: Metrics * * constructor (components: MyServiceComponents) { * this.metrics = components.metrics * } * * // later * doSomething () { * const connection = {} // create a connection * this.metrics.trackMultiaddrConnection(connection) * } * } * ``` * * @example How to track protocol streams * * This is something only libp2p connections need to do. * * ```typescript * import { Metrics } from '@libp2p/interface/metrics' * * interface MyServiceComponents { * metrics: Metrics * } * * class MyService { * private readonly metrics: Metrics * * constructor (components: MyServiceComponents) { * this.metrics = components.metrics * } * * // later * doSomething () { * const stream = {} // create a stream * this.metrics.trackProtocolStream(stream) * } * } * ``` */ export interface Metrics { /** * Track a newly opened multiaddr connection */ trackMultiaddrConnection(maConn: MultiaddrConnection): void /** * Track a newly opened protocol stream */ trackProtocolStream(stream: Stream): void /** * Register an arbitrary metric. Call this to set help/labels for metrics * and update/increment/decrement/etc them by calling methods on the returned * metric object */ registerMetric: ((name: string, options?: MetricOptions) => Metric) & ((name: string, options: CalculatedMetricOptions) => void) /** * Register a a group of related metrics. Call this to set help/labels for * groups of related metrics that will be updated with by calling `.update`, * `.increment` and/or `.decrement` methods on the returned metric group object */ registerMetricGroup: ((name: string, options?: MetricOptions) => MetricGroup) & ((name: string, options: CalculatedMetricOptions<Record<string, number>>) => void) /** * Register an arbitrary counter. Call this to set help/labels for counters * and increment them by calling methods on the returned counter object */ registerCounter: ((name: string, options?: MetricOptions) => Counter) & ((name: string, options: CalculatedMetricOptions) => void) /** * Register a a group of related counters. Call this to set help/labels for * groups of related counters that will be updated with by calling the `.increment` * method on the returned counter group object */ registerCounterGroup: ((name: string, options?: MetricOptions) => CounterGroup) & ((name: string, options: CalculatedMetricOptions<Record<string, number>>) => void) /** * Register an arbitrary histogram. Call this to set help/labels for histograms * and observe them by calling methods on the returned histogram object */ registerHistogram: ((name: string, options?: HistogramOptions) => Histogram) & ((name: string, options: CalculatedHistogramOptions) => void) /** * Register a a group of related histograms. Call this to set help/labels for * groups of related histograms that will be updated with by calling the `.observe` * method on the returned histogram group object */ registerHistogramGroup: ((name: string, options?: HistogramOptions) => HistogramGroup) & ((name: string, options: CalculatedHistogramOptions<Record<string, number>>) => void) /** * Register an arbitrary summary. Call this to set help/labels for summaries * and observe them by calling methods on the returned summary object */ registerSummary: ((name: string, options?: SummaryOptions) => Summary) & ((name: string, options: CalculatedSummaryOptions) => void) /** * Register a a group of related summaries. Call this to set help/labels for * groups of related summaries that will be updated with by calling the `.observe` * method on the returned summary group object */ registerSummaryGroup: ((name: string, options?: SummaryOptions) => SummaryGroup) & ((name: string, options: CalculatedSummaryOptions<Record<string, number>>) => void) /** * Wrap a function for tracing purposes. * * All functions wrapped like this should accept a final optional options arg. * * In order to pass an execution context along to create a multi-layered * trace, the index of the options arg must be specified. */ traceFunction <F extends (...args: any[]) => AsyncIterator<any>> (name: string, fn: F, options?: TraceGeneratorFunctionOptions<Parameters<F>, ReturnType<F>, YieldType<ReturnType<F>>>): F traceFunction <F extends (...args: any[]) => Iterator<any>> (name: string, fn: F, options?: TraceGeneratorFunctionOptions<Parameters<F>, ReturnType<F>, YieldType<ReturnType<F>>>): F traceFunction <F extends (...args: any[]) => any = (...args: any[]) => any> (name: string, fn: F, options?: TraceFunctionOptions<Parameters<F>, ReturnType<F>>): F /** * Creates a tracing context that can be used to trace a method call */ createTrace(): any } /** * Infer the yielded type of an (async)iterable */ export type YieldType<T extends AsyncIterator<any> | Iterator<any>> = T extends AsyncIterator<infer Y> ? Y : T extends Iterator<infer Y, any, any> ? Y : never export type TraceAttributes = Record<string, number | string | boolean | number[] | string[] | boolean[]> export interface TraceFunctionOptions<A, B> { /** * To construct a trace that spans multiple method invocations, it's necessary * to pass the trace context onwards as part of the options object. * * Specify the index of the options object in the args array here. * * @default 0 */ optionsIndex?: number /** * Set attributes on the trace by modifying the passed attributes object. */ getAttributesFromArgs?(args: A, attributes: TraceAttributes): TraceAttributes /** * Set attributes on the trace by modifying the passed attributes object. The * object will have previously been passed to `appendAttributesFromArgs` * and/or `appendAttributesFromYieldedValue` (if defined) */ getAttributesFromReturnValue?(value: B, attributes: TraceAttributes): TraceAttributes } export interface TraceGeneratorFunctionOptions<A, B, C = any> extends TraceFunctionOptions<A, B> { /** * Set attributes on the trace by modifying the passed attributes object. The * object will have previously been passed to `appendAttributesFromArgs` (if * defined) */ getAttributesFromYieldedValue? (value: C, attributes: TraceAttributes, index: number): TraceAttributes }