feat(observability): Replace Prometheus package with OpenTelemetry

This commit is contained in:
Julian Tölle 2022-02-27 17:57:33 +01:00
parent f67383b761
commit 6b1640b753
22 changed files with 2391 additions and 568 deletions

View file

@ -0,0 +1,25 @@
import { Module, OnApplicationShutdown } from "@nestjs/common";
import { OpenTelemetryModule as UpstreamModule } from "nestjs-otel";
import { otelSDK } from "./sdk";
@Module({
imports: [
UpstreamModule.forRoot({
metrics: {
hostMetrics: true, // Includes Host Metrics
defaultMetrics: true, // Includes Default Metrics
apiMetrics: {
enable: true, // Includes api metrics
timeBuckets: [], // You can change the default time buckets
ignoreUndefinedRoutes: false, //Records metrics for all URLs, even undefined ones
},
},
}),
],
exports: [UpstreamModule],
})
export class OpenTelemetryModule implements OnApplicationShutdown {
async onApplicationShutdown(): Promise<void> {
await otelSDK.shutdown();
}
}

48
src/open-telemetry/sdk.ts Normal file
View file

@ -0,0 +1,48 @@
import { AsyncLocalStorageContextManager } from "@opentelemetry/context-async-hooks";
import { PrometheusExporter } from "@opentelemetry/exporter-prometheus";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
import { DnsInstrumentation } from "@opentelemetry/instrumentation-dns";
import { ExpressInstrumentation } from "@opentelemetry/instrumentation-express";
import { HttpInstrumentation } from "@opentelemetry/instrumentation-http";
import { NestInstrumentation } from "@opentelemetry/instrumentation-nestjs-core";
import { PgInstrumentation } from "@opentelemetry/instrumentation-pg";
import { PinoInstrumentation } from "@opentelemetry/instrumentation-pino";
import { Resource } from "@opentelemetry/resources";
import { NodeSDK, NodeSDKConfiguration } from "@opentelemetry/sdk-node";
import { SemanticResourceAttributes } from "@opentelemetry/semantic-conventions";
import { hostname } from "os";
const metricsEnabled = process.env.OTEL_METRICS_ENABLED === "true";
const tracesEnabled = process.env.OTEL_TRACES_ENABLED === "true";
const anyEnabled = metricsEnabled || tracesEnabled;
// We can not use ConfigService because the SDK needs to be initialized before
// Nest is allowed to start.
let sdkOptions: Partial<NodeSDKConfiguration> = {};
if (metricsEnabled) {
sdkOptions.metricExporter = new PrometheusExporter();
}
if (tracesEnabled) {
sdkOptions.traceExporter = new OTLPTraceExporter({});
sdkOptions.contextManager = new AsyncLocalStorageContextManager();
sdkOptions.resource = new Resource({
[SemanticResourceAttributes.SERVICE_NAMESPACE]: "listory",
[SemanticResourceAttributes.SERVICE_NAME]: "api",
[SemanticResourceAttributes.SERVICE_INSTANCE_ID]: hostname(),
});
}
if (anyEnabled) {
sdkOptions.instrumentations = [
new DnsInstrumentation(),
new HttpInstrumentation(),
new ExpressInstrumentation(),
new NestInstrumentation(),
new PgInstrumentation(),
new PinoInstrumentation(),
];
}
export const otelSDK = new NodeSDK(sdkOptions);