@morsehq-dev/sdk 0.4.0-rc.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.
- package/LICENSE +21 -0
- package/README.md +294 -0
- package/dist/anthropic/index.cjs +39 -0
- package/dist/anthropic/index.cjs.map +1 -0
- package/dist/anthropic/index.d.cts +213 -0
- package/dist/anthropic/index.d.ts +213 -0
- package/dist/anthropic/index.js +6 -0
- package/dist/anthropic/index.js.map +1 -0
- package/dist/anthropic-agent-sdk/index.cjs +744 -0
- package/dist/anthropic-agent-sdk/index.cjs.map +1 -0
- package/dist/anthropic-agent-sdk/index.d.cts +371 -0
- package/dist/anthropic-agent-sdk/index.d.ts +371 -0
- package/dist/anthropic-agent-sdk/index.js +735 -0
- package/dist/anthropic-agent-sdk/index.js.map +1 -0
- package/dist/browser/anthropic/index.cjs +39 -0
- package/dist/browser/anthropic/index.cjs.map +1 -0
- package/dist/browser/anthropic/index.js +6 -0
- package/dist/browser/anthropic/index.js.map +1 -0
- package/dist/browser/anthropic-agent-sdk/index.cjs +744 -0
- package/dist/browser/anthropic-agent-sdk/index.cjs.map +1 -0
- package/dist/browser/anthropic-agent-sdk/index.js +735 -0
- package/dist/browser/anthropic-agent-sdk/index.js.map +1 -0
- package/dist/browser/chunk-3643DC7K.cjs +365 -0
- package/dist/browser/chunk-3643DC7K.cjs.map +1 -0
- package/dist/browser/chunk-4FALQMOZ.js +232 -0
- package/dist/browser/chunk-4FALQMOZ.js.map +1 -0
- package/dist/browser/chunk-5J2QBK75.js +884 -0
- package/dist/browser/chunk-5J2QBK75.js.map +1 -0
- package/dist/browser/chunk-7MSXWGAH.js +53 -0
- package/dist/browser/chunk-7MSXWGAH.js.map +1 -0
- package/dist/browser/chunk-A24L5N5N.js +596 -0
- package/dist/browser/chunk-A24L5N5N.js.map +1 -0
- package/dist/browser/chunk-B7DEUDP6.cjs +177 -0
- package/dist/browser/chunk-B7DEUDP6.cjs.map +1 -0
- package/dist/browser/chunk-F6CJACNH.cjs +604 -0
- package/dist/browser/chunk-F6CJACNH.cjs.map +1 -0
- package/dist/browser/chunk-JBOYFQSB.js +412 -0
- package/dist/browser/chunk-JBOYFQSB.js.map +1 -0
- package/dist/browser/chunk-KRBADE6R.cjs +183 -0
- package/dist/browser/chunk-KRBADE6R.cjs.map +1 -0
- package/dist/browser/chunk-MCJYZH6W.cjs +415 -0
- package/dist/browser/chunk-MCJYZH6W.cjs.map +1 -0
- package/dist/browser/chunk-NQG2IAQS.js +178 -0
- package/dist/browser/chunk-NQG2IAQS.js.map +1 -0
- package/dist/browser/chunk-O4HG3OSK.cjs +929 -0
- package/dist/browser/chunk-O4HG3OSK.cjs.map +1 -0
- package/dist/browser/chunk-QWRQJO57.js +363 -0
- package/dist/browser/chunk-QWRQJO57.js.map +1 -0
- package/dist/browser/chunk-SWQOPFE4.cjs +234 -0
- package/dist/browser/chunk-SWQOPFE4.cjs.map +1 -0
- package/dist/browser/chunk-TYDG747E.js +171 -0
- package/dist/browser/chunk-TYDG747E.js.map +1 -0
- package/dist/browser/chunk-TZRSDDFP.cjs +56 -0
- package/dist/browser/chunk-TZRSDDFP.cjs.map +1 -0
- package/dist/browser/index.cjs +587 -0
- package/dist/browser/index.cjs.map +1 -0
- package/dist/browser/index.js +522 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/integrations/pino.cjs +89 -0
- package/dist/browser/integrations/pino.cjs.map +1 -0
- package/dist/browser/integrations/pino.js +86 -0
- package/dist/browser/integrations/pino.js.map +1 -0
- package/dist/browser/langchain/index.cjs +535 -0
- package/dist/browser/langchain/index.cjs.map +1 -0
- package/dist/browser/langchain/index.js +528 -0
- package/dist/browser/langchain/index.js.map +1 -0
- package/dist/browser/langgraph/index.cjs +377 -0
- package/dist/browser/langgraph/index.cjs.map +1 -0
- package/dist/browser/langgraph/index.js +371 -0
- package/dist/browser/langgraph/index.js.map +1 -0
- package/dist/browser/openai/index.cjs +125 -0
- package/dist/browser/openai/index.cjs.map +1 -0
- package/dist/browser/openai/index.js +122 -0
- package/dist/browser/openai/index.js.map +1 -0
- package/dist/browser/openai-agents/index.cjs +689 -0
- package/dist/browser/openai-agents/index.cjs.map +1 -0
- package/dist/browser/openai-agents/index.js +678 -0
- package/dist/browser/openai-agents/index.js.map +1 -0
- package/dist/browser/vercel-ai/index.cjs +233 -0
- package/dist/browser/vercel-ai/index.cjs.map +1 -0
- package/dist/browser/vercel-ai/index.js +231 -0
- package/dist/browser/vercel-ai/index.js.map +1 -0
- package/dist/chunk-4R4SHGOK.js +363 -0
- package/dist/chunk-4R4SHGOK.js.map +1 -0
- package/dist/chunk-7EO7MQBA.cjs +183 -0
- package/dist/chunk-7EO7MQBA.cjs.map +1 -0
- package/dist/chunk-7YCENA54.cjs +604 -0
- package/dist/chunk-7YCENA54.cjs.map +1 -0
- package/dist/chunk-CKFOGDUF.js +596 -0
- package/dist/chunk-CKFOGDUF.js.map +1 -0
- package/dist/chunk-FJUNILZT.cjs +1324 -0
- package/dist/chunk-FJUNILZT.cjs.map +1 -0
- package/dist/chunk-HDAFUKQ3.js +171 -0
- package/dist/chunk-HDAFUKQ3.js.map +1 -0
- package/dist/chunk-KBWPNIH4.cjs +234 -0
- package/dist/chunk-KBWPNIH4.cjs.map +1 -0
- package/dist/chunk-KJEO52QS.cjs +365 -0
- package/dist/chunk-KJEO52QS.cjs.map +1 -0
- package/dist/chunk-KZBCOZIQ.cjs +177 -0
- package/dist/chunk-KZBCOZIQ.cjs.map +1 -0
- package/dist/chunk-ME5JALGT.js +53 -0
- package/dist/chunk-ME5JALGT.js.map +1 -0
- package/dist/chunk-PVHDEPRE.cjs +56 -0
- package/dist/chunk-PVHDEPRE.cjs.map +1 -0
- package/dist/chunk-RTL23YOQ.js +178 -0
- package/dist/chunk-RTL23YOQ.js.map +1 -0
- package/dist/chunk-TQWI4UYO.js +1277 -0
- package/dist/chunk-TQWI4UYO.js.map +1 -0
- package/dist/chunk-VXDBDPDR.cjs +415 -0
- package/dist/chunk-VXDBDPDR.cjs.map +1 -0
- package/dist/chunk-XTKMUJWI.js +232 -0
- package/dist/chunk-XTKMUJWI.js.map +1 -0
- package/dist/chunk-ZKUGOWER.js +412 -0
- package/dist/chunk-ZKUGOWER.js.map +1 -0
- package/dist/index.cjs +843 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +464 -0
- package/dist/index.d.ts +464 -0
- package/dist/index.js +778 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/pino.cjs +89 -0
- package/dist/integrations/pino.cjs.map +1 -0
- package/dist/integrations/pino.d.cts +65 -0
- package/dist/integrations/pino.d.ts +65 -0
- package/dist/integrations/pino.js +86 -0
- package/dist/integrations/pino.js.map +1 -0
- package/dist/langchain/index.cjs +535 -0
- package/dist/langchain/index.cjs.map +1 -0
- package/dist/langchain/index.d.cts +265 -0
- package/dist/langchain/index.d.ts +265 -0
- package/dist/langchain/index.js +528 -0
- package/dist/langchain/index.js.map +1 -0
- package/dist/langgraph/index.cjs +377 -0
- package/dist/langgraph/index.cjs.map +1 -0
- package/dist/langgraph/index.d.cts +324 -0
- package/dist/langgraph/index.d.ts +324 -0
- package/dist/langgraph/index.js +371 -0
- package/dist/langgraph/index.js.map +1 -0
- package/dist/openai/index.cjs +125 -0
- package/dist/openai/index.cjs.map +1 -0
- package/dist/openai/index.d.cts +136 -0
- package/dist/openai/index.d.ts +136 -0
- package/dist/openai/index.js +122 -0
- package/dist/openai/index.js.map +1 -0
- package/dist/openai-agents/index.cjs +689 -0
- package/dist/openai-agents/index.cjs.map +1 -0
- package/dist/openai-agents/index.d.cts +502 -0
- package/dist/openai-agents/index.d.ts +502 -0
- package/dist/openai-agents/index.js +678 -0
- package/dist/openai-agents/index.js.map +1 -0
- package/dist/spans-DZtMuBvc.d.cts +73 -0
- package/dist/spans-DZtMuBvc.d.ts +73 -0
- package/dist/tracing-BYAqjT5Q.d.cts +114 -0
- package/dist/tracing-rz9cWQ8d.d.ts +114 -0
- package/dist/vercel-ai/index.cjs +233 -0
- package/dist/vercel-ai/index.cjs.map +1 -0
- package/dist/vercel-ai/index.d.cts +93 -0
- package/dist/vercel-ai/index.d.ts +93 -0
- package/dist/vercel-ai/index.js +231 -0
- package/dist/vercel-ai/index.js.map +1 -0
- package/package.json +182 -0
|
@@ -0,0 +1,1277 @@
|
|
|
1
|
+
import { createHash } from 'crypto';
|
|
2
|
+
import { TraceFlags, trace, ROOT_CONTEXT, SpanKind, SpanStatusCode, context } from '@opentelemetry/api';
|
|
3
|
+
import { ExportResultCode } from '@opentelemetry/core';
|
|
4
|
+
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto';
|
|
5
|
+
import { CompressionAlgorithm } from '@opentelemetry/otlp-exporter-base';
|
|
6
|
+
import { ParentBasedSampler, TraceIdRatioBasedSampler, BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';
|
|
7
|
+
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
|
|
8
|
+
import { registerInstrumentations } from '@opentelemetry/instrumentation';
|
|
9
|
+
import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks';
|
|
10
|
+
|
|
11
|
+
var __defProp = Object.defineProperty;
|
|
12
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
13
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
14
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
15
|
+
var __esm = (fn, res, err) => function __init() {
|
|
16
|
+
if (err) throw err[0];
|
|
17
|
+
try {
|
|
18
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
19
|
+
} catch (e) {
|
|
20
|
+
throw err = [e], e;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
var __export = (target, all) => {
|
|
24
|
+
for (var name in all)
|
|
25
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
26
|
+
};
|
|
27
|
+
var __copyProps = (to, from, except, desc) => {
|
|
28
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
29
|
+
for (let key of __getOwnPropNames(from))
|
|
30
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
31
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
32
|
+
}
|
|
33
|
+
return to;
|
|
34
|
+
};
|
|
35
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
36
|
+
|
|
37
|
+
// src/_internal/env.ts
|
|
38
|
+
function readEnv(key) {
|
|
39
|
+
if (typeof process !== "undefined" && process.env) {
|
|
40
|
+
const v = process.env[key];
|
|
41
|
+
if (typeof v === "string") return v;
|
|
42
|
+
}
|
|
43
|
+
const denoGlobal = globalThis.Deno;
|
|
44
|
+
if (denoGlobal?.env?.get) {
|
|
45
|
+
try {
|
|
46
|
+
const v = denoGlobal.env.get(key);
|
|
47
|
+
if (typeof v === "string") return v;
|
|
48
|
+
} catch {
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return void 0;
|
|
52
|
+
}
|
|
53
|
+
function truthy(value) {
|
|
54
|
+
if (!value) return false;
|
|
55
|
+
return ["1", "true", "yes", "on"].includes(value.trim().toLowerCase());
|
|
56
|
+
}
|
|
57
|
+
function getApiKey() {
|
|
58
|
+
const raw = readEnv("MORSE_API_KEY");
|
|
59
|
+
if (!raw) return void 0;
|
|
60
|
+
const trimmed = raw.trim();
|
|
61
|
+
return trimmed || void 0;
|
|
62
|
+
}
|
|
63
|
+
function getEndpoint() {
|
|
64
|
+
const raw = readEnv("MORSE_ENDPOINT");
|
|
65
|
+
if (!raw) return void 0;
|
|
66
|
+
const trimmed = raw.trim();
|
|
67
|
+
return trimmed || void 0;
|
|
68
|
+
}
|
|
69
|
+
function getFlushIntervalSeconds(defaultSeconds = 2) {
|
|
70
|
+
const raw = readEnv("MORSE_FLUSH_INTERVAL_SECONDS");
|
|
71
|
+
if (!raw) return defaultSeconds;
|
|
72
|
+
const parsed = Number.parseFloat(raw.trim());
|
|
73
|
+
if (!Number.isFinite(parsed) || parsed <= 0) return defaultSeconds;
|
|
74
|
+
return parsed;
|
|
75
|
+
}
|
|
76
|
+
function isDisabled() {
|
|
77
|
+
return truthy(readEnv("MORSE_DISABLED"));
|
|
78
|
+
}
|
|
79
|
+
function isDebug() {
|
|
80
|
+
return truthy(readEnv("MORSE_SDK_DEBUG"));
|
|
81
|
+
}
|
|
82
|
+
function isTelemetryDisabled() {
|
|
83
|
+
return truthy(readEnv("MORSE_SDK_DISABLE_TELEMETRY"));
|
|
84
|
+
}
|
|
85
|
+
function isAutoDetectDisabled() {
|
|
86
|
+
return truthy(readEnv("MORSE_DISABLE_AUTO_DETECT"));
|
|
87
|
+
}
|
|
88
|
+
function getInternalSource() {
|
|
89
|
+
const raw = readEnv("MORSE_INTERNAL_SOURCE");
|
|
90
|
+
if (!raw) return void 0;
|
|
91
|
+
const trimmed = raw.trim().toLowerCase();
|
|
92
|
+
if (!trimmed) return void 0;
|
|
93
|
+
return VALID_INTERNAL_SOURCES.has(trimmed) ? trimmed : void 0;
|
|
94
|
+
}
|
|
95
|
+
function isValidInternalSource(value) {
|
|
96
|
+
return typeof value === "string" && VALID_INTERNAL_SOURCES.has(value);
|
|
97
|
+
}
|
|
98
|
+
function getSampleRate(defaultRate = 1) {
|
|
99
|
+
const raw = readEnv("MORSE_SAMPLE_RATE");
|
|
100
|
+
if (!raw) return defaultRate;
|
|
101
|
+
const parsed = Number.parseFloat(raw.trim());
|
|
102
|
+
if (!Number.isFinite(parsed) || parsed < 0 || parsed > 1) return defaultRate;
|
|
103
|
+
return parsed;
|
|
104
|
+
}
|
|
105
|
+
function getMaxFieldBytes(defaultBytes = 65536) {
|
|
106
|
+
const raw = readEnv("MORSE_MAX_FIELD_BYTES");
|
|
107
|
+
if (!raw) return defaultBytes;
|
|
108
|
+
const parsed = Number.parseInt(raw.trim(), 10);
|
|
109
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : defaultBytes;
|
|
110
|
+
}
|
|
111
|
+
function getMaxQueueSize(defaultSize = 2048) {
|
|
112
|
+
const raw = readEnv("MORSE_MAX_QUEUE_SIZE");
|
|
113
|
+
if (!raw) return defaultSize;
|
|
114
|
+
const parsed = Number.parseInt(raw.trim(), 10);
|
|
115
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : defaultSize;
|
|
116
|
+
}
|
|
117
|
+
function getMaxBatchSize(defaultSize = 512) {
|
|
118
|
+
const raw = readEnv("MORSE_MAX_BATCH_SIZE");
|
|
119
|
+
if (!raw) return defaultSize;
|
|
120
|
+
const parsed = Number.parseInt(raw.trim(), 10);
|
|
121
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : defaultSize;
|
|
122
|
+
}
|
|
123
|
+
function isLegacyTransport() {
|
|
124
|
+
return truthy(readEnv("MORSE_LEGACY_TRANSPORT"));
|
|
125
|
+
}
|
|
126
|
+
function isDbCaptureEnabled() {
|
|
127
|
+
return truthy(readEnv("MORSE_CAPTURE_DB")) || truthy(readEnv("MORSE_CAPTURE_INFRA"));
|
|
128
|
+
}
|
|
129
|
+
var DEFAULT_ENDPOINT, VALID_INTERNAL_SOURCES;
|
|
130
|
+
var init_env = __esm({
|
|
131
|
+
"src/_internal/env.ts"() {
|
|
132
|
+
DEFAULT_ENDPOINT = "https://api.morsehq.dev/api/v1/traces/batch";
|
|
133
|
+
VALID_INTERNAL_SOURCES = /* @__PURE__ */ new Set(["copilot", "investigator", "refagent", "ui-bot"]);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// src/_internal/spans.ts
|
|
138
|
+
function generateTraceId() {
|
|
139
|
+
return randomHex(32);
|
|
140
|
+
}
|
|
141
|
+
function generateSpanId() {
|
|
142
|
+
return randomHex(32);
|
|
143
|
+
}
|
|
144
|
+
function randomHex(chars) {
|
|
145
|
+
const bytes = new Uint8Array(Math.ceil(chars / 2));
|
|
146
|
+
const cryptoObj = globalThis.crypto;
|
|
147
|
+
if (cryptoObj?.getRandomValues) {
|
|
148
|
+
cryptoObj.getRandomValues(bytes);
|
|
149
|
+
} else {
|
|
150
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
151
|
+
bytes[i] = Math.floor(Math.random() * 256);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
let hex = "";
|
|
155
|
+
for (const b of bytes) {
|
|
156
|
+
hex += b.toString(16).padStart(2, "0");
|
|
157
|
+
}
|
|
158
|
+
return hex.slice(0, chars);
|
|
159
|
+
}
|
|
160
|
+
function nowIso() {
|
|
161
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
162
|
+
}
|
|
163
|
+
function spanToWire(span) {
|
|
164
|
+
const out = {};
|
|
165
|
+
for (const [k, v] of Object.entries(span)) {
|
|
166
|
+
if (v !== void 0 && v !== null) {
|
|
167
|
+
out[k] = v;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return out;
|
|
171
|
+
}
|
|
172
|
+
function buildTraceEntry(fields, spans) {
|
|
173
|
+
return {
|
|
174
|
+
trace: fields,
|
|
175
|
+
spans: spans.map(spanToWire)
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
var SpanType;
|
|
179
|
+
var init_spans = __esm({
|
|
180
|
+
"src/_internal/spans.ts"() {
|
|
181
|
+
SpanType = {
|
|
182
|
+
AGENT: "agent",
|
|
183
|
+
LLM: "llm",
|
|
184
|
+
TOOL: "tool",
|
|
185
|
+
HTTP: "http",
|
|
186
|
+
DB: "db",
|
|
187
|
+
CUSTOM: "custom",
|
|
188
|
+
MEMORY: "memory",
|
|
189
|
+
// MHQ-482: matches Python's `SpanType.RETRIEVER` (apps/sdk/python/src/morse_ai/spans.py).
|
|
190
|
+
// @beta — retriever span type is subject to change before SDK v1.0 (see
|
|
191
|
+
// the plain-LangChain adapter's on_retriever_* callbacks in src/langchain/).
|
|
192
|
+
RETRIEVER: "retriever"
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
// src/_internal/redaction.ts
|
|
198
|
+
function buildRedactionConfig(options) {
|
|
199
|
+
const opts = options ?? {};
|
|
200
|
+
const enabled = opts.enabled !== false;
|
|
201
|
+
if (!enabled) {
|
|
202
|
+
return {
|
|
203
|
+
enabled: false,
|
|
204
|
+
enabledPatterns: /* @__PURE__ */ new Set(),
|
|
205
|
+
extraCompiled: []
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
const disabled = new Set(opts.disabledPatterns ?? []);
|
|
209
|
+
for (const key of disabled) {
|
|
210
|
+
if (MANDATORY_PATTERNS.has(key)) {
|
|
211
|
+
throw new Error(`redaction pattern '${key}' cannot be disabled (server-side mandatory)`);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
const active = /* @__PURE__ */ new Set();
|
|
215
|
+
for (const key of PATTERN_ORDER) {
|
|
216
|
+
if (DEFAULT_OFF_PATTERNS.has(key)) continue;
|
|
217
|
+
if (disabled.has(key)) continue;
|
|
218
|
+
active.add(key);
|
|
219
|
+
}
|
|
220
|
+
const extraInput = opts.extraPatterns ?? [];
|
|
221
|
+
if (extraInput.length > EXTRA_PATTERN_CAP) {
|
|
222
|
+
throw new Error(
|
|
223
|
+
`too many redaction extra patterns: ${extraInput.length} (max ${EXTRA_PATTERN_CAP})`
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
const extraCompiled = [];
|
|
227
|
+
for (const raw of extraInput) {
|
|
228
|
+
if (typeof raw !== "string") {
|
|
229
|
+
throw new Error(`redaction extra pattern must be a string, got ${typeof raw}`);
|
|
230
|
+
}
|
|
231
|
+
if (raw.length > EXTRA_PATTERN_CHAR_CAP) {
|
|
232
|
+
throw new Error(`redaction extra pattern exceeds ${EXTRA_PATTERN_CHAR_CAP} chars`);
|
|
233
|
+
}
|
|
234
|
+
let compiled;
|
|
235
|
+
try {
|
|
236
|
+
compiled = new RegExp(raw, "g");
|
|
237
|
+
} catch (err) {
|
|
238
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
239
|
+
throw new Error(`redaction extra pattern failed to compile: ${JSON.stringify(raw)} \u2014 ${msg}`);
|
|
240
|
+
}
|
|
241
|
+
extraCompiled.push(compiled);
|
|
242
|
+
}
|
|
243
|
+
return {
|
|
244
|
+
enabled: true,
|
|
245
|
+
enabledPatterns: active,
|
|
246
|
+
extraCompiled
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
function luhnValid(s) {
|
|
250
|
+
let sum = 0;
|
|
251
|
+
let alt = false;
|
|
252
|
+
let digits = 0;
|
|
253
|
+
for (let i = s.length - 1; i >= 0; i--) {
|
|
254
|
+
const ch = s.charCodeAt(i);
|
|
255
|
+
if (ch < 48 || ch > 57) continue;
|
|
256
|
+
let n = ch - 48;
|
|
257
|
+
if (alt) {
|
|
258
|
+
n *= 2;
|
|
259
|
+
if (n > 9) n -= 9;
|
|
260
|
+
}
|
|
261
|
+
sum += n;
|
|
262
|
+
alt = !alt;
|
|
263
|
+
digits++;
|
|
264
|
+
}
|
|
265
|
+
if (digits < 13 || digits > 19) return false;
|
|
266
|
+
return sum % 10 === 0;
|
|
267
|
+
}
|
|
268
|
+
function resolveEnabled(config, override) {
|
|
269
|
+
return config.enabledPatterns;
|
|
270
|
+
}
|
|
271
|
+
function redactString(s, config, enabledOverride) {
|
|
272
|
+
if (!config.enabled && enabledOverride === void 0) {
|
|
273
|
+
return s;
|
|
274
|
+
}
|
|
275
|
+
if (s.length === 0) return s;
|
|
276
|
+
const enabled = resolveEnabled(config);
|
|
277
|
+
let out = s;
|
|
278
|
+
for (const key of PATTERN_ORDER) {
|
|
279
|
+
if (!enabled.has(key)) continue;
|
|
280
|
+
const re = PATTERNS[key];
|
|
281
|
+
if (re === void 0) continue;
|
|
282
|
+
re.lastIndex = 0;
|
|
283
|
+
const replacement = `[REDACTED:${SHORT_KEYS[key]}]`;
|
|
284
|
+
if (key === "credit_card") {
|
|
285
|
+
out = out.replace(re, (m) => luhnValid(m) ? replacement : m);
|
|
286
|
+
} else {
|
|
287
|
+
out = out.replace(re, replacement);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
for (const re of config.extraCompiled) {
|
|
291
|
+
re.lastIndex = 0;
|
|
292
|
+
out = out.replace(re, "[REDACTED:custom]");
|
|
293
|
+
}
|
|
294
|
+
return out;
|
|
295
|
+
}
|
|
296
|
+
function redactValue(value, config, depth = 0) {
|
|
297
|
+
if (!config.enabled) return value;
|
|
298
|
+
if (value === null || value === void 0) return value;
|
|
299
|
+
if (typeof value === "string") return redactString(value, config);
|
|
300
|
+
if (typeof value === "number" || typeof value === "boolean") return value;
|
|
301
|
+
if (depth >= MAX_DEPTH) return value;
|
|
302
|
+
if (Array.isArray(value)) {
|
|
303
|
+
return value.map((item) => redactValue(item, config, depth + 1));
|
|
304
|
+
}
|
|
305
|
+
if (typeof value === "object") {
|
|
306
|
+
const proto = Object.getPrototypeOf(value);
|
|
307
|
+
if (proto === Object.prototype || proto === null) {
|
|
308
|
+
const out = {};
|
|
309
|
+
for (const [k, v] of Object.entries(value)) {
|
|
310
|
+
out[k] = redactValue(v, config, depth + 1);
|
|
311
|
+
}
|
|
312
|
+
return out;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
return value;
|
|
316
|
+
}
|
|
317
|
+
var PATTERN_ORDER, MANDATORY_PATTERNS, DEFAULT_OFF_PATTERNS, SHORT_KEYS, PATTERNS, EXTRA_PATTERN_CAP, EXTRA_PATTERN_CHAR_CAP, MAX_DEPTH;
|
|
318
|
+
var init_redaction = __esm({
|
|
319
|
+
"src/_internal/redaction.ts"() {
|
|
320
|
+
PATTERN_ORDER = [
|
|
321
|
+
"api_key_prefixed",
|
|
322
|
+
"jwt",
|
|
323
|
+
"credit_card",
|
|
324
|
+
"email",
|
|
325
|
+
"phone_us",
|
|
326
|
+
"phone_e164",
|
|
327
|
+
"ssn_us",
|
|
328
|
+
"ip_address"
|
|
329
|
+
];
|
|
330
|
+
MANDATORY_PATTERNS = /* @__PURE__ */ new Set([
|
|
331
|
+
"api_key_prefixed",
|
|
332
|
+
"jwt",
|
|
333
|
+
"credit_card",
|
|
334
|
+
"ssn_us"
|
|
335
|
+
]);
|
|
336
|
+
DEFAULT_OFF_PATTERNS = /* @__PURE__ */ new Set(["ip_address"]);
|
|
337
|
+
SHORT_KEYS = {
|
|
338
|
+
api_key_prefixed: "api_key",
|
|
339
|
+
jwt: "jwt",
|
|
340
|
+
credit_card: "credit_card",
|
|
341
|
+
email: "email",
|
|
342
|
+
phone_us: "phone",
|
|
343
|
+
phone_e164: "phone",
|
|
344
|
+
ssn_us: "ssn",
|
|
345
|
+
ip_address: "ip"
|
|
346
|
+
};
|
|
347
|
+
PATTERNS = {
|
|
348
|
+
api_key_prefixed: new RegExp(
|
|
349
|
+
"\\b(?:sk-[A-Za-z0-9_-]{20,}|sk_(?:live|test)_[A-Za-z0-9]{20,}|mhq_[A-Za-z0-9]{20,}|av_[A-Za-z0-9]{20,}|ghp_[A-Za-z0-9]{36}|gho_[A-Za-z0-9]{36}|ghu_[A-Za-z0-9]{36}|ghs_[A-Za-z0-9]{36}|ghr_[A-Za-z0-9]{36}|xox[bopsa]-[0-9A-Za-z\\-]{10,}|(?:AKIA|ASIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASCA)[0-9A-Z]{16})\\b",
|
|
350
|
+
"g"
|
|
351
|
+
),
|
|
352
|
+
jwt: new RegExp(
|
|
353
|
+
"\\beyJ[A-Za-z0-9_=-]{16,}\\.eyJ[A-Za-z0-9_=-]{16,}\\.[A-Za-z0-9_=-]{16,}\\b",
|
|
354
|
+
"g"
|
|
355
|
+
),
|
|
356
|
+
credit_card: new RegExp("\\b(?:\\d[ -]?){12,18}\\d\\b", "g"),
|
|
357
|
+
email: new RegExp("\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}\\b", "gi"),
|
|
358
|
+
// The leading `(?<!\d)` and trailing `(?!\d)` lookarounds prevent
|
|
359
|
+
// the phone matcher from carving a 10-digit substring out of a longer
|
|
360
|
+
// continuous digit run (e.g., a 16-digit credit-card-shaped number that
|
|
361
|
+
// failed Luhn). Without them, `1234567890123456` would emit a
|
|
362
|
+
// `[REDACTED:phone]` for digits 7-16 even though the whole run was
|
|
363
|
+
// never a real phone number. The canonical Python regex needs the same
|
|
364
|
+
// shim — see redaction.py.
|
|
365
|
+
phone_us: new RegExp(
|
|
366
|
+
"(?<!\\d)(?:\\+?1[ \\-.])?\\(?[2-9]\\d{2}\\)?[ \\-.]?\\d{3}[ \\-.]?\\d{4}(?!\\d)",
|
|
367
|
+
"g"
|
|
368
|
+
),
|
|
369
|
+
phone_e164: new RegExp("(?<!\\d)\\+(?:[0-9][ \\-.]?){8,14}[0-9](?!\\d)", "g"),
|
|
370
|
+
ssn_us: new RegExp(
|
|
371
|
+
"\\b(?!000|666|9\\d{2})\\d{3}[ \\-.](?!00)\\d{2}[ \\-.](?!0000)\\d{4}\\b",
|
|
372
|
+
"g"
|
|
373
|
+
),
|
|
374
|
+
ip_address: new RegExp(
|
|
375
|
+
"\\b(?:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}|(?:[A-F0-9]{1,4}:){2,7}[A-F0-9]{1,4})\\b",
|
|
376
|
+
"gi"
|
|
377
|
+
)
|
|
378
|
+
};
|
|
379
|
+
EXTRA_PATTERN_CAP = 10;
|
|
380
|
+
EXTRA_PATTERN_CHAR_CAP = 256;
|
|
381
|
+
MAX_DEPTH = 10;
|
|
382
|
+
}
|
|
383
|
+
});
|
|
384
|
+
function ensureGlobalContextManager() {
|
|
385
|
+
if (contextManagerRegistered) return;
|
|
386
|
+
contextManagerRegistered = true;
|
|
387
|
+
try {
|
|
388
|
+
context.setGlobalContextManager(new AsyncHooksContextManager().enable());
|
|
389
|
+
} catch {
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
function withOtelSpanContext(traceIdHex, spanIdHex, fn) {
|
|
393
|
+
const eng = getEngine();
|
|
394
|
+
if (eng.provider === null) return fn();
|
|
395
|
+
ensureGlobalContextManager();
|
|
396
|
+
const sampled = eng.resolveSampled(traceIdHex);
|
|
397
|
+
const spanCtx = {
|
|
398
|
+
traceId: traceIdHex,
|
|
399
|
+
spanId: spanIdHex,
|
|
400
|
+
isRemote: true,
|
|
401
|
+
traceFlags: sampled ? TraceFlags.SAMPLED : TraceFlags.NONE
|
|
402
|
+
};
|
|
403
|
+
const withCtx = trace.setSpanContext(context.active(), spanCtx);
|
|
404
|
+
return context.with(withCtx, fn);
|
|
405
|
+
}
|
|
406
|
+
function capBytes(value, maxBytes) {
|
|
407
|
+
if (maxBytes <= 0) return value;
|
|
408
|
+
const encoded = Buffer.from(value, "utf-8");
|
|
409
|
+
if (encoded.length <= maxBytes) return value;
|
|
410
|
+
const markerBytes = Buffer.byteLength(TRUNCATION_MARKER, "utf-8");
|
|
411
|
+
const budget = Math.max(maxBytes - markerBytes, 0);
|
|
412
|
+
let truncated = encoded.subarray(0, budget);
|
|
413
|
+
const decoder = new TextDecoder("utf-8", { fatal: true });
|
|
414
|
+
while (truncated.length > 0) {
|
|
415
|
+
try {
|
|
416
|
+
return decoder.decode(truncated) + TRUNCATION_MARKER;
|
|
417
|
+
} catch {
|
|
418
|
+
truncated = truncated.subarray(0, truncated.length - 1);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
return TRUNCATION_MARKER;
|
|
422
|
+
}
|
|
423
|
+
function jsonCapped(value, maxBytes) {
|
|
424
|
+
if (value === null || value === void 0) return null;
|
|
425
|
+
if (typeof value === "string") {
|
|
426
|
+
return JSON.stringify(capBytes(value, maxBytes));
|
|
427
|
+
}
|
|
428
|
+
let encoded;
|
|
429
|
+
try {
|
|
430
|
+
encoded = JSON.stringify(value, (_k, v) => typeof v === "bigint" ? String(v) : v) ?? "null";
|
|
431
|
+
} catch {
|
|
432
|
+
encoded = JSON.stringify(String(value));
|
|
433
|
+
}
|
|
434
|
+
return capBytes(encoded, maxBytes);
|
|
435
|
+
}
|
|
436
|
+
function decorrelateTraceIdForSampling(traceIdHex) {
|
|
437
|
+
const traceIdBytes = Buffer.from(traceIdHex.padStart(32, "0").slice(0, 32), "hex");
|
|
438
|
+
return createHash("sha256").update(traceIdBytes).digest();
|
|
439
|
+
}
|
|
440
|
+
function ratioSample(traceIdHex, rate) {
|
|
441
|
+
if (rate <= 0) return false;
|
|
442
|
+
if (rate >= 1) return true;
|
|
443
|
+
const digest = decorrelateTraceIdForSampling(traceIdHex);
|
|
444
|
+
const low64 = digest.subarray(8, 16).readBigUInt64BE();
|
|
445
|
+
const threshold = BigInt(Math.round(rate * Number(MAX_U64)));
|
|
446
|
+
return low64 < threshold;
|
|
447
|
+
}
|
|
448
|
+
function redactAttrValue(value, config) {
|
|
449
|
+
if (typeof value === "string") return redactString(value, config);
|
|
450
|
+
if (Array.isArray(value)) {
|
|
451
|
+
return value.map((v) => typeof v === "string" ? redactString(v, config) : v);
|
|
452
|
+
}
|
|
453
|
+
return value;
|
|
454
|
+
}
|
|
455
|
+
function getEngine() {
|
|
456
|
+
if (engine === null) engine = new OtelEngine();
|
|
457
|
+
return engine;
|
|
458
|
+
}
|
|
459
|
+
function spanDictToOtelAttributes(spanDict, traceDict, resourceDict, opts) {
|
|
460
|
+
const attrs = {};
|
|
461
|
+
const spanType = spanDict.type;
|
|
462
|
+
if (typeof spanType === "string" && spanType) attrs["av.span_type"] = spanType;
|
|
463
|
+
const model = spanDict.model;
|
|
464
|
+
if (model !== void 0 && model !== null) attrs["gen_ai.request.model"] = String(model);
|
|
465
|
+
const tokenFields = [
|
|
466
|
+
["input_tokens", "gen_ai.usage.input_tokens"],
|
|
467
|
+
["output_tokens", "gen_ai.usage.output_tokens"],
|
|
468
|
+
["cached_input_tokens", "gen_ai.usage.cache_read_input_tokens"],
|
|
469
|
+
["cache_write_tokens", "gen_ai.usage.cache_creation_input_tokens"],
|
|
470
|
+
["reasoning_tokens", "gen_ai.usage.reasoning_tokens"]
|
|
471
|
+
];
|
|
472
|
+
for (const [src, otelKey] of tokenFields) {
|
|
473
|
+
const v = spanDict[src];
|
|
474
|
+
if (v !== void 0 && v !== null) {
|
|
475
|
+
const n = Number(v);
|
|
476
|
+
if (Number.isFinite(n)) attrs[otelKey] = Math.trunc(n);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
const costUsd = spanDict.cost_usd;
|
|
480
|
+
if (costUsd !== void 0 && costUsd !== null) {
|
|
481
|
+
attrs["av.cost_usd"] = String(costUsd);
|
|
482
|
+
}
|
|
483
|
+
for (const [src, otelKey] of [
|
|
484
|
+
["input_data", "av.input_data"],
|
|
485
|
+
["output_data", "av.output_data"],
|
|
486
|
+
["context_segments", "av.context_segments"]
|
|
487
|
+
]) {
|
|
488
|
+
const v = spanDict[src];
|
|
489
|
+
if (v !== void 0 && v !== null) {
|
|
490
|
+
const encoded = jsonCapped(v, opts.maxFieldBytes);
|
|
491
|
+
if (encoded !== null) attrs[otelKey] = encoded;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
const metadata = spanDict.metadata;
|
|
495
|
+
if (metadata && typeof metadata === "object") {
|
|
496
|
+
for (const [key, value] of Object.entries(metadata)) {
|
|
497
|
+
const encoded = jsonCapped(value, opts.maxFieldBytes);
|
|
498
|
+
if (encoded !== null) attrs[`av.metadata.${key}`] = encoded;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
const errorMessage = spanDict.error_message;
|
|
502
|
+
if (opts.isRoot) {
|
|
503
|
+
const threadId = traceDict.thread_id;
|
|
504
|
+
if (threadId !== void 0 && threadId !== null) attrs["av.thread_id"] = String(threadId);
|
|
505
|
+
const userId = traceDict.user_id;
|
|
506
|
+
if (userId !== void 0 && userId !== null) attrs["av.user_id"] = String(userId);
|
|
507
|
+
const userMetadata = traceDict.user_metadata;
|
|
508
|
+
if (userMetadata && typeof userMetadata === "object") {
|
|
509
|
+
const entries = Object.entries(userMetadata);
|
|
510
|
+
if (entries.length > 0) {
|
|
511
|
+
attrs["av.user_metadata"] = JSON.stringify(
|
|
512
|
+
Object.fromEntries(entries.map(([k, v]) => [k, String(v)]))
|
|
513
|
+
);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
const success = traceDict.success;
|
|
517
|
+
if (success !== void 0 && success !== null) attrs["av.outcome.success"] = Boolean(success);
|
|
518
|
+
const outcome = traceDict.outcome;
|
|
519
|
+
if (outcome !== void 0 && outcome !== null) attrs["av.outcome.label"] = String(outcome);
|
|
520
|
+
const framework = resourceDict["morse_ai.framework"];
|
|
521
|
+
if (typeof framework === "string" && framework) attrs["av.framework"] = framework;
|
|
522
|
+
const source = resourceDict["morse_ai.source"];
|
|
523
|
+
if (typeof source === "string" && source) attrs["av.source"] = source;
|
|
524
|
+
}
|
|
525
|
+
if (errorMessage && spanDict.status === "failed") {
|
|
526
|
+
attrs["av.error_message"] = String(errorMessage);
|
|
527
|
+
}
|
|
528
|
+
return attrs;
|
|
529
|
+
}
|
|
530
|
+
function isoToTimeInputMillis(value) {
|
|
531
|
+
if (typeof value !== "string" || !value) return void 0;
|
|
532
|
+
const ms = Date.parse(value);
|
|
533
|
+
return Number.isNaN(ms) ? void 0 : ms;
|
|
534
|
+
}
|
|
535
|
+
function emitTraceEntry(entry) {
|
|
536
|
+
const eng = getEngine();
|
|
537
|
+
const tracer = eng.tracer;
|
|
538
|
+
if (tracer === null) return;
|
|
539
|
+
const traceDict = entry.trace ?? {};
|
|
540
|
+
const spanDicts = entry.spans ?? [];
|
|
541
|
+
const resourceDict = entry.resource ?? {};
|
|
542
|
+
if (spanDicts.length === 0) return;
|
|
543
|
+
const traceIdHexRaw = traceDict.trace_id;
|
|
544
|
+
if (typeof traceIdHexRaw !== "string" || traceIdHexRaw.length === 0) return;
|
|
545
|
+
const traceIdHex = traceIdHexRaw.toLowerCase().padStart(32, "0").slice(0, 32);
|
|
546
|
+
if (!/^[0-9a-f]{32}$/.test(traceIdHex) || /^0+$/.test(traceIdHex)) return;
|
|
547
|
+
const sampled = eng.resolveSampled(traceIdHex);
|
|
548
|
+
const syntheticParentContext = {
|
|
549
|
+
traceId: traceIdHex,
|
|
550
|
+
// Placeholder — only traceId/traceFlags matter here; every real span
|
|
551
|
+
// in the trace gets its own OTel-minted spanId via startSpan().
|
|
552
|
+
spanId: "0000000000000001",
|
|
553
|
+
isRemote: true,
|
|
554
|
+
traceFlags: sampled ? TraceFlags.SAMPLED : TraceFlags.NONE
|
|
555
|
+
};
|
|
556
|
+
const rootParentCtx = trace.setSpanContext(ROOT_CONTEXT, syntheticParentContext);
|
|
557
|
+
let rootSpanId;
|
|
558
|
+
for (const s of spanDicts) {
|
|
559
|
+
if (!s.parent_span_id) {
|
|
560
|
+
rootSpanId = s.span_id;
|
|
561
|
+
break;
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
if (rootSpanId === void 0 && spanDicts.length > 0) {
|
|
565
|
+
rootSpanId = spanDicts[0].span_id;
|
|
566
|
+
}
|
|
567
|
+
const ordered = [...spanDicts].sort((a, b) => {
|
|
568
|
+
const aIsRoot = a.span_id === rootSpanId ? 0 : 1;
|
|
569
|
+
const bIsRoot = b.span_id === rootSpanId ? 0 : 1;
|
|
570
|
+
return aIsRoot - bIsRoot;
|
|
571
|
+
});
|
|
572
|
+
const spanCtxById = /* @__PURE__ */ new Map();
|
|
573
|
+
const maxFieldBytes = eng.maxFieldBytes;
|
|
574
|
+
for (const spanDict of ordered) {
|
|
575
|
+
const spanIdHex = typeof spanDict.span_id === "string" ? spanDict.span_id : void 0;
|
|
576
|
+
const parentIdHex = typeof spanDict.parent_span_id === "string" ? spanDict.parent_span_id : void 0;
|
|
577
|
+
let parentCtx = rootParentCtx;
|
|
578
|
+
if (parentIdHex && spanCtxById.has(parentIdHex)) {
|
|
579
|
+
parentCtx = trace.setSpanContext(ROOT_CONTEXT, spanCtxById.get(parentIdHex));
|
|
580
|
+
}
|
|
581
|
+
const attributes = spanDictToOtelAttributes(spanDict, traceDict, resourceDict, {
|
|
582
|
+
isRoot: spanDict.span_id === rootSpanId,
|
|
583
|
+
maxFieldBytes
|
|
584
|
+
});
|
|
585
|
+
const startTime = isoToTimeInputMillis(spanDict.started_at);
|
|
586
|
+
const endTime = isoToTimeInputMillis(spanDict.ended_at) ?? startTime;
|
|
587
|
+
try {
|
|
588
|
+
const otelSpan = tracer.startSpan(
|
|
589
|
+
typeof spanDict.name === "string" && spanDict.name ? spanDict.name : "span",
|
|
590
|
+
{
|
|
591
|
+
kind: SpanKind.INTERNAL,
|
|
592
|
+
attributes,
|
|
593
|
+
startTime
|
|
594
|
+
},
|
|
595
|
+
parentCtx
|
|
596
|
+
);
|
|
597
|
+
if (spanIdHex) {
|
|
598
|
+
spanCtxById.set(spanIdHex, otelSpan.spanContext());
|
|
599
|
+
}
|
|
600
|
+
if (spanDict.status === "failed") {
|
|
601
|
+
otelSpan.setStatus({
|
|
602
|
+
code: SpanStatusCode.ERROR,
|
|
603
|
+
message: String(spanDict.error_message ?? "")
|
|
604
|
+
});
|
|
605
|
+
}
|
|
606
|
+
otelSpan.end(endTime);
|
|
607
|
+
} catch {
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
var INSTRUMENTATION_NAME, DEFAULT_MAX_FIELD_BYTES, TRUNCATION_MARKER, contextManagerRegistered, MAX_U64, RedactingSpanExporter, RecordingSpanExporter, ResultCapturingExporter, OtelEngine, engine;
|
|
612
|
+
var init_otel_provider = __esm({
|
|
613
|
+
"src/_internal/otel-provider.ts"() {
|
|
614
|
+
init_redaction();
|
|
615
|
+
INSTRUMENTATION_NAME = "morse-typescript";
|
|
616
|
+
DEFAULT_MAX_FIELD_BYTES = 65536;
|
|
617
|
+
TRUNCATION_MARKER = "\u2026[truncated]";
|
|
618
|
+
contextManagerRegistered = false;
|
|
619
|
+
MAX_U64 = (1n << 64n) - 1n;
|
|
620
|
+
RedactingSpanExporter = class {
|
|
621
|
+
constructor(inner, redactionConfig2) {
|
|
622
|
+
this.inner = inner;
|
|
623
|
+
this.redactionConfig = redactionConfig2;
|
|
624
|
+
}
|
|
625
|
+
inner;
|
|
626
|
+
redactionConfig;
|
|
627
|
+
export(spans, resultCallback) {
|
|
628
|
+
const config = this.redactionConfig;
|
|
629
|
+
if (config && (config.enabled || config.extraCompiled.length > 0)) {
|
|
630
|
+
for (const span of spans) {
|
|
631
|
+
const attrs = span.attributes;
|
|
632
|
+
if (!attrs) continue;
|
|
633
|
+
for (const key of Object.keys(attrs)) {
|
|
634
|
+
attrs[key] = redactAttrValue(attrs[key], config);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
this.inner.export(spans, resultCallback);
|
|
639
|
+
}
|
|
640
|
+
shutdown() {
|
|
641
|
+
return this.inner.shutdown();
|
|
642
|
+
}
|
|
643
|
+
forceFlush() {
|
|
644
|
+
return this.inner.forceFlush ? this.inner.forceFlush() : Promise.resolve();
|
|
645
|
+
}
|
|
646
|
+
};
|
|
647
|
+
RecordingSpanExporter = class {
|
|
648
|
+
spans = [];
|
|
649
|
+
export(spans, resultCallback) {
|
|
650
|
+
this.spans.push(...spans);
|
|
651
|
+
resultCallback({ code: ExportResultCode.SUCCESS });
|
|
652
|
+
}
|
|
653
|
+
shutdown() {
|
|
654
|
+
return Promise.resolve();
|
|
655
|
+
}
|
|
656
|
+
forceFlush() {
|
|
657
|
+
return Promise.resolve();
|
|
658
|
+
}
|
|
659
|
+
clear() {
|
|
660
|
+
this.spans = [];
|
|
661
|
+
}
|
|
662
|
+
};
|
|
663
|
+
ResultCapturingExporter = class {
|
|
664
|
+
constructor(inner, sink) {
|
|
665
|
+
this.inner = inner;
|
|
666
|
+
this.sink = sink;
|
|
667
|
+
}
|
|
668
|
+
inner;
|
|
669
|
+
sink;
|
|
670
|
+
export(spans, resultCallback) {
|
|
671
|
+
this.inner.export(spans, (result) => {
|
|
672
|
+
this.sink(result);
|
|
673
|
+
resultCallback(result);
|
|
674
|
+
});
|
|
675
|
+
}
|
|
676
|
+
shutdown() {
|
|
677
|
+
return this.inner.shutdown();
|
|
678
|
+
}
|
|
679
|
+
forceFlush() {
|
|
680
|
+
return this.inner.forceFlush ? this.inner.forceFlush() : Promise.resolve();
|
|
681
|
+
}
|
|
682
|
+
};
|
|
683
|
+
OtelEngine = class {
|
|
684
|
+
provider = null;
|
|
685
|
+
tracer = null;
|
|
686
|
+
sampleRate = 1;
|
|
687
|
+
recorder = null;
|
|
688
|
+
maxFieldBytes = DEFAULT_MAX_FIELD_BYTES;
|
|
689
|
+
exitHookRegistered = false;
|
|
690
|
+
/**
|
|
691
|
+
* (Re)build the provider. Mirrors Python's `_Client.__init__` semantics:
|
|
692
|
+
* calling this again (e.g. a second `init()`) tears down the previous
|
|
693
|
+
* provider first (fire-and-forget — Node has no synchronous blocking
|
|
694
|
+
* shutdown equivalent to Python's `atexit`).
|
|
695
|
+
*/
|
|
696
|
+
configure(opts) {
|
|
697
|
+
if (this.provider !== null) {
|
|
698
|
+
const prior = this.provider;
|
|
699
|
+
void prior.shutdown().catch(() => {
|
|
700
|
+
});
|
|
701
|
+
}
|
|
702
|
+
this.maxFieldBytes = opts.maxFieldBytes;
|
|
703
|
+
this.sampleRate = Math.min(1, Math.max(0, opts.sampleRate));
|
|
704
|
+
const sampler = new ParentBasedSampler({
|
|
705
|
+
root: new TraceIdRatioBasedSampler(this.sampleRate)
|
|
706
|
+
});
|
|
707
|
+
const otlpExporter = new OTLPTraceExporter({
|
|
708
|
+
url: opts.endpoint,
|
|
709
|
+
headers: { Authorization: `Bearer ${opts.apiKey}` },
|
|
710
|
+
compression: CompressionAlgorithm.GZIP,
|
|
711
|
+
timeoutMillis: opts.timeoutMillis
|
|
712
|
+
});
|
|
713
|
+
let exporter = new RedactingSpanExporter(otlpExporter, opts.redactionConfig);
|
|
714
|
+
if (opts.resultSink) {
|
|
715
|
+
exporter = new ResultCapturingExporter(exporter, opts.resultSink);
|
|
716
|
+
}
|
|
717
|
+
this.recorder = opts.captureForTests ? new RecordingSpanExporter() : null;
|
|
718
|
+
const spanProcessors = [
|
|
719
|
+
new BatchSpanProcessor(exporter, {
|
|
720
|
+
maxQueueSize: opts.maxQueueSize,
|
|
721
|
+
scheduledDelayMillis: opts.scheduleDelayMillis,
|
|
722
|
+
maxExportBatchSize: opts.maxExportBatchSize
|
|
723
|
+
})
|
|
724
|
+
];
|
|
725
|
+
if (this.recorder !== null) {
|
|
726
|
+
spanProcessors.push(new BatchSpanProcessor(this.recorder));
|
|
727
|
+
}
|
|
728
|
+
this.provider = new NodeTracerProvider({ sampler, spanProcessors });
|
|
729
|
+
this.tracer = this.provider.getTracer(INSTRUMENTATION_NAME);
|
|
730
|
+
if (!this.exitHookRegistered) {
|
|
731
|
+
process.once("beforeExit", () => {
|
|
732
|
+
this.shutdown();
|
|
733
|
+
});
|
|
734
|
+
this.exitHookRegistered = true;
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
shutdown() {
|
|
738
|
+
if (this.provider !== null) {
|
|
739
|
+
const provider = this.provider;
|
|
740
|
+
void provider.shutdown().catch(() => {
|
|
741
|
+
});
|
|
742
|
+
this.provider = null;
|
|
743
|
+
this.tracer = null;
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
/**
|
|
747
|
+
* Test-only fast reset: drop the provider reference WITHOUT blocking on
|
|
748
|
+
* `shutdown()`. Mirrors Python's `reset_for_testing` — the OTLP
|
|
749
|
+
* exporter's retry-with-backoff behavior against an unreachable test
|
|
750
|
+
* endpoint would otherwise make every test file's teardown slow. The
|
|
751
|
+
* queued background work is not awaited; it either finishes or is
|
|
752
|
+
* abandoned with the process, same trade-off as Python's daemon worker
|
|
753
|
+
* thread.
|
|
754
|
+
*/
|
|
755
|
+
resetForTesting() {
|
|
756
|
+
this.provider = null;
|
|
757
|
+
this.tracer = null;
|
|
758
|
+
this.recorder = null;
|
|
759
|
+
}
|
|
760
|
+
/** Block until in-flight exports finish (or the timeout elapses). */
|
|
761
|
+
async flush() {
|
|
762
|
+
const provider = this.provider;
|
|
763
|
+
if (provider !== null) {
|
|
764
|
+
try {
|
|
765
|
+
await provider.forceFlush();
|
|
766
|
+
} catch {
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
/**
|
|
771
|
+
* Run the deterministic ratio sampler directly for a trace id with no
|
|
772
|
+
* real parent. See `ratioSample` for the decorrelation rationale — feeding
|
|
773
|
+
* a raw uuid4 trace id straight to a ratio sampler produces a hard
|
|
774
|
+
* 0%/100% step function because of uuid4's fixed variant bits.
|
|
775
|
+
*/
|
|
776
|
+
resolveSampled(traceIdHex) {
|
|
777
|
+
return ratioSample(traceIdHex, this.sampleRate);
|
|
778
|
+
}
|
|
779
|
+
/**
|
|
780
|
+
* Register OTel `Instrumentation` instances (e.g. the community DB-driver
|
|
781
|
+
* auto-instrumentation packages, see `./db-capture.ts`, MHQ-482) against
|
|
782
|
+
* THIS engine's `NodeTracerProvider` — so spans they emit flow through
|
|
783
|
+
* the same `BatchSpanProcessor` -> `RedactingSpanExporter` ->
|
|
784
|
+
* `OTLPTraceExporter` pipeline `configure()` built, landing in the same
|
|
785
|
+
* OTLP stream (and, when nested inside an active OTel context, the same
|
|
786
|
+
* trace) as the rest of the SDK's spans.
|
|
787
|
+
*
|
|
788
|
+
* No-op (silently, returns `null`) if `configure()` hasn't run yet —
|
|
789
|
+
* mirrors `emitTraceEntry`'s "no transport configured -> silent"
|
|
790
|
+
* contract. Callers (`index.ts::buildSingleton`) must call this AFTER
|
|
791
|
+
* `configure()`.
|
|
792
|
+
*/
|
|
793
|
+
registerInstrumentations(instrumentations) {
|
|
794
|
+
if (this.provider === null) return null;
|
|
795
|
+
return registerInstrumentations({
|
|
796
|
+
tracerProvider: this.provider,
|
|
797
|
+
instrumentations
|
|
798
|
+
});
|
|
799
|
+
}
|
|
800
|
+
};
|
|
801
|
+
engine = null;
|
|
802
|
+
}
|
|
803
|
+
});
|
|
804
|
+
|
|
805
|
+
// src/_internal/tracing.ts
|
|
806
|
+
function tryLoadAls() {
|
|
807
|
+
if (alsLoaded) return als;
|
|
808
|
+
alsLoaded = true;
|
|
809
|
+
if (typeof process === "undefined" || !process.versions?.node) {
|
|
810
|
+
als = null;
|
|
811
|
+
return als;
|
|
812
|
+
}
|
|
813
|
+
try {
|
|
814
|
+
const dynamicRequire = Function("m", "return require(m)");
|
|
815
|
+
const mod = dynamicRequire("node:async_hooks");
|
|
816
|
+
if (mod?.AsyncLocalStorage) {
|
|
817
|
+
als = new mod.AsyncLocalStorage();
|
|
818
|
+
return als;
|
|
819
|
+
}
|
|
820
|
+
} catch {
|
|
821
|
+
}
|
|
822
|
+
als = null;
|
|
823
|
+
return als;
|
|
824
|
+
}
|
|
825
|
+
function getActiveTraceState() {
|
|
826
|
+
const store = tryLoadAls();
|
|
827
|
+
if (store) {
|
|
828
|
+
return store.getStore() ?? null;
|
|
829
|
+
}
|
|
830
|
+
return browserState;
|
|
831
|
+
}
|
|
832
|
+
function setActiveTraceState(state) {
|
|
833
|
+
const previous = browserState;
|
|
834
|
+
browserState = state;
|
|
835
|
+
return () => {
|
|
836
|
+
browserState = previous;
|
|
837
|
+
};
|
|
838
|
+
}
|
|
839
|
+
function setTransport(t) {
|
|
840
|
+
transport = t;
|
|
841
|
+
}
|
|
842
|
+
function getTransport() {
|
|
843
|
+
return transport;
|
|
844
|
+
}
|
|
845
|
+
function setRedactionConfig(config) {
|
|
846
|
+
redactionConfig = config;
|
|
847
|
+
}
|
|
848
|
+
function getRedactionConfig() {
|
|
849
|
+
return redactionConfig;
|
|
850
|
+
}
|
|
851
|
+
function setSource(value) {
|
|
852
|
+
_source = value && value.length > 0 ? value : null;
|
|
853
|
+
}
|
|
854
|
+
function getLastTrace() {
|
|
855
|
+
return lastTrace;
|
|
856
|
+
}
|
|
857
|
+
function nowMonotonic() {
|
|
858
|
+
if (typeof performance !== "undefined" && typeof performance.now === "function") {
|
|
859
|
+
return performance.now();
|
|
860
|
+
}
|
|
861
|
+
return Date.now();
|
|
862
|
+
}
|
|
863
|
+
function elapsedMs(startMonotonic) {
|
|
864
|
+
return Math.max(0, Math.round(nowMonotonic() - startMonotonic));
|
|
865
|
+
}
|
|
866
|
+
function finalizeSpan(span, startMono, status = "completed", errorMessage) {
|
|
867
|
+
span.ended_at = nowIso();
|
|
868
|
+
span.duration_ms = elapsedMs(startMono);
|
|
869
|
+
span.status = status;
|
|
870
|
+
if (errorMessage !== void 0) {
|
|
871
|
+
span.error_message = errorMessage;
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
function redactSpanDict(raw, config) {
|
|
875
|
+
if (!config.enabled) return raw;
|
|
876
|
+
const out = {};
|
|
877
|
+
for (const [k, v] of Object.entries(raw)) {
|
|
878
|
+
if (SPAN_REDACTABLE_FIELDS.has(k)) {
|
|
879
|
+
out[k] = redactValue(v, config);
|
|
880
|
+
} else {
|
|
881
|
+
out[k] = v;
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
return out;
|
|
885
|
+
}
|
|
886
|
+
function redactTraceDict(raw, config) {
|
|
887
|
+
if (!config.enabled) return raw;
|
|
888
|
+
const out = {};
|
|
889
|
+
for (const [k, v] of Object.entries(raw)) {
|
|
890
|
+
if (TRACE_REDACTABLE_FIELDS.has(k)) {
|
|
891
|
+
out[k] = redactValue(v, config);
|
|
892
|
+
} else {
|
|
893
|
+
out[k] = v;
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
return out;
|
|
897
|
+
}
|
|
898
|
+
function buildTraceDict(state, rootSpan) {
|
|
899
|
+
const trace = {
|
|
900
|
+
trace_id: state.traceId,
|
|
901
|
+
// Wire-format field is `agent` (matches backend TracePayloadIn schema +
|
|
902
|
+
// sibling Python SDK). Was `agent_name` historically — the mismatch
|
|
903
|
+
// caused dev ingest to reject every TS-emitted trace with a 422
|
|
904
|
+
// until Phase 13 Option A dogfood surfaced it.
|
|
905
|
+
agent: state.agentName,
|
|
906
|
+
status: rootSpan.status,
|
|
907
|
+
started_at: rootSpan.started_at
|
|
908
|
+
};
|
|
909
|
+
if (rootSpan.ended_at) trace.ended_at = rootSpan.ended_at;
|
|
910
|
+
if (rootSpan.duration_ms !== void 0) trace.duration_ms = rootSpan.duration_ms;
|
|
911
|
+
if (rootSpan.error_message) trace.error_message = rootSpan.error_message;
|
|
912
|
+
if (state.success !== void 0) trace.success = state.success;
|
|
913
|
+
if (state.outcome !== void 0) trace.outcome = state.outcome;
|
|
914
|
+
if (state.threadId !== void 0) trace.thread_id = state.threadId;
|
|
915
|
+
if (state.userId !== void 0) trace.user_id = state.userId;
|
|
916
|
+
if (state.userMetadata && Object.keys(state.userMetadata).length > 0) {
|
|
917
|
+
trace.user_metadata = state.userMetadata;
|
|
918
|
+
}
|
|
919
|
+
const allSpans = [rootSpan, ...state.completedSpans];
|
|
920
|
+
const spans = allSpans.map((s) => {
|
|
921
|
+
const out2 = {};
|
|
922
|
+
for (const [k, v] of Object.entries(s)) {
|
|
923
|
+
if (v !== void 0 && v !== null) {
|
|
924
|
+
out2[k] = v;
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
return out2;
|
|
928
|
+
});
|
|
929
|
+
const config = redactionConfig;
|
|
930
|
+
const out = {
|
|
931
|
+
trace: redactTraceDict(trace, config),
|
|
932
|
+
spans: spans.map((s) => redactSpanDict(s, config))
|
|
933
|
+
};
|
|
934
|
+
const effectiveSource = state.sourceOverride || _source;
|
|
935
|
+
if (effectiveSource) {
|
|
936
|
+
out.resource = { "morse_ai.source": effectiveSource };
|
|
937
|
+
}
|
|
938
|
+
return out;
|
|
939
|
+
}
|
|
940
|
+
function sendTrace(entry) {
|
|
941
|
+
lastTrace = entry;
|
|
942
|
+
if (isLegacyTransport() || false) {
|
|
943
|
+
if (transport !== null) {
|
|
944
|
+
try {
|
|
945
|
+
transport.track({ traces: [entry] });
|
|
946
|
+
} catch {
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
return;
|
|
950
|
+
}
|
|
951
|
+
try {
|
|
952
|
+
emitTraceEntry(entry);
|
|
953
|
+
} catch {
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
function withDbCaptureContext(traceId, spanIdHex, fn) {
|
|
957
|
+
try {
|
|
958
|
+
return withOtelSpanContext(traceId, spanIdHex.slice(0, 16), fn);
|
|
959
|
+
} catch {
|
|
960
|
+
return fn();
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
function buildRunHandle(state) {
|
|
964
|
+
return {
|
|
965
|
+
setOutcome(success, outcome) {
|
|
966
|
+
state.success = success;
|
|
967
|
+
if (outcome !== void 0) state.outcome = outcome;
|
|
968
|
+
},
|
|
969
|
+
setError(message) {
|
|
970
|
+
state.errorMessage = message;
|
|
971
|
+
state.success = false;
|
|
972
|
+
},
|
|
973
|
+
_state: state
|
|
974
|
+
};
|
|
975
|
+
}
|
|
976
|
+
function startTrace(opts) {
|
|
977
|
+
let traceId;
|
|
978
|
+
if (opts.incomingTraceparent) {
|
|
979
|
+
const { extractTraceparent: extractTraceparent2 } = (init_propagation(), __toCommonJS(propagation_exports));
|
|
980
|
+
const ctx = extractTraceparent2(opts.incomingTraceparent);
|
|
981
|
+
if (ctx) {
|
|
982
|
+
traceId = ctx.traceId;
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
if (!traceId) traceId = generateTraceId();
|
|
986
|
+
const state = {
|
|
987
|
+
traceId,
|
|
988
|
+
agentName: opts.agentName,
|
|
989
|
+
spanStack: [],
|
|
990
|
+
completedSpans: []
|
|
991
|
+
};
|
|
992
|
+
if (opts.threadId !== void 0) state.threadId = opts.threadId;
|
|
993
|
+
if (opts.userId !== void 0) state.userId = opts.userId;
|
|
994
|
+
if (opts.userMetadata) {
|
|
995
|
+
state.userMetadata = Object.fromEntries(
|
|
996
|
+
Object.entries(opts.userMetadata).map(([k, v]) => [k, String(v)])
|
|
997
|
+
);
|
|
998
|
+
}
|
|
999
|
+
if (isValidInternalSource(opts.source)) {
|
|
1000
|
+
state.sourceOverride = opts.source;
|
|
1001
|
+
}
|
|
1002
|
+
const rootSpan = {
|
|
1003
|
+
trace_id: traceId,
|
|
1004
|
+
span_id: generateSpanId(),
|
|
1005
|
+
type: "agent",
|
|
1006
|
+
name: opts.agentName,
|
|
1007
|
+
started_at: nowIso(),
|
|
1008
|
+
status: "completed"
|
|
1009
|
+
};
|
|
1010
|
+
state.spanStack.push(rootSpan);
|
|
1011
|
+
return { state, rootSpan, startMono: nowMonotonic() };
|
|
1012
|
+
}
|
|
1013
|
+
function endTrace(state, rootSpan, startMono, threwError) {
|
|
1014
|
+
state.spanStack.pop();
|
|
1015
|
+
if (threwError !== void 0) {
|
|
1016
|
+
const msg = state.errorMessage ?? errToString(threwError);
|
|
1017
|
+
finalizeSpan(rootSpan, startMono, "failed", msg);
|
|
1018
|
+
if (state.success === void 0) state.success = false;
|
|
1019
|
+
} else if (state.errorMessage !== void 0) {
|
|
1020
|
+
finalizeSpan(rootSpan, startMono, "failed", state.errorMessage);
|
|
1021
|
+
} else {
|
|
1022
|
+
finalizeSpan(rootSpan, startMono);
|
|
1023
|
+
if (state.success === void 0) state.success = true;
|
|
1024
|
+
}
|
|
1025
|
+
const dict = buildTraceDict(state, rootSpan);
|
|
1026
|
+
sendTrace(dict);
|
|
1027
|
+
}
|
|
1028
|
+
function errToString(e) {
|
|
1029
|
+
if (e instanceof Error) return e.message;
|
|
1030
|
+
return String(e);
|
|
1031
|
+
}
|
|
1032
|
+
function runSync(opts, fn) {
|
|
1033
|
+
const { state, rootSpan, startMono } = startTrace(opts);
|
|
1034
|
+
const handle = buildRunHandle(state);
|
|
1035
|
+
const store = tryLoadAls();
|
|
1036
|
+
const runFn = () => withDbCaptureContext(state.traceId, rootSpan.span_id, () => fn(handle));
|
|
1037
|
+
if (store) {
|
|
1038
|
+
try {
|
|
1039
|
+
const result = store.run(state, runFn);
|
|
1040
|
+
endTrace(state, rootSpan, startMono, void 0);
|
|
1041
|
+
return result;
|
|
1042
|
+
} catch (err) {
|
|
1043
|
+
endTrace(state, rootSpan, startMono, err);
|
|
1044
|
+
throw err;
|
|
1045
|
+
}
|
|
1046
|
+
} else {
|
|
1047
|
+
const reset = setActiveTraceState(state);
|
|
1048
|
+
try {
|
|
1049
|
+
const result = runFn();
|
|
1050
|
+
endTrace(state, rootSpan, startMono, void 0);
|
|
1051
|
+
return result;
|
|
1052
|
+
} catch (err) {
|
|
1053
|
+
endTrace(state, rootSpan, startMono, err);
|
|
1054
|
+
throw err;
|
|
1055
|
+
} finally {
|
|
1056
|
+
reset();
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
async function runAsync(opts, fn) {
|
|
1061
|
+
const { state, rootSpan, startMono } = startTrace(opts);
|
|
1062
|
+
const handle = buildRunHandle(state);
|
|
1063
|
+
const store = tryLoadAls();
|
|
1064
|
+
const runFn = () => withDbCaptureContext(state.traceId, rootSpan.span_id, () => fn(handle));
|
|
1065
|
+
if (store) {
|
|
1066
|
+
try {
|
|
1067
|
+
const result = await store.run(state, runFn);
|
|
1068
|
+
endTrace(state, rootSpan, startMono, void 0);
|
|
1069
|
+
return result;
|
|
1070
|
+
} catch (err) {
|
|
1071
|
+
endTrace(state, rootSpan, startMono, err);
|
|
1072
|
+
throw err;
|
|
1073
|
+
}
|
|
1074
|
+
} else {
|
|
1075
|
+
const reset = setActiveTraceState(state);
|
|
1076
|
+
try {
|
|
1077
|
+
const result = await runFn();
|
|
1078
|
+
endTrace(state, rootSpan, startMono, void 0);
|
|
1079
|
+
return result;
|
|
1080
|
+
} catch (err) {
|
|
1081
|
+
endTrace(state, rootSpan, startMono, err);
|
|
1082
|
+
throw err;
|
|
1083
|
+
} finally {
|
|
1084
|
+
reset();
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
function setContext(dims) {
|
|
1089
|
+
const state = getActiveTraceState();
|
|
1090
|
+
if (state === null) return;
|
|
1091
|
+
if (state.userMetadata === void 0) state.userMetadata = {};
|
|
1092
|
+
for (const [k, v] of Object.entries(dims)) {
|
|
1093
|
+
state.userMetadata[k] = String(v);
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
function startSpan(opts) {
|
|
1097
|
+
const state = getActiveTraceState();
|
|
1098
|
+
if (state === null) return null;
|
|
1099
|
+
const parent = state.spanStack[state.spanStack.length - 1];
|
|
1100
|
+
const span = {
|
|
1101
|
+
trace_id: state.traceId,
|
|
1102
|
+
span_id: generateSpanId(),
|
|
1103
|
+
type: opts.type ?? "custom",
|
|
1104
|
+
name: opts.name,
|
|
1105
|
+
parent_span_id: parent?.span_id,
|
|
1106
|
+
started_at: nowIso(),
|
|
1107
|
+
status: "completed",
|
|
1108
|
+
metadata: opts.metadata
|
|
1109
|
+
};
|
|
1110
|
+
const startMono = nowMonotonic();
|
|
1111
|
+
state.spanStack.push(span);
|
|
1112
|
+
return {
|
|
1113
|
+
span,
|
|
1114
|
+
end(error) {
|
|
1115
|
+
if (state.spanStack[state.spanStack.length - 1] === span) {
|
|
1116
|
+
state.spanStack.pop();
|
|
1117
|
+
}
|
|
1118
|
+
if (error !== void 0) {
|
|
1119
|
+
finalizeSpan(span, startMono, "failed", errToString(error));
|
|
1120
|
+
} else {
|
|
1121
|
+
finalizeSpan(span, startMono);
|
|
1122
|
+
}
|
|
1123
|
+
state.completedSpans.push(span);
|
|
1124
|
+
}
|
|
1125
|
+
};
|
|
1126
|
+
}
|
|
1127
|
+
function spanSync(opts, fn) {
|
|
1128
|
+
const handle = startSpan(opts);
|
|
1129
|
+
try {
|
|
1130
|
+
const result = handle ? withDbCaptureContext(handle.span.trace_id, handle.span.span_id, () => fn(handle)) : fn(handle);
|
|
1131
|
+
handle?.end();
|
|
1132
|
+
return result;
|
|
1133
|
+
} catch (err) {
|
|
1134
|
+
handle?.end(err);
|
|
1135
|
+
throw err;
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
async function spanAsync(opts, fn) {
|
|
1139
|
+
const handle = startSpan(opts);
|
|
1140
|
+
try {
|
|
1141
|
+
const result = handle ? await withDbCaptureContext(handle.span.trace_id, handle.span.span_id, () => fn(handle)) : await fn(handle);
|
|
1142
|
+
handle?.end();
|
|
1143
|
+
return result;
|
|
1144
|
+
} catch (err) {
|
|
1145
|
+
handle?.end(err);
|
|
1146
|
+
throw err;
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
function _resetForTesting() {
|
|
1150
|
+
browserState = null;
|
|
1151
|
+
lastTrace = null;
|
|
1152
|
+
redactionConfig = buildRedactionConfig();
|
|
1153
|
+
}
|
|
1154
|
+
var als, alsLoaded, browserState, transport, redactionConfig, _source, lastTrace, SPAN_REDACTABLE_FIELDS, TRACE_REDACTABLE_FIELDS;
|
|
1155
|
+
var init_tracing = __esm({
|
|
1156
|
+
"src/_internal/tracing.ts"() {
|
|
1157
|
+
init_env();
|
|
1158
|
+
init_otel_provider();
|
|
1159
|
+
init_redaction();
|
|
1160
|
+
init_spans();
|
|
1161
|
+
als = null;
|
|
1162
|
+
alsLoaded = false;
|
|
1163
|
+
browserState = null;
|
|
1164
|
+
transport = null;
|
|
1165
|
+
redactionConfig = buildRedactionConfig();
|
|
1166
|
+
_source = null;
|
|
1167
|
+
lastTrace = null;
|
|
1168
|
+
SPAN_REDACTABLE_FIELDS = /* @__PURE__ */ new Set([
|
|
1169
|
+
"name",
|
|
1170
|
+
"input_data",
|
|
1171
|
+
"output_data",
|
|
1172
|
+
"error_message",
|
|
1173
|
+
"metadata"
|
|
1174
|
+
]);
|
|
1175
|
+
TRACE_REDACTABLE_FIELDS = /* @__PURE__ */ new Set(["agent", "outcome", "error_message"]);
|
|
1176
|
+
}
|
|
1177
|
+
});
|
|
1178
|
+
|
|
1179
|
+
// src/propagation.ts
|
|
1180
|
+
var propagation_exports = {};
|
|
1181
|
+
__export(propagation_exports, {
|
|
1182
|
+
W3C_FLAGS_SAMPLED: () => W3C_FLAGS_SAMPLED,
|
|
1183
|
+
W3C_TRACEPARENT_HEADER: () => W3C_TRACEPARENT_HEADER,
|
|
1184
|
+
W3C_VERSION: () => W3C_VERSION,
|
|
1185
|
+
extractFromRequest: () => extractFromRequest,
|
|
1186
|
+
extractTraceparent: () => extractTraceparent,
|
|
1187
|
+
formatTraceparent: () => formatTraceparent,
|
|
1188
|
+
injectIntoRequestInit: () => injectIntoRequestInit,
|
|
1189
|
+
injectTraceparent: () => injectTraceparent
|
|
1190
|
+
});
|
|
1191
|
+
function formatTraceparent(traceId, spanId) {
|
|
1192
|
+
const tid = traceId.slice(0, TRACE_ID_LEN).padStart(TRACE_ID_LEN, "0").toLowerCase();
|
|
1193
|
+
const sid = spanId.slice(0, SPAN_ID_LEN).padStart(SPAN_ID_LEN, "0").toLowerCase();
|
|
1194
|
+
return `${W3C_VERSION}-${tid}-${sid}-${W3C_FLAGS_SAMPLED}`;
|
|
1195
|
+
}
|
|
1196
|
+
function injectTraceparent(headers) {
|
|
1197
|
+
const state = getActiveTraceState();
|
|
1198
|
+
if (state === null) return headers;
|
|
1199
|
+
const traceId = state.traceId;
|
|
1200
|
+
const span = state.spanStack.length > 0 ? state.spanStack[state.spanStack.length - 1] : state.completedSpans[state.completedSpans.length - 1];
|
|
1201
|
+
const rawSpanId = span?.span_id ?? traceId;
|
|
1202
|
+
const spanId = rawSpanId.slice(0, SPAN_ID_LEN);
|
|
1203
|
+
const value = formatTraceparent(traceId, spanId);
|
|
1204
|
+
setHeader(headers, W3C_TRACEPARENT_HEADER, value);
|
|
1205
|
+
return headers;
|
|
1206
|
+
}
|
|
1207
|
+
function extractTraceparent(headers) {
|
|
1208
|
+
if (headers === null || headers === void 0) return null;
|
|
1209
|
+
const raw = typeof headers === "string" ? headers : getHeader(headers, W3C_TRACEPARENT_HEADER);
|
|
1210
|
+
if (!raw) return null;
|
|
1211
|
+
const parts = raw.split("-");
|
|
1212
|
+
if (parts.length !== 4) return null;
|
|
1213
|
+
const [version, traceId, spanId] = parts;
|
|
1214
|
+
if (version !== W3C_VERSION) return null;
|
|
1215
|
+
if (traceId.length !== TRACE_ID_LEN) return null;
|
|
1216
|
+
if (spanId.length !== SPAN_ID_LEN) return null;
|
|
1217
|
+
if (!/^[0-9a-f]+$/.test(traceId)) return null;
|
|
1218
|
+
if (!/^[0-9a-f]+$/.test(spanId)) return null;
|
|
1219
|
+
if (/^0+$/.test(traceId)) return null;
|
|
1220
|
+
if (/^0+$/.test(spanId)) return null;
|
|
1221
|
+
return { traceId, parentSpanId: spanId };
|
|
1222
|
+
}
|
|
1223
|
+
function extractFromRequest(req) {
|
|
1224
|
+
return extractTraceparent(req.headers);
|
|
1225
|
+
}
|
|
1226
|
+
function injectIntoRequestInit(init) {
|
|
1227
|
+
const merged = new Headers(init?.headers ?? {});
|
|
1228
|
+
injectTraceparent(merged);
|
|
1229
|
+
return { ...init ?? {}, headers: merged };
|
|
1230
|
+
}
|
|
1231
|
+
function getHeader(headers, name) {
|
|
1232
|
+
if (headers instanceof Headers) {
|
|
1233
|
+
return headers.get(name);
|
|
1234
|
+
}
|
|
1235
|
+
const maybeGet = headers.get;
|
|
1236
|
+
if (typeof maybeGet === "function") {
|
|
1237
|
+
const v = maybeGet.call(headers, name);
|
|
1238
|
+
if (typeof v === "string") return v;
|
|
1239
|
+
if (v === null || v === void 0) return null;
|
|
1240
|
+
}
|
|
1241
|
+
const lower = name.toLowerCase();
|
|
1242
|
+
for (const [k, v] of Object.entries(headers)) {
|
|
1243
|
+
if (k.toLowerCase() === lower) {
|
|
1244
|
+
if (typeof v === "string") return v;
|
|
1245
|
+
if (Array.isArray(v) && v.length > 0 && typeof v[0] === "string") return v[0];
|
|
1246
|
+
return null;
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
return null;
|
|
1250
|
+
}
|
|
1251
|
+
function setHeader(headers, name, value) {
|
|
1252
|
+
if (headers instanceof Headers) {
|
|
1253
|
+
headers.set(name, value);
|
|
1254
|
+
return;
|
|
1255
|
+
}
|
|
1256
|
+
const maybeSet = headers.set;
|
|
1257
|
+
if (typeof maybeSet === "function") {
|
|
1258
|
+
maybeSet.call(headers, name, value);
|
|
1259
|
+
return;
|
|
1260
|
+
}
|
|
1261
|
+
headers[name] = value;
|
|
1262
|
+
}
|
|
1263
|
+
var W3C_TRACEPARENT_HEADER, W3C_VERSION, W3C_FLAGS_SAMPLED, TRACE_ID_LEN, SPAN_ID_LEN;
|
|
1264
|
+
var init_propagation = __esm({
|
|
1265
|
+
"src/propagation.ts"() {
|
|
1266
|
+
init_tracing();
|
|
1267
|
+
W3C_TRACEPARENT_HEADER = "traceparent";
|
|
1268
|
+
W3C_VERSION = "00";
|
|
1269
|
+
W3C_FLAGS_SAMPLED = "01";
|
|
1270
|
+
TRACE_ID_LEN = 32;
|
|
1271
|
+
SPAN_ID_LEN = 16;
|
|
1272
|
+
}
|
|
1273
|
+
});
|
|
1274
|
+
|
|
1275
|
+
export { DEFAULT_ENDPOINT, SpanType, W3C_TRACEPARENT_HEADER, _resetForTesting, buildRedactionConfig, buildTraceEntry, extractTraceparent, formatTraceparent, generateSpanId, generateTraceId, getActiveTraceState, getApiKey, getEndpoint, getEngine, getFlushIntervalSeconds, getInternalSource, getLastTrace, getMaxBatchSize, getMaxFieldBytes, getMaxQueueSize, getRedactionConfig, getSampleRate, getTransport, init_env, init_otel_provider, init_propagation, init_redaction, init_spans, init_tracing, injectIntoRequestInit, injectTraceparent, isAutoDetectDisabled, isDbCaptureEnabled, isDebug, isDisabled, isTelemetryDisabled, isValidInternalSource, nowIso, redactValue, runAsync, runSync, sendTrace, setContext, setRedactionConfig, setSource, setTransport, spanAsync, spanSync, startSpan };
|
|
1276
|
+
//# sourceMappingURL=chunk-TQWI4UYO.js.map
|
|
1277
|
+
//# sourceMappingURL=chunk-TQWI4UYO.js.map
|