UNPKG

@flowcore/generator-library-template

Version:

A Yeoman generator for adding flowcore library components to a typescript service or application

128 lines (112 loc) 4.03 kB
import { ApiInternalServerErrorException } from "@components/api-exceptions" import Elysia from "elysia" import client, { type Metric } from "prom-client" /** * Builder class for creating and configuring Prometheus metrics * * @example * const metricsBuilder = new MetricsBuilder() * .withPrefix('myapp_') * .withoutDefaultMetrics(false) * .build() */ export class MetricsBuilder { private register: client.Registry private prefix = "app_" private defaultMetrics = true constructor() { this.register = new client.Registry() } /** * Sets the prefix for all metrics * @param prefix - The prefix to add to all metric names * @returns The builder instance for method chaining */ withPrefix(prefix: string) { this.prefix = prefix return this } /** * Configures whether to collect default metrics * @param defaultMetrics - If false, disables default metrics collection * @returns The builder instance for method chaining */ withDefaultMetrics(newVal: boolean) { this.defaultMetrics = newVal return this } /** * Builds and returns the metrics registry with the configured settings * @returns An object containing registry methods and properties */ build() { if (this.defaultMetrics) { client.collectDefaultMetrics({ register: this.register, prefix: this.prefix, }) } return { contentType: this.register.contentType, registerMetrics: this.register.registerMetric.bind(this.register), metrics: this.register.metrics.bind(this.register), getMetric: this.register.getSingleMetric.bind(this.register), } } } /** * Factory function to create an Elysia plugin with metrics registry * @param defaultMetrics - Whether to collect default metrics * @param prefix - Prefix for metric names * @returns Elysia plugin with configured metrics registry */ export const metricsFactory = (defaultMetrics = true, prefix = "app_") => new Elysia().decorate( "registry", new MetricsBuilder().withPrefix(prefix).withDefaultMetrics(defaultMetrics).build(), ) /** * Factory function to create an Elysia plugin with a pre-configured metrics registry * @param metricsBuilder - A built metrics registry instance from MetricsBuilder * @returns Elysia plugin decorated with the provided metrics registry */ export const globalMetricsFactory = (metricsBuilder: ReturnType<typeof MetricsBuilder.prototype.build>) => new Elysia().decorate("registry", metricsBuilder) /** * Creates an Elysia plugin that registers and retrieves a specific metric * @param metric - The Prometheus metric to register * @returns Elysia plugin that provides access to the metric * @throws Error if metrics registry is not found */ export const getMetric = <T extends Metric>(metric: T) => new Elysia().derive({ as: "scoped" }, async (context) => { // biome-ignore lint/suspicious/noExplicitAny: Required for context type const registry = (context as any).registry as ReturnType<typeof MetricsBuilder.prototype.build> if (registry) { const metricValue = await metric.get() const registeredMetric = registry.getMetric(metricValue.name) if (!registeredMetric) { registry.registerMetrics(metric) } return { [metricValue.name]: metric, } } throw new ApiInternalServerErrorException("Metric registry not found") }) /** * Creates an Elysia plugin that provides access to the metrics registry * @returns Elysia plugin with registry access * @throws Error if metrics registry is not found */ export const getRegistry = () => new Elysia().derive({ as: "scoped" }, async (context) => { // biome-ignore lint/suspicious/noExplicitAny: Required for context type const registry = (context as any).registry as ReturnType<typeof MetricsBuilder.prototype.build> if (registry) { return { registry, } } throw new ApiInternalServerErrorException("Metrics registry not found") })