Files
illusory-mapp/apps/processor/src/telemetry/http.middleware.ts

78 lines
2.2 KiB
TypeScript

import { context, metrics, SpanStatusCode, trace } from "@opentelemetry/api";
import type { MiddlewareHandler } from "hono";
const tracer = trace.getTracer("processor.http");
const meter = metrics.getMeter("processor.http");
const requestCount = meter.createCounter("processor.http.server.requests", {
description: "Total number of processor HTTP requests",
});
const requestDuration = meter.createHistogram(
"processor.http.server.duration",
{
description: "Processor HTTP request duration",
unit: "ms",
},
);
const activeRequests = meter.createUpDownCounter(
"processor.http.server.active_requests",
{
description: "Number of in-flight processor HTTP requests",
},
);
export const httpTelemetryMiddleware: MiddlewareHandler = async (c, next) => {
const startedAt = performance.now();
const method = c.req.method;
const route = c.req.path;
const span = tracer.startSpan(`http ${method} ${route}`, {
attributes: {
"http.request.method": method,
"url.path": route,
},
});
activeRequests.add(1, {
"http.request.method": method,
"url.path": route,
});
try {
await context.with(trace.setSpan(context.active(), span), next);
span.setAttribute("http.response.status_code", c.res.status);
span.setStatus({
code:
c.res.status >= 500
? SpanStatusCode.ERROR
: SpanStatusCode.OK,
});
} catch (error) {
span.recordException(error as Error);
span.setStatus({
code: SpanStatusCode.ERROR,
message: "Unhandled processor request error",
});
throw error;
} finally {
const durationMs = performance.now() - startedAt;
const attrs = {
"http.request.method": method,
"http.response.status_code": c.res.status,
"url.path": route,
};
requestCount.add(1, attrs);
requestDuration.record(durationMs, attrs);
activeRequests.add(-1, {
"http.request.method": method,
"url.path": route,
});
span.end();
}
};