This commit was merged in pull request #87.
This commit is contained in:
@@ -4,7 +4,19 @@ export interface LogContext {
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
const LEVEL_ORDER: Record<LogLevel, number> = { debug: 0, info: 1, warn: 2, error: 3 };
|
||||
|
||||
function resolveMinLevel(): LogLevel {
|
||||
const env = (process.env["LOG_LEVEL"] ?? "").toLowerCase();
|
||||
if (env === "debug" || env === "info" || env === "warn" || env === "error") return env;
|
||||
return "debug";
|
||||
}
|
||||
|
||||
const minLevel: number = LEVEL_ORDER[resolveMinLevel()];
|
||||
|
||||
function emit(level: LogLevel, component: string, message: string, ctx?: LogContext): void {
|
||||
if (LEVEL_ORDER[level] < minLevel) return;
|
||||
|
||||
const line: Record<string, unknown> = {
|
||||
timestamp: new Date().toISOString(),
|
||||
level,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { db, jobs, invoices } from "@workspace/db";
|
||||
import { sql } from "drizzle-orm";
|
||||
import { latencyHistogram, type BucketStats } from "./histogram.js";
|
||||
import { requestCounters, type RequestCountsSnapshot } from "./request-counters.js";
|
||||
|
||||
export interface JobStateCounts {
|
||||
awaiting_eval: number;
|
||||
@@ -12,6 +13,7 @@ export interface JobStateCounts {
|
||||
|
||||
export interface MetricsSnapshot {
|
||||
uptime_s: number;
|
||||
http: RequestCountsSnapshot;
|
||||
jobs: {
|
||||
total: number;
|
||||
by_state: JobStateCounts;
|
||||
@@ -94,6 +96,7 @@ export class MetricsService {
|
||||
|
||||
return {
|
||||
uptime_s: Math.floor((Date.now() - START_TIME) / 1000),
|
||||
http: requestCounters.snapshot(),
|
||||
jobs: {
|
||||
total: jobsTotal,
|
||||
by_state: byState,
|
||||
|
||||
37
artifacts/api-server/src/lib/request-counters.ts
Normal file
37
artifacts/api-server/src/lib/request-counters.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
/** In-memory HTTP request counters for the /api/metrics endpoint. */
|
||||
|
||||
export interface RequestCountsSnapshot {
|
||||
total: number;
|
||||
by_status: Record<string, number>;
|
||||
errors_4xx: number;
|
||||
errors_5xx: number;
|
||||
}
|
||||
|
||||
class RequestCounters {
|
||||
private total = 0;
|
||||
private byStatus: Record<number, number> = {};
|
||||
private errors4xx = 0;
|
||||
private errors5xx = 0;
|
||||
|
||||
record(statusCode: number): void {
|
||||
this.total++;
|
||||
this.byStatus[statusCode] = (this.byStatus[statusCode] ?? 0) + 1;
|
||||
if (statusCode >= 400 && statusCode < 500) this.errors4xx++;
|
||||
else if (statusCode >= 500) this.errors5xx++;
|
||||
}
|
||||
|
||||
snapshot(): RequestCountsSnapshot {
|
||||
const byStatus: Record<string, number> = {};
|
||||
for (const [code, count] of Object.entries(this.byStatus)) {
|
||||
byStatus[code] = count;
|
||||
}
|
||||
return {
|
||||
total: this.total,
|
||||
by_status: byStatus,
|
||||
errors_4xx: this.errors4xx,
|
||||
errors_5xx: this.errors5xx,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export const requestCounters = new RequestCounters();
|
||||
Reference in New Issue
Block a user