diff --git a/src/core/configuration/Config.ts b/src/core/configuration/Config.ts index f32028205..4937e7b5a 100644 --- a/src/core/configuration/Config.ts +++ b/src/core/configuration/Config.ts @@ -48,8 +48,7 @@ export interface ServerConfig { r2AccessKey(): string; r2SecretKey(): string; otelEndpoint(): string; - otelUsername(): string; - otelPassword(): string; + otelAuthHeader(): string; otelEnabled(): boolean; jwtAudience(): string; jwtIssuer(): string; diff --git a/src/core/configuration/DefaultConfig.ts b/src/core/configuration/DefaultConfig.ts index 33de80407..aa4ba0621 100644 --- a/src/core/configuration/DefaultConfig.ts +++ b/src/core/configuration/DefaultConfig.ts @@ -119,19 +119,16 @@ export abstract class DefaultServerConfig implements ServerConfig { } otelEnabled(): boolean { return ( + this.env() !== GameEnv.Dev && Boolean(this.otelEndpoint()) && - Boolean(this.otelUsername()) && - Boolean(this.otelPassword()) + Boolean(this.otelAuthHeader()) ); } otelEndpoint(): string { - return process.env.OTEL_ENDPOINT ?? ""; + return process.env.OTEL_EXPORTER_OTLP_ENDPOINT ?? ""; } - otelUsername(): string { - return process.env.OTEL_USERNAME ?? ""; - } - otelPassword(): string { - return process.env.OTEL_PASSWORD ?? ""; + otelAuthHeader(): string { + return process.env.OTEL_AUTH_HEADER ?? ""; } gitCommit(): string { return process.env.GIT_COMMIT ?? ""; diff --git a/src/server/Logger.ts b/src/server/Logger.ts index 94e508fbb..f6d6e62cc 100644 --- a/src/server/Logger.ts +++ b/src/server/Logger.ts @@ -7,7 +7,6 @@ import { import { OpenTelemetryTransportV3 } from "@opentelemetry/winston-transport"; import * as dotenv from "dotenv"; import winston from "winston"; -import { GameEnv } from "../core/configuration/Config"; import { getServerConfigFromServer } from "../core/configuration/ConfigLoader"; import { getOtelResource } from "./OtelResource"; dotenv.config(); @@ -21,17 +20,11 @@ const loggerProvider = new LoggerProvider({ resource, }); -if (config.env() === GameEnv.Prod && config.otelEnabled()) { +if (config.otelEnabled()) { console.log("OTEL enabled"); // Configure OpenTelemetry endpoint with basic auth (if provided) const headers = {}; - if (config.otelUsername() && config.otelPassword()) { - headers["Authorization"] = - "Basic " + - Buffer.from(`${config.otelUsername()}:${config.otelPassword()}`).toString( - "base64", - ); - } + headers["Authorization"] = config.otelAuthHeader(); // Add OTLP exporter for logs const logExporter = new OTLPLogExporter({ diff --git a/src/server/OtelResource.ts b/src/server/OtelResource.ts index 99d2b155f..6fd7f0025 100644 --- a/src/server/OtelResource.ts +++ b/src/server/OtelResource.ts @@ -11,6 +11,12 @@ export function getOtelResource() { return resourceFromAttributes({ [ATTR_SERVICE_NAME]: "openfront", [ATTR_SERVICE_VERSION]: "1.0.0", + ...getPromLabels(), + }); +} + +export function getPromLabels() { + return { "service.instance.id": process.env.HOSTNAME, "openfront.environment": config.env(), "openfront.host": process.env.HOST, @@ -19,9 +25,5 @@ export function getOtelResource() { "openfront.component": process.env.WORKER_ID ? "Worker " + process.env.WORKER_ID : "Master", - // The comma-separated list tells OpenTelemetry which resource attributes - // should be converted to Loki labels - "loki.resource.labels": - "service.name,service.instance.id,openfront.environment,openfront.host,openfront.domain,openfront.subdomain,openfront.component", - }); + }; } diff --git a/src/server/Worker.ts b/src/server/Worker.ts index c916530b2..2c6476b57 100644 --- a/src/server/Worker.ts +++ b/src/server/Worker.ts @@ -47,7 +47,7 @@ export function startWorker() { const privilegeChecker = new PrivilegeChecker(COSMETICS, base64url.decode); - if (config.env() === GameEnv.Prod && config.otelEnabled()) { + if (config.otelEnabled()) { initWorkerMetrics(gm); } diff --git a/src/server/WorkerMetrics.ts b/src/server/WorkerMetrics.ts index 1576b0f73..42ad2ad20 100644 --- a/src/server/WorkerMetrics.ts +++ b/src/server/WorkerMetrics.ts @@ -6,7 +6,7 @@ import { import * as dotenv from "dotenv"; import { getServerConfigFromServer } from "../core/configuration/ConfigLoader"; import { GameManager } from "./GameManager"; -import { getOtelResource } from "./OtelResource"; +import { getOtelResource, getPromLabels } from "./OtelResource"; dotenv.config(); @@ -20,11 +20,7 @@ export function initWorkerMetrics(gameManager: GameManager): void { // Configure auth headers const headers = {}; if (config.otelEnabled()) { - headers["Authorization"] = - "Basic " + - Buffer.from(`${config.otelUsername()}:${config.otelPassword()}`).toString( - "base64", - ); + headers["Authorization"] = config.otelAuthHeader(); } // Create metrics exporter @@ -73,19 +69,19 @@ export function initWorkerMetrics(gameManager: GameManager): void { // Register callback for active games metric activeGamesGauge.addCallback((result) => { const count = gameManager.activeGames(); - result.observe(count); + result.observe(count, getPromLabels()); }); // Register callback for connected clients metric connectedClientsGauge.addCallback((result) => { const count = gameManager.activeClients(); - result.observe(count); + result.observe(count, getPromLabels()); }); // Register callback for memory usage metric memoryUsageGauge.addCallback((result) => { const memoryUsage = process.memoryUsage(); - result.observe(memoryUsage.heapUsed); + result.observe(memoryUsage.heapUsed, getPromLabels()); }); console.log("Metrics initialized with GameManager"); diff --git a/tests/util/TestServerConfig.ts b/tests/util/TestServerConfig.ts index 5babd040f..86a277d65 100644 --- a/tests/util/TestServerConfig.ts +++ b/tests/util/TestServerConfig.ts @@ -43,10 +43,7 @@ export class TestServerConfig implements ServerConfig { otelEndpoint(): string { throw new Error("Method not implemented."); } - otelUsername(): string { - throw new Error("Method not implemented."); - } - otelPassword(): string { + otelAuthHeader(): string { throw new Error("Method not implemented."); } turnIntervalMs(): number {