@astroscope/opentelemetry 0.1.0 → 0.1.1

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.
@@ -1,155 +0,0 @@
1
- import {
2
- recordActionDuration,
3
- recordHttpRequestDuration,
4
- recordHttpRequestStart
5
- } from "./chunk-DPYEL3WF.js";
6
-
7
- // src/middleware.ts
8
- import {
9
- SpanKind,
10
- SpanStatusCode,
11
- context,
12
- propagation,
13
- trace
14
- } from "@opentelemetry/api";
15
- import { RPCType, setRPCMetadata } from "@opentelemetry/core";
16
- var LIB_NAME = "@astroscope/opentelemetry";
17
- var ACTIONS_PREFIX = "/_actions/";
18
- function matchesPattern(path, pattern) {
19
- if ("pattern" in pattern) {
20
- return pattern.pattern.test(path);
21
- }
22
- if ("prefix" in pattern) {
23
- return path.startsWith(pattern.prefix);
24
- }
25
- return path === pattern.exact;
26
- }
27
- function shouldExclude(ctx, exclude) {
28
- if (!exclude) return false;
29
- if (typeof exclude === "function") {
30
- return exclude(ctx);
31
- }
32
- const path = ctx.url.pathname;
33
- return exclude.some((pattern) => matchesPattern(path, pattern));
34
- }
35
- function getClientIp(request) {
36
- return request.headers.get("x-forwarded-for")?.split(",")[0].trim() ?? request.headers.get("x-real-ip") ?? request.headers.get("cf-connecting-ip") ?? // Cloudflare
37
- void 0;
38
- }
39
- function createOpenTelemetryMiddleware(options = {}) {
40
- const tracer = trace.getTracer(LIB_NAME);
41
- return async (ctx, next) => {
42
- if (shouldExclude(ctx, options.exclude)) {
43
- return next();
44
- }
45
- const { request, url } = ctx;
46
- const input = {
47
- traceparent: request.headers.get("traceparent"),
48
- tracestate: request.headers.get("tracestate")
49
- };
50
- const parentContext = propagation.extract(context.active(), input);
51
- const clientIp = getClientIp(request);
52
- const contentLength = request.headers.get("content-length");
53
- const spanOptions = {
54
- attributes: {
55
- "http.request.method": request.method,
56
- "url.full": request.url,
57
- "url.path": url.pathname,
58
- "url.query": url.search.slice(1),
59
- // Remove leading "?"
60
- "url.scheme": url.protocol.replace(":", ""),
61
- "server.address": url.hostname,
62
- "server.port": url.port ? parseInt(url.port) : url.protocol === "https:" ? 443 : 80,
63
- "user_agent.original": request.headers.get("user-agent") ?? "",
64
- ...contentLength && { "http.request.body.size": parseInt(contentLength) },
65
- ...clientIp && { "client.address": clientIp }
66
- },
67
- kind: SpanKind.SERVER
68
- };
69
- const isAction = url.pathname.startsWith(ACTIONS_PREFIX);
70
- const actionName = url.pathname.slice(ACTIONS_PREFIX.length).replace(/\/$/, "");
71
- const spanName = isAction ? `ACTION ${actionName}` : `${request.method} ${url.pathname}`;
72
- const span = tracer.startSpan(spanName, spanOptions, parentContext);
73
- const spanContext = trace.setSpan(parentContext, span);
74
- const rpcMetadata = { type: RPCType.HTTP, span };
75
- const metricsEnabled = options.metrics ?? false;
76
- const startTime = metricsEnabled ? performance.now() : 0;
77
- const endActiveRequest = metricsEnabled ? recordHttpRequestStart({ method: request.method, route: url.pathname }) : void 0;
78
- return context.with(
79
- setRPCMetadata(spanContext, rpcMetadata),
80
- async () => {
81
- const finalize = (status, responseSize) => {
82
- span.setAttribute("http.response.status_code", status);
83
- span.setAttribute("http.response.body.size", responseSize);
84
- if (status >= 400) {
85
- span.setStatus({
86
- code: SpanStatusCode.ERROR,
87
- message: `HTTP ${status}`
88
- });
89
- } else {
90
- span.setStatus({ code: SpanStatusCode.OK });
91
- }
92
- span.end();
93
- if (metricsEnabled) {
94
- endActiveRequest?.();
95
- const duration = performance.now() - startTime;
96
- recordHttpRequestDuration(
97
- { method: request.method, route: url.pathname, status },
98
- duration
99
- );
100
- if (isAction) {
101
- recordActionDuration({ name: actionName, status }, duration);
102
- }
103
- }
104
- };
105
- try {
106
- const response = await next();
107
- if (!response.body) {
108
- finalize(response.status, 0);
109
- return response;
110
- }
111
- const [measureStream, clientStream] = response.body.tee();
112
- let responseSize = 0;
113
- (async () => {
114
- const reader = measureStream.getReader();
115
- try {
116
- while (true) {
117
- const { done, value } = await reader.read();
118
- if (done) break;
119
- responseSize += value.length;
120
- }
121
- } finally {
122
- finalize(response.status, responseSize);
123
- }
124
- })();
125
- return new Response(clientStream, {
126
- status: response.status,
127
- headers: response.headers
128
- });
129
- } catch (e) {
130
- span.setStatus({
131
- code: SpanStatusCode.ERROR,
132
- message: e instanceof Error ? e.message : "Unknown error"
133
- });
134
- span.end();
135
- if (metricsEnabled) {
136
- endActiveRequest?.();
137
- const duration = performance.now() - startTime;
138
- recordHttpRequestDuration(
139
- { method: request.method, route: url.pathname, status: 500 },
140
- duration
141
- );
142
- if (isAction) {
143
- recordActionDuration({ name: actionName, status: 500 }, duration);
144
- }
145
- }
146
- throw e;
147
- }
148
- }
149
- );
150
- };
151
- }
152
-
153
- export {
154
- createOpenTelemetryMiddleware
155
- };
@@ -1,7 +0,0 @@
1
- import {
2
- instrumentFetch
3
- } from "./chunk-QIWOBUML.js";
4
- import "./chunk-UPNRPRAW.js";
5
- export {
6
- instrumentFetch
7
- };
@@ -1,6 +0,0 @@
1
- import {
2
- instrumentFetch
3
- } from "./chunk-QTSNLOSC.js";
4
- export {
5
- instrumentFetch
6
- };
@@ -1,6 +0,0 @@
1
- import {
2
- instrumentFetch
3
- } from "./chunk-FEC4ETRL.js";
4
- export {
5
- instrumentFetch
6
- };
@@ -1,7 +0,0 @@
1
- import {
2
- instrumentFetch
3
- } from "./chunk-BQFWPPEO.js";
4
- import "./chunk-DPYEL3WF.js";
5
- export {
6
- instrumentFetch
7
- };
@@ -1,7 +0,0 @@
1
- import {
2
- instrumentFetch
3
- } from "./chunk-CEPTXEJV.js";
4
- import "./chunk-DPYEL3WF.js";
5
- export {
6
- instrumentFetch
7
- };