@0xchain/telemetry 1.1.0-beta.6 → 1.1.0-beta.8

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/README.md CHANGED
@@ -1,11 +1,137 @@
1
1
  # telemetry
2
2
 
3
- This library was generated with [Nx](https://nx.dev).
3
+ 面向 Next.js 16 App Router 的链路追踪方案,提供巡检识别、请求过滤与多维采样能力,基于 OpenTelemetry 输出。
4
4
 
5
- ## Building
5
+ ## 快速开始
6
6
 
7
- Run `nx build telemetry` to build the library.
7
+ 安装依赖:
8
8
 
9
- ## Running unit tests
9
+ ```bash
10
+ pnpm add @0xchain/telemetry
11
+ ```
10
12
 
11
- Run `nx test telemetry` to execute the unit tests via [Vitest](https://vitest.dev/).
13
+ Next.js App Router 接入:
14
+
15
+ ```ts
16
+ import { registerTelemetry } from "@0xchain/telemetry/next";
17
+
18
+ export async function register() {
19
+ await registerTelemetry(() => ({
20
+ serviceName: "web-app",
21
+ environment: "production",
22
+ url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT,
23
+ headers: {
24
+ Authorization: process.env.OTEL_EXPORTER_OTLP_HEADERS || "",
25
+ },
26
+ samplingRules: [
27
+ { name: "inspection", ratio: 1, when: { inspection: true } },
28
+ { name: "errors", ratio: 0.8, when: { minStatusCode: 500 } },
29
+ { name: "default", ratio: 0.1 },
30
+ ],
31
+ }));
32
+ }
33
+ ```
34
+
35
+ `middleware.ts` 中启用请求上下文写入:
36
+
37
+ ```ts
38
+ import { createTelemetryMiddleware, defaultTelemetryMiddlewareConfig } from "@0xchain/telemetry/next";
39
+
40
+ export const config = defaultTelemetryMiddlewareConfig;
41
+ export default createTelemetryMiddleware({
42
+ ignore: {
43
+ paths: ["/health", "/metrics"],
44
+ extensions: [".png", ".css"],
45
+ },
46
+ });
47
+ ```
48
+
49
+ ## API 说明
50
+
51
+ ### 核心入口
52
+
53
+ - `registerTelemetry(configOrProvider)`:用于 `instrumentation.ts` 中初始化 OpenTelemetry。
54
+ - `createTelemetryMiddleware(options)`:用于 `middleware.ts` 注入请求头与用户类型标记。
55
+ - `startTelemetry(config)`:在 Node 环境中直接启动 SDK。
56
+ - `updateTelemetryConfig(partial)`:运行时更新采样、忽略规则等配置。
57
+ - `shutdownTelemetry()`:停止追踪 SDK。
58
+
59
+ ### 配置类型
60
+
61
+ `TelemetryConfig` 关键字段:
62
+
63
+ - `serviceName`:服务名称
64
+ - `environment`:环境标识
65
+ - `defaultSamplingRatio`:默认采样比例
66
+ - `samplingRules`:多维采样规则
67
+ - `ignore`:忽略规则
68
+ - `inspectionHeader`:巡检标记请求头
69
+ - `userTypeHeader`:用户类型请求头
70
+ - `requestStartHeader`:请求开始时间请求头
71
+
72
+ ### 采样规则
73
+
74
+ ```json
75
+ [
76
+ {
77
+ "name": "inspection",
78
+ "ratio": 1,
79
+ "when": { "inspection": true }
80
+ },
81
+ {
82
+ "name": "error",
83
+ "ratio": 0.8,
84
+ "when": { "minStatusCode": 500 }
85
+ },
86
+ {
87
+ "name": "api",
88
+ "ratio": 0.2,
89
+ "when": { "path": ["/api/**"], "method": ["POST"] }
90
+ }
91
+ ]
92
+ ```
93
+
94
+ ### 忽略规则
95
+
96
+ ```json
97
+ {
98
+ "paths": ["/health", "/metrics", "/_next/**"],
99
+ "extensions": [".png", ".css", ".js"],
100
+ "methods": ["HEAD", "OPTIONS"]
101
+ }
102
+ ```
103
+
104
+ ## 环境变量
105
+
106
+ - `TELEMETRY_CONFIG_FILE`:JSON 配置文件路径
107
+ - `TELEMETRY_SAMPLING_RATIO`:默认采样比例
108
+ - `TELEMETRY_SAMPLING_RULES`:采样规则 JSON 字符串
109
+ - `TELEMETRY_IGNORE_PATHS`:逗号分隔的忽略路径
110
+ - `TELEMETRY_IGNORE_EXTENSIONS`:逗号分隔的忽略扩展名
111
+ - `TELEMETRY_IGNORE_METHODS`:逗号分隔的忽略方法
112
+ - `TELEMETRY_INSPECTION_HEADER`:巡检请求头
113
+ - `TELEMETRY_USER_TYPE_HEADER`:用户类型请求头
114
+ - `TELEMETRY_REQUEST_START_HEADER`:请求开始时间请求头
115
+ - `OTEL_EXPORTER_OTLP_ENDPOINT`:OTLP endpoint
116
+ - `OTEL_EXPORTER_OTLP_HEADERS`:OTLP headers
117
+ - `OTEL_SERVICE_NAME`:服务名称
118
+
119
+ ## 部署说明
120
+
121
+ 1. 配置 OTLP endpoint 与 headers。
122
+ 2. 在 `instrumentation.ts` 中调用 `registerTelemetry`。
123
+ 3. 在 `middleware.ts` 中加入 `createTelemetryMiddleware`。
124
+ 4. 确认生产环境可访问 APM 的 OTLP 接收端。
125
+
126
+ ## 迁移指南
127
+
128
+ - 旧 `startTelemetry` 初始化方式可直接替换为 `registerTelemetry`,配置项保持一致。
129
+ - `ignorePaths` 替换为 `ignore` 配置对象以便使用扩展名与方法过滤。
130
+ - 原巡检逻辑继续使用 `x-inspection` 请求头,默认保持兼容。
131
+
132
+ ## 构建与测试
133
+
134
+ ```bash
135
+ pnpm nx build @0xchain/telemetry
136
+ pnpm nx test @0xchain/telemetry
137
+ ```
@@ -1,2 +1,4 @@
1
- export default function getInstrumentations(ignoredPaths: string[]): any;
1
+ import { TelemetryConfig } from './types';
2
+ /** 生成 OpenTelemetry 自动检测配置 */
3
+ export default function getInstrumentations(config: TelemetryConfig): any;
2
4
  //# sourceMappingURL=Instrumentations.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Instrumentations.d.ts","sourceRoot":"","sources":["../src/Instrumentations.ts"],"names":[],"mappings":"AAgBA,MAAM,CAAC,OAAO,UAAU,mBAAmB,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,GAAG,CAiCvE"}
1
+ {"version":3,"file":"Instrumentations.d.ts","sourceRoot":"","sources":["../src/Instrumentations.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AA4B/C,8BAA8B;AAC9B,MAAM,CAAC,OAAO,UAAU,mBAAmB,CAAC,MAAM,EAAE,eAAe,GAAG,GAAG,CA0ExE"}
package/dist/Sampler.d.ts CHANGED
@@ -1,11 +1,22 @@
1
- import { Sampler, SamplingResult } from '@opentelemetry/sdk-trace-base';
2
- import { SpanKind, Attributes, Link, Context } from '@opentelemetry/api';
3
- declare class InspectionSampler implements Sampler {
4
- private defaultSampler;
5
- private inspectionSampler;
6
- constructor(ratio: number);
7
- shouldSample(context: Context, traceId: string, spanName: string, spanKind: SpanKind, attributes: Attributes, links: Link[]): SamplingResult;
8
- toString(): string;
1
+ import { Sampler, SpanExporter } from '@opentelemetry/sdk-trace-base';
2
+ import { Attributes } from '@opentelemetry/api';
3
+ import { SamplingRule, TelemetryRuntime } from './types';
4
+ export interface SamplingContext {
5
+ path?: string;
6
+ method?: string;
7
+ userType?: string;
8
+ statusCode?: number;
9
+ inspection?: boolean;
9
10
  }
10
- export default InspectionSampler;
11
+ /** 基于 span attributes 构建采样上下文 */
12
+ export declare const buildSamplingContextFromAttributes: (attributes: Attributes) => SamplingContext;
13
+ /** 判断采样规则是否命中 */
14
+ export declare const matchSamplingRule: (rule: SamplingRule, context: SamplingContext) => boolean;
15
+ /** 根据规则解析采样比例 */
16
+ export declare const resolveSamplingRatio: (rules: SamplingRule[] | undefined, context: SamplingContext, defaultRatio: number) => number;
17
+ /** 创建基于规则的采样器 */
18
+ export declare const createRuleBasedSampler: (runtime: TelemetryRuntime) => Sampler;
19
+ /** 构建带采样过滤的导出器 */
20
+ export declare const createFilteringTraceExporter: (exporter: SpanExporter, runtime: TelemetryRuntime) => SpanExporter;
21
+ export default createRuleBasedSampler;
11
22
  //# sourceMappingURL=Sampler.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Sampler.d.ts","sourceRoot":"","sources":["../src/Sampler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,cAAc,EAA+D,MAAM,+BAA+B,CAAC;AACrI,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAqB,MAAM,oBAAoB,CAAC;AAG5F,cAAM,iBAAkB,YAAW,OAAO;IACtC,OAAO,CAAC,cAAc,CAAU;IAChC,OAAO,CAAC,iBAAiB,CAAU;gBAEvB,KAAK,EAAE,MAAM;IAKzB,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,cAAc;IAuB5I,QAAQ;CAGT;AAED,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"Sampler.d.ts","sourceRoot":"","sources":["../src/Sampler.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EAIP,YAAY,EACb,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAEL,UAAU,EAMX,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAG9D,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAoCD,iCAAiC;AACjC,eAAO,MAAM,kCAAkC,GAAI,YAAY,UAAU,KAAG,eA4B3E,CAAC;AAcF,iBAAiB;AACjB,eAAO,MAAM,iBAAiB,GAAI,MAAM,YAAY,EAAE,SAAS,eAAe,YAiC7E,CAAC;AAKF,iBAAiB;AACjB,eAAO,MAAM,oBAAoB,GAC/B,OAAO,YAAY,EAAE,GAAG,SAAS,EACjC,SAAS,eAAe,EACxB,cAAc,MAAM,WASrB,CAAC;AAoBF,iBAAiB;AACjB,eAAO,MAAM,sBAAsB,GAAI,SAAS,gBAAgB,KAAG,OAyBlE,CAAC;AAwBF,kBAAkB;AAClB,eAAO,MAAM,4BAA4B,GAAI,UAAU,YAAY,EAAE,SAAS,gBAAgB,KAAG,YAehG,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { IgnoreConfig, PathPattern } from './types';
2
+ export declare const defaultIgnoreConfig: Required<IgnoreConfig>;
3
+ /** 判断路径是否匹配规则 */
4
+ export declare const matchesPathPattern: (pattern: PathPattern, pathname: string) => boolean;
5
+ /** 创建忽略规则匹配器 */
6
+ export declare const createIgnoreMatcher: (config?: IgnoreConfig) => (pathname: string, method?: string) => boolean;
7
+ //# sourceMappingURL=ignore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ignore.d.ts","sourceRoot":"","sources":["../src/ignore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAqCzD,eAAO,MAAM,mBAAmB,EAAE,QAAQ,CAAC,YAAY,CAItD,CAAC;AAcF,iBAAiB;AACjB,eAAO,MAAM,kBAAkB,GAAI,SAAS,WAAW,EAAE,UAAU,MAAM,YAmBxE,CAAC;AAQF,gBAAgB;AAChB,eAAO,MAAM,mBAAmB,GAAI,SAAS,YAAY,MAS/C,UAAU,MAAM,EAAE,SAAS,MAAM,YAU1C,CAAC"}
package/dist/index ADDED
@@ -0,0 +1,442 @@
1
+ import { NodeSDK as q } from "@opentelemetry/sdk-node";
2
+ import { OTLPTraceExporter as z } from "@opentelemetry/exporter-trace-otlp-http";
3
+ import { resourceFromAttributes as j } from "@opentelemetry/resources";
4
+ import { ATTR_SERVICE_VERSION as U, ATTR_SERVICE_NAME as k } from "@opentelemetry/semantic-conventions";
5
+ import { SamplingDecision as f, TraceIdRatioBasedSampler as L, AlwaysOnSampler as B, BatchSpanProcessor as G } from "@opentelemetry/sdk-trace-base";
6
+ import { trace as W, TraceFlags as A, context as x, SpanKind as $, propagation as D, SpanStatusCode as Q } from "@opentelemetry/api";
7
+ import { readFileSync as K } from "node:fs";
8
+ import { getNodeAutoInstrumentations as X } from "@opentelemetry/auto-instrumentations-node";
9
+ import { UndiciInstrumentation as J } from "@opentelemetry/instrumentation-undici";
10
+ const Z = "deployment.environment.name", tt = [
11
+ "/health",
12
+ "/metrics",
13
+ "/readyz",
14
+ "/livez",
15
+ "/favicon.ico",
16
+ "/robots.txt",
17
+ "/sitemap.xml",
18
+ "/_next",
19
+ "/__nextjs_",
20
+ "/.well-known"
21
+ ], et = [
22
+ ".css",
23
+ ".js",
24
+ ".mjs",
25
+ ".cjs",
26
+ ".png",
27
+ ".jpg",
28
+ ".jpeg",
29
+ ".gif",
30
+ ".svg",
31
+ ".ico",
32
+ ".webp",
33
+ ".avif",
34
+ ".woff",
35
+ ".woff2",
36
+ ".ttf",
37
+ ".eot",
38
+ ".map",
39
+ ".txt",
40
+ ".xml"
41
+ ], E = {
42
+ paths: tt,
43
+ extensions: et,
44
+ methods: ["HEAD", "OPTIONS"]
45
+ }, rt = (t) => t.map((e) => {
46
+ const r = e.trim().toLowerCase();
47
+ return r && (r.startsWith(".") ? r : `.${r}`);
48
+ }), st = (t) => t.replace(/[.+^${}()|[\]\\]/g, "\\$&"), b = (t, e) => {
49
+ if (t instanceof RegExp)
50
+ return t.test(e);
51
+ const r = t.trim();
52
+ if (!r) return !1;
53
+ if (r.includes("*")) {
54
+ const n = `^${st(r).replace(/\\\*\\\*/g, ".*").replace(/\\\*/g, "[^/]*")}$`;
55
+ return new RegExp(n).test(e);
56
+ }
57
+ return e === r ? !0 : r.endsWith("/") ? e.startsWith(r) : e.startsWith(`${r}/`) || e.startsWith(r);
58
+ }, nt = (t, e) => {
59
+ const r = e.toLowerCase();
60
+ return t.some((s) => s && r.endsWith(s));
61
+ }, ot = (t) => {
62
+ var o, n, i;
63
+ const e = (o = t == null ? void 0 : t.paths) != null && o.length ? t.paths : E.paths, r = (n = t == null ? void 0 : t.extensions) != null && n.length ? rt(t.extensions) : E.extensions, s = (i = t == null ? void 0 : t.methods) != null && i.length ? t.methods.map((a) => a.toUpperCase()) : E.methods;
64
+ return (a, u) => u && s.includes(u.toUpperCase()) ? !0 : a ? nt(r, a) ? !0 : e.some((c) => b(c, a)) : !1;
65
+ }, h = (t, e) => {
66
+ if (!t) return;
67
+ const r = t[e.toLowerCase()];
68
+ if (Array.isArray(r)) {
69
+ const s = r[0];
70
+ return typeof s == "string" ? s : void 0;
71
+ }
72
+ return typeof r == "string" ? r : void 0;
73
+ }, T = (t) => {
74
+ if (!t) return "";
75
+ try {
76
+ return t.startsWith("http://") || t.startsWith("https://") ? new URL(t).pathname : new URL(t, "http://localhost").pathname;
77
+ } catch {
78
+ return t.split("?")[0] || t;
79
+ }
80
+ }, O = /* @__PURE__ */ new WeakMap();
81
+ function it(t) {
82
+ const e = ot(t.ignore), r = (t.inspectionHeader ?? "x-inspection").toLowerCase(), s = (t.userTypeHeader ?? "x-telemetry-user-type").toLowerCase(), o = (t.requestStartHeader ?? "x-telemetry-start").toLowerCase();
83
+ return [
84
+ X({
85
+ "@opentelemetry/instrumentation-grpc": {
86
+ enabled: !1
87
+ },
88
+ "@opentelemetry/instrumentation-http": {
89
+ enabled: !0,
90
+ startIncomingSpanHook: (n) => {
91
+ const i = "headers" in n ? n.headers : void 0, a = h(i, r), u = h(i, s), c = h(i, o), d = "method" in n ? n.method : void 0, M = T("url" in n ? n.url : void 0), w = Number(c || Date.now()), m = {
92
+ "telemetry.request.start_time_ms": Number.isFinite(w) ? w : Date.now()
93
+ };
94
+ return M && (m["url.path"] = M), d && (m["http.request.method"] = d), a && (m["telemetry.request.inspection"] = !0, m["http.request.header.x-inspection"] = a), u && (m["enduser.type"] = u, m["telemetry.request.user_type"] = u), m;
95
+ },
96
+ requestHook: (n, i) => {
97
+ const a = "headers" in i ? i.headers : void 0, u = h(a, o), c = Number(u || Date.now());
98
+ O.set(n, Number.isFinite(c) ? c : Date.now());
99
+ },
100
+ responseHook: (n, i) => {
101
+ const a = "statusCode" in i ? i.statusCode : void 0;
102
+ typeof a == "number" && (n.setAttribute("http.response.status_code", a), n.setAttribute("telemetry.response.status_code", a), a >= 500 && n.setAttribute("telemetry.request.error", !0));
103
+ const u = O.get(n);
104
+ typeof u == "number" && n.setAttribute("telemetry.request.duration_ms", Date.now() - u);
105
+ },
106
+ ignoreIncomingRequestHook: (n) => {
107
+ const i = "url" in n ? n.url : void 0, a = T(i), u = "method" in n ? n.method : void 0;
108
+ return e(a, u);
109
+ },
110
+ ignoreOutgoingRequestHook: (n) => {
111
+ const i = typeof n == "string" ? n : n.path || "";
112
+ return e(T(i));
113
+ }
114
+ }
115
+ }),
116
+ new J()
117
+ ];
118
+ }
119
+ const R = (t) => {
120
+ if (typeof t == "string") return t;
121
+ if (Array.isArray(t)) {
122
+ const e = t[0];
123
+ return typeof e == "string" ? e : void 0;
124
+ }
125
+ }, H = (t) => {
126
+ if (typeof t == "number") return t;
127
+ if (typeof t == "string") {
128
+ const e = Number(t);
129
+ return Number.isFinite(e) ? e : void 0;
130
+ }
131
+ if (Array.isArray(t)) {
132
+ const e = t[0];
133
+ return H(e);
134
+ }
135
+ }, l = (t, e) => {
136
+ for (const r of e)
137
+ if (r in t)
138
+ return t[r];
139
+ }, V = (t) => {
140
+ const e = l(t, ["url.path", "http.target", "http.route"]), r = l(t, ["http.request.method", "http.method"]), s = l(t, ["enduser.type", "telemetry.request.user_type"]), o = l(t, [
141
+ "http.response.status_code",
142
+ "http.status_code",
143
+ "telemetry.response.status_code"
144
+ ]), n = l(t, [
145
+ "telemetry.request.inspection",
146
+ "http.request.header.x-inspection",
147
+ "x-inspection"
148
+ ]), i = n === !0 || n === "true" || n === "1" || n === 1;
149
+ return {
150
+ path: R(e),
151
+ method: R(r),
152
+ userType: R(s),
153
+ statusCode: H(o),
154
+ inspection: i
155
+ };
156
+ }, I = (t, e) => !t || !(e != null && e.length) ? !1 : e.some((r) => r.toLowerCase() === t.toLowerCase()), at = (t, e) => !t || !(e != null && e.length) ? !1 : e.some((r) => b(r, t)), ut = (t, e) => {
157
+ const r = t.when;
158
+ if (!r) return !0;
159
+ if (r.inspection !== void 0 && r.inspection !== e.inspection || r.path && !at(e.path, r.path) || r.method && !I(e.method, r.method) || r.userType && !I(e.userType, r.userType))
160
+ return !1;
161
+ if (r.statusCode && typeof e.statusCode == "number") {
162
+ if (!r.statusCode.includes(e.statusCode))
163
+ return !1;
164
+ } else if (r.statusCode && r.statusCode.length)
165
+ return !1;
166
+ return !(typeof r.minStatusCode == "number" && (typeof e.statusCode != "number" || e.statusCode < r.minStatusCode) || typeof r.maxStatusCode == "number" && (typeof e.statusCode != "number" || e.statusCode > r.maxStatusCode));
167
+ }, S = (t) => Math.max(0, Math.min(1, t)), v = (t, e, r) => {
168
+ if (!(t != null && t.length)) return S(r);
169
+ for (const s of t)
170
+ if (ut(s, e))
171
+ return S(s.ratio);
172
+ return S(r);
173
+ }, P = /* @__PURE__ */ new Map(), F = (t) => {
174
+ if (t <= 0)
175
+ return new L(0);
176
+ if (t >= 1)
177
+ return new B();
178
+ const e = Number(t.toFixed(6)), r = P.get(e);
179
+ if (r) return r;
180
+ const s = new L(e);
181
+ return P.set(e, s), s;
182
+ }, ct = (t) => ({
183
+ shouldSample(e, r, s, o, n, i) {
184
+ const a = W.getSpanContext(e);
185
+ if (a)
186
+ return (a.traceFlags & A.SAMPLED) === A.SAMPLED ? { decision: f.RECORD_AND_SAMPLED } : { decision: f.NOT_RECORD };
187
+ const u = t.getConfig(), c = V(n);
188
+ if (c.inspection)
189
+ return { decision: f.RECORD_AND_SAMPLED };
190
+ const d = v(
191
+ u.samplingRules,
192
+ c,
193
+ u.defaultSamplingRatio ?? 0.01
194
+ );
195
+ return F(d).shouldSample(e, r, s, o, n, i);
196
+ },
197
+ toString: () => "RuleBasedSampler"
198
+ }), mt = (t, e, r) => {
199
+ const s = t.getConfig(), o = V(e);
200
+ if (o.inspection) return !0;
201
+ const n = v(
202
+ s.samplingRules,
203
+ o,
204
+ s.defaultSamplingRatio ?? 0.01
205
+ );
206
+ return F(n).shouldSample(
207
+ x.active(),
208
+ r,
209
+ "export",
210
+ $.INTERNAL,
211
+ e,
212
+ []
213
+ ).decision === f.RECORD_AND_SAMPLED;
214
+ }, pt = (t, e) => ({
215
+ export: (r, s) => {
216
+ const o = r.filter(
217
+ (n) => mt(e, n.attributes, n.spanContext().traceId)
218
+ );
219
+ if (!o.length) {
220
+ s({ code: 0 });
221
+ return;
222
+ }
223
+ t.export(o, s);
224
+ },
225
+ shutdown: () => t.shutdown(),
226
+ forceFlush: () => {
227
+ var r;
228
+ return ((r = t.forceFlush) == null ? void 0 : r.call(t)) ?? Promise.resolve();
229
+ }
230
+ });
231
+ let g, p;
232
+ const _ = (t) => Array.from(new Set(t)), y = (t) => (t == null ? void 0 : t.split(",").map((e) => e.trim()).filter(Boolean)) ?? [], lt = (t) => {
233
+ if (!t) return;
234
+ const e = {};
235
+ for (const r of t.split(",")) {
236
+ const [s, ...o] = r.split("="), n = s == null ? void 0 : s.trim();
237
+ n && (e[n] = o.join("=").trim());
238
+ }
239
+ return e;
240
+ }, C = (t) => {
241
+ if (t)
242
+ try {
243
+ return JSON.parse(t);
244
+ } catch {
245
+ return;
246
+ }
247
+ }, dt = (t) => {
248
+ if (t)
249
+ try {
250
+ const e = K(t, "utf8");
251
+ return C(e);
252
+ } catch {
253
+ return;
254
+ }
255
+ }, Y = (t, e) => {
256
+ const r = _([...(t == null ? void 0 : t.paths) ?? [], ...(e == null ? void 0 : e.paths) ?? []]), s = _([
257
+ ...(t == null ? void 0 : t.extensions) ?? [],
258
+ ...(e == null ? void 0 : e.extensions) ?? []
259
+ ]), o = _([...(t == null ? void 0 : t.methods) ?? [], ...(e == null ? void 0 : e.methods) ?? []]);
260
+ return {
261
+ paths: r.length ? r : void 0,
262
+ extensions: s.length ? s : void 0,
263
+ methods: o.length ? o : void 0
264
+ };
265
+ }, ht = (t) => {
266
+ if (t != null && t.length)
267
+ return t.map((e) => ({
268
+ ...e,
269
+ ratio: Number.isFinite(e.ratio) ? Math.max(0, Math.min(1, e.ratio)) : 0
270
+ })).filter((e) => e.ratio >= 0);
271
+ }, ft = (t = process.env) => {
272
+ const e = dt(t.TELEMETRY_CONFIG_FILE), r = y(t.TELEMETRY_IGNORE_PATHS), s = y(t.TELEMETRY_IGNORE_EXTENSIONS), o = y(t.TELEMETRY_IGNORE_METHODS), n = C(t.TELEMETRY_SAMPLING_RULES), i = typeof (e == null ? void 0 : e.samplingRules) == "string" ? C(e.samplingRules) : e == null ? void 0 : e.samplingRules, a = {
273
+ serviceName: t.OTEL_SERVICE_NAME || t.TELEMETRY_SERVICE_NAME,
274
+ serviceVersion: t.OTEL_SERVICE_VERSION || t.TELEMETRY_SERVICE_VERSION,
275
+ environment: t.OTEL_RESOURCE_ATTRIBUTES || t.TELEMETRY_ENVIRONMENT,
276
+ defaultSamplingRatio: t.TELEMETRY_SAMPLING_RATIO ? Number(t.TELEMETRY_SAMPLING_RATIO) : void 0,
277
+ url: t.OTEL_EXPORTER_OTLP_ENDPOINT || t.TELEMETRY_OTLP_ENDPOINT,
278
+ headers: lt(t.OTEL_EXPORTER_OTLP_HEADERS || t.TELEMETRY_OTLP_HEADERS),
279
+ inspectionHeader: t.TELEMETRY_INSPECTION_HEADER,
280
+ userTypeHeader: t.TELEMETRY_USER_TYPE_HEADER,
281
+ requestStartHeader: t.TELEMETRY_REQUEST_START_HEADER,
282
+ samplingRules: n || i,
283
+ ignore: r.length || s.length || o.length ? {
284
+ paths: r.length ? r : void 0,
285
+ extensions: s.length ? s : void 0,
286
+ methods: o.length ? o : void 0
287
+ } : void 0
288
+ };
289
+ return e && typeof e == "object" ? { ...e, ...a } : a;
290
+ }, Et = (t) => {
291
+ if (!t) return process.env.NODE_ENV || "development";
292
+ if (t.includes("deployment.environment")) {
293
+ const r = t.split(",").find((o) => o.includes("deployment.environment"));
294
+ if (!r) return t;
295
+ const [, s] = r.split("=");
296
+ return (s == null ? void 0 : s.trim()) || t;
297
+ }
298
+ return t;
299
+ }, gt = (t, e) => {
300
+ var s, o;
301
+ const r = [
302
+ { name: "inspection", ratio: 1, when: { inspection: !0 } },
303
+ { name: "error", ratio: 1, when: { minStatusCode: 500 } }
304
+ ];
305
+ if ((s = t == null ? void 0 : t.criticalPaths) != null && s.length && r.push({
306
+ name: "critical-path",
307
+ ratio: 1,
308
+ when: { path: t.criticalPaths }
309
+ }), (o = t == null ? void 0 : t.criticalUserTypes) != null && o.length && r.push({
310
+ name: "critical-user",
311
+ ratio: 1,
312
+ when: { userType: t.criticalUserTypes }
313
+ }), t != null && t.pathSampling)
314
+ for (const [n, i] of Object.entries(t.pathSampling))
315
+ r.push({
316
+ name: `path:${n}`,
317
+ ratio: i,
318
+ when: { path: [n] }
319
+ });
320
+ if (t != null && t.userTypeSampling)
321
+ for (const [n, i] of Object.entries(t.userTypeSampling))
322
+ r.push({
323
+ name: `user:${n}`,
324
+ ratio: i,
325
+ when: { userType: [n] }
326
+ });
327
+ return r.push({ name: "default", ratio: e }), r;
328
+ }, N = (t = {}, e = process.env) => {
329
+ const s = { ...ft(e), ...t }, o = Et(s.environment), n = Y(E, s.ignore), i = typeof s.defaultSamplingRatio == "number" ? Math.max(0, Math.min(1, s.defaultSamplingRatio)) : 0.01, a = ht(s.samplingRules) ?? gt(s.layeredSampling, i);
330
+ return {
331
+ ...s,
332
+ serviceName: s.serviceName || "unknown-service",
333
+ serviceVersion: s.serviceVersion,
334
+ environment: o,
335
+ defaultSamplingRatio: i,
336
+ ignore: n,
337
+ samplingRules: a,
338
+ inspectionHeader: s.inspectionHeader ?? "x-inspection",
339
+ userTypeHeader: s.userTypeHeader ?? "x-telemetry-user-type",
340
+ requestStartHeader: s.requestStartHeader ?? "x-telemetry-start",
341
+ scheduledDelayMillis: s.scheduledDelayMillis ?? 1e3,
342
+ maxQueueSize: s.maxQueueSize ?? 2048,
343
+ maxExportBatchSize: s.maxExportBatchSize ?? 512,
344
+ exporterTimeoutMillis: s.exporterTimeoutMillis ?? 3e4
345
+ };
346
+ }, Tt = (t) => {
347
+ let e = N(t);
348
+ return {
349
+ getConfig: () => e,
350
+ updateConfig: (r) => {
351
+ e = N({
352
+ ...e,
353
+ ...r,
354
+ ignore: Y(e.ignore, r.ignore)
355
+ });
356
+ }
357
+ };
358
+ }, Rt = (t) => t[0] * 1e3 + t[1] / 1e6, St = (t, e) => {
359
+ for (const r of e) {
360
+ const s = t.attributes[r];
361
+ if (typeof s == "number") return s;
362
+ }
363
+ }, _t = (t) => {
364
+ const e = t.events.find((s) => s.name === "exception");
365
+ if (!(e != null && e.attributes)) return;
366
+ const r = e.attributes["exception.message"];
367
+ return typeof r == "string" ? r : void 0;
368
+ }, yt = () => ({
369
+ onStart: () => {
370
+ },
371
+ onEnd: (t) => {
372
+ const e = Rt(t.duration);
373
+ t.attributes["telemetry.request.duration_ms"] = Math.round(e), typeof t.attributes["telemetry.request.start_time_ms"] != "number" && (t.attributes["telemetry.request.start_time_ms"] = Date.now() - Math.round(e));
374
+ const r = St(t, [
375
+ "http.response.status_code",
376
+ "http.status_code",
377
+ "telemetry.response.status_code"
378
+ ]);
379
+ if (typeof r == "number" && (t.attributes["telemetry.response.status_code"] = r), t.status.code === Q.ERROR || typeof r == "number" && r >= 500) {
380
+ t.attributes["telemetry.request.error"] = !0;
381
+ const o = t.status.message || _t(t);
382
+ o && (t.attributes["telemetry.request.error_message"] = o);
383
+ }
384
+ },
385
+ shutdown: () => Promise.resolve(),
386
+ forceFlush: () => Promise.resolve()
387
+ }), Pt = async (t) => {
388
+ const e = N(t);
389
+ p = Tt(e);
390
+ const r = j({
391
+ [k]: e.serviceName,
392
+ [U]: e.serviceVersion || "1.0.0",
393
+ [Z]: e.environment || "development"
394
+ }), s = new z(e), o = pt(s, p), n = [
395
+ yt(),
396
+ new G(o, {
397
+ scheduledDelayMillis: e.scheduledDelayMillis,
398
+ maxQueueSize: e.maxQueueSize,
399
+ maxExportBatchSize: e.maxExportBatchSize,
400
+ exportTimeoutMillis: e.exporterTimeoutMillis
401
+ })
402
+ ];
403
+ g = new q({
404
+ serviceName: e.serviceName,
405
+ resource: r,
406
+ spanProcessors: n,
407
+ sampler: ct(p),
408
+ instrumentations: it(e)
409
+ });
410
+ try {
411
+ await g.start();
412
+ } catch (i) {
413
+ console.warn("Telemetry start failed:", i);
414
+ }
415
+ return p;
416
+ }, Dt = (t) => {
417
+ p == null || p.updateConfig(t);
418
+ }, bt = (t) => (D.inject(x.active(), t), t), Ht = (t = fetch) => async (e, r) => {
419
+ const s = (r == null ? void 0 : r.headers) ?? (e instanceof Request ? e.headers : void 0), o = new Headers(s);
420
+ return D.inject(x.active(), o, {
421
+ set: (n, i, a) => {
422
+ n.set(i, a);
423
+ }
424
+ }), t(e, { ...r, headers: o });
425
+ }, Vt = async () => {
426
+ g && await g.shutdown();
427
+ };
428
+ export {
429
+ V as buildSamplingContextFromAttributes,
430
+ ot as createIgnoreMatcher,
431
+ Ht as createPropagatingFetch,
432
+ Tt as createTelemetryRuntime,
433
+ E as defaultIgnoreConfig,
434
+ bt as injectTraceHeaders,
435
+ ft as loadTelemetryConfigFromEnv,
436
+ ut as matchSamplingRule,
437
+ v as resolveSamplingRatio,
438
+ N as resolveTelemetryConfig,
439
+ Vt as shutdownTelemetry,
440
+ Pt as startTelemetry,
441
+ Dt as updateTelemetryConfig
442
+ };
package/dist/index.d.ts CHANGED
@@ -1,12 +1,23 @@
1
- import { OTLPExporterNodeConfigBase } from '@opentelemetry/otlp-exporter-base';
2
- interface TelemetryOptions extends OTLPExporterNodeConfigBase {
3
- serviceName: string;
4
- serviceVersion?: string;
5
- environment: string;
6
- ignorePaths?: string[];
7
- inspectionRatio?: number;
8
- }
9
- export declare function startTelemetry(otlpOptions: TelemetryOptions): void;
10
- export declare function shutdownTelemetry(): void;
11
- export {};
1
+ import { buildSamplingContextFromAttributes, matchSamplingRule, resolveSamplingRatio } from './Sampler';
2
+ import { createIgnoreMatcher, defaultIgnoreConfig } from './ignore';
3
+ import { TelemetryConfig, TelemetryRuntime } from './types';
4
+ export * from './types';
5
+ export { buildSamplingContextFromAttributes, matchSamplingRule, resolveSamplingRatio, createIgnoreMatcher, defaultIgnoreConfig, };
6
+ /** 从环境变量加载 Telemetry 配置 */
7
+ /** 从环境变量加载 Telemetry 配置 */
8
+ export declare const loadTelemetryConfigFromEnv: (env?: NodeJS.ProcessEnv) => Partial<TelemetryConfig>;
9
+ /** 合并环境变量与显式配置得到最终配置 */
10
+ export declare const resolveTelemetryConfig: (options?: Partial<TelemetryConfig>, env?: NodeJS.ProcessEnv) => TelemetryConfig;
11
+ /** 创建可运行时更新的配置容器 */
12
+ export declare const createTelemetryRuntime: (initialConfig: TelemetryConfig) => TelemetryRuntime;
13
+ /** 启动 OpenTelemetry SDK */
14
+ export declare const startTelemetry: (options: TelemetryConfig) => Promise<TelemetryRuntime>;
15
+ /** 运行时更新 Telemetry 配置 */
16
+ export declare const updateTelemetryConfig: (partial: Partial<TelemetryConfig>) => void;
17
+ /** 注入 traceparent 等传播头 */
18
+ export declare const injectTraceHeaders: (headers: Record<string, string>) => Record<string, string>;
19
+ /** 创建带 traceparent 注入的 fetch */
20
+ export declare const createPropagatingFetch: (fetchImpl?: typeof fetch) => (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
21
+ /** 停止并释放 Telemetry SDK */
22
+ export declare const shutdownTelemetry: () => Promise<void>;
12
23
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAC;AAY/E,UAAU,gBAAiB,SAAQ,0BAA0B;IAC3D,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAID,wBAAgB,cAAc,CAAC,WAAW,EAAE,gBAAgB,QAiC3D;AAED,wBAAgB,iBAAiB,SAIhC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAgBA,OAAO,EACL,kCAAkC,EAGlC,iBAAiB,EACjB,oBAAoB,EACrB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AACpE,OAAO,KAAK,EAIV,eAAe,EACf,gBAAgB,EACjB,MAAM,SAAS,CAAC;AAEjB,cAAc,SAAS,CAAC;AACxB,OAAO,EACL,kCAAkC,EAClC,iBAAiB,EACjB,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,GACpB,CAAC;AA4EF,2BAA2B;AAC3B,2BAA2B;AAC3B,eAAO,MAAM,0BAA0B,GACrC,MAAK,MAAM,CAAC,UAAwB,KACnC,OAAO,CAAC,eAAe,CAuCzB,CAAC;AAoEF,wBAAwB;AACxB,eAAO,MAAM,sBAAsB,GACjC,UAAS,OAAO,CAAC,eAAe,CAAM,EACtC,MAAK,MAAM,CAAC,UAAwB,KACnC,eA4BF,CAAC;AAEF,oBAAoB;AACpB,eAAO,MAAM,sBAAsB,GAAI,eAAe,eAAe,KAAG,gBAYvE,CAAC;AAwDF,2BAA2B;AAC3B,eAAO,MAAM,cAAc,GAAU,SAAS,eAAe,8BAqC5D,CAAC;AAEF,yBAAyB;AACzB,eAAO,MAAM,qBAAqB,GAAI,SAAS,OAAO,CAAC,eAAe,CAAC,SAEtE,CAAC;AAEF,0BAA0B;AAC1B,eAAO,MAAM,kBAAkB,GAAI,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,2BAGjE,CAAC;AAEF,gCAAgC;AAChC,eAAO,MAAM,sBAAsB,GAAI,YAAW,OAAO,KAAa,MACtD,OAAO,WAAW,GAAG,GAAG,EAAE,OAAO,WAAW,sBAY3D,CAAC;AAEF,0BAA0B;AAC1B,eAAO,MAAM,iBAAiB,qBAI7B,CAAC"}
package/dist/next ADDED
@@ -0,0 +1,30 @@
1
+ import { NextResponse as o } from "next/server";
2
+ import { createIgnoreMatcher as p, resolveTelemetryConfig as d, startTelemetry as g } from "./index";
3
+ const u = {
4
+ matcher: [
5
+ "/((?!_next/static|_next/image|favicon.ico|robots.txt|sitemap.xml|.*\\.(?:css|js|mjs|cjs|png|jpg|jpeg|gif|svg|ico|webp|avif|woff|woff2|ttf|eot|map|txt|xml)).*)"
6
+ ]
7
+ }, w = (e = {}) => {
8
+ const n = p(e.ignore), r = (e.inspectionHeader ?? "x-inspection").toLowerCase(), f = (e.requestStartHeader ?? "x-telemetry-start").toLowerCase(), c = (e.userTypeHeader ?? "x-telemetry-user-type").toLowerCase(), a = e.resolveUserType;
9
+ return (s) => {
10
+ try {
11
+ const l = s.nextUrl.pathname;
12
+ if (n(l, s.method))
13
+ return o.next();
14
+ const t = new Headers(s.headers), i = t.get(r);
15
+ i && t.set(r, i);
16
+ const m = (a == null ? void 0 : a(s)) || t.get(c);
17
+ return m && t.set(c, m), t.set(f, String(Date.now())), o.next({ request: { headers: t } });
18
+ } catch {
19
+ return o.next();
20
+ }
21
+ };
22
+ }, h = async (e) => {
23
+ const n = typeof e == "function" ? await e() : e, r = d(n);
24
+ await g(r);
25
+ };
26
+ export {
27
+ w as createTelemetryMiddleware,
28
+ u as defaultTelemetryMiddlewareConfig,
29
+ h as registerTelemetry
30
+ };
package/dist/next.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ import { NextResponse, NextRequest } from 'next/server';
2
+ import { TelemetryConfig, TelemetryMiddlewareOptions } from './types';
3
+ export declare const defaultTelemetryMiddlewareConfig: {
4
+ matcher: string[];
5
+ };
6
+ /** 创建 Next.js Middleware 链路追踪注入器 */
7
+ export declare const createTelemetryMiddleware: (options?: TelemetryMiddlewareOptions) => (request: NextRequest) => NextResponse<unknown>;
8
+ /** 在 Next.js instrumentation.ts 中注册追踪 */
9
+ export declare const registerTelemetry: (configOrProvider: TelemetryConfig | (() => TelemetryConfig | Promise<TelemetryConfig>)) => Promise<void>;
10
+ //# sourceMappingURL=next.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"next.d.ts","sourceRoot":"","sources":["../src/next.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAE7D,OAAO,KAAK,EAAE,eAAe,EAAE,0BAA0B,EAAE,MAAM,SAAS,CAAC;AAG3E,eAAO,MAAM,gCAAgC;;CAI5C,CAAC;AAEF,oCAAoC;AACpC,eAAO,MAAM,yBAAyB,GAAI,UAAS,0BAA+B,MAOxE,SAAS,WAAW,0BAqB7B,CAAC;AAEF,yCAAyC;AACzC,eAAO,MAAM,iBAAiB,GAC5B,kBAAkB,eAAe,GAAG,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC,kBAMvF,CAAC"}
@@ -0,0 +1,55 @@
1
+ import { OTLPExporterNodeConfigBase } from '@opentelemetry/otlp-exporter-base';
2
+ export type PathPattern = string | RegExp;
3
+ export interface IgnoreConfig {
4
+ paths?: PathPattern[];
5
+ extensions?: string[];
6
+ methods?: string[];
7
+ }
8
+ export interface SamplingRuleCondition {
9
+ path?: PathPattern[];
10
+ method?: string[];
11
+ userType?: string[];
12
+ statusCode?: number[];
13
+ minStatusCode?: number;
14
+ maxStatusCode?: number;
15
+ inspection?: boolean;
16
+ }
17
+ export interface SamplingRule {
18
+ name?: string;
19
+ ratio: number;
20
+ when?: SamplingRuleCondition;
21
+ }
22
+ export interface LayeredSamplingConfig {
23
+ criticalPaths?: PathPattern[];
24
+ criticalUserTypes?: string[];
25
+ pathSampling?: Record<string, number>;
26
+ userTypeSampling?: Record<string, number>;
27
+ }
28
+ export interface TelemetryConfig extends OTLPExporterNodeConfigBase {
29
+ serviceName: string;
30
+ serviceVersion?: string;
31
+ environment?: string;
32
+ defaultSamplingRatio?: number;
33
+ samplingRules?: SamplingRule[];
34
+ layeredSampling?: LayeredSamplingConfig;
35
+ ignore?: IgnoreConfig;
36
+ inspectionHeader?: string;
37
+ userTypeHeader?: string;
38
+ requestStartHeader?: string;
39
+ exporterTimeoutMillis?: number;
40
+ maxQueueSize?: number;
41
+ maxExportBatchSize?: number;
42
+ scheduledDelayMillis?: number;
43
+ }
44
+ export interface TelemetryRuntime {
45
+ getConfig: () => TelemetryConfig;
46
+ updateConfig: (partial: Partial<TelemetryConfig>) => void;
47
+ }
48
+ export interface TelemetryMiddlewareOptions {
49
+ ignore?: IgnoreConfig;
50
+ inspectionHeader?: string;
51
+ requestStartHeader?: string;
52
+ userTypeHeader?: string;
53
+ resolveUserType?: (request: import('next/server').NextRequest) => string | undefined;
54
+ }
55
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAC;AAEpF,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,CAAC;AAE1C,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,WAAW,EAAE,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,CAAC,EAAE,WAAW,EAAE,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,qBAAqB,CAAC;CAC9B;AAED,MAAM,WAAW,qBAAqB;IACpC,aAAa,CAAC,EAAE,WAAW,EAAE,CAAC;IAC9B,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,eAAgB,SAAQ,0BAA0B;IACjE,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAC/B,eAAe,CAAC,EAAE,qBAAqB,CAAC;IACxC,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,eAAe,CAAC;IACjC,YAAY,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,eAAe,CAAC,KAAK,IAAI,CAAC;CAC3D;AAED,MAAM,WAAW,0BAA0B;IACzC,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,aAAa,EAAE,WAAW,KAAK,MAAM,GAAG,SAAS,CAAC;CACtF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@0xchain/telemetry",
3
- "version": "1.1.0-beta.6",
3
+ "version": "1.1.0-beta.8",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -11,6 +11,11 @@
11
11
  "types": "./dist/index.d.ts",
12
12
  "import": "./dist/index.js",
13
13
  "default": "./dist/index.js"
14
+ },
15
+ "./next": {
16
+ "types": "./dist/next.d.ts",
17
+ "import": "./dist/next.js",
18
+ "default": "./dist/next.js"
14
19
  }
15
20
  },
16
21
  "files": [
@@ -19,14 +24,15 @@
19
24
  ],
20
25
  "dependencies": {
21
26
  "@opentelemetry/api": "1.9.0",
22
- "@opentelemetry/auto-instrumentations-node": "0.62.0",
23
- "@opentelemetry/exporter-trace-otlp-http": "0.203.0",
24
- "@opentelemetry/instrumentation-undici": "0.14.0",
25
- "@opentelemetry/otlp-exporter-base": "0.203.0",
26
- "@opentelemetry/resources": "2.0.1",
27
- "@opentelemetry/sdk-node": "0.203.0",
28
- "@opentelemetry/sdk-trace-base": "2.0.1",
29
- "@opentelemetry/semantic-conventions": "1.36.0"
27
+ "@opentelemetry/auto-instrumentations-node": "0.69.0",
28
+ "@opentelemetry/exporter-trace-otlp-http": "0.211.0",
29
+ "@opentelemetry/instrumentation-undici": "0.21.0",
30
+ "@opentelemetry/otlp-exporter-base": "0.211.0",
31
+ "@opentelemetry/resources": "2.5.0",
32
+ "@opentelemetry/sdk-node": "0.211.0",
33
+ "@opentelemetry/sdk-trace-base": "2.5.0",
34
+ "@opentelemetry/semantic-conventions": "1.39.0",
35
+ "next": "16.1.6"
30
36
  },
31
37
  "publishConfig": {
32
38
  "access": "public"
package/dist/index.js DELETED
@@ -1,98 +0,0 @@
1
- var S = Object.defineProperty;
2
- var f = (n, e, t) => e in n ? S(n, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : n[e] = t;
3
- var m = (n, e, t) => f(n, typeof e != "symbol" ? e + "" : e, t);
4
- import { NodeSDK as g } from "@opentelemetry/sdk-node";
5
- import { OTLPTraceExporter as E } from "@opentelemetry/exporter-trace-otlp-http";
6
- import { resourceFromAttributes as I } from "@opentelemetry/resources";
7
- import { ATTR_SERVICE_VERSION as T, ATTR_SERVICE_NAME as R } from "@opentelemetry/semantic-conventions";
8
- import { TraceIdRatioBasedSampler as _, AlwaysOnSampler as x, SamplingDecision as l, BatchSpanProcessor as w } from "@opentelemetry/sdk-trace-base";
9
- import { trace as A, TraceFlags as u } from "@opentelemetry/api";
10
- import { getNodeAutoInstrumentations as N } from "@opentelemetry/auto-instrumentations-node";
11
- import { UndiciInstrumentation as P } from "@opentelemetry/instrumentation-undici";
12
- const y = "deployment.environment.name";
13
- class D {
14
- constructor(e) {
15
- m(this, "defaultSampler");
16
- m(this, "inspectionSampler");
17
- this.defaultSampler = new _(e), this.inspectionSampler = new x();
18
- }
19
- shouldSample(e, t, r, s, o, i) {
20
- if (o["http.request.header.x-inspection"] === "true" || o["x-inspection"] === "true")
21
- return this.inspectionSampler.shouldSample(e, t, r, s, o, i);
22
- const a = A.getSpanContext(e);
23
- return a ? (a.traceFlags & u.SAMPLED) === u.SAMPLED ? { decision: l.RECORD_AND_SAMPLED } : { decision: l.NOT_RECORD } : this.defaultSampler.shouldSample(e, t, r, s, o, i);
24
- }
25
- toString() {
26
- return "InspectionSampler";
27
- }
28
- }
29
- const O = [
30
- "/health",
31
- "/metrics",
32
- "/_next/static",
33
- "/favicon.ico",
34
- "/__nextjs_",
35
- "/.well-known"
36
- ], d = (n, e) => n.some((t) => e.includes(t));
37
- function M(n) {
38
- const e = [...O, ...n];
39
- return [
40
- N({
41
- // 禁用可能导致问题的检测器
42
- "@opentelemetry/instrumentation-grpc": {
43
- enabled: !1
44
- },
45
- "@opentelemetry/instrumentation-http": {
46
- enabled: !0,
47
- startIncomingSpanHook: (t) => "headers" in t && t.headers["x-inspection"] === "true" ? {
48
- "http.request.header.x-inspection": "true",
49
- "x-inspection": "true"
50
- } : {},
51
- ignoreIncomingRequestHook: (t) => {
52
- const r = t.url || "";
53
- return d(e, r);
54
- },
55
- ignoreOutgoingRequestHook: (t) => {
56
- const r = typeof t == "string" ? t : t.path || "";
57
- return d(e, r);
58
- }
59
- }
60
- }),
61
- new P()
62
- ];
63
- }
64
- let c;
65
- function j(n) {
66
- const {
67
- serviceName: e,
68
- serviceVersion: t,
69
- environment: r,
70
- ignorePaths: s = [],
71
- inspectionRatio: o = 0.01,
72
- ...i
73
- } = n, p = I({
74
- [R]: e || "ichaingo-seo",
75
- [T]: t || "1.0.0",
76
- [y]: r || "development"
77
- }), a = new E(i), h = new w(a, {
78
- scheduledDelayMillis: 1e3,
79
- // 1秒延迟
80
- maxQueueSize: 2048,
81
- maxExportBatchSize: 512
82
- });
83
- c = new g({
84
- serviceName: e,
85
- resource: p,
86
- spanProcessors: [h],
87
- sampler: new D(o),
88
- // traceExporter,
89
- instrumentations: M(s)
90
- }), c.start(), console.log("OpenTelemetry started:", JSON.stringify(n, null, 2));
91
- }
92
- function q() {
93
- c && c.shutdown();
94
- }
95
- export {
96
- q as shutdownTelemetry,
97
- j as startTelemetry
98
- };