@telemetry-dev/sdk 0.1.2 → 0.1.3
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 +6 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.mjs +16 -2
- package/package.json +3 -3
- package/src/client.ts +2 -0
- package/src/config.ts +12 -0
- package/src/logs.ts +22 -2
- package/src/span.ts +9 -5
package/README.md
CHANGED
|
@@ -60,6 +60,12 @@ Other `init()` options: `enabled` (kill switch), `registerGlobal`, `exportMode:
|
|
|
60
60
|
`exportTimeoutMillis` 30000), `spanFilter`, `resourceAttributes`, `logLevel` (SDK diagnostics,
|
|
61
61
|
default `"warn"`), `fetch`, `waitUntil`, `onError`.
|
|
62
62
|
|
|
63
|
+
Root spans remain independent by default. `init({ sessionMode: "process" })` groups otherwise
|
|
64
|
+
uncorrelated spans and logs using a fresh opaque UUID for each enabled SDK initialization.
|
|
65
|
+
Explicit and propagated session IDs take precedence, and valid parent trace context is preserved.
|
|
66
|
+
The generated session ends when the client is shut down or replaced; a later `init()` generates a
|
|
67
|
+
new ID. It is not persisted across processes.
|
|
68
|
+
|
|
63
69
|
`sampler` accepts an OpenTelemetry `Sampler` and overrides `OTEL_TRACES_SAMPLER` / `OTEL_TRACES_SAMPLER_ARG`.
|
|
64
70
|
The default is parent-based always-on. Session roots keep the configured root policy.
|
|
65
71
|
Nested spans and explicitly parented spans keep the real parent's policy.
|
package/dist/index.d.mts
CHANGED
|
@@ -20,6 +20,8 @@ interface TelemetryOptions {
|
|
|
20
20
|
serviceName?: string;
|
|
21
21
|
/** Kill switch: `false` makes the SDK a complete no-op (tests). Default true. */
|
|
22
22
|
enabled?: boolean;
|
|
23
|
+
/** Group otherwise uncorrelated spans and logs for this SDK initialization. Default "explicit". */
|
|
24
|
+
sessionMode?: "explicit" | "process";
|
|
23
25
|
/** Register this SDK's TracerProvider/context manager/propagator globally. Default false (isolated). */
|
|
24
26
|
registerGlobal?: boolean;
|
|
25
27
|
/** "batched" (default) buffers spans; "immediate" exports per span (serverless). */
|
package/dist/index.mjs
CHANGED
|
@@ -7,6 +7,7 @@ import { AlsContextManager, BATCHED_METRIC_INTERVAL_MS, DEFAULT_BASE_URL, DEFAUL
|
|
|
7
7
|
import { SeverityNumber } from "@opentelemetry/api-logs";
|
|
8
8
|
function resolveConfig(options = {}) {
|
|
9
9
|
const env = resolveEnv();
|
|
10
|
+
if (options.sessionMode !== void 0 && options.sessionMode !== "explicit" && options.sessionMode !== "process") throw new TypeError(`Invalid sessionMode: ${String(options.sessionMode)}`);
|
|
10
11
|
const baseUrl = (options.baseUrl ?? env.TELEMETRY_DEV_BASE_URL ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
11
12
|
return {
|
|
12
13
|
apiKey: options.apiKey ?? env.TELEMETRY_DEV_API_KEY,
|
|
@@ -14,6 +15,7 @@ function resolveConfig(options = {}) {
|
|
|
14
15
|
environment: options.environment ?? env.TELEMETRY_DEV_ENVIRONMENT ?? "production",
|
|
15
16
|
serviceName: options.serviceName ?? env.OTEL_SERVICE_NAME ?? "unknown_service",
|
|
16
17
|
enabled: options.enabled ?? true,
|
|
18
|
+
sessionMode: options.sessionMode ?? "explicit",
|
|
17
19
|
registerGlobal: options.registerGlobal ?? false,
|
|
18
20
|
exportMode: options.exportMode ?? "batched",
|
|
19
21
|
sampler: options.sampler,
|
|
@@ -73,6 +75,7 @@ function initInner(options, overrides) {
|
|
|
73
75
|
activeClient = NOOP_CLIENT;
|
|
74
76
|
return NOOP_CLIENT;
|
|
75
77
|
}
|
|
78
|
+
if (config.sessionMode === "process") config.processSessionId = globalThis.crypto.randomUUID();
|
|
76
79
|
const resource = resourceFromAttributes({
|
|
77
80
|
"service.name": config.serviceName,
|
|
78
81
|
"deployment.environment.name": config.environment,
|
|
@@ -237,7 +240,14 @@ function log(message, options) {
|
|
|
237
240
|
onError: cfg.onError
|
|
238
241
|
};
|
|
239
242
|
const severity = SEVERITIES[options?.level ?? "info"];
|
|
240
|
-
const
|
|
243
|
+
const active = activeContext$1();
|
|
244
|
+
const explicitSession = options?.attributes?.["gen_ai.conversation.id"];
|
|
245
|
+
const propagatedSession = propagatedFromContext(active)?.["gen_ai.conversation.id"];
|
|
246
|
+
const sessionId = explicitSession !== void 0 ? void 0 : typeof propagatedSession === "string" ? propagatedSession : cfg.processSessionId;
|
|
247
|
+
const ctx = sessionId === void 0 ? active : active.setValue(PROPAGATED_KEY, {
|
|
248
|
+
...propagatedFromContext(active),
|
|
249
|
+
"gen_ai.conversation.id": sessionId
|
|
250
|
+
});
|
|
241
251
|
const attributes = {};
|
|
242
252
|
for (const [key, value] of Object.entries(options?.attributes ?? {})) {
|
|
243
253
|
if (value === void 0) continue;
|
|
@@ -425,7 +435,11 @@ function metaFor(core, options) {
|
|
|
425
435
|
function createSpanHandle(core, name, options = {}) {
|
|
426
436
|
const meta = metaFor(core, options);
|
|
427
437
|
const resolved = resolveParent(options.parent);
|
|
428
|
-
const
|
|
438
|
+
const sessionId = sessionIdOf(resolved, options.attributes) ?? core.config.processSessionId;
|
|
439
|
+
const parentCtx = withSessionParent(sessionId === void 0 ? resolved : resolved.setValue(PROPAGATED_KEY, {
|
|
440
|
+
...propagatedFromContext(resolved),
|
|
441
|
+
"gen_ai.conversation.id": sessionId
|
|
442
|
+
}), sessionId, core.config.apiKey);
|
|
429
443
|
const attrs = fieldsToAttributes(options, meta.type, meta.capture);
|
|
430
444
|
const span = core.tracer.startSpan(name, {
|
|
431
445
|
kind: options.kind ?? SpanKind.INTERNAL,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@telemetry-dev/sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Pure TypeScript SDK for telemetry.dev: LLM traces, logs, and GenAI metrics on OpenTelemetry, for Node and edge runtimes.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"genai",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"license": "MIT",
|
|
17
17
|
"repository": {
|
|
18
18
|
"type": "git",
|
|
19
|
-
"url": "git+https://github.com/telemetry-dev/
|
|
19
|
+
"url": "git+https://github.com/telemetry-dev/sdks.git",
|
|
20
20
|
"directory": "packages/sdk"
|
|
21
21
|
},
|
|
22
22
|
"files": [
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"@opentelemetry/sdk-logs": "^0.218.0",
|
|
43
43
|
"@opentelemetry/sdk-metrics": "^2.7.1",
|
|
44
44
|
"@opentelemetry/sdk-trace-base": "^2.7.1",
|
|
45
|
-
"@telemetry-dev/otel": "^0.1.
|
|
45
|
+
"@telemetry-dev/otel": "^0.1.3"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@opentelemetry/api": "^1.9.1",
|
package/src/client.ts
CHANGED
|
@@ -112,6 +112,8 @@ function initInner(options?: TelemetryOptions, overrides?: ClientOverrides): Tel
|
|
|
112
112
|
return NOOP_CLIENT;
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
+
if (config.sessionMode === "process") config.processSessionId = globalThis.crypto.randomUUID();
|
|
116
|
+
|
|
115
117
|
const resource = resourceFromAttributes({
|
|
116
118
|
"service.name": config.serviceName,
|
|
117
119
|
"deployment.environment.name": config.environment,
|
package/src/config.ts
CHANGED
|
@@ -26,6 +26,8 @@ export interface TelemetryOptions {
|
|
|
26
26
|
serviceName?: string;
|
|
27
27
|
/** Kill switch: `false` makes the SDK a complete no-op (tests). Default true. */
|
|
28
28
|
enabled?: boolean;
|
|
29
|
+
/** Group otherwise uncorrelated spans and logs for this SDK initialization. Default "explicit". */
|
|
30
|
+
sessionMode?: "explicit" | "process";
|
|
29
31
|
/** Register this SDK's TracerProvider/context manager/propagator globally. Default false (isolated). */
|
|
30
32
|
registerGlobal?: boolean;
|
|
31
33
|
/** "batched" (default) buffers spans; "immediate" exports per span (serverless). */
|
|
@@ -69,6 +71,8 @@ export interface ResolvedConfig {
|
|
|
69
71
|
environment: string;
|
|
70
72
|
serviceName: string;
|
|
71
73
|
enabled: boolean;
|
|
74
|
+
sessionMode: "explicit" | "process";
|
|
75
|
+
processSessionId?: string;
|
|
72
76
|
registerGlobal: boolean;
|
|
73
77
|
exportMode: ExportMode;
|
|
74
78
|
sampler?: Sampler;
|
|
@@ -91,6 +95,13 @@ export const DEFAULT_MAX_ATTRIBUTE_LENGTH = 65536;
|
|
|
91
95
|
|
|
92
96
|
export function resolveConfig(options: TelemetryOptions = {}): ResolvedConfig {
|
|
93
97
|
const env = resolveEnv();
|
|
98
|
+
if (
|
|
99
|
+
options.sessionMode !== undefined &&
|
|
100
|
+
options.sessionMode !== "explicit" &&
|
|
101
|
+
options.sessionMode !== "process"
|
|
102
|
+
) {
|
|
103
|
+
throw new TypeError(`Invalid sessionMode: ${String(options.sessionMode)}`);
|
|
104
|
+
}
|
|
94
105
|
const baseUrl = (options.baseUrl ?? env.TELEMETRY_DEV_BASE_URL ?? DEFAULT_BASE_URL).replace(
|
|
95
106
|
/\/+$/,
|
|
96
107
|
"",
|
|
@@ -101,6 +112,7 @@ export function resolveConfig(options: TelemetryOptions = {}): ResolvedConfig {
|
|
|
101
112
|
environment: options.environment ?? env.TELEMETRY_DEV_ENVIRONMENT ?? "production",
|
|
102
113
|
serviceName: options.serviceName ?? env.OTEL_SERVICE_NAME ?? "unknown_service",
|
|
103
114
|
enabled: options.enabled ?? true,
|
|
115
|
+
sessionMode: options.sessionMode ?? "explicit",
|
|
104
116
|
registerGlobal: options.registerGlobal ?? false,
|
|
105
117
|
exportMode: options.exportMode ?? "batched",
|
|
106
118
|
sampler: options.sampler,
|
package/src/logs.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import type { AttributeValue } from "@opentelemetry/api";
|
|
2
2
|
import { SeverityNumber } from "@opentelemetry/api-logs";
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
activeContext,
|
|
6
|
+
PROPAGATED_KEY,
|
|
7
|
+
propagatedFromContext,
|
|
8
|
+
reportError,
|
|
9
|
+
} from "@telemetry-dev/otel";
|
|
5
10
|
|
|
6
11
|
import { prepareCaptureValue, truncate } from "./capture.ts";
|
|
7
12
|
import { currentClient } from "./client.ts";
|
|
@@ -40,7 +45,22 @@ export function log(message: string, options?: LogOptions): void {
|
|
|
40
45
|
onError: cfg.onError,
|
|
41
46
|
};
|
|
42
47
|
const severity = SEVERITIES[options?.level ?? "info"];
|
|
43
|
-
const
|
|
48
|
+
const active = activeContext();
|
|
49
|
+
const explicitSession = options?.attributes?.["gen_ai.conversation.id"];
|
|
50
|
+
const propagatedSession = propagatedFromContext(active)?.["gen_ai.conversation.id"];
|
|
51
|
+
const sessionId =
|
|
52
|
+
explicitSession !== undefined
|
|
53
|
+
? undefined
|
|
54
|
+
: typeof propagatedSession === "string"
|
|
55
|
+
? propagatedSession
|
|
56
|
+
: cfg.processSessionId;
|
|
57
|
+
const ctx =
|
|
58
|
+
sessionId === undefined
|
|
59
|
+
? active
|
|
60
|
+
: active.setValue(PROPAGATED_KEY, {
|
|
61
|
+
...propagatedFromContext(active),
|
|
62
|
+
"gen_ai.conversation.id": sessionId,
|
|
63
|
+
});
|
|
44
64
|
|
|
45
65
|
const attributes: Record<string, AttributeValue> = {};
|
|
46
66
|
for (const [key, value] of Object.entries(options?.attributes ?? {})) {
|
package/src/span.ts
CHANGED
|
@@ -174,11 +174,15 @@ export function createSpanHandle(
|
|
|
174
174
|
): SpanHandle {
|
|
175
175
|
const meta = metaFor(core, options);
|
|
176
176
|
const resolved = resolveParent(options.parent);
|
|
177
|
-
const
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
177
|
+
const sessionId = sessionIdOf(resolved, options.attributes) ?? core.config.processSessionId;
|
|
178
|
+
const sessionContext =
|
|
179
|
+
sessionId === undefined
|
|
180
|
+
? resolved
|
|
181
|
+
: resolved.setValue(PROPAGATED_KEY, {
|
|
182
|
+
...propagatedFromContext(resolved),
|
|
183
|
+
"gen_ai.conversation.id": sessionId,
|
|
184
|
+
});
|
|
185
|
+
const parentCtx = withSessionParent(sessionContext, sessionId, core.config.apiKey);
|
|
182
186
|
const attrs = fieldsToAttributes(options, meta.type, meta.capture);
|
|
183
187
|
const span = core.tracer.startSpan(
|
|
184
188
|
name,
|