use grafana cloud (#1518)

## Description:

Self hosted grafana has maintenance burden, so migrate to grafana cloud 

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
- [x] I have read and accepted the CLA aggreement (only required once).

## Please put your Discord username so you can be contacted if a bug or
regression is found:

evan
This commit is contained in:
evanpelle
2025-07-21 16:05:35 -07:00
committed by GitHub
parent 98420ccf97
commit ad01714323
7 changed files with 22 additions and 38 deletions
+1 -2
View File
@@ -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;
+5 -8
View File
@@ -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 ?? "";
+2 -9
View File
@@ -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({
+7 -5
View File
@@ -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",
});
};
}
+1 -1
View File
@@ -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);
}
+5 -9
View File
@@ -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");
+1 -4
View File
@@ -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 {