diff --git a/package.json b/package.json index af7d237a..dedf5d28 100644 --- a/package.json +++ b/package.json @@ -116,7 +116,7 @@ "prettier": "3.0.3", "prettier-plugin-organize-imports": "3.2.3", "prettier-plugin-packagejson": "2.4.6", - "prom-client": "14.2.0", + "prom-client": "15.0.0", "reflect-metadata": "0.1.13", "rimraf": "5.0.5", "rxjs": "7.8.1", @@ -130,7 +130,7 @@ }, "peerDependencies": { "@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0", - "prom-client": "^13.0.0 || ^14.0.0" + "prom-client": "^15.0.0" }, "packageManager": "pnpm@8.9.0", "volta": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7decf71e..4d51071d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -120,8 +120,8 @@ devDependencies: specifier: 2.4.6 version: 2.4.6(prettier@3.0.3) prom-client: - specifier: 14.2.0 - version: 14.2.0 + specifier: 15.0.0 + version: 15.0.0 reflect-metadata: specifier: 0.1.13 version: 0.1.13 @@ -951,6 +951,11 @@ packages: '@octokit/openapi-types': 17.2.0 dev: true + /@opentelemetry/api@1.6.0: + resolution: {integrity: sha512-OWlrQAnWn9577PhVgqjUvMr1pg57Bc4jv0iL4w0PRuOSRvq67rvHW9Ie/dZVMvCzhSCB+UxhcY/PmCmFj33Q+g==} + engines: {node: '>=8.0.0'} + dev: true + /@pkgjs/parseargs@0.11.0: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -5649,10 +5654,11 @@ packages: resolution: {integrity: sha512-/1WZ8+VQjR6avWOgHeEPd7SDQmFQ1B5mC1eRXsCm5TarlNmx/wCsa5GEaxGm05BORRtyG/Ex/3xq3TuRvq57qg==} dev: true - /prom-client@14.2.0: - resolution: {integrity: sha512-sF308EhTenb/pDRPakm+WgiN+VdM/T1RaHj1x+MvAuT8UiQP8JmOEbxVqtkbfR4LrvOg5n7ic01kRBDGXjYikA==} - engines: {node: '>=10'} + /prom-client@15.0.0: + resolution: {integrity: sha512-UocpgIrKyA2TKLVZDSfm8rGkL13C19YrQBAiG3xo3aDFWcHedxRxI3z+cIcucoxpSO0h5lff5iv/SXoxyeopeA==} + engines: {node: ^16 || ^18 || >=20} dependencies: + '@opentelemetry/api': 1.6.0 tdigest: 0.1.2 dev: true diff --git a/src/interfaces.ts b/src/interfaces.ts index 2c1dfbbd..7bfc27f5 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -1,13 +1,16 @@ import { Type } from "@nestjs/common"; import { ModuleMetadata } from "@nestjs/common/interfaces"; import * as client from "prom-client"; +import { PrometheusContentType, RegistryContentType } from "prom-client"; /** * Configuration for the defaultMetrics collected by `prom-client`. * * @public */ -export interface PrometheusDefaultMetrics { +export interface PrometheusDefaultMetrics< + T extends RegistryContentType = PrometheusContentType, +> { /** * Whether or not default metrics are collected. * @@ -17,7 +20,7 @@ export interface PrometheusDefaultMetrics { /** * {@link https://github.com/siimon/prom-client#default-metrics | Default Metrics} */ - config?: client.DefaultMetricsCollectorConfiguration; + config?: client.DefaultMetricsCollectorConfiguration; } /** @@ -25,7 +28,9 @@ export interface PrometheusDefaultMetrics { * * @public */ -export interface PrometheusOptions { +export interface PrometheusOptions< + T extends RegistryContentType = PrometheusContentType, +> { /** * Make the module global when set to true * */ @@ -68,7 +73,7 @@ export interface PrometheusOptions { */ path?: string; /** {@inheritDoc PrometheusDefaultMetrics} */ - defaultMetrics?: PrometheusDefaultMetrics; + defaultMetrics?: PrometheusDefaultMetrics; /** * Will be passed into `setDefaultLabels` * @@ -84,15 +89,19 @@ export interface PrometheusOptions { }; } -export type PrometheusOptionsWithDefaults = Required< - Omit ->; +export type PrometheusOptionsWithDefaults< + T extends RegistryContentType = PrometheusContentType, +> = Required, "pushgateway" | "customMetricPrefix">>; /** * @internal */ -export interface PrometheusOptionsFactory { - createPrometheusOptions(): Promise | PrometheusOptions; +export interface PrometheusOptionsFactory< + T extends RegistryContentType = PrometheusContentType, +> { + createPrometheusOptions(): + | Promise> + | PrometheusOptions; } /** @@ -100,18 +109,19 @@ export interface PrometheusOptionsFactory { * * @public */ -export interface PrometheusAsyncOptions - extends Pick { +export interface PrometheusAsyncOptions< + T extends RegistryContentType = PrometheusContentType, +> extends Pick { global?: boolean; - useExisting?: Type; - useClass?: Type; + useExisting?: Type>; + useClass?: Type>; // eslint-disable-next-line @typescript-eslint/no-explicit-any inject?: any[]; /** {@inheritDoc PrometheusOptions.controller} */ - controller?: PrometheusOptions["controller"]; + controller?: PrometheusOptions["controller"]; useFactory?( ...args: unknown[] - ): Promise | PrometheusOptions; + ): Promise> | PrometheusOptions; } diff --git a/src/metrics/counter.ts b/src/metrics/counter.ts index 07a77082..b1eb818c 100644 --- a/src/metrics/counter.ts +++ b/src/metrics/counter.ts @@ -1,5 +1,6 @@ import { Provider } from "@nestjs/common"; import * as client from "prom-client"; +import { PrometheusContentType, RegistryContentType } from "prom-client"; import { PROMETHEUS_OPTIONS } from "../constants"; import { PrometheusOptions } from "../interfaces"; import { getOrCreateMetric, getToken } from "./utils"; @@ -12,7 +13,9 @@ export function makeCounterProvider( ): Provider { return { provide: getToken(options.name), - useFactory(config?: PrometheusOptions): client.Metric { + useFactory( + config?: PrometheusOptions, + ): client.Metric { return getOrCreateMetric("Counter", options, config); }, inject: [ diff --git a/src/metrics/gauge.ts b/src/metrics/gauge.ts index b020033a..666de53b 100644 --- a/src/metrics/gauge.ts +++ b/src/metrics/gauge.ts @@ -1,5 +1,6 @@ import { Provider } from "@nestjs/common"; import * as client from "prom-client"; +import { PrometheusContentType, RegistryContentType } from "prom-client"; import { PROMETHEUS_OPTIONS } from "../constants"; import { PrometheusOptions } from "../interfaces"; import { getOrCreateMetric, getToken } from "./utils"; @@ -12,7 +13,9 @@ export function makeGaugeProvider( ): Provider { return { provide: getToken(options.name), - useFactory(config?: PrometheusOptions): client.Metric { + useFactory( + config?: PrometheusOptions, + ): client.Metric { return getOrCreateMetric("Gauge", options, config); }, inject: [ diff --git a/src/metrics/histogram.ts b/src/metrics/histogram.ts index 16583483..0813b27a 100644 --- a/src/metrics/histogram.ts +++ b/src/metrics/histogram.ts @@ -1,5 +1,6 @@ import { Provider } from "@nestjs/common"; import * as client from "prom-client"; +import { PrometheusContentType, RegistryContentType } from "prom-client"; import { PROMETHEUS_OPTIONS } from "../constants"; import { PrometheusOptions } from "../interfaces"; import { getOrCreateMetric, getToken } from "./utils"; @@ -12,7 +13,9 @@ export function makeHistogramProvider( ): Provider { return { provide: getToken(options.name), - useFactory(config?: PrometheusOptions): client.Metric { + useFactory( + config?: PrometheusOptions, + ): client.Metric { return getOrCreateMetric("Histogram", options, config); }, inject: [ diff --git a/src/metrics/summary.ts b/src/metrics/summary.ts index 5a59e530..c891b862 100644 --- a/src/metrics/summary.ts +++ b/src/metrics/summary.ts @@ -1,5 +1,6 @@ import { Provider } from "@nestjs/common"; import * as client from "prom-client"; +import { PrometheusContentType, RegistryContentType } from "prom-client"; import { PROMETHEUS_OPTIONS } from "../constants"; import { PrometheusOptions } from "../interfaces"; import { getOrCreateMetric, getToken } from "./utils"; @@ -12,7 +13,9 @@ export function makeSummaryProvider( ): Provider { return { provide: getToken(options.name), - useFactory(config?: PrometheusOptions): client.Metric { + useFactory( + config?: PrometheusOptions, + ): client.Metric { return getOrCreateMetric("Summary", options, config); }, inject: [ diff --git a/src/metrics/utils.ts b/src/metrics/utils.ts index 9a50b3b1..667ddde5 100644 --- a/src/metrics/utils.ts +++ b/src/metrics/utils.ts @@ -1,4 +1,5 @@ import * as client from "prom-client"; +import { PrometheusContentType, RegistryContentType } from "prom-client"; import { PrometheusOptions } from "../interfaces"; /** @@ -18,10 +19,12 @@ export type Options = /** * @internal */ -export function getOrCreateMetric( +export function getOrCreateMetric< + T extends RegistryContentType = PrometheusContentType, +>( type: Metrics, options: Options, - prometheusOptions?: PrometheusOptions, + prometheusOptions?: PrometheusOptions, ): client.Metric { const opts: Options = { ...options, diff --git a/src/module.ts b/src/module.ts index 016f4922..31f76eff 100644 --- a/src/module.ts +++ b/src/module.ts @@ -5,6 +5,7 @@ import { Provider, } from "@nestjs/common"; import * as promClient from "prom-client"; +import { RegistryContentType } from "prom-client"; import { PROMETHEUS_OPTIONS, PROM_CLIENT } from "./constants"; import { PrometheusController } from "./controller"; import { @@ -21,7 +22,9 @@ import { */ @Module({}) export class PrometheusModule { - public static register(options?: PrometheusOptions): DynamicModule { + public static register( + options?: PrometheusOptions, + ): DynamicModule { const opts = PrometheusModule.makeDefaultOptions(options); PrometheusModule.configureServer(opts); @@ -53,7 +56,9 @@ export class PrometheusModule { }; } - public static registerAsync(options: PrometheusAsyncOptions): DynamicModule { + public static registerAsync( + options: PrometheusAsyncOptions, + ): DynamicModule { const providers = this.createAsyncProviders(options); const controller = options.controller ?? PrometheusController; @@ -67,7 +72,9 @@ export class PrometheusModule { { provide: PROM_CLIENT, inject: [PROMETHEUS_OPTIONS], - useFactory(userOptions: PrometheusOptions) { + useFactory( + userOptions: PrometheusOptions, + ) { const opts = PrometheusModule.makeDefaultOptions(userOptions); PrometheusModule.configureServer(opts); @@ -80,8 +87,8 @@ export class PrometheusModule { }; } - public static createAsyncProviders( - options: PrometheusAsyncOptions, + public static createAsyncProviders( + options: PrometheusAsyncOptions, ): Provider[] { if (options.useExisting || options.useFactory) { return [ @@ -104,8 +111,8 @@ export class PrometheusModule { ]; } - public static createAsyncOptionsProvider( - options: PrometheusAsyncOptions, + public static createAsyncOptionsProvider( + options: PrometheusAsyncOptions, ): Provider { if (options.useFactory) { return { @@ -126,16 +133,18 @@ export class PrometheusModule { return { provide: PROMETHEUS_OPTIONS, - async useFactory( - optionsFactory: PrometheusOptionsFactory, - ): Promise { + async useFactory( + optionsFactory: PrometheusOptionsFactory, + ): Promise> { return optionsFactory.createPrometheusOptions(); }, inject: [inject], }; } - private static configureServer(options: PrometheusOptionsWithDefaults): void { + private static configureServer( + options: PrometheusOptionsWithDefaults, + ): void { if (options.defaultMetrics.enabled) { promClient.collectDefaultMetrics(options.defaultMetrics.config); } @@ -147,11 +156,11 @@ export class PrometheusModule { Reflect.defineMetadata("path", options.path, options.controller); } - private static configurePushgateway( + private static configurePushgateway( url: string, options?: unknown, registry?: promClient.Registry, - ): promClient.Pushgateway { + ): promClient.Pushgateway { return new promClient.Pushgateway(url, options, registry); } @@ -159,7 +168,7 @@ export class PrometheusModule { return { provide: promClient.Pushgateway, inject: [PROMETHEUS_OPTIONS], - useFactory(options: PrometheusOptions) { + useFactory(options: PrometheusOptions) { if (options?.pushgateway !== undefined) { const { url, @@ -179,9 +188,9 @@ export class PrometheusModule { }; } - private static makeDefaultOptions( - options?: PrometheusOptions, - ): PrometheusOptionsWithDefaults { + private static makeDefaultOptions( + options?: PrometheusOptions, + ): PrometheusOptionsWithDefaults { return { global: false, path: "/metrics", diff --git a/test/push-gateway.spec.ts b/test/push-gateway.spec.ts index 9664da31..ae9630e1 100644 --- a/test/push-gateway.spec.ts +++ b/test/push-gateway.spec.ts @@ -1,7 +1,7 @@ import { Injectable, Module } from "@nestjs/common"; import { Test } from "@nestjs/testing"; import { expect } from "chai"; -import { Pushgateway, register } from "prom-client"; +import { PrometheusContentType, Pushgateway, register } from "prom-client"; import { PrometheusModule, PrometheusOptions, @@ -23,7 +23,9 @@ describe("Pushgateway", function () { @Injectable() class MockService { - constructor(public readonly pushgateway: Pushgateway) {} + constructor( + public readonly pushgateway: Pushgateway, + ) {} } @Module({