@geekmidas/telescope 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/lambda.cjs +1 -1
- package/dist/adapters/lambda.mjs +1 -1
- package/dist/adapters/middy.cjs +1 -1
- package/dist/adapters/middy.mjs +1 -1
- package/dist/{hono-CPHX7FAm.cjs → hono-C4EgpbKQ.cjs} +2 -2
- package/dist/{hono-CPHX7FAm.cjs.map → hono-C4EgpbKQ.cjs.map} +1 -1
- package/dist/{hono-Bw-ey6CT.mjs → hono-DxhvnVbF.mjs} +2 -2
- package/dist/{hono-Bw-ey6CT.mjs.map → hono-DxhvnVbF.mjs.map} +1 -1
- package/dist/{http-GB-Nlvwc.d.mts → http-D5kn3_Mt.d.mts} +3 -3
- package/dist/{http-GB-Nlvwc.d.mts.map → http-D5kn3_Mt.d.mts.map} +1 -1
- package/dist/{http-BIvr0YdI.mjs → http-DQzgLczm.mjs} +1 -1
- package/dist/{http-BIvr0YdI.mjs.map → http-DQzgLczm.mjs.map} +1 -1
- package/dist/{http-BsqmhurZ.cjs → http-D_Z8sYXZ.cjs} +1 -1
- package/dist/{http-BsqmhurZ.cjs.map → http-D_Z8sYXZ.cjs.map} +1 -1
- package/dist/instrumentation/hono.cjs +2 -2
- package/dist/instrumentation/hono.mjs +2 -2
- package/dist/instrumentation/http.cjs +1 -1
- package/dist/instrumentation/http.d.mts +1 -1
- package/dist/instrumentation/http.mjs +1 -1
- package/dist/instrumentation/index.cjs +5 -5
- package/dist/instrumentation/index.d.mts +1 -1
- package/dist/instrumentation/index.mjs +5 -5
- package/dist/instrumentation/middleware.cjs +2 -2
- package/dist/instrumentation/middleware.mjs +2 -2
- package/dist/instrumentation/otel.cjs +2 -2
- package/dist/instrumentation/otel.mjs +2 -2
- package/dist/instrumentation/setup.cjs +1 -1
- package/dist/instrumentation/setup.mjs +1 -1
- package/dist/logger/pino.d.cts +2 -2
- package/dist/{middleware-DqPQpcup.cjs → middleware-B2jFUukM.cjs} +2 -2
- package/dist/{middleware-DqPQpcup.cjs.map → middleware-B2jFUukM.cjs.map} +1 -1
- package/dist/{middleware-4-GrQlOT.mjs → middleware-BTDncHwm.mjs} +2 -2
- package/dist/{middleware-4-GrQlOT.mjs.map → middleware-BTDncHwm.mjs.map} +1 -1
- package/dist/{middy-DHWLmUAD.mjs → middy-BIpTCy9H.mjs} +1 -1
- package/dist/{middy-DHWLmUAD.mjs.map → middy-BIpTCy9H.mjs.map} +1 -1
- package/dist/{middy-DlWnZilH.cjs → middy-DhMWMJbG.cjs} +1 -1
- package/dist/{middy-DlWnZilH.cjs.map → middy-DhMWMJbG.cjs.map} +1 -1
- package/dist/{otel-COrpz_GZ.cjs → otel-C1HqHA2O.cjs} +2 -2
- package/dist/{otel-COrpz_GZ.cjs.map → otel-C1HqHA2O.cjs.map} +1 -1
- package/dist/{otel-40udNP5g.mjs → otel-wulj5B-X.mjs} +2 -2
- package/dist/{otel-40udNP5g.mjs.map → otel-wulj5B-X.mjs.map} +1 -1
- package/dist/{setup-DC9JMEYZ.mjs → setup-B9jM77Qk.mjs} +1 -1
- package/dist/{setup-DC9JMEYZ.mjs.map → setup-B9jM77Qk.mjs.map} +1 -1
- package/dist/{setup-DufxQpi9.cjs → setup-CYpff5B9.cjs} +1 -1
- package/dist/{setup-DufxQpi9.cjs.map → setup-CYpff5B9.cjs.map} +1 -1
- package/dist/tracing-BX8uY2nR.d.cts.map +1 -1
- package/dist/tracing-PnECEbEu.d.mts.map +1 -1
- package/dist/types-l7Rlb5Mg.d.cts.map +1 -1
- package/package.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
package/dist/adapters/lambda.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const require_chunk = require('../chunk-CUT6urMc.cjs');
|
|
2
2
|
const require_core = require('../core-CtVHRJGv.cjs');
|
|
3
|
-
const require_middy = require('../middy-
|
|
3
|
+
const require_middy = require('../middy-DhMWMJbG.cjs');
|
|
4
4
|
const nanoid = require_chunk.__toESM(require("nanoid"));
|
|
5
5
|
|
|
6
6
|
//#region src/adapters/lambda.ts
|
package/dist/adapters/lambda.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { flushTelemetry } from "../core-D6hJ6exL.mjs";
|
|
2
|
-
import { createTelescopeHandler, telescopeMiddleware } from "../middy-
|
|
2
|
+
import { createTelescopeHandler, telescopeMiddleware } from "../middy-BIpTCy9H.mjs";
|
|
3
3
|
import { nanoid } from "nanoid";
|
|
4
4
|
|
|
5
5
|
//#region src/adapters/lambda.ts
|
package/dist/adapters/middy.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
require('../core-CtVHRJGv.cjs');
|
|
2
|
-
const require_middy = require('../middy-
|
|
2
|
+
const require_middy = require('../middy-DhMWMJbG.cjs');
|
|
3
3
|
|
|
4
4
|
exports.createTelescopeHandler = require_middy.createTelescopeHandler;
|
|
5
5
|
exports.telescopeMiddleware = require_middy.telescopeMiddleware;
|
package/dist/adapters/middy.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_chunk = require('./chunk-CUT6urMc.cjs');
|
|
2
|
-
const require_http = require('./http-
|
|
2
|
+
const require_http = require('./http-D_Z8sYXZ.cjs');
|
|
3
3
|
const __opentelemetry_api = require_chunk.__toESM(require("@opentelemetry/api"));
|
|
4
4
|
|
|
5
5
|
//#region src/instrumentation/hono.ts
|
|
@@ -157,4 +157,4 @@ Object.defineProperty(exports, 'withHonoSpanContext', {
|
|
|
157
157
|
return withHonoSpanContext;
|
|
158
158
|
}
|
|
159
159
|
});
|
|
160
|
-
//# sourceMappingURL=hono-
|
|
160
|
+
//# sourceMappingURL=hono-C4EgpbKQ.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hono-
|
|
1
|
+
{"version":3,"file":"hono-C4EgpbKQ.cjs","names":["c: Context","options: HonoTelemetryMiddlewareOptions","headers: Record<string, string | string[] | undefined>","attrs: HttpSpanAttributes","path: string","ignorePaths: string[]","fn: () => Promise<T>"],"sources":["../src/instrumentation/hono.ts"],"sourcesContent":["import { context, type Span, trace } from '@opentelemetry/api';\n/**\n * OpenTelemetry instrumentation middleware for Hono\n *\n * This middleware automatically creates spans for HTTP requests,\n * extracts trace context from incoming headers, and records\n * request/response metadata as span attributes.\n */\nimport type { Context, MiddlewareHandler } from 'hono';\nimport {\n\tcreateHttpServerSpan,\n\tendHttpSpan,\n\textractTraceContext,\n\ttype HttpSpanAttributes,\n} from './http';\n\n/**\n * Options for the Hono telemetry middleware\n */\nexport interface HonoTelemetryMiddlewareOptions {\n\t/**\n\t * Whether to record request body as span attribute\n\t * @default false\n\t */\n\trecordBody?: boolean;\n\n\t/**\n\t * Whether to record response body as span attribute\n\t * @default false\n\t */\n\trecordResponseBody?: boolean;\n\n\t/**\n\t * Custom function to extract user ID from context\n\t */\n\tgetUserId?: (c: Context) => string | undefined;\n\n\t/**\n\t * Paths to skip tracing (supports wildcards)\n\t */\n\tignorePaths?: string[];\n\n\t/**\n\t * Whether to skip tracing for this request\n\t */\n\tshouldSkip?: (c: Context) => boolean;\n}\n\n// Key for storing span on context\nconst SPAN_KEY = 'telemetry.span';\nconst CONTEXT_KEY = 'telemetry.context';\n\n/**\n * Get the current span from Hono context\n */\nexport function getSpanFromContext(c: Context): Span | undefined {\n\treturn c.get(SPAN_KEY);\n}\n\n/**\n * Get the current trace context from Hono context\n */\nexport function getTraceContextFromHono(c: Context): any {\n\treturn c.get(CONTEXT_KEY);\n}\n\n/**\n * Create a telemetry middleware for Hono applications\n *\n * @example\n * ```typescript\n * import { honoTelemetryMiddleware } from '@geekmidas/telescope/instrumentation';\n *\n * const app = new Hono();\n * app.use('*', honoTelemetryMiddleware());\n * ```\n */\nexport function honoTelemetryMiddleware(\n\toptions: HonoTelemetryMiddlewareOptions = {},\n): MiddlewareHandler {\n\treturn async (c, next) => {\n\t\t// Check if path should be ignored\n\t\tif (\n\t\t\toptions.ignorePaths &&\n\t\t\tshouldIgnorePath(c.req.path, options.ignorePaths)\n\t\t) {\n\t\t\treturn next();\n\t\t}\n\n\t\t// Skip if custom skip function returns true\n\t\tif (options.shouldSkip?.(c)) {\n\t\t\treturn next();\n\t\t}\n\n\t\t// Extract trace context from headers\n\t\tconst headers: Record<string, string | string[] | undefined> = {};\n\t\tc.req.raw.headers.forEach((value, key) => {\n\t\t\theaders[key] = value;\n\t\t});\n\t\tconst parentContext = extractTraceContext(headers);\n\n\t\t// Build span attributes from request\n\t\tconst attrs = buildHonoSpanAttributes(c, options);\n\n\t\t// Create the span\n\t\tconst span = createHttpServerSpan(attrs, parentContext);\n\t\tconst spanContext = trace.setSpan(parentContext, span);\n\n\t\t// Store span and context on Hono context\n\t\tc.set(SPAN_KEY, span);\n\t\tc.set(CONTEXT_KEY, spanContext);\n\n\t\t// Record body if requested\n\t\tif (options.recordBody) {\n\t\t\ttry {\n\t\t\t\tconst body = await c.req.text();\n\t\t\t\tif (body) {\n\t\t\t\t\tspan.setAttribute(\n\t\t\t\t\t\t'http.request.body',\n\t\t\t\t\t\tbody.length > 4096 ? `${body.slice(0, 4096)}...` : body,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Body may have already been consumed\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\t// Execute the rest of the middleware chain within span context\n\t\t\tawait context.with(spanContext, async () => {\n\t\t\t\tawait next();\n\t\t\t});\n\n\t\t\t// Record response\n\t\t\tconst statusCode = c.res.status;\n\n\t\t\tif (options.recordResponseBody) {\n\t\t\t\ttry {\n\t\t\t\t\tconst body = await c.res.clone().text();\n\t\t\t\t\tif (body) {\n\t\t\t\t\t\tspan.setAttribute(\n\t\t\t\t\t\t\t'http.response.body',\n\t\t\t\t\t\t\tbody.length > 4096 ? `${body.slice(0, 4096)}...` : body,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Response body may not be available\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tendHttpSpan(span, { statusCode });\n\t\t} catch (error) {\n\t\t\tendHttpSpan(\n\t\t\t\tspan,\n\t\t\t\t{ statusCode: 500 },\n\t\t\t\terror instanceof Error ? error : new Error(String(error)),\n\t\t\t);\n\t\t\tthrow error;\n\t\t}\n\t};\n}\n\n/**\n * Build span attributes from Hono context\n */\nfunction buildHonoSpanAttributes(\n\tc: Context,\n\toptions: HonoTelemetryMiddlewareOptions,\n): HttpSpanAttributes {\n\tconst req = c.req;\n\tconst url = new URL(req.url);\n\n\t// Use actual path for route unless it's a specific route pattern\n\tconst routePath = c.req.routePath;\n\tconst route =\n\t\troutePath && routePath !== '*' && !routePath.includes('/*')\n\t\t\t? routePath\n\t\t\t: url.pathname;\n\n\tconst attrs: HttpSpanAttributes = {\n\t\tmethod: req.method,\n\t\turl: req.url,\n\t\tpath: url.pathname,\n\t\troute,\n\t\thost: url.host,\n\t\tscheme: url.protocol.replace(':', '') as 'http' | 'https',\n\t\tuserAgent: req.header('user-agent'),\n\t\tclientIp: getClientIp(c),\n\t\trequestId: req.header('x-request-id') || req.header('x-amzn-requestid'),\n\t};\n\n\t// Add user metadata if extractor provided\n\tif (options.getUserId) {\n\t\tconst userId = options.getUserId(c);\n\t\tif (userId) {\n\t\t\tattrs.user = { userId };\n\t\t}\n\t}\n\n\treturn attrs;\n}\n\n/**\n * Extract client IP from Hono context\n */\nfunction getClientIp(c: Context): string | undefined {\n\t// Try various headers in order of preference\n\tconst xForwardedFor = c.req.header('x-forwarded-for');\n\tif (xForwardedFor) {\n\t\tconst first = xForwardedFor.split(',')[0];\n\t\treturn first?.trim();\n\t}\n\n\tconst xRealIp = c.req.header('x-real-ip');\n\tif (xRealIp) {\n\t\treturn xRealIp;\n\t}\n\n\t// Try CF-Connecting-IP (Cloudflare)\n\tconst cfConnectingIp = c.req.header('cf-connecting-ip');\n\tif (cfConnectingIp) {\n\t\treturn cfConnectingIp;\n\t}\n\n\treturn undefined;\n}\n\n/**\n * Check if path should be ignored\n */\nfunction shouldIgnorePath(path: string, ignorePaths: string[]): boolean {\n\tfor (const pattern of ignorePaths) {\n\t\tif (pattern.endsWith('*')) {\n\t\t\t// Wildcard match\n\t\t\tconst prefix = pattern.slice(0, -1);\n\t\t\tif (path.startsWith(prefix)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t} else if (path === pattern) {\n\t\t\t// Exact match\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Run a function within the span context from Hono context\n *\n * @example\n * ```typescript\n * app.get('/api/users', async (c) => {\n * return withHonoSpanContext(c, async () => {\n * // Any spans created here will be children of the request span\n * const users = await fetchUsers();\n * return c.json(users);\n * });\n * });\n * ```\n */\nexport async function withHonoSpanContext<T>(\n\tc: Context,\n\tfn: () => Promise<T>,\n): Promise<T> {\n\tconst ctx = getTraceContextFromHono(c);\n\tif (!ctx) {\n\t\treturn fn();\n\t}\n\treturn context.with(ctx, fn);\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createHttpServerSpan, endHttpSpan, extractTraceContext } from "./http-
|
|
1
|
+
import { createHttpServerSpan, endHttpSpan, extractTraceContext } from "./http-DQzgLczm.mjs";
|
|
2
2
|
import { context, trace } from "@opentelemetry/api";
|
|
3
3
|
|
|
4
4
|
//#region src/instrumentation/hono.ts
|
|
@@ -133,4 +133,4 @@ async function withHonoSpanContext(c, fn) {
|
|
|
133
133
|
|
|
134
134
|
//#endregion
|
|
135
135
|
export { getSpanFromContext, getTraceContextFromHono, honoTelemetryMiddleware, withHonoSpanContext };
|
|
136
|
-
//# sourceMappingURL=hono-
|
|
136
|
+
//# sourceMappingURL=hono-DxhvnVbF.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hono-
|
|
1
|
+
{"version":3,"file":"hono-DxhvnVbF.mjs","names":["c: Context","options: HonoTelemetryMiddlewareOptions","headers: Record<string, string | string[] | undefined>","attrs: HttpSpanAttributes","path: string","ignorePaths: string[]","fn: () => Promise<T>"],"sources":["../src/instrumentation/hono.ts"],"sourcesContent":["import { context, type Span, trace } from '@opentelemetry/api';\n/**\n * OpenTelemetry instrumentation middleware for Hono\n *\n * This middleware automatically creates spans for HTTP requests,\n * extracts trace context from incoming headers, and records\n * request/response metadata as span attributes.\n */\nimport type { Context, MiddlewareHandler } from 'hono';\nimport {\n\tcreateHttpServerSpan,\n\tendHttpSpan,\n\textractTraceContext,\n\ttype HttpSpanAttributes,\n} from './http';\n\n/**\n * Options for the Hono telemetry middleware\n */\nexport interface HonoTelemetryMiddlewareOptions {\n\t/**\n\t * Whether to record request body as span attribute\n\t * @default false\n\t */\n\trecordBody?: boolean;\n\n\t/**\n\t * Whether to record response body as span attribute\n\t * @default false\n\t */\n\trecordResponseBody?: boolean;\n\n\t/**\n\t * Custom function to extract user ID from context\n\t */\n\tgetUserId?: (c: Context) => string | undefined;\n\n\t/**\n\t * Paths to skip tracing (supports wildcards)\n\t */\n\tignorePaths?: string[];\n\n\t/**\n\t * Whether to skip tracing for this request\n\t */\n\tshouldSkip?: (c: Context) => boolean;\n}\n\n// Key for storing span on context\nconst SPAN_KEY = 'telemetry.span';\nconst CONTEXT_KEY = 'telemetry.context';\n\n/**\n * Get the current span from Hono context\n */\nexport function getSpanFromContext(c: Context): Span | undefined {\n\treturn c.get(SPAN_KEY);\n}\n\n/**\n * Get the current trace context from Hono context\n */\nexport function getTraceContextFromHono(c: Context): any {\n\treturn c.get(CONTEXT_KEY);\n}\n\n/**\n * Create a telemetry middleware for Hono applications\n *\n * @example\n * ```typescript\n * import { honoTelemetryMiddleware } from '@geekmidas/telescope/instrumentation';\n *\n * const app = new Hono();\n * app.use('*', honoTelemetryMiddleware());\n * ```\n */\nexport function honoTelemetryMiddleware(\n\toptions: HonoTelemetryMiddlewareOptions = {},\n): MiddlewareHandler {\n\treturn async (c, next) => {\n\t\t// Check if path should be ignored\n\t\tif (\n\t\t\toptions.ignorePaths &&\n\t\t\tshouldIgnorePath(c.req.path, options.ignorePaths)\n\t\t) {\n\t\t\treturn next();\n\t\t}\n\n\t\t// Skip if custom skip function returns true\n\t\tif (options.shouldSkip?.(c)) {\n\t\t\treturn next();\n\t\t}\n\n\t\t// Extract trace context from headers\n\t\tconst headers: Record<string, string | string[] | undefined> = {};\n\t\tc.req.raw.headers.forEach((value, key) => {\n\t\t\theaders[key] = value;\n\t\t});\n\t\tconst parentContext = extractTraceContext(headers);\n\n\t\t// Build span attributes from request\n\t\tconst attrs = buildHonoSpanAttributes(c, options);\n\n\t\t// Create the span\n\t\tconst span = createHttpServerSpan(attrs, parentContext);\n\t\tconst spanContext = trace.setSpan(parentContext, span);\n\n\t\t// Store span and context on Hono context\n\t\tc.set(SPAN_KEY, span);\n\t\tc.set(CONTEXT_KEY, spanContext);\n\n\t\t// Record body if requested\n\t\tif (options.recordBody) {\n\t\t\ttry {\n\t\t\t\tconst body = await c.req.text();\n\t\t\t\tif (body) {\n\t\t\t\t\tspan.setAttribute(\n\t\t\t\t\t\t'http.request.body',\n\t\t\t\t\t\tbody.length > 4096 ? `${body.slice(0, 4096)}...` : body,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Body may have already been consumed\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\t// Execute the rest of the middleware chain within span context\n\t\t\tawait context.with(spanContext, async () => {\n\t\t\t\tawait next();\n\t\t\t});\n\n\t\t\t// Record response\n\t\t\tconst statusCode = c.res.status;\n\n\t\t\tif (options.recordResponseBody) {\n\t\t\t\ttry {\n\t\t\t\t\tconst body = await c.res.clone().text();\n\t\t\t\t\tif (body) {\n\t\t\t\t\t\tspan.setAttribute(\n\t\t\t\t\t\t\t'http.response.body',\n\t\t\t\t\t\t\tbody.length > 4096 ? `${body.slice(0, 4096)}...` : body,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Response body may not be available\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tendHttpSpan(span, { statusCode });\n\t\t} catch (error) {\n\t\t\tendHttpSpan(\n\t\t\t\tspan,\n\t\t\t\t{ statusCode: 500 },\n\t\t\t\terror instanceof Error ? error : new Error(String(error)),\n\t\t\t);\n\t\t\tthrow error;\n\t\t}\n\t};\n}\n\n/**\n * Build span attributes from Hono context\n */\nfunction buildHonoSpanAttributes(\n\tc: Context,\n\toptions: HonoTelemetryMiddlewareOptions,\n): HttpSpanAttributes {\n\tconst req = c.req;\n\tconst url = new URL(req.url);\n\n\t// Use actual path for route unless it's a specific route pattern\n\tconst routePath = c.req.routePath;\n\tconst route =\n\t\troutePath && routePath !== '*' && !routePath.includes('/*')\n\t\t\t? routePath\n\t\t\t: url.pathname;\n\n\tconst attrs: HttpSpanAttributes = {\n\t\tmethod: req.method,\n\t\turl: req.url,\n\t\tpath: url.pathname,\n\t\troute,\n\t\thost: url.host,\n\t\tscheme: url.protocol.replace(':', '') as 'http' | 'https',\n\t\tuserAgent: req.header('user-agent'),\n\t\tclientIp: getClientIp(c),\n\t\trequestId: req.header('x-request-id') || req.header('x-amzn-requestid'),\n\t};\n\n\t// Add user metadata if extractor provided\n\tif (options.getUserId) {\n\t\tconst userId = options.getUserId(c);\n\t\tif (userId) {\n\t\t\tattrs.user = { userId };\n\t\t}\n\t}\n\n\treturn attrs;\n}\n\n/**\n * Extract client IP from Hono context\n */\nfunction getClientIp(c: Context): string | undefined {\n\t// Try various headers in order of preference\n\tconst xForwardedFor = c.req.header('x-forwarded-for');\n\tif (xForwardedFor) {\n\t\tconst first = xForwardedFor.split(',')[0];\n\t\treturn first?.trim();\n\t}\n\n\tconst xRealIp = c.req.header('x-real-ip');\n\tif (xRealIp) {\n\t\treturn xRealIp;\n\t}\n\n\t// Try CF-Connecting-IP (Cloudflare)\n\tconst cfConnectingIp = c.req.header('cf-connecting-ip');\n\tif (cfConnectingIp) {\n\t\treturn cfConnectingIp;\n\t}\n\n\treturn undefined;\n}\n\n/**\n * Check if path should be ignored\n */\nfunction shouldIgnorePath(path: string, ignorePaths: string[]): boolean {\n\tfor (const pattern of ignorePaths) {\n\t\tif (pattern.endsWith('*')) {\n\t\t\t// Wildcard match\n\t\t\tconst prefix = pattern.slice(0, -1);\n\t\t\tif (path.startsWith(prefix)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t} else if (path === pattern) {\n\t\t\t// Exact match\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Run a function within the span context from Hono context\n *\n * @example\n * ```typescript\n * app.get('/api/users', async (c) => {\n * return withHonoSpanContext(c, async () => {\n * // Any spans created here will be children of the request span\n * const users = await fetchUsers();\n * return c.json(users);\n * });\n * });\n * ```\n */\nexport async function withHonoSpanContext<T>(\n\tc: Context,\n\tfn: () => Promise<T>,\n): Promise<T> {\n\tconst ctx = getTraceContextFromHono(c);\n\tif (!ctx) {\n\t\treturn fn();\n\t}\n\treturn context.with(ctx, fn);\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as _opentelemetry_api2 from "@opentelemetry/api";
|
|
2
2
|
import { Attributes, Context, Span } from "@opentelemetry/api";
|
|
3
3
|
|
|
4
4
|
//#region src/instrumentation/http.d.ts
|
|
@@ -51,7 +51,7 @@ interface HttpSpanAttributes extends HttpRequestAttributes {
|
|
|
51
51
|
/**
|
|
52
52
|
* Get or create a tracer for constructs instrumentation
|
|
53
53
|
*/
|
|
54
|
-
declare function getConstructsTracer():
|
|
54
|
+
declare function getConstructsTracer(): _opentelemetry_api2.Tracer;
|
|
55
55
|
/**
|
|
56
56
|
* Convert HTTP attributes to OpenTelemetry semantic conventions
|
|
57
57
|
*/
|
|
@@ -104,4 +104,4 @@ declare function isTracingEnabled(): boolean;
|
|
|
104
104
|
//# sourceMappingURL=http.d.ts.map
|
|
105
105
|
//#endregion
|
|
106
106
|
export { EndpointAttributes, HttpRequestAttributes, HttpResponseAttributes, HttpSpanAttributes, UserAttributes, createChildSpan, createHttpServerSpan, endHttpSpan, extractTraceContext, getConstructsTracer, injectTraceContext, isTracingEnabled, toOtelAttributes, withChildSpan, withHttpSpan };
|
|
107
|
-
//# sourceMappingURL=http-
|
|
107
|
+
//# sourceMappingURL=http-D5kn3_Mt.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-
|
|
1
|
+
{"version":3,"file":"http-D5kn3_Mt.d.mts","names":[],"sources":["../src/instrumentation/http.ts"],"sourcesContent":[],"mappings":";;;;;;;AAciB,UAAA,qBAAA,CAAqB;EAerB,MAAA,EAAA,MAAA;EAQA,GAAA,CAAA,EAAA,MAAA;EASA,IAAA,CAAA,EAAA,MAAA;EASA,KAAA,CAAA,EAAA,MAAA;EAAmB,IAAA,CAAA,EAAA,MAAA;EAAA,MACxB,CAAA,EAAA,MAAA,GAAA,OAAA;EAAsB,SACtB,CAAA,EAAA,MAAA;EAAkB,QACtB,CAAA,EAAA,MAAA;EAAc,SACZ,CAAA,EAAA,MAAA;;AAJuD;AAYjE;AAOA;AAAgC,UA7Cf,sBAAA,CA6Ce;EAAA,UAAQ,EAAA,MAAA;EAAkB,YAAG,CAAA,EAAA,MAAA;AAAU;AAgDvE;;;AAEG,UAvFc,kBAAA,CAuFd;EAAO,IAAA,CAAA,EAAA,MAAA;EAkBM,WAAA,CAAA,EAAA,MAAA;EAAkB,IAAA,CAAA,EAAA,MAAA,EAAA;;;;AAGzB;AASO,UA5GC,cAAA,CA4GmB;EAAA,MAAA,CAAA,EAAA,MAAA;EAAA,SAC5B,CAAA,EAAA,MAAA;EAAkB,KACT,CAAA,EAAA,MAAA,EAAA;;AACV;AAqBP;;AACO,UA5HU,kBAAA,SAA2B,qBA4HrC,CAAA;EAAI,QACA,CAAA,EA5HC,sBA4HD;EAAsB,QACxB,CAAA,EA5HG,kBA4HH;EAAK,IAAA,CAAA,EA3HN,cA2HM;EAwCQ,MAAA,CAAA,EAlKZ,UAkKwB;;;;;AAEb,iBA5JL,mBAAA,CAAA,CA4JK,EA5Jc,mBAAA,CAAA,MA4Jd;;;;AAEX,iBAvJM,gBAAA,CAuJN,KAAA,EAvJ8B,kBAuJ9B,CAAA,EAvJmD,UAuJnD;AA0BV;;;AAAwE,iBAjIxD,mBAAA,CAiIwD,OAAA,EAhI9D,MAgI8D,CAAA,MAAA,EAAA,MAAA,GAAA,MAAA,EAAA,GAAA,SAAA,CAAA,CAAA,EA/HrE,OA+HqE;AAAI;AAW5E;;AAEY,iBA1HI,kBAAA,CA0HJ,OAAA,EAzHF,MAyHE,CAAA,MAAA,EAAA,MAAA,CAAA,EAAA,GAAA,CAAA,EAxHL,OAwHK,CAAA,EAvHT,MAuHS,CAAA,MAAA,EAAA,MAAA,CAAA;;;;AAED,iBAhHK,oBAAA,CAgHL,KAAA,EA/GH,kBA+GG,EAAA,aAAA,CAAA,EA9GM,OA8GN,CAAA,EA7GR,IA6GQ;;AAAD;AA2BV;iBAnHgB,WAAA,OACT,gBACI,gCACF;;;;;;;;;;;;;;;iBAwCa,uBACd,+BACI,SAAS,QAAQ;;oBACZ,UACd,QAAQ;;;;iBA0BK,eAAA,4BAA2C,aAAa;;;;iBAWlD,0CAEV,SAAS,QAAQ,iBACf,aACX,QAAQ;;;;iBA2BK,gBAAA,CAAA"}
|
|
@@ -156,4 +156,4 @@ function isTracingEnabled() {
|
|
|
156
156
|
|
|
157
157
|
//#endregion
|
|
158
158
|
export { createChildSpan, createHttpServerSpan, endHttpSpan, extractTraceContext, getConstructsTracer, injectTraceContext, isTracingEnabled, toOtelAttributes, withChildSpan, withHttpSpan };
|
|
159
|
-
//# sourceMappingURL=http-
|
|
159
|
+
//# sourceMappingURL=http-DQzgLczm.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-BIvr0YdI.mjs","names":["attrs: HttpSpanAttributes","otelAttrs: Attributes","headers: Record<string, string | string[] | undefined>","normalizedHeaders: Record<string, string>","headers: Record<string, string>","ctx?: Context","parentContext?: Context","span: Span","response: HttpResponseAttributes","error?: Error","fn: (span: Span) => Promise<T & { statusCode?: number }>","name: string","attributes?: Attributes","fn: (span: Span) => Promise<T>"],"sources":["../src/instrumentation/http.ts"],"sourcesContent":["import {\n\ttype Attributes,\n\ttype Context,\n\tcontext,\n\tpropagation,\n\ttype Span,\n\tSpanKind,\n\tSpanStatusCode,\n\ttrace,\n} from '@opentelemetry/api';\n\n/**\n * HTTP request attributes following OpenTelemetry semantic conventions\n */\nexport interface HttpRequestAttributes {\n\tmethod: string;\n\turl?: string;\n\tpath?: string;\n\troute?: string;\n\thost?: string;\n\tscheme?: 'http' | 'https';\n\tuserAgent?: string;\n\tclientIp?: string;\n\trequestId?: string;\n}\n\n/**\n * HTTP response attributes\n */\nexport interface HttpResponseAttributes {\n\tstatusCode: number;\n\tresponseSize?: number;\n}\n\n/**\n * Endpoint-specific attributes\n */\nexport interface EndpointAttributes {\n\tname?: string;\n\toperationId?: string;\n\ttags?: string[];\n}\n\n/**\n * User/session attributes\n */\nexport interface UserAttributes {\n\tuserId?: string;\n\tsessionId?: string;\n\troles?: string[];\n}\n\n/**\n * Full span attributes for HTTP requests\n */\nexport interface HttpSpanAttributes extends HttpRequestAttributes {\n\tresponse?: HttpResponseAttributes;\n\tendpoint?: EndpointAttributes;\n\tuser?: UserAttributes;\n\tcustom?: Attributes;\n}\n\nconst TRACER_NAME = '@geekmidas/constructs';\n\n/**\n * Get or create a tracer for constructs instrumentation\n */\nexport function getConstructsTracer() {\n\treturn trace.getTracer(TRACER_NAME);\n}\n\n/**\n * Convert HTTP attributes to OpenTelemetry semantic conventions\n */\nexport function toOtelAttributes(attrs: HttpSpanAttributes): Attributes {\n\tconst otelAttrs: Attributes = {};\n\n\t// HTTP request attributes (OpenTelemetry semantic conventions)\n\tif (attrs.method) otelAttrs['http.request.method'] = attrs.method;\n\tif (attrs.url) otelAttrs['url.full'] = attrs.url;\n\tif (attrs.path) otelAttrs['url.path'] = attrs.path;\n\tif (attrs.route) otelAttrs['http.route'] = attrs.route;\n\tif (attrs.host) otelAttrs['server.address'] = attrs.host;\n\tif (attrs.scheme) otelAttrs['url.scheme'] = attrs.scheme;\n\tif (attrs.userAgent) otelAttrs['user_agent.original'] = attrs.userAgent;\n\tif (attrs.clientIp) otelAttrs['client.address'] = attrs.clientIp;\n\tif (attrs.requestId) otelAttrs['http.request.id'] = attrs.requestId;\n\n\t// HTTP response attributes\n\tif (attrs.response?.statusCode) {\n\t\totelAttrs['http.response.status_code'] = attrs.response.statusCode;\n\t}\n\tif (attrs.response?.responseSize) {\n\t\totelAttrs['http.response.body.size'] = attrs.response.responseSize;\n\t}\n\n\t// Endpoint attributes\n\tif (attrs.endpoint?.name) otelAttrs['endpoint.name'] = attrs.endpoint.name;\n\tif (attrs.endpoint?.operationId) {\n\t\totelAttrs['endpoint.operation_id'] = attrs.endpoint.operationId;\n\t}\n\tif (attrs.endpoint?.tags?.length) {\n\t\totelAttrs['endpoint.tags'] = attrs.endpoint.tags;\n\t}\n\n\t// User attributes\n\tif (attrs.user?.userId) otelAttrs['enduser.id'] = attrs.user.userId;\n\tif (attrs.user?.sessionId) otelAttrs['session.id'] = attrs.user.sessionId;\n\tif (attrs.user?.roles?.length)\n\t\totelAttrs['enduser.role'] = attrs.user.roles.join(',');\n\n\t// Custom attributes\n\tif (attrs.custom) {\n\t\tObject.assign(otelAttrs, attrs.custom);\n\t}\n\n\treturn otelAttrs;\n}\n\n/**\n * Extract trace context from HTTP headers\n */\nexport function extractTraceContext(\n\theaders: Record<string, string | string[] | undefined>,\n): Context {\n\t// Normalize headers to Record<string, string>\n\tconst normalizedHeaders: Record<string, string> = {};\n\tfor (const [key, value] of Object.entries(headers)) {\n\t\tif (value) {\n\t\t\tconst stringValue = Array.isArray(value) ? value[0] : value;\n\t\t\tif (stringValue) {\n\t\t\t\tnormalizedHeaders[key.toLowerCase()] = stringValue;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn propagation.extract(context.active(), normalizedHeaders);\n}\n\n/**\n * Inject trace context into HTTP headers\n */\nexport function injectTraceContext(\n\theaders: Record<string, string>,\n\tctx?: Context,\n): Record<string, string> {\n\tconst result = { ...headers };\n\tpropagation.inject(ctx ?? context.active(), result);\n\treturn result;\n}\n\n/**\n * Create an HTTP server span for an incoming request\n */\nexport function createHttpServerSpan(\n\tattrs: HttpSpanAttributes,\n\tparentContext?: Context,\n): Span {\n\tconst tracer = getConstructsTracer();\n\tconst spanName = attrs.route\n\t\t? `${attrs.method} ${attrs.route}`\n\t\t: `${attrs.method} ${attrs.path || '/'}`;\n\n\tconst ctx = parentContext ?? context.active();\n\n\treturn tracer.startSpan(\n\t\tspanName,\n\t\t{\n\t\t\tkind: SpanKind.SERVER,\n\t\t\tattributes: toOtelAttributes(attrs),\n\t\t},\n\t\tctx,\n\t);\n}\n\n/**\n * End an HTTP span with response data\n */\nexport function endHttpSpan(\n\tspan: Span,\n\tresponse: HttpResponseAttributes,\n\terror?: Error,\n): void {\n\tspan.setAttribute('http.response.status_code', response.statusCode);\n\n\tif (response.responseSize) {\n\t\tspan.setAttribute('http.response.body.size', response.responseSize);\n\t}\n\n\tif (error) {\n\t\tspan.recordException(error);\n\t\tspan.setStatus({\n\t\t\tcode: SpanStatusCode.ERROR,\n\t\t\tmessage: error.message,\n\t\t});\n\t} else if (response.statusCode >= 400) {\n\t\tspan.setStatus({\n\t\t\tcode: SpanStatusCode.ERROR,\n\t\t\tmessage: `HTTP ${response.statusCode}`,\n\t\t});\n\t} else {\n\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t}\n\n\tspan.end();\n}\n\n/**\n * Execute a function within an HTTP server span context\n *\n * @example\n * ```typescript\n * const result = await withHttpSpan(\n * { method: 'GET', path: '/users', route: '/users' },\n * async (span) => {\n * const users = await getUsers();\n * return { statusCode: 200, body: users };\n * }\n * );\n * ```\n */\nexport async function withHttpSpan<T>(\n\tattrs: HttpSpanAttributes,\n\tfn: (span: Span) => Promise<T & { statusCode?: number }>,\n\tparentContext?: Context,\n): Promise<T> {\n\tconst span = createHttpServerSpan(attrs, parentContext);\n\n\ttry {\n\t\tconst result = await context.with(\n\t\t\ttrace.setSpan(parentContext ?? context.active(), span),\n\t\t\t() => fn(span),\n\t\t);\n\n\t\tconst statusCode = (result as { statusCode?: number }).statusCode ?? 200;\n\t\tendHttpSpan(span, { statusCode });\n\n\t\treturn result;\n\t} catch (error) {\n\t\tendHttpSpan(\n\t\t\tspan,\n\t\t\t{ statusCode: 500 },\n\t\t\terror instanceof Error ? error : new Error(String(error)),\n\t\t);\n\t\tthrow error;\n\t}\n}\n\n/**\n * Create a child span for internal operations (middleware, handlers, etc.)\n */\nexport function createChildSpan(name: string, attributes?: Attributes): Span {\n\tconst tracer = getConstructsTracer();\n\treturn tracer.startSpan(name, {\n\t\tkind: SpanKind.INTERNAL,\n\t\tattributes,\n\t});\n}\n\n/**\n * Execute a function within a child span\n */\nexport async function withChildSpan<T>(\n\tname: string,\n\tfn: (span: Span) => Promise<T>,\n\tattributes?: Attributes,\n): Promise<T> {\n\tconst span = createChildSpan(name, attributes);\n\n\ttry {\n\t\tconst result = await context.with(\n\t\t\ttrace.setSpan(context.active(), span),\n\t\t\t() => fn(span),\n\t\t);\n\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\treturn result;\n\t} catch (error) {\n\t\tspan.setStatus({\n\t\t\tcode: SpanStatusCode.ERROR,\n\t\t\tmessage: error instanceof Error ? error.message : 'Unknown error',\n\t\t});\n\t\tspan.recordException(\n\t\t\terror instanceof Error ? error : new Error(String(error)),\n\t\t);\n\t\tthrow error;\n\t} finally {\n\t\tspan.end();\n\t}\n}\n\n/**\n * Check if tracing is enabled (OpenTelemetry API is available and configured)\n */\nexport function isTracingEnabled(): boolean {\n\ttry {\n\t\tconst tracer = trace.getTracer(TRACER_NAME);\n\t\t// Check if we have a real tracer (not a no-op)\n\t\tconst span = tracer.startSpan('test');\n\t\tconst isReal =\n\t\t\tspan.spanContext().traceId !== '00000000000000000000000000000000';\n\t\tspan.end();\n\t\treturn isReal;\n\t} catch {\n\t\treturn false;\n\t}\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"http-DQzgLczm.mjs","names":["attrs: HttpSpanAttributes","otelAttrs: Attributes","headers: Record<string, string | string[] | undefined>","normalizedHeaders: Record<string, string>","headers: Record<string, string>","ctx?: Context","parentContext?: Context","span: Span","response: HttpResponseAttributes","error?: Error","fn: (span: Span) => Promise<T & { statusCode?: number }>","name: string","attributes?: Attributes","fn: (span: Span) => Promise<T>"],"sources":["../src/instrumentation/http.ts"],"sourcesContent":["import {\n\ttype Attributes,\n\ttype Context,\n\tcontext,\n\tpropagation,\n\ttype Span,\n\tSpanKind,\n\tSpanStatusCode,\n\ttrace,\n} from '@opentelemetry/api';\n\n/**\n * HTTP request attributes following OpenTelemetry semantic conventions\n */\nexport interface HttpRequestAttributes {\n\tmethod: string;\n\turl?: string;\n\tpath?: string;\n\troute?: string;\n\thost?: string;\n\tscheme?: 'http' | 'https';\n\tuserAgent?: string;\n\tclientIp?: string;\n\trequestId?: string;\n}\n\n/**\n * HTTP response attributes\n */\nexport interface HttpResponseAttributes {\n\tstatusCode: number;\n\tresponseSize?: number;\n}\n\n/**\n * Endpoint-specific attributes\n */\nexport interface EndpointAttributes {\n\tname?: string;\n\toperationId?: string;\n\ttags?: string[];\n}\n\n/**\n * User/session attributes\n */\nexport interface UserAttributes {\n\tuserId?: string;\n\tsessionId?: string;\n\troles?: string[];\n}\n\n/**\n * Full span attributes for HTTP requests\n */\nexport interface HttpSpanAttributes extends HttpRequestAttributes {\n\tresponse?: HttpResponseAttributes;\n\tendpoint?: EndpointAttributes;\n\tuser?: UserAttributes;\n\tcustom?: Attributes;\n}\n\nconst TRACER_NAME = '@geekmidas/constructs';\n\n/**\n * Get or create a tracer for constructs instrumentation\n */\nexport function getConstructsTracer() {\n\treturn trace.getTracer(TRACER_NAME);\n}\n\n/**\n * Convert HTTP attributes to OpenTelemetry semantic conventions\n */\nexport function toOtelAttributes(attrs: HttpSpanAttributes): Attributes {\n\tconst otelAttrs: Attributes = {};\n\n\t// HTTP request attributes (OpenTelemetry semantic conventions)\n\tif (attrs.method) otelAttrs['http.request.method'] = attrs.method;\n\tif (attrs.url) otelAttrs['url.full'] = attrs.url;\n\tif (attrs.path) otelAttrs['url.path'] = attrs.path;\n\tif (attrs.route) otelAttrs['http.route'] = attrs.route;\n\tif (attrs.host) otelAttrs['server.address'] = attrs.host;\n\tif (attrs.scheme) otelAttrs['url.scheme'] = attrs.scheme;\n\tif (attrs.userAgent) otelAttrs['user_agent.original'] = attrs.userAgent;\n\tif (attrs.clientIp) otelAttrs['client.address'] = attrs.clientIp;\n\tif (attrs.requestId) otelAttrs['http.request.id'] = attrs.requestId;\n\n\t// HTTP response attributes\n\tif (attrs.response?.statusCode) {\n\t\totelAttrs['http.response.status_code'] = attrs.response.statusCode;\n\t}\n\tif (attrs.response?.responseSize) {\n\t\totelAttrs['http.response.body.size'] = attrs.response.responseSize;\n\t}\n\n\t// Endpoint attributes\n\tif (attrs.endpoint?.name) otelAttrs['endpoint.name'] = attrs.endpoint.name;\n\tif (attrs.endpoint?.operationId) {\n\t\totelAttrs['endpoint.operation_id'] = attrs.endpoint.operationId;\n\t}\n\tif (attrs.endpoint?.tags?.length) {\n\t\totelAttrs['endpoint.tags'] = attrs.endpoint.tags;\n\t}\n\n\t// User attributes\n\tif (attrs.user?.userId) otelAttrs['enduser.id'] = attrs.user.userId;\n\tif (attrs.user?.sessionId) otelAttrs['session.id'] = attrs.user.sessionId;\n\tif (attrs.user?.roles?.length)\n\t\totelAttrs['enduser.role'] = attrs.user.roles.join(',');\n\n\t// Custom attributes\n\tif (attrs.custom) {\n\t\tObject.assign(otelAttrs, attrs.custom);\n\t}\n\n\treturn otelAttrs;\n}\n\n/**\n * Extract trace context from HTTP headers\n */\nexport function extractTraceContext(\n\theaders: Record<string, string | string[] | undefined>,\n): Context {\n\t// Normalize headers to Record<string, string>\n\tconst normalizedHeaders: Record<string, string> = {};\n\tfor (const [key, value] of Object.entries(headers)) {\n\t\tif (value) {\n\t\t\tconst stringValue = Array.isArray(value) ? value[0] : value;\n\t\t\tif (stringValue) {\n\t\t\t\tnormalizedHeaders[key.toLowerCase()] = stringValue;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn propagation.extract(context.active(), normalizedHeaders);\n}\n\n/**\n * Inject trace context into HTTP headers\n */\nexport function injectTraceContext(\n\theaders: Record<string, string>,\n\tctx?: Context,\n): Record<string, string> {\n\tconst result = { ...headers };\n\tpropagation.inject(ctx ?? context.active(), result);\n\treturn result;\n}\n\n/**\n * Create an HTTP server span for an incoming request\n */\nexport function createHttpServerSpan(\n\tattrs: HttpSpanAttributes,\n\tparentContext?: Context,\n): Span {\n\tconst tracer = getConstructsTracer();\n\tconst spanName = attrs.route\n\t\t? `${attrs.method} ${attrs.route}`\n\t\t: `${attrs.method} ${attrs.path || '/'}`;\n\n\tconst ctx = parentContext ?? context.active();\n\n\treturn tracer.startSpan(\n\t\tspanName,\n\t\t{\n\t\t\tkind: SpanKind.SERVER,\n\t\t\tattributes: toOtelAttributes(attrs),\n\t\t},\n\t\tctx,\n\t);\n}\n\n/**\n * End an HTTP span with response data\n */\nexport function endHttpSpan(\n\tspan: Span,\n\tresponse: HttpResponseAttributes,\n\terror?: Error,\n): void {\n\tspan.setAttribute('http.response.status_code', response.statusCode);\n\n\tif (response.responseSize) {\n\t\tspan.setAttribute('http.response.body.size', response.responseSize);\n\t}\n\n\tif (error) {\n\t\tspan.recordException(error);\n\t\tspan.setStatus({\n\t\t\tcode: SpanStatusCode.ERROR,\n\t\t\tmessage: error.message,\n\t\t});\n\t} else if (response.statusCode >= 400) {\n\t\tspan.setStatus({\n\t\t\tcode: SpanStatusCode.ERROR,\n\t\t\tmessage: `HTTP ${response.statusCode}`,\n\t\t});\n\t} else {\n\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t}\n\n\tspan.end();\n}\n\n/**\n * Execute a function within an HTTP server span context\n *\n * @example\n * ```typescript\n * const result = await withHttpSpan(\n * { method: 'GET', path: '/users', route: '/users' },\n * async (span) => {\n * const users = await getUsers();\n * return { statusCode: 200, body: users };\n * }\n * );\n * ```\n */\nexport async function withHttpSpan<T>(\n\tattrs: HttpSpanAttributes,\n\tfn: (span: Span) => Promise<T & { statusCode?: number }>,\n\tparentContext?: Context,\n): Promise<T> {\n\tconst span = createHttpServerSpan(attrs, parentContext);\n\n\ttry {\n\t\tconst result = await context.with(\n\t\t\ttrace.setSpan(parentContext ?? context.active(), span),\n\t\t\t() => fn(span),\n\t\t);\n\n\t\tconst statusCode = (result as { statusCode?: number }).statusCode ?? 200;\n\t\tendHttpSpan(span, { statusCode });\n\n\t\treturn result;\n\t} catch (error) {\n\t\tendHttpSpan(\n\t\t\tspan,\n\t\t\t{ statusCode: 500 },\n\t\t\terror instanceof Error ? error : new Error(String(error)),\n\t\t);\n\t\tthrow error;\n\t}\n}\n\n/**\n * Create a child span for internal operations (middleware, handlers, etc.)\n */\nexport function createChildSpan(name: string, attributes?: Attributes): Span {\n\tconst tracer = getConstructsTracer();\n\treturn tracer.startSpan(name, {\n\t\tkind: SpanKind.INTERNAL,\n\t\tattributes,\n\t});\n}\n\n/**\n * Execute a function within a child span\n */\nexport async function withChildSpan<T>(\n\tname: string,\n\tfn: (span: Span) => Promise<T>,\n\tattributes?: Attributes,\n): Promise<T> {\n\tconst span = createChildSpan(name, attributes);\n\n\ttry {\n\t\tconst result = await context.with(\n\t\t\ttrace.setSpan(context.active(), span),\n\t\t\t() => fn(span),\n\t\t);\n\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\treturn result;\n\t} catch (error) {\n\t\tspan.setStatus({\n\t\t\tcode: SpanStatusCode.ERROR,\n\t\t\tmessage: error instanceof Error ? error.message : 'Unknown error',\n\t\t});\n\t\tspan.recordException(\n\t\t\terror instanceof Error ? error : new Error(String(error)),\n\t\t);\n\t\tthrow error;\n\t} finally {\n\t\tspan.end();\n\t}\n}\n\n/**\n * Check if tracing is enabled (OpenTelemetry API is available and configured)\n */\nexport function isTracingEnabled(): boolean {\n\ttry {\n\t\tconst tracer = trace.getTracer(TRACER_NAME);\n\t\t// Check if we have a real tracer (not a no-op)\n\t\tconst span = tracer.startSpan('test');\n\t\tconst isReal =\n\t\t\tspan.spanContext().traceId !== '00000000000000000000000000000000';\n\t\tspan.end();\n\t\treturn isReal;\n\t} catch {\n\t\treturn false;\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-BsqmhurZ.cjs","names":["attrs: HttpSpanAttributes","otelAttrs: Attributes","headers: Record<string, string | string[] | undefined>","normalizedHeaders: Record<string, string>","headers: Record<string, string>","ctx?: Context","parentContext?: Context","SpanKind","span: Span","response: HttpResponseAttributes","error?: Error","SpanStatusCode","fn: (span: Span) => Promise<T & { statusCode?: number }>","name: string","attributes?: Attributes","fn: (span: Span) => Promise<T>"],"sources":["../src/instrumentation/http.ts"],"sourcesContent":["import {\n\ttype Attributes,\n\ttype Context,\n\tcontext,\n\tpropagation,\n\ttype Span,\n\tSpanKind,\n\tSpanStatusCode,\n\ttrace,\n} from '@opentelemetry/api';\n\n/**\n * HTTP request attributes following OpenTelemetry semantic conventions\n */\nexport interface HttpRequestAttributes {\n\tmethod: string;\n\turl?: string;\n\tpath?: string;\n\troute?: string;\n\thost?: string;\n\tscheme?: 'http' | 'https';\n\tuserAgent?: string;\n\tclientIp?: string;\n\trequestId?: string;\n}\n\n/**\n * HTTP response attributes\n */\nexport interface HttpResponseAttributes {\n\tstatusCode: number;\n\tresponseSize?: number;\n}\n\n/**\n * Endpoint-specific attributes\n */\nexport interface EndpointAttributes {\n\tname?: string;\n\toperationId?: string;\n\ttags?: string[];\n}\n\n/**\n * User/session attributes\n */\nexport interface UserAttributes {\n\tuserId?: string;\n\tsessionId?: string;\n\troles?: string[];\n}\n\n/**\n * Full span attributes for HTTP requests\n */\nexport interface HttpSpanAttributes extends HttpRequestAttributes {\n\tresponse?: HttpResponseAttributes;\n\tendpoint?: EndpointAttributes;\n\tuser?: UserAttributes;\n\tcustom?: Attributes;\n}\n\nconst TRACER_NAME = '@geekmidas/constructs';\n\n/**\n * Get or create a tracer for constructs instrumentation\n */\nexport function getConstructsTracer() {\n\treturn trace.getTracer(TRACER_NAME);\n}\n\n/**\n * Convert HTTP attributes to OpenTelemetry semantic conventions\n */\nexport function toOtelAttributes(attrs: HttpSpanAttributes): Attributes {\n\tconst otelAttrs: Attributes = {};\n\n\t// HTTP request attributes (OpenTelemetry semantic conventions)\n\tif (attrs.method) otelAttrs['http.request.method'] = attrs.method;\n\tif (attrs.url) otelAttrs['url.full'] = attrs.url;\n\tif (attrs.path) otelAttrs['url.path'] = attrs.path;\n\tif (attrs.route) otelAttrs['http.route'] = attrs.route;\n\tif (attrs.host) otelAttrs['server.address'] = attrs.host;\n\tif (attrs.scheme) otelAttrs['url.scheme'] = attrs.scheme;\n\tif (attrs.userAgent) otelAttrs['user_agent.original'] = attrs.userAgent;\n\tif (attrs.clientIp) otelAttrs['client.address'] = attrs.clientIp;\n\tif (attrs.requestId) otelAttrs['http.request.id'] = attrs.requestId;\n\n\t// HTTP response attributes\n\tif (attrs.response?.statusCode) {\n\t\totelAttrs['http.response.status_code'] = attrs.response.statusCode;\n\t}\n\tif (attrs.response?.responseSize) {\n\t\totelAttrs['http.response.body.size'] = attrs.response.responseSize;\n\t}\n\n\t// Endpoint attributes\n\tif (attrs.endpoint?.name) otelAttrs['endpoint.name'] = attrs.endpoint.name;\n\tif (attrs.endpoint?.operationId) {\n\t\totelAttrs['endpoint.operation_id'] = attrs.endpoint.operationId;\n\t}\n\tif (attrs.endpoint?.tags?.length) {\n\t\totelAttrs['endpoint.tags'] = attrs.endpoint.tags;\n\t}\n\n\t// User attributes\n\tif (attrs.user?.userId) otelAttrs['enduser.id'] = attrs.user.userId;\n\tif (attrs.user?.sessionId) otelAttrs['session.id'] = attrs.user.sessionId;\n\tif (attrs.user?.roles?.length)\n\t\totelAttrs['enduser.role'] = attrs.user.roles.join(',');\n\n\t// Custom attributes\n\tif (attrs.custom) {\n\t\tObject.assign(otelAttrs, attrs.custom);\n\t}\n\n\treturn otelAttrs;\n}\n\n/**\n * Extract trace context from HTTP headers\n */\nexport function extractTraceContext(\n\theaders: Record<string, string | string[] | undefined>,\n): Context {\n\t// Normalize headers to Record<string, string>\n\tconst normalizedHeaders: Record<string, string> = {};\n\tfor (const [key, value] of Object.entries(headers)) {\n\t\tif (value) {\n\t\t\tconst stringValue = Array.isArray(value) ? value[0] : value;\n\t\t\tif (stringValue) {\n\t\t\t\tnormalizedHeaders[key.toLowerCase()] = stringValue;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn propagation.extract(context.active(), normalizedHeaders);\n}\n\n/**\n * Inject trace context into HTTP headers\n */\nexport function injectTraceContext(\n\theaders: Record<string, string>,\n\tctx?: Context,\n): Record<string, string> {\n\tconst result = { ...headers };\n\tpropagation.inject(ctx ?? context.active(), result);\n\treturn result;\n}\n\n/**\n * Create an HTTP server span for an incoming request\n */\nexport function createHttpServerSpan(\n\tattrs: HttpSpanAttributes,\n\tparentContext?: Context,\n): Span {\n\tconst tracer = getConstructsTracer();\n\tconst spanName = attrs.route\n\t\t? `${attrs.method} ${attrs.route}`\n\t\t: `${attrs.method} ${attrs.path || '/'}`;\n\n\tconst ctx = parentContext ?? context.active();\n\n\treturn tracer.startSpan(\n\t\tspanName,\n\t\t{\n\t\t\tkind: SpanKind.SERVER,\n\t\t\tattributes: toOtelAttributes(attrs),\n\t\t},\n\t\tctx,\n\t);\n}\n\n/**\n * End an HTTP span with response data\n */\nexport function endHttpSpan(\n\tspan: Span,\n\tresponse: HttpResponseAttributes,\n\terror?: Error,\n): void {\n\tspan.setAttribute('http.response.status_code', response.statusCode);\n\n\tif (response.responseSize) {\n\t\tspan.setAttribute('http.response.body.size', response.responseSize);\n\t}\n\n\tif (error) {\n\t\tspan.recordException(error);\n\t\tspan.setStatus({\n\t\t\tcode: SpanStatusCode.ERROR,\n\t\t\tmessage: error.message,\n\t\t});\n\t} else if (response.statusCode >= 400) {\n\t\tspan.setStatus({\n\t\t\tcode: SpanStatusCode.ERROR,\n\t\t\tmessage: `HTTP ${response.statusCode}`,\n\t\t});\n\t} else {\n\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t}\n\n\tspan.end();\n}\n\n/**\n * Execute a function within an HTTP server span context\n *\n * @example\n * ```typescript\n * const result = await withHttpSpan(\n * { method: 'GET', path: '/users', route: '/users' },\n * async (span) => {\n * const users = await getUsers();\n * return { statusCode: 200, body: users };\n * }\n * );\n * ```\n */\nexport async function withHttpSpan<T>(\n\tattrs: HttpSpanAttributes,\n\tfn: (span: Span) => Promise<T & { statusCode?: number }>,\n\tparentContext?: Context,\n): Promise<T> {\n\tconst span = createHttpServerSpan(attrs, parentContext);\n\n\ttry {\n\t\tconst result = await context.with(\n\t\t\ttrace.setSpan(parentContext ?? context.active(), span),\n\t\t\t() => fn(span),\n\t\t);\n\n\t\tconst statusCode = (result as { statusCode?: number }).statusCode ?? 200;\n\t\tendHttpSpan(span, { statusCode });\n\n\t\treturn result;\n\t} catch (error) {\n\t\tendHttpSpan(\n\t\t\tspan,\n\t\t\t{ statusCode: 500 },\n\t\t\terror instanceof Error ? error : new Error(String(error)),\n\t\t);\n\t\tthrow error;\n\t}\n}\n\n/**\n * Create a child span for internal operations (middleware, handlers, etc.)\n */\nexport function createChildSpan(name: string, attributes?: Attributes): Span {\n\tconst tracer = getConstructsTracer();\n\treturn tracer.startSpan(name, {\n\t\tkind: SpanKind.INTERNAL,\n\t\tattributes,\n\t});\n}\n\n/**\n * Execute a function within a child span\n */\nexport async function withChildSpan<T>(\n\tname: string,\n\tfn: (span: Span) => Promise<T>,\n\tattributes?: Attributes,\n): Promise<T> {\n\tconst span = createChildSpan(name, attributes);\n\n\ttry {\n\t\tconst result = await context.with(\n\t\t\ttrace.setSpan(context.active(), span),\n\t\t\t() => fn(span),\n\t\t);\n\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\treturn result;\n\t} catch (error) {\n\t\tspan.setStatus({\n\t\t\tcode: SpanStatusCode.ERROR,\n\t\t\tmessage: error instanceof Error ? error.message : 'Unknown error',\n\t\t});\n\t\tspan.recordException(\n\t\t\terror instanceof Error ? error : new Error(String(error)),\n\t\t);\n\t\tthrow error;\n\t} finally {\n\t\tspan.end();\n\t}\n}\n\n/**\n * Check if tracing is enabled (OpenTelemetry API is available and configured)\n */\nexport function isTracingEnabled(): boolean {\n\ttry {\n\t\tconst tracer = trace.getTracer(TRACER_NAME);\n\t\t// Check if we have a real tracer (not a no-op)\n\t\tconst span = tracer.startSpan('test');\n\t\tconst isReal =\n\t\t\tspan.spanContext().traceId !== '00000000000000000000000000000000';\n\t\tspan.end();\n\t\treturn isReal;\n\t} catch {\n\t\treturn false;\n\t}\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"http-D_Z8sYXZ.cjs","names":["attrs: HttpSpanAttributes","otelAttrs: Attributes","headers: Record<string, string | string[] | undefined>","normalizedHeaders: Record<string, string>","headers: Record<string, string>","ctx?: Context","parentContext?: Context","SpanKind","span: Span","response: HttpResponseAttributes","error?: Error","SpanStatusCode","fn: (span: Span) => Promise<T & { statusCode?: number }>","name: string","attributes?: Attributes","fn: (span: Span) => Promise<T>"],"sources":["../src/instrumentation/http.ts"],"sourcesContent":["import {\n\ttype Attributes,\n\ttype Context,\n\tcontext,\n\tpropagation,\n\ttype Span,\n\tSpanKind,\n\tSpanStatusCode,\n\ttrace,\n} from '@opentelemetry/api';\n\n/**\n * HTTP request attributes following OpenTelemetry semantic conventions\n */\nexport interface HttpRequestAttributes {\n\tmethod: string;\n\turl?: string;\n\tpath?: string;\n\troute?: string;\n\thost?: string;\n\tscheme?: 'http' | 'https';\n\tuserAgent?: string;\n\tclientIp?: string;\n\trequestId?: string;\n}\n\n/**\n * HTTP response attributes\n */\nexport interface HttpResponseAttributes {\n\tstatusCode: number;\n\tresponseSize?: number;\n}\n\n/**\n * Endpoint-specific attributes\n */\nexport interface EndpointAttributes {\n\tname?: string;\n\toperationId?: string;\n\ttags?: string[];\n}\n\n/**\n * User/session attributes\n */\nexport interface UserAttributes {\n\tuserId?: string;\n\tsessionId?: string;\n\troles?: string[];\n}\n\n/**\n * Full span attributes for HTTP requests\n */\nexport interface HttpSpanAttributes extends HttpRequestAttributes {\n\tresponse?: HttpResponseAttributes;\n\tendpoint?: EndpointAttributes;\n\tuser?: UserAttributes;\n\tcustom?: Attributes;\n}\n\nconst TRACER_NAME = '@geekmidas/constructs';\n\n/**\n * Get or create a tracer for constructs instrumentation\n */\nexport function getConstructsTracer() {\n\treturn trace.getTracer(TRACER_NAME);\n}\n\n/**\n * Convert HTTP attributes to OpenTelemetry semantic conventions\n */\nexport function toOtelAttributes(attrs: HttpSpanAttributes): Attributes {\n\tconst otelAttrs: Attributes = {};\n\n\t// HTTP request attributes (OpenTelemetry semantic conventions)\n\tif (attrs.method) otelAttrs['http.request.method'] = attrs.method;\n\tif (attrs.url) otelAttrs['url.full'] = attrs.url;\n\tif (attrs.path) otelAttrs['url.path'] = attrs.path;\n\tif (attrs.route) otelAttrs['http.route'] = attrs.route;\n\tif (attrs.host) otelAttrs['server.address'] = attrs.host;\n\tif (attrs.scheme) otelAttrs['url.scheme'] = attrs.scheme;\n\tif (attrs.userAgent) otelAttrs['user_agent.original'] = attrs.userAgent;\n\tif (attrs.clientIp) otelAttrs['client.address'] = attrs.clientIp;\n\tif (attrs.requestId) otelAttrs['http.request.id'] = attrs.requestId;\n\n\t// HTTP response attributes\n\tif (attrs.response?.statusCode) {\n\t\totelAttrs['http.response.status_code'] = attrs.response.statusCode;\n\t}\n\tif (attrs.response?.responseSize) {\n\t\totelAttrs['http.response.body.size'] = attrs.response.responseSize;\n\t}\n\n\t// Endpoint attributes\n\tif (attrs.endpoint?.name) otelAttrs['endpoint.name'] = attrs.endpoint.name;\n\tif (attrs.endpoint?.operationId) {\n\t\totelAttrs['endpoint.operation_id'] = attrs.endpoint.operationId;\n\t}\n\tif (attrs.endpoint?.tags?.length) {\n\t\totelAttrs['endpoint.tags'] = attrs.endpoint.tags;\n\t}\n\n\t// User attributes\n\tif (attrs.user?.userId) otelAttrs['enduser.id'] = attrs.user.userId;\n\tif (attrs.user?.sessionId) otelAttrs['session.id'] = attrs.user.sessionId;\n\tif (attrs.user?.roles?.length)\n\t\totelAttrs['enduser.role'] = attrs.user.roles.join(',');\n\n\t// Custom attributes\n\tif (attrs.custom) {\n\t\tObject.assign(otelAttrs, attrs.custom);\n\t}\n\n\treturn otelAttrs;\n}\n\n/**\n * Extract trace context from HTTP headers\n */\nexport function extractTraceContext(\n\theaders: Record<string, string | string[] | undefined>,\n): Context {\n\t// Normalize headers to Record<string, string>\n\tconst normalizedHeaders: Record<string, string> = {};\n\tfor (const [key, value] of Object.entries(headers)) {\n\t\tif (value) {\n\t\t\tconst stringValue = Array.isArray(value) ? value[0] : value;\n\t\t\tif (stringValue) {\n\t\t\t\tnormalizedHeaders[key.toLowerCase()] = stringValue;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn propagation.extract(context.active(), normalizedHeaders);\n}\n\n/**\n * Inject trace context into HTTP headers\n */\nexport function injectTraceContext(\n\theaders: Record<string, string>,\n\tctx?: Context,\n): Record<string, string> {\n\tconst result = { ...headers };\n\tpropagation.inject(ctx ?? context.active(), result);\n\treturn result;\n}\n\n/**\n * Create an HTTP server span for an incoming request\n */\nexport function createHttpServerSpan(\n\tattrs: HttpSpanAttributes,\n\tparentContext?: Context,\n): Span {\n\tconst tracer = getConstructsTracer();\n\tconst spanName = attrs.route\n\t\t? `${attrs.method} ${attrs.route}`\n\t\t: `${attrs.method} ${attrs.path || '/'}`;\n\n\tconst ctx = parentContext ?? context.active();\n\n\treturn tracer.startSpan(\n\t\tspanName,\n\t\t{\n\t\t\tkind: SpanKind.SERVER,\n\t\t\tattributes: toOtelAttributes(attrs),\n\t\t},\n\t\tctx,\n\t);\n}\n\n/**\n * End an HTTP span with response data\n */\nexport function endHttpSpan(\n\tspan: Span,\n\tresponse: HttpResponseAttributes,\n\terror?: Error,\n): void {\n\tspan.setAttribute('http.response.status_code', response.statusCode);\n\n\tif (response.responseSize) {\n\t\tspan.setAttribute('http.response.body.size', response.responseSize);\n\t}\n\n\tif (error) {\n\t\tspan.recordException(error);\n\t\tspan.setStatus({\n\t\t\tcode: SpanStatusCode.ERROR,\n\t\t\tmessage: error.message,\n\t\t});\n\t} else if (response.statusCode >= 400) {\n\t\tspan.setStatus({\n\t\t\tcode: SpanStatusCode.ERROR,\n\t\t\tmessage: `HTTP ${response.statusCode}`,\n\t\t});\n\t} else {\n\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t}\n\n\tspan.end();\n}\n\n/**\n * Execute a function within an HTTP server span context\n *\n * @example\n * ```typescript\n * const result = await withHttpSpan(\n * { method: 'GET', path: '/users', route: '/users' },\n * async (span) => {\n * const users = await getUsers();\n * return { statusCode: 200, body: users };\n * }\n * );\n * ```\n */\nexport async function withHttpSpan<T>(\n\tattrs: HttpSpanAttributes,\n\tfn: (span: Span) => Promise<T & { statusCode?: number }>,\n\tparentContext?: Context,\n): Promise<T> {\n\tconst span = createHttpServerSpan(attrs, parentContext);\n\n\ttry {\n\t\tconst result = await context.with(\n\t\t\ttrace.setSpan(parentContext ?? context.active(), span),\n\t\t\t() => fn(span),\n\t\t);\n\n\t\tconst statusCode = (result as { statusCode?: number }).statusCode ?? 200;\n\t\tendHttpSpan(span, { statusCode });\n\n\t\treturn result;\n\t} catch (error) {\n\t\tendHttpSpan(\n\t\t\tspan,\n\t\t\t{ statusCode: 500 },\n\t\t\terror instanceof Error ? error : new Error(String(error)),\n\t\t);\n\t\tthrow error;\n\t}\n}\n\n/**\n * Create a child span for internal operations (middleware, handlers, etc.)\n */\nexport function createChildSpan(name: string, attributes?: Attributes): Span {\n\tconst tracer = getConstructsTracer();\n\treturn tracer.startSpan(name, {\n\t\tkind: SpanKind.INTERNAL,\n\t\tattributes,\n\t});\n}\n\n/**\n * Execute a function within a child span\n */\nexport async function withChildSpan<T>(\n\tname: string,\n\tfn: (span: Span) => Promise<T>,\n\tattributes?: Attributes,\n): Promise<T> {\n\tconst span = createChildSpan(name, attributes);\n\n\ttry {\n\t\tconst result = await context.with(\n\t\t\ttrace.setSpan(context.active(), span),\n\t\t\t() => fn(span),\n\t\t);\n\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\treturn result;\n\t} catch (error) {\n\t\tspan.setStatus({\n\t\t\tcode: SpanStatusCode.ERROR,\n\t\t\tmessage: error instanceof Error ? error.message : 'Unknown error',\n\t\t});\n\t\tspan.recordException(\n\t\t\terror instanceof Error ? error : new Error(String(error)),\n\t\t);\n\t\tthrow error;\n\t} finally {\n\t\tspan.end();\n\t}\n}\n\n/**\n * Check if tracing is enabled (OpenTelemetry API is available and configured)\n */\nexport function isTracingEnabled(): boolean {\n\ttry {\n\t\tconst tracer = trace.getTracer(TRACER_NAME);\n\t\t// Check if we have a real tracer (not a no-op)\n\t\tconst span = tracer.startSpan('test');\n\t\tconst isReal =\n\t\t\tspan.spanContext().traceId !== '00000000000000000000000000000000';\n\t\tspan.end();\n\t\treturn isReal;\n\t} catch {\n\t\treturn false;\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
require('../http-
|
|
2
|
-
const require_hono = require('../hono-
|
|
1
|
+
require('../http-D_Z8sYXZ.cjs');
|
|
2
|
+
const require_hono = require('../hono-C4EgpbKQ.cjs');
|
|
3
3
|
|
|
4
4
|
exports.getSpanFromContext = require_hono.getSpanFromContext;
|
|
5
5
|
exports.getTraceContextFromHono = require_hono.getTraceContextFromHono;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "../http-
|
|
2
|
-
import { getSpanFromContext, getTraceContextFromHono, honoTelemetryMiddleware, withHonoSpanContext } from "../hono-
|
|
1
|
+
import "../http-DQzgLczm.mjs";
|
|
2
|
+
import { getSpanFromContext, getTraceContextFromHono, honoTelemetryMiddleware, withHonoSpanContext } from "../hono-DxhvnVbF.mjs";
|
|
3
3
|
|
|
4
4
|
export { getSpanFromContext, getTraceContextFromHono, honoTelemetryMiddleware, withHonoSpanContext };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { EndpointAttributes, HttpRequestAttributes, HttpResponseAttributes, HttpSpanAttributes, UserAttributes, createChildSpan, createHttpServerSpan, endHttpSpan, extractTraceContext, getConstructsTracer, injectTraceContext, isTracingEnabled, toOtelAttributes, withChildSpan, withHttpSpan } from "../http-
|
|
1
|
+
import { EndpointAttributes, HttpRequestAttributes, HttpResponseAttributes, HttpSpanAttributes, UserAttributes, createChildSpan, createHttpServerSpan, endHttpSpan, extractTraceContext, getConstructsTracer, injectTraceContext, isTracingEnabled, toOtelAttributes, withChildSpan, withHttpSpan } from "../http-D5kn3_Mt.mjs";
|
|
2
2
|
export { EndpointAttributes, HttpRequestAttributes, HttpResponseAttributes, HttpSpanAttributes, UserAttributes, createChildSpan, createHttpServerSpan, endHttpSpan, extractTraceContext, getConstructsTracer, injectTraceContext, isTracingEnabled, toOtelAttributes, withChildSpan, withHttpSpan };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { createChildSpan, createHttpServerSpan, endHttpSpan, extractTraceContext, getConstructsTracer, injectTraceContext, isTracingEnabled, toOtelAttributes, withChildSpan, withHttpSpan } from "../http-
|
|
1
|
+
import { createChildSpan, createHttpServerSpan, endHttpSpan, extractTraceContext, getConstructsTracer, injectTraceContext, isTracingEnabled, toOtelAttributes, withChildSpan, withHttpSpan } from "../http-DQzgLczm.mjs";
|
|
2
2
|
|
|
3
3
|
export { createChildSpan, createHttpServerSpan, endHttpSpan, extractTraceContext, getConstructsTracer, injectTraceContext, isTracingEnabled, toOtelAttributes, withChildSpan, withHttpSpan };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
const require_core = require('../core-CtVHRJGv.cjs');
|
|
2
2
|
const require_tracing = require('../tracing-Bt1zWRlb.cjs');
|
|
3
|
-
const require_http = require('../http-
|
|
4
|
-
const require_hono = require('../hono-
|
|
5
|
-
const require_middleware = require('../middleware-
|
|
6
|
-
const require_otel = require('../otel-
|
|
7
|
-
const require_setup = require('../setup-
|
|
3
|
+
const require_http = require('../http-D_Z8sYXZ.cjs');
|
|
4
|
+
const require_hono = require('../hono-C4EgpbKQ.cjs');
|
|
5
|
+
const require_middleware = require('../middleware-B2jFUukM.cjs');
|
|
6
|
+
const require_otel = require('../otel-C1HqHA2O.cjs');
|
|
7
|
+
const require_setup = require('../setup-CYpff5B9.cjs');
|
|
8
8
|
|
|
9
9
|
exports.NoopSpanProcessor = require_core.NoopSpanProcessor;
|
|
10
10
|
exports.OTelTelemetry = require_otel.OTelTelemetry;
|
|
@@ -2,7 +2,7 @@ import { SpanProcessorOptions, SpanProcessorStrategy } from "../types-BzQ78Efw.m
|
|
|
2
2
|
import { NoopSpanProcessor, createSpanProcessor, enableTelemetryDebug, flushTelemetry, getRecommendedStrategy, isTelemetryInitialized, setGlobalLogProcessor, setGlobalSpanProcessor, withTelemetryFlush } from "../core--quSp5Qr.mjs";
|
|
3
3
|
import { addSpanEvent, createSpan, getActiveSpan, getSpanId, getTraceId, recordException, setSpanAttributes, withSpan, withSpanSync } from "../tracing-PnECEbEu.mjs";
|
|
4
4
|
import { HonoTelemetryMiddlewareOptions, getSpanFromContext, getTraceContextFromHono, honoTelemetryMiddleware, withHonoSpanContext } from "../hono--uKQ7Jgi.mjs";
|
|
5
|
-
import { EndpointAttributes, HttpRequestAttributes, HttpResponseAttributes, HttpSpanAttributes, UserAttributes, createChildSpan, createHttpServerSpan, endHttpSpan, extractTraceContext, getConstructsTracer, injectTraceContext, isTracingEnabled, toOtelAttributes, withChildSpan, withHttpSpan } from "../http-
|
|
5
|
+
import { EndpointAttributes, HttpRequestAttributes, HttpResponseAttributes, HttpSpanAttributes, UserAttributes, createChildSpan, createHttpServerSpan, endHttpSpan, extractTraceContext, getConstructsTracer, injectTraceContext, isTracingEnabled, toOtelAttributes, withChildSpan, withHttpSpan } from "../http-D5kn3_Mt.mjs";
|
|
6
6
|
import { TelemetryMiddlewareOptions, getContextFromEvent, getSpanFromEvent, telemetryMiddleware, withEventContext } from "../middleware-DAceVpfw.mjs";
|
|
7
7
|
import { OTelTelemetry, OTelTelemetryOptions } from "../otel-1bJPb2Z7.mjs";
|
|
8
8
|
import { TelemetryOptions, setupTelemetry, shutdownTelemetry } from "../setup-Bkxm4g6b.mjs";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { NoopSpanProcessor, createSpanProcessor, enableTelemetryDebug, flushTelemetry, getRecommendedStrategy, isTelemetryInitialized, setGlobalLogProcessor, setGlobalSpanProcessor, withTelemetryFlush } from "../core-D6hJ6exL.mjs";
|
|
2
2
|
import { addSpanEvent, createSpan, getActiveSpan, getSpanId, getTraceId, recordException, setSpanAttributes, withSpan, withSpanSync } from "../tracing-Cijm_5NI.mjs";
|
|
3
|
-
import { createChildSpan, createHttpServerSpan, endHttpSpan, extractTraceContext, getConstructsTracer, injectTraceContext, isTracingEnabled, toOtelAttributes, withChildSpan, withHttpSpan } from "../http-
|
|
4
|
-
import { getSpanFromContext, getTraceContextFromHono, honoTelemetryMiddleware, withHonoSpanContext } from "../hono-
|
|
5
|
-
import { getContextFromEvent, getSpanFromEvent, telemetryMiddleware, withEventContext } from "../middleware-
|
|
6
|
-
import { OTelTelemetry } from "../otel-
|
|
7
|
-
import { setupTelemetry, shutdownTelemetry } from "../setup-
|
|
3
|
+
import { createChildSpan, createHttpServerSpan, endHttpSpan, extractTraceContext, getConstructsTracer, injectTraceContext, isTracingEnabled, toOtelAttributes, withChildSpan, withHttpSpan } from "../http-DQzgLczm.mjs";
|
|
4
|
+
import { getSpanFromContext, getTraceContextFromHono, honoTelemetryMiddleware, withHonoSpanContext } from "../hono-DxhvnVbF.mjs";
|
|
5
|
+
import { getContextFromEvent, getSpanFromEvent, telemetryMiddleware, withEventContext } from "../middleware-BTDncHwm.mjs";
|
|
6
|
+
import { OTelTelemetry } from "../otel-wulj5B-X.mjs";
|
|
7
|
+
import { setupTelemetry, shutdownTelemetry } from "../setup-B9jM77Qk.mjs";
|
|
8
8
|
|
|
9
9
|
export { NoopSpanProcessor, OTelTelemetry, addSpanEvent, createChildSpan, createHttpServerSpan, createSpan, createSpanProcessor, enableTelemetryDebug, endHttpSpan, extractTraceContext, flushTelemetry, getActiveSpan, getConstructsTracer, getContextFromEvent, getRecommendedStrategy, getSpanFromContext, getSpanFromEvent, getSpanId, getTraceContextFromHono, getTraceId, honoTelemetryMiddleware, injectTraceContext, isTelemetryInitialized, isTracingEnabled, recordException, setGlobalLogProcessor, setGlobalSpanProcessor, setSpanAttributes, setupTelemetry, shutdownTelemetry, telemetryMiddleware, toOtelAttributes, withChildSpan, withEventContext, withHonoSpanContext, withHttpSpan, withSpan, withSpanSync, withTelemetryFlush };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
require('../http-
|
|
2
|
-
const require_middleware = require('../middleware-
|
|
1
|
+
require('../http-D_Z8sYXZ.cjs');
|
|
2
|
+
const require_middleware = require('../middleware-B2jFUukM.cjs');
|
|
3
3
|
|
|
4
4
|
exports.getContextFromEvent = require_middleware.getContextFromEvent;
|
|
5
5
|
exports.getSpanFromEvent = require_middleware.getSpanFromEvent;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "../http-
|
|
2
|
-
import { getContextFromEvent, getSpanFromEvent, telemetryMiddleware, withEventContext } from "../middleware-
|
|
1
|
+
import "../http-DQzgLczm.mjs";
|
|
2
|
+
import { getContextFromEvent, getSpanFromEvent, telemetryMiddleware, withEventContext } from "../middleware-BTDncHwm.mjs";
|
|
3
3
|
|
|
4
4
|
export { getContextFromEvent, getSpanFromEvent, telemetryMiddleware, withEventContext };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
require('../core-CtVHRJGv.cjs');
|
|
2
|
-
const require_setup = require('../setup-
|
|
2
|
+
const require_setup = require('../setup-CYpff5B9.cjs');
|
|
3
3
|
|
|
4
4
|
exports.setupTelemetry = require_setup.setupTelemetry;
|
|
5
5
|
exports.shutdownTelemetry = require_setup.shutdownTelemetry;
|
package/dist/logger/pino.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "../types-l7Rlb5Mg.cjs";
|
|
2
2
|
import "../MetricsAggregator-4SqelGcG.cjs";
|
|
3
3
|
import { Telescope } from "../Telescope-D4nmwDRA.cjs";
|
|
4
|
-
import * as
|
|
4
|
+
import * as stream1 from "stream";
|
|
5
5
|
import build from "pino-abstract-transport";
|
|
6
6
|
|
|
7
7
|
//#region src/logger/pino.d.ts
|
|
@@ -62,7 +62,7 @@ interface TelescopePinoTransportOptions {
|
|
|
62
62
|
* logger.info({ userId: '123' }, 'User logged in');
|
|
63
63
|
* ```
|
|
64
64
|
*/
|
|
65
|
-
declare function createPinoTransport(options: TelescopePinoTransportOptions):
|
|
65
|
+
declare function createPinoTransport(options: TelescopePinoTransportOptions): stream1.Transform & build.OnUnknown;
|
|
66
66
|
/**
|
|
67
67
|
* Create a Pino destination that sends logs to Telescope.
|
|
68
68
|
* Alias for createPinoTransport for API compatibility.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_chunk = require('./chunk-CUT6urMc.cjs');
|
|
2
|
-
const require_http = require('./http-
|
|
2
|
+
const require_http = require('./http-D_Z8sYXZ.cjs');
|
|
3
3
|
const __opentelemetry_api = require_chunk.__toESM(require("@opentelemetry/api"));
|
|
4
4
|
|
|
5
5
|
//#region src/instrumentation/middleware.ts
|
|
@@ -181,4 +181,4 @@ Object.defineProperty(exports, 'withEventContext', {
|
|
|
181
181
|
return withEventContext;
|
|
182
182
|
}
|
|
183
183
|
});
|
|
184
|
-
//# sourceMappingURL=middleware-
|
|
184
|
+
//# sourceMappingURL=middleware-B2jFUukM.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware-DqPQpcup.cjs","names":["event: any","options: TelemetryMiddlewareOptions","lambdaContext: LambdaContext","route: string | undefined","host: string | undefined","scheme: 'http' | 'https' | undefined","userAgent: string | undefined","clientIp: string | undefined","requestId: string | undefined","attrs: HttpSpanAttributes","headers: Record<string, string | string[] | undefined>","normalized: Record<string, string | string[] | undefined>","fn: () => Promise<T>"],"sources":["../src/instrumentation/middleware.ts"],"sourcesContent":["/**\n * OpenTelemetry instrumentation middleware for @geekmidas/constructs\n *\n * This middleware automatically creates spans for HTTP requests,\n * extracts trace context from incoming headers, and records\n * request/response metadata as span attributes.\n */\nimport type { MiddlewareObj } from '@middy/core';\nimport { context, type Span, trace } from '@opentelemetry/api';\nimport type { Context as LambdaContext } from 'aws-lambda';\nimport {\n\tcreateHttpServerSpan,\n\tendHttpSpan,\n\textractTraceContext,\n\ttype HttpSpanAttributes,\n} from './http';\n\n/**\n * Options for the telemetry middleware\n */\nexport interface TelemetryMiddlewareOptions {\n\t/**\n\t * Whether to record request body as span attribute\n\t * @default false\n\t */\n\trecordBody?: boolean;\n\n\t/**\n\t * Whether to record response body as span attribute\n\t * @default false\n\t */\n\trecordResponseBody?: boolean;\n\n\t/**\n\t * Custom function to extract endpoint name from event\n\t */\n\tgetEndpointName?: (event: any) => string | undefined;\n\n\t/**\n\t * Custom function to extract operation ID from event\n\t */\n\tgetOperationId?: (event: any) => string | undefined;\n\n\t/**\n\t * Custom function to extract user ID from event\n\t */\n\tgetUserId?: (event: any) => string | undefined;\n\n\t/**\n\t * Whether to skip tracing for this request\n\t */\n\tshouldSkip?: (event: any) => boolean;\n}\n\n// Symbol for storing span on event\nconst SPAN_SYMBOL = Symbol('telemetry.span');\nconst CONTEXT_SYMBOL = Symbol('telemetry.context');\n\n/**\n * Get the current span from the Lambda event\n */\nexport function getSpanFromEvent(event: any): Span | undefined {\n\treturn event?.[SPAN_SYMBOL];\n}\n\n/**\n * Get the current trace context from the Lambda event\n */\nexport function getContextFromEvent(event: any): any {\n\treturn event?.[CONTEXT_SYMBOL];\n}\n\n/**\n * Create a telemetry middleware for Lambda handlers\n *\n * @example\n * ```typescript\n * import { telemetryMiddleware } from '@geekmidas/telescope/instrumentation';\n *\n * const adaptor = new AmazonApiGatewayV2Endpoint(envParser, endpoint, {\n * telemetry: { middleware: telemetryMiddleware() },\n * });\n * ```\n */\nexport function telemetryMiddleware(\n\toptions: TelemetryMiddlewareOptions = {},\n): MiddlewareObj<any, any, Error, LambdaContext> {\n\treturn {\n\t\tbefore: async (request) => {\n\t\t\t// Skip if custom skip function returns true\n\t\t\tif (options.shouldSkip?.(request.event)) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst event = request.event;\n\t\t\tconst lambdaContext = request.context;\n\n\t\t\t// Extract trace context from headers\n\t\t\tconst headers = normalizeHeaders(event.headers || {});\n\t\t\tconst parentContext = extractTraceContext(headers);\n\n\t\t\t// Build span attributes from event\n\t\t\tconst attrs = buildSpanAttributes(event, lambdaContext, options);\n\n\t\t\t// Create the span\n\t\t\tconst span = createHttpServerSpan(attrs, parentContext);\n\n\t\t\t// Store span and context on event for access in handler\n\t\t\tevent[SPAN_SYMBOL] = span;\n\t\t\tevent[CONTEXT_SYMBOL] = trace.setSpan(parentContext, span);\n\n\t\t\t// Add Lambda-specific attributes\n\t\t\tspan.setAttribute('faas.invocation_id', lambdaContext.awsRequestId);\n\t\t\tspan.setAttribute('faas.name', lambdaContext.functionName);\n\n\t\t\tif (options.recordBody && event.body) {\n\t\t\t\tconst bodyStr =\n\t\t\t\t\ttypeof event.body === 'string'\n\t\t\t\t\t\t? event.body\n\t\t\t\t\t\t: JSON.stringify(event.body);\n\t\t\t\t// Truncate large bodies\n\t\t\t\tspan.setAttribute(\n\t\t\t\t\t'http.request.body',\n\t\t\t\t\tbodyStr.length > 4096 ? `${bodyStr.slice(0, 4096)}...` : bodyStr,\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\n\t\tafter: async (request) => {\n\t\t\tconst span = getSpanFromEvent(request.event);\n\t\t\tif (!span) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst response = request.response;\n\t\t\tconst statusCode =\n\t\t\t\ttypeof response?.statusCode === 'number' ? response.statusCode : 200;\n\n\t\t\tif (options.recordResponseBody && response?.body) {\n\t\t\t\tconst bodyStr =\n\t\t\t\t\ttypeof response.body === 'string'\n\t\t\t\t\t\t? response.body\n\t\t\t\t\t\t: JSON.stringify(response.body);\n\t\t\t\tspan.setAttribute(\n\t\t\t\t\t'http.response.body',\n\t\t\t\t\tbodyStr.length > 4096 ? `${bodyStr.slice(0, 4096)}...` : bodyStr,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tendHttpSpan(span, { statusCode });\n\t\t},\n\n\t\tonError: async (request) => {\n\t\t\tconst span = getSpanFromEvent(request.event);\n\t\t\tif (!span) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst error = request.error;\n\t\t\tconst response = request.response;\n\n\t\t\t// Determine status code from response or error\n\t\t\tlet statusCode = 500;\n\t\t\tif (response?.statusCode) {\n\t\t\t\tstatusCode = response.statusCode;\n\t\t\t} else if (error && 'statusCode' in error) {\n\t\t\t\tstatusCode = (error as any).statusCode;\n\t\t\t}\n\n\t\t\tendHttpSpan(\n\t\t\t\tspan,\n\t\t\t\t{ statusCode },\n\t\t\t\terror instanceof Error ? error : new Error(String(error)),\n\t\t\t);\n\t\t},\n\t};\n}\n\n/**\n * Build span attributes from Lambda event\n */\nfunction buildSpanAttributes(\n\tevent: any,\n\tlambdaContext: LambdaContext,\n\toptions: TelemetryMiddlewareOptions,\n): HttpSpanAttributes {\n\t// Detect event type (API Gateway v1, v2, ALB, or direct invoke)\n\tconst isV2 =\n\t\t'requestContext' in event && 'http' in (event.requestContext || {});\n\tconst isV1 =\n\t\t'requestContext' in event &&\n\t\t'httpMethod' in event &&\n\t\t!('http' in (event.requestContext || {}));\n\n\tlet method = 'INVOKE';\n\tlet path = '/';\n\tlet route: string | undefined;\n\tlet host: string | undefined;\n\tlet scheme: 'http' | 'https' | undefined;\n\tlet userAgent: string | undefined;\n\tlet clientIp: string | undefined;\n\tlet requestId: string | undefined;\n\n\tif (isV2) {\n\t\t// API Gateway v2 (HTTP API)\n\t\tconst http = event.requestContext.http;\n\t\tmethod = http.method;\n\t\tpath = event.rawPath || http.path;\n\t\troute = event.routeKey?.replace(/^[A-Z]+\\s+/, ''); // Remove HTTP method prefix\n\t\thost = event.headers?.host;\n\t\tscheme = 'https';\n\t\tuserAgent = http.userAgent;\n\t\tclientIp = http.sourceIp;\n\t\trequestId = event.requestContext.requestId;\n\t} else if (isV1) {\n\t\t// API Gateway v1 (REST API)\n\t\tmethod = event.httpMethod;\n\t\tpath = event.path;\n\t\troute = event.resource;\n\t\thost = event.headers?.Host || event.headers?.host;\n\t\tscheme = 'https';\n\t\tuserAgent = event.headers?.['User-Agent'] || event.headers?.['user-agent'];\n\t\tclientIp = event.requestContext?.identity?.sourceIp;\n\t\trequestId = event.requestContext?.requestId;\n\t} else if ('httpMethod' in event) {\n\t\t// ALB event\n\t\tmethod = event.httpMethod;\n\t\tpath = event.path;\n\t\thost = event.headers?.host;\n\t\tuserAgent = event.headers?.['user-agent'] || event.headers?.['User-Agent'];\n\t\tclientIp = event.headers?.['x-forwarded-for']?.split(',')[0]?.trim();\n\t}\n\n\tconst attrs: HttpSpanAttributes = {\n\t\tmethod,\n\t\tpath,\n\t\troute,\n\t\thost,\n\t\tscheme,\n\t\tuserAgent,\n\t\tclientIp,\n\t\trequestId: requestId || lambdaContext.awsRequestId,\n\t};\n\n\t// Add endpoint metadata if extractors provided\n\tif (options.getEndpointName || options.getOperationId) {\n\t\tattrs.endpoint = {\n\t\t\tname: options.getEndpointName?.(event),\n\t\t\toperationId: options.getOperationId?.(event),\n\t\t};\n\t}\n\n\t// Add user metadata if extractor provided\n\tif (options.getUserId) {\n\t\tconst userId = options.getUserId(event);\n\t\tif (userId) {\n\t\t\tattrs.user = { userId };\n\t\t}\n\t}\n\n\treturn attrs;\n}\n\n/**\n * Normalize headers to lowercase keys\n */\nfunction normalizeHeaders(\n\theaders: Record<string, string | string[] | undefined>,\n): Record<string, string | string[] | undefined> {\n\tconst normalized: Record<string, string | string[] | undefined> = {};\n\tfor (const [key, value] of Object.entries(headers)) {\n\t\tnormalized[key.toLowerCase()] = value;\n\t}\n\treturn normalized;\n}\n\n/**\n * Run a function within the span context from a Lambda event\n *\n * @example\n * ```typescript\n * await withEventContext(event, async () => {\n * // Any spans created here will be children of the request span\n * await doSomething();\n * });\n * ```\n */\nexport async function withEventContext<T>(\n\tevent: any,\n\tfn: () => Promise<T>,\n): Promise<T> {\n\tconst ctx = getContextFromEvent(event);\n\tif (!ctx) {\n\t\treturn fn();\n\t}\n\treturn context.with(ctx, fn);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"middleware-B2jFUukM.cjs","names":["event: any","options: TelemetryMiddlewareOptions","lambdaContext: LambdaContext","route: string | undefined","host: string | undefined","scheme: 'http' | 'https' | undefined","userAgent: string | undefined","clientIp: string | undefined","requestId: string | undefined","attrs: HttpSpanAttributes","headers: Record<string, string | string[] | undefined>","normalized: Record<string, string | string[] | undefined>","fn: () => Promise<T>"],"sources":["../src/instrumentation/middleware.ts"],"sourcesContent":["/**\n * OpenTelemetry instrumentation middleware for @geekmidas/constructs\n *\n * This middleware automatically creates spans for HTTP requests,\n * extracts trace context from incoming headers, and records\n * request/response metadata as span attributes.\n */\nimport type { MiddlewareObj } from '@middy/core';\nimport { context, type Span, trace } from '@opentelemetry/api';\nimport type { Context as LambdaContext } from 'aws-lambda';\nimport {\n\tcreateHttpServerSpan,\n\tendHttpSpan,\n\textractTraceContext,\n\ttype HttpSpanAttributes,\n} from './http';\n\n/**\n * Options for the telemetry middleware\n */\nexport interface TelemetryMiddlewareOptions {\n\t/**\n\t * Whether to record request body as span attribute\n\t * @default false\n\t */\n\trecordBody?: boolean;\n\n\t/**\n\t * Whether to record response body as span attribute\n\t * @default false\n\t */\n\trecordResponseBody?: boolean;\n\n\t/**\n\t * Custom function to extract endpoint name from event\n\t */\n\tgetEndpointName?: (event: any) => string | undefined;\n\n\t/**\n\t * Custom function to extract operation ID from event\n\t */\n\tgetOperationId?: (event: any) => string | undefined;\n\n\t/**\n\t * Custom function to extract user ID from event\n\t */\n\tgetUserId?: (event: any) => string | undefined;\n\n\t/**\n\t * Whether to skip tracing for this request\n\t */\n\tshouldSkip?: (event: any) => boolean;\n}\n\n// Symbol for storing span on event\nconst SPAN_SYMBOL = Symbol('telemetry.span');\nconst CONTEXT_SYMBOL = Symbol('telemetry.context');\n\n/**\n * Get the current span from the Lambda event\n */\nexport function getSpanFromEvent(event: any): Span | undefined {\n\treturn event?.[SPAN_SYMBOL];\n}\n\n/**\n * Get the current trace context from the Lambda event\n */\nexport function getContextFromEvent(event: any): any {\n\treturn event?.[CONTEXT_SYMBOL];\n}\n\n/**\n * Create a telemetry middleware for Lambda handlers\n *\n * @example\n * ```typescript\n * import { telemetryMiddleware } from '@geekmidas/telescope/instrumentation';\n *\n * const adaptor = new AmazonApiGatewayV2Endpoint(envParser, endpoint, {\n * telemetry: { middleware: telemetryMiddleware() },\n * });\n * ```\n */\nexport function telemetryMiddleware(\n\toptions: TelemetryMiddlewareOptions = {},\n): MiddlewareObj<any, any, Error, LambdaContext> {\n\treturn {\n\t\tbefore: async (request) => {\n\t\t\t// Skip if custom skip function returns true\n\t\t\tif (options.shouldSkip?.(request.event)) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst event = request.event;\n\t\t\tconst lambdaContext = request.context;\n\n\t\t\t// Extract trace context from headers\n\t\t\tconst headers = normalizeHeaders(event.headers || {});\n\t\t\tconst parentContext = extractTraceContext(headers);\n\n\t\t\t// Build span attributes from event\n\t\t\tconst attrs = buildSpanAttributes(event, lambdaContext, options);\n\n\t\t\t// Create the span\n\t\t\tconst span = createHttpServerSpan(attrs, parentContext);\n\n\t\t\t// Store span and context on event for access in handler\n\t\t\tevent[SPAN_SYMBOL] = span;\n\t\t\tevent[CONTEXT_SYMBOL] = trace.setSpan(parentContext, span);\n\n\t\t\t// Add Lambda-specific attributes\n\t\t\tspan.setAttribute('faas.invocation_id', lambdaContext.awsRequestId);\n\t\t\tspan.setAttribute('faas.name', lambdaContext.functionName);\n\n\t\t\tif (options.recordBody && event.body) {\n\t\t\t\tconst bodyStr =\n\t\t\t\t\ttypeof event.body === 'string'\n\t\t\t\t\t\t? event.body\n\t\t\t\t\t\t: JSON.stringify(event.body);\n\t\t\t\t// Truncate large bodies\n\t\t\t\tspan.setAttribute(\n\t\t\t\t\t'http.request.body',\n\t\t\t\t\tbodyStr.length > 4096 ? `${bodyStr.slice(0, 4096)}...` : bodyStr,\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\n\t\tafter: async (request) => {\n\t\t\tconst span = getSpanFromEvent(request.event);\n\t\t\tif (!span) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst response = request.response;\n\t\t\tconst statusCode =\n\t\t\t\ttypeof response?.statusCode === 'number' ? response.statusCode : 200;\n\n\t\t\tif (options.recordResponseBody && response?.body) {\n\t\t\t\tconst bodyStr =\n\t\t\t\t\ttypeof response.body === 'string'\n\t\t\t\t\t\t? response.body\n\t\t\t\t\t\t: JSON.stringify(response.body);\n\t\t\t\tspan.setAttribute(\n\t\t\t\t\t'http.response.body',\n\t\t\t\t\tbodyStr.length > 4096 ? `${bodyStr.slice(0, 4096)}...` : bodyStr,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tendHttpSpan(span, { statusCode });\n\t\t},\n\n\t\tonError: async (request) => {\n\t\t\tconst span = getSpanFromEvent(request.event);\n\t\t\tif (!span) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst error = request.error;\n\t\t\tconst response = request.response;\n\n\t\t\t// Determine status code from response or error\n\t\t\tlet statusCode = 500;\n\t\t\tif (response?.statusCode) {\n\t\t\t\tstatusCode = response.statusCode;\n\t\t\t} else if (error && 'statusCode' in error) {\n\t\t\t\tstatusCode = (error as any).statusCode;\n\t\t\t}\n\n\t\t\tendHttpSpan(\n\t\t\t\tspan,\n\t\t\t\t{ statusCode },\n\t\t\t\terror instanceof Error ? error : new Error(String(error)),\n\t\t\t);\n\t\t},\n\t};\n}\n\n/**\n * Build span attributes from Lambda event\n */\nfunction buildSpanAttributes(\n\tevent: any,\n\tlambdaContext: LambdaContext,\n\toptions: TelemetryMiddlewareOptions,\n): HttpSpanAttributes {\n\t// Detect event type (API Gateway v1, v2, ALB, or direct invoke)\n\tconst isV2 =\n\t\t'requestContext' in event && 'http' in (event.requestContext || {});\n\tconst isV1 =\n\t\t'requestContext' in event &&\n\t\t'httpMethod' in event &&\n\t\t!('http' in (event.requestContext || {}));\n\n\tlet method = 'INVOKE';\n\tlet path = '/';\n\tlet route: string | undefined;\n\tlet host: string | undefined;\n\tlet scheme: 'http' | 'https' | undefined;\n\tlet userAgent: string | undefined;\n\tlet clientIp: string | undefined;\n\tlet requestId: string | undefined;\n\n\tif (isV2) {\n\t\t// API Gateway v2 (HTTP API)\n\t\tconst http = event.requestContext.http;\n\t\tmethod = http.method;\n\t\tpath = event.rawPath || http.path;\n\t\troute = event.routeKey?.replace(/^[A-Z]+\\s+/, ''); // Remove HTTP method prefix\n\t\thost = event.headers?.host;\n\t\tscheme = 'https';\n\t\tuserAgent = http.userAgent;\n\t\tclientIp = http.sourceIp;\n\t\trequestId = event.requestContext.requestId;\n\t} else if (isV1) {\n\t\t// API Gateway v1 (REST API)\n\t\tmethod = event.httpMethod;\n\t\tpath = event.path;\n\t\troute = event.resource;\n\t\thost = event.headers?.Host || event.headers?.host;\n\t\tscheme = 'https';\n\t\tuserAgent = event.headers?.['User-Agent'] || event.headers?.['user-agent'];\n\t\tclientIp = event.requestContext?.identity?.sourceIp;\n\t\trequestId = event.requestContext?.requestId;\n\t} else if ('httpMethod' in event) {\n\t\t// ALB event\n\t\tmethod = event.httpMethod;\n\t\tpath = event.path;\n\t\thost = event.headers?.host;\n\t\tuserAgent = event.headers?.['user-agent'] || event.headers?.['User-Agent'];\n\t\tclientIp = event.headers?.['x-forwarded-for']?.split(',')[0]?.trim();\n\t}\n\n\tconst attrs: HttpSpanAttributes = {\n\t\tmethod,\n\t\tpath,\n\t\troute,\n\t\thost,\n\t\tscheme,\n\t\tuserAgent,\n\t\tclientIp,\n\t\trequestId: requestId || lambdaContext.awsRequestId,\n\t};\n\n\t// Add endpoint metadata if extractors provided\n\tif (options.getEndpointName || options.getOperationId) {\n\t\tattrs.endpoint = {\n\t\t\tname: options.getEndpointName?.(event),\n\t\t\toperationId: options.getOperationId?.(event),\n\t\t};\n\t}\n\n\t// Add user metadata if extractor provided\n\tif (options.getUserId) {\n\t\tconst userId = options.getUserId(event);\n\t\tif (userId) {\n\t\t\tattrs.user = { userId };\n\t\t}\n\t}\n\n\treturn attrs;\n}\n\n/**\n * Normalize headers to lowercase keys\n */\nfunction normalizeHeaders(\n\theaders: Record<string, string | string[] | undefined>,\n): Record<string, string | string[] | undefined> {\n\tconst normalized: Record<string, string | string[] | undefined> = {};\n\tfor (const [key, value] of Object.entries(headers)) {\n\t\tnormalized[key.toLowerCase()] = value;\n\t}\n\treturn normalized;\n}\n\n/**\n * Run a function within the span context from a Lambda event\n *\n * @example\n * ```typescript\n * await withEventContext(event, async () => {\n * // Any spans created here will be children of the request span\n * await doSomething();\n * });\n * ```\n */\nexport async function withEventContext<T>(\n\tevent: any,\n\tfn: () => Promise<T>,\n): Promise<T> {\n\tconst ctx = getContextFromEvent(event);\n\tif (!ctx) {\n\t\treturn fn();\n\t}\n\treturn context.with(ctx, fn);\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createHttpServerSpan, endHttpSpan, extractTraceContext } from "./http-
|
|
1
|
+
import { createHttpServerSpan, endHttpSpan, extractTraceContext } from "./http-DQzgLczm.mjs";
|
|
2
2
|
import { context, trace } from "@opentelemetry/api";
|
|
3
3
|
|
|
4
4
|
//#region src/instrumentation/middleware.ts
|
|
@@ -157,4 +157,4 @@ async function withEventContext(event, fn) {
|
|
|
157
157
|
|
|
158
158
|
//#endregion
|
|
159
159
|
export { getContextFromEvent, getSpanFromEvent, telemetryMiddleware, withEventContext };
|
|
160
|
-
//# sourceMappingURL=middleware-
|
|
160
|
+
//# sourceMappingURL=middleware-BTDncHwm.mjs.map
|