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(); } };