UNPKG

@fiberplane/hono-otel

Version:

Hono middleware to forward OpenTelemetry traces to a local instance of @fiberplane/studio

59 lines (58 loc) 2.85 kB
import { getFpResolvedConfig, getShouldTraceEverything, } from "../../config/index.js"; import { EXTRA_SEMATTRS_HTTP_REQUEST_METHOD, EXTRA_SEMATTRS_URL_FULL, FPX_REQUEST_BODY, FPX_REQUEST_PATHNAME, FPX_REQUEST_SCHEME, FPX_REQUEST_SEARCH, } from "../../constants.js"; import { getLogger } from "../../logger.js"; import { formatBody } from "./body.js"; import { getSafeHeaderValue, headersToObject } from "./headers.js"; import { getRedactedUrl } from "./url.js"; /** * Get the request attributes for a given request. * * The `config` param is optional, and if not provided, * we will try to use the config that's currently in the active OpenTelemetry context. */ export function getRequestAttributes(input, init, config) { const resolvedConfig = config ?? getFpResolvedConfig(); const shouldTraceEverything = getShouldTraceEverything(resolvedConfig); const logger = getLogger(resolvedConfig?.logLevel ?? "debug"); if (!resolvedConfig) { logger.debug("[getRequestAttributes] No config found in otel context, using default values"); logger.debug("input", input); if (input instanceof Request) { logger.debug("input.url", input.url); } } const requestMethod = typeof input === "string" || input instanceof URL ? "GET" : input.method; const requestUrl = input instanceof Request ? input.url : input; const url = new URL(requestUrl); const urlScheme = url.protocol.replace(":", ""); const attributes = { [EXTRA_SEMATTRS_HTTP_REQUEST_METHOD]: requestMethod, // [HTTP_REQUEST_METHOD_ORIGINAL]: request.method, // TODO: remove login/password from URL (if we want to follow // the otel spec for this attribute) // TODO: think about how to handle a redirect [EXTRA_SEMATTRS_URL_FULL]: getRedactedUrl(url), // Bunch of custom attributes even though some experimental // packages from otel already have similar attributes [FPX_REQUEST_PATHNAME]: url.pathname, [FPX_REQUEST_SEARCH]: getRedactedUrl(url).split("?")[1] || "", // TODO: Add path // [SEMATTRS_] [FPX_REQUEST_SCHEME]: urlScheme, }; // Init should not be null or undefined - but we do call it with undefined for the root request if (init) { const { body } = init; if (!shouldTraceEverything && body != null) { attributes[FPX_REQUEST_BODY] = formatBody(body); } if (init.headers) { const headers = headersToObject(new Headers(init.headers)); for (const [key, value] of Object.entries(headers)) { // Redact sensitive headers when running in production attributes[`http.request.header.${key}`] = getSafeHeaderValue(key, value, resolvedConfig); } } } return attributes; }