@struktur/telemetry 2.1.1 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,146 +1,89 @@
1
- /**
2
- * Phoenix (Arize) telemetry adapter
3
- *
4
- * Implements TelemetryAdapter for Phoenix using OpenTelemetry and
5
- * OpenInference semantic conventions.
6
- */
7
-
8
- import type {
9
- TelemetryAdapter,
10
- SpanContext,
11
- Span,
12
- SpanResult,
13
- TelemetryEvent,
14
- TelemetryContext,
15
- PhoenixConfig,
16
- LLMCallEvent,
17
- ValidationEvent,
18
- ChunkEvent,
19
- ToolCallEvent,
20
- MergeEvent,
21
- ParseEvent,
22
- TokenUsage,
23
- } from "../../types.js";
24
-
25
- type OtelSpan = {
26
- spanContext: () => { spanId: string; traceId: string };
27
- setStatus: (status: { code: number; message?: string }) => void;
28
- setAttribute: (key: string, value: string | number | boolean | undefined) => void;
29
- setAttributes: (attrs: Record<string, string | number | boolean>) => void;
30
- recordException: (error: Error) => void;
31
- end: () => void;
32
- };
33
-
34
- /**
35
- * Phoenix telemetry adapter using OpenTelemetry
36
- */
37
- export class PhoenixAdapter implements TelemetryAdapter {
38
- readonly name = "phoenix";
39
- readonly version = "1.0.0";
40
-
41
- private config: PhoenixConfig;
42
- private tracerProvider: { forceFlush?: () => Promise<void> } | null = null;
43
- private activeSpans = new Map<string, OtelSpan>();
44
- private otelApi: typeof import("@opentelemetry/api") | null = null;
45
- private phoenixOtel: typeof import("@arizeai/phoenix-otel") | null = null;
46
-
47
- constructor(config: PhoenixConfig) {
1
+ // src/adapters/phoenix/PhoenixAdapter.ts
2
+ var PhoenixAdapter = class {
3
+ name = "phoenix";
4
+ version = "1.0.0";
5
+ config;
6
+ tracerProvider = null;
7
+ activeSpans = /* @__PURE__ */ new Map();
8
+ otelApi = null;
9
+ phoenixOtel = null;
10
+ constructor(config) {
48
11
  this.config = {
49
12
  url: "http://localhost:6006",
50
13
  batch: true,
51
- ...config,
14
+ ...config
52
15
  };
53
16
  }
54
-
55
- async initialize(): Promise<void> {
56
- // Dynamically import OTel dependencies
17
+ async initialize() {
57
18
  const [{ register }, otelApi] = await Promise.all([
58
19
  import("@arizeai/phoenix-otel"),
59
- import("@opentelemetry/api"),
20
+ import("@opentelemetry/api")
60
21
  ]);
61
-
62
22
  this.otelApi = otelApi;
63
- this.phoenixOtel = { register } as typeof import("@arizeai/phoenix-otel");
64
-
23
+ this.phoenixOtel = { register };
65
24
  this.tracerProvider = register({
66
25
  projectName: this.config.projectName,
67
26
  url: this.config.url,
68
27
  apiKey: this.config.apiKey,
69
28
  batch: this.config.batch,
70
- headers: this.config.headers,
29
+ headers: this.config.headers
71
30
  });
72
31
  }
73
-
74
- async shutdown(): Promise<void> {
32
+ async shutdown() {
75
33
  if (this.tracerProvider?.forceFlush) {
76
34
  await this.tracerProvider.forceFlush();
77
35
  }
78
36
  }
79
-
80
- startSpan(context: SpanContext): Span {
37
+ startSpan(context) {
81
38
  if (!this.otelApi) {
82
39
  throw new Error("PhoenixAdapter not initialized");
83
40
  }
84
-
85
41
  const tracer = this.otelApi.trace.getTracer("struktur");
86
-
87
42
  const spanKind = context.kind;
88
43
  const otelSpan = tracer.startSpan(context.name, {
89
44
  attributes: {
90
45
  "openinference.span.kind": spanKind,
91
- ...context.attributes,
92
- },
93
- }) as OtelSpan;
94
-
46
+ ...context.attributes
47
+ }
48
+ });
95
49
  const spanContext = otelSpan.spanContext();
96
- const span: Span = {
50
+ const span = {
97
51
  id: spanContext.spanId,
98
52
  traceId: spanContext.traceId,
99
53
  name: context.name,
100
54
  kind: context.kind,
101
55
  startTime: context.startTime ?? Date.now(),
102
- parentId: context.parentSpan?.id,
56
+ parentId: context.parentSpan?.id
103
57
  };
104
-
105
58
  this.activeSpans.set(span.id, otelSpan);
106
59
  return span;
107
60
  }
108
-
109
- endSpan(span: Span, result?: SpanResult): void {
61
+ endSpan(span, result) {
110
62
  const otelSpan = this.activeSpans.get(span.id);
111
63
  if (!otelSpan) return;
112
-
113
64
  if (result) {
114
- // OTel status codes: 1 = OK, 2 = ERROR
115
65
  otelSpan.setStatus({
116
66
  code: result.status === "ok" ? 1 : 2,
117
- message: result.error?.message,
67
+ message: result.error?.message
118
68
  });
119
-
120
- if (result.output !== undefined) {
69
+ if (result.output !== void 0) {
121
70
  try {
122
- const outputStr = typeof result.output === "string"
123
- ? result.output
124
- : JSON.stringify(result.output);
71
+ const outputStr = typeof result.output === "string" ? result.output : JSON.stringify(result.output);
125
72
  otelSpan.setAttribute("output.value", outputStr);
126
73
  } catch {
127
74
  otelSpan.setAttribute("output.value", "[object]");
128
75
  }
129
76
  }
130
-
131
- if (result.latencyMs !== undefined) {
77
+ if (result.latencyMs !== void 0) {
132
78
  otelSpan.setAttribute("latency_ms", result.latencyMs);
133
79
  }
134
80
  }
135
-
136
81
  otelSpan.end();
137
82
  this.activeSpans.delete(span.id);
138
83
  }
139
-
140
- recordEvent(span: Span, event: TelemetryEvent): void {
84
+ recordEvent(span, event) {
141
85
  const otelSpan = this.activeSpans.get(span.id);
142
86
  if (!otelSpan) return;
143
-
144
87
  switch (event.type) {
145
88
  case "llm_call":
146
89
  this.recordLLMCall(otelSpan, event);
@@ -162,14 +105,12 @@ export class PhoenixAdapter implements TelemetryAdapter {
162
105
  break;
163
106
  }
164
107
  }
165
-
166
- setAttributes(span: Span, attributes: Record<string, unknown>): void {
108
+ setAttributes(span, attributes) {
167
109
  const otelSpan = this.activeSpans.get(span.id);
168
110
  if (!otelSpan) return;
169
-
170
- const stringAttrs: Record<string, string | number | boolean> = {};
111
+ const stringAttrs = {};
171
112
  for (const [key, value] of Object.entries(attributes)) {
172
- if (value !== undefined && value !== null) {
113
+ if (value !== void 0 && value !== null) {
173
114
  if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
174
115
  stringAttrs[key] = value;
175
116
  } else {
@@ -181,158 +122,119 @@ export class PhoenixAdapter implements TelemetryAdapter {
181
122
  }
182
123
  }
183
124
  }
184
-
185
125
  otelSpan.setAttributes(stringAttrs);
186
126
  }
187
-
188
- setContext(_context: TelemetryContext): void {
189
- // Phoenix/OpenInference supports context via OTel context propagation
190
- // This would require setting up context managers
191
- // For now, attributes can be set on spans directly
127
+ setContext(_context) {
192
128
  }
193
-
194
- private recordLLMCall(span: OtelSpan, event: LLMCallEvent): void {
195
- const attrs: Record<string, string | number | boolean> = {
129
+ recordLLMCall(span, event) {
130
+ const attrs = {
196
131
  "llm.model_name": event.model,
197
132
  "llm.provider": event.provider,
198
133
  "llm.temperature": event.input.temperature ?? "",
199
- "llm.max_tokens": event.input.maxTokens ?? "",
134
+ "llm.max_tokens": event.input.maxTokens ?? ""
200
135
  };
201
-
202
- // Record input messages
203
136
  if (event.input.messages.length > 0) {
204
137
  attrs["llm.input_messages"] = JSON.stringify(event.input.messages);
205
138
  }
206
-
207
- // Record schema if present
208
139
  if (event.input.schema) {
209
140
  try {
210
141
  attrs["llm.schema"] = JSON.stringify(event.input.schema);
211
142
  } catch {
212
- // Ignore schema serialization errors
213
143
  }
214
144
  }
215
-
216
- // Record output
217
145
  if (event.output) {
218
146
  attrs["output.value"] = event.output.content;
219
147
  attrs["llm.structured_output"] = event.output.structured ?? false;
220
-
221
- // Record token usage
222
148
  if (event.output.usage) {
223
149
  this.setTokenUsageAttrs(attrs, event.output.usage);
224
150
  }
225
151
  }
226
-
227
152
  attrs["latency_ms"] = event.latencyMs;
228
-
229
153
  if (event.error) {
230
154
  span.recordException(event.error);
231
155
  }
232
-
233
156
  span.setAttributes(attrs);
234
157
  }
235
-
236
- private setTokenUsageAttrs(attrs: Record<string, string | number | boolean>, usage: TokenUsage): void {
158
+ setTokenUsageAttrs(attrs, usage) {
237
159
  attrs["llm.token_count.prompt"] = usage.input;
238
160
  attrs["llm.token_count.completion"] = usage.output;
239
161
  attrs["llm.token_count.total"] = usage.total;
240
162
  }
241
-
242
- private recordValidation(span: OtelSpan, event: ValidationEvent): void {
243
- const attrs: Record<string, string | number | boolean> = {
163
+ recordValidation(span, event) {
164
+ const attrs = {
244
165
  "validation.attempt": event.attempt,
245
166
  "validation.max_attempts": event.maxAttempts,
246
- "validation.success": event.success,
167
+ "validation.success": event.success
247
168
  };
248
-
249
169
  if (event.errors && event.errors.length > 0) {
250
170
  attrs["validation.errors"] = JSON.stringify(event.errors);
251
171
  }
252
-
253
- if (event.latencyMs !== undefined) {
172
+ if (event.latencyMs !== void 0) {
254
173
  attrs["latency_ms"] = event.latencyMs;
255
174
  }
256
-
257
175
  span.setAttributes(attrs);
258
176
  }
259
-
260
- private recordChunk(span: OtelSpan, event: ChunkEvent): void {
177
+ recordChunk(span, event) {
261
178
  span.setAttributes({
262
179
  "chunk.index": event.chunkIndex,
263
180
  "chunk.total": event.totalChunks,
264
181
  "chunk.tokens": event.tokens,
265
- "chunk.images": event.images,
182
+ "chunk.images": event.images
266
183
  });
267
-
268
184
  if (event.content) {
269
- span.setAttribute("chunk.content_preview", event.content.slice(0, 1000));
185
+ span.setAttribute("chunk.content_preview", event.content.slice(0, 1e3));
270
186
  }
271
187
  }
272
-
273
- private recordToolCall(span: OtelSpan, event: ToolCallEvent): void {
274
- const attrs: Record<string, string | number | boolean> = {
188
+ recordToolCall(span, event) {
189
+ const attrs = {
275
190
  "tool.name": event.toolName,
276
- "tool.args": JSON.stringify(event.args),
191
+ "tool.args": JSON.stringify(event.args)
277
192
  };
278
-
279
- if (event.result !== undefined) {
193
+ if (event.result !== void 0) {
280
194
  try {
281
195
  attrs["tool.result"] = JSON.stringify(event.result);
282
196
  } catch {
283
197
  attrs["tool.result"] = "[object]";
284
198
  }
285
199
  }
286
-
287
200
  if (event.error) {
288
201
  attrs["tool.error"] = event.error.message;
289
202
  }
290
-
291
- if (event.latencyMs !== undefined) {
203
+ if (event.latencyMs !== void 0) {
292
204
  attrs["latency_ms"] = event.latencyMs;
293
205
  }
294
-
295
206
  span.setAttributes(attrs);
296
-
297
207
  if (event.error) {
298
208
  span.recordException(event.error);
299
209
  }
300
210
  }
301
-
302
- private recordMerge(span: OtelSpan, event: MergeEvent): void {
303
- const attrs: Record<string, string | number | boolean> = {
211
+ recordMerge(span, event) {
212
+ const attrs = {
304
213
  "merge.strategy": event.strategy,
305
214
  "merge.input_count": event.inputCount,
306
- "merge.output_count": event.outputCount,
215
+ "merge.output_count": event.outputCount
307
216
  };
308
-
309
- if (event.deduped !== undefined) {
217
+ if (event.deduped !== void 0) {
310
218
  attrs["merge.deduped"] = event.deduped;
311
219
  }
312
-
313
220
  span.setAttributes(attrs);
314
221
  }
315
-
316
- private recordParse(span: OtelSpan, event: ParseEvent): void {
222
+ recordParse(span, event) {
317
223
  span.setAttributes({
318
224
  "parse.mime_type": event.mimeType,
319
225
  "parse.parser": event.parser,
320
226
  "parse.input_size": event.inputSize,
321
227
  "parse.output_tokens": event.outputTokens,
322
228
  "parse.output_images": event.outputImages,
323
- "latency_ms": event.latencyMs,
229
+ "latency_ms": event.latencyMs
324
230
  });
325
231
  }
326
- }
327
-
328
- /**
329
- * Create a Phoenix telemetry adapter
330
- *
331
- * @param config - Phoenix configuration
332
- * @returns Phoenix telemetry adapter
333
- */
334
- export function createPhoenixAdapter(config: PhoenixConfig): PhoenixAdapter {
232
+ };
233
+ function createPhoenixAdapter(config) {
335
234
  return new PhoenixAdapter(config);
336
235
  }
337
-
338
- export type { PhoenixConfig };
236
+ export {
237
+ PhoenixAdapter,
238
+ createPhoenixAdapter
239
+ };
240
+ //# sourceMappingURL=phoenix.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/adapters/phoenix/PhoenixAdapter.ts"],"sourcesContent":["/**\n * Phoenix (Arize) telemetry adapter\n * \n * Implements TelemetryAdapter for Phoenix using OpenTelemetry and\n * OpenInference semantic conventions.\n */\n\nimport type {\n TelemetryAdapter,\n SpanContext,\n Span,\n SpanResult,\n TelemetryEvent,\n TelemetryContext,\n PhoenixConfig,\n LLMCallEvent,\n ValidationEvent,\n ChunkEvent,\n ToolCallEvent,\n MergeEvent,\n ParseEvent,\n TokenUsage,\n} from \"../../types.js\";\n\ntype OtelSpan = {\n spanContext: () => { spanId: string; traceId: string };\n setStatus: (status: { code: number; message?: string }) => void;\n setAttribute: (key: string, value: string | number | boolean | undefined) => void;\n setAttributes: (attrs: Record<string, string | number | boolean>) => void;\n recordException: (error: Error) => void;\n end: () => void;\n};\n\n/**\n * Phoenix telemetry adapter using OpenTelemetry\n */\nexport class PhoenixAdapter implements TelemetryAdapter {\n readonly name = \"phoenix\";\n readonly version = \"1.0.0\";\n\n private config: PhoenixConfig;\n private tracerProvider: { forceFlush?: () => Promise<void> } | null = null;\n private activeSpans = new Map<string, OtelSpan>();\n private otelApi: typeof import(\"@opentelemetry/api\") | null = null;\n private phoenixOtel: typeof import(\"@arizeai/phoenix-otel\") | null = null;\n\n constructor(config: PhoenixConfig) {\n this.config = {\n url: \"http://localhost:6006\",\n batch: true,\n ...config,\n };\n }\n\n async initialize(): Promise<void> {\n // Dynamically import OTel dependencies\n const [{ register }, otelApi] = await Promise.all([\n import(\"@arizeai/phoenix-otel\"),\n import(\"@opentelemetry/api\"),\n ]);\n\n this.otelApi = otelApi;\n this.phoenixOtel = { register } as typeof import(\"@arizeai/phoenix-otel\");\n\n this.tracerProvider = register({\n projectName: this.config.projectName,\n url: this.config.url,\n apiKey: this.config.apiKey,\n batch: this.config.batch,\n headers: this.config.headers,\n });\n }\n\n async shutdown(): Promise<void> {\n if (this.tracerProvider?.forceFlush) {\n await this.tracerProvider.forceFlush();\n }\n }\n\n startSpan(context: SpanContext): Span {\n if (!this.otelApi) {\n throw new Error(\"PhoenixAdapter not initialized\");\n }\n\n const tracer = this.otelApi.trace.getTracer(\"struktur\");\n \n const spanKind = context.kind;\n const otelSpan = tracer.startSpan(context.name, {\n attributes: {\n \"openinference.span.kind\": spanKind,\n ...context.attributes,\n },\n }) as OtelSpan;\n\n const spanContext = otelSpan.spanContext();\n const span: Span = {\n id: spanContext.spanId,\n traceId: spanContext.traceId,\n name: context.name,\n kind: context.kind,\n startTime: context.startTime ?? Date.now(),\n parentId: context.parentSpan?.id,\n };\n\n this.activeSpans.set(span.id, otelSpan);\n return span;\n }\n\n endSpan(span: Span, result?: SpanResult): void {\n const otelSpan = this.activeSpans.get(span.id);\n if (!otelSpan) return;\n\n if (result) {\n // OTel status codes: 1 = OK, 2 = ERROR\n otelSpan.setStatus({\n code: result.status === \"ok\" ? 1 : 2,\n message: result.error?.message,\n });\n\n if (result.output !== undefined) {\n try {\n const outputStr = typeof result.output === \"string\" \n ? result.output \n : JSON.stringify(result.output);\n otelSpan.setAttribute(\"output.value\", outputStr);\n } catch {\n otelSpan.setAttribute(\"output.value\", \"[object]\");\n }\n }\n\n if (result.latencyMs !== undefined) {\n otelSpan.setAttribute(\"latency_ms\", result.latencyMs);\n }\n }\n\n otelSpan.end();\n this.activeSpans.delete(span.id);\n }\n\n recordEvent(span: Span, event: TelemetryEvent): void {\n const otelSpan = this.activeSpans.get(span.id);\n if (!otelSpan) return;\n\n switch (event.type) {\n case \"llm_call\":\n this.recordLLMCall(otelSpan, event);\n break;\n case \"validation\":\n this.recordValidation(otelSpan, event);\n break;\n case \"chunk\":\n this.recordChunk(otelSpan, event);\n break;\n case \"tool_call\":\n this.recordToolCall(otelSpan, event);\n break;\n case \"merge\":\n this.recordMerge(otelSpan, event);\n break;\n case \"parse\":\n this.recordParse(otelSpan, event);\n break;\n }\n }\n\n setAttributes(span: Span, attributes: Record<string, unknown>): void {\n const otelSpan = this.activeSpans.get(span.id);\n if (!otelSpan) return;\n\n const stringAttrs: Record<string, string | number | boolean> = {};\n for (const [key, value] of Object.entries(attributes)) {\n if (value !== undefined && value !== null) {\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") {\n stringAttrs[key] = value;\n } else {\n try {\n stringAttrs[key] = JSON.stringify(value);\n } catch {\n stringAttrs[key] = String(value);\n }\n }\n }\n }\n\n otelSpan.setAttributes(stringAttrs);\n }\n\n setContext(_context: TelemetryContext): void {\n // Phoenix/OpenInference supports context via OTel context propagation\n // This would require setting up context managers\n // For now, attributes can be set on spans directly\n }\n\n private recordLLMCall(span: OtelSpan, event: LLMCallEvent): void {\n const attrs: Record<string, string | number | boolean> = {\n \"llm.model_name\": event.model,\n \"llm.provider\": event.provider,\n \"llm.temperature\": event.input.temperature ?? \"\",\n \"llm.max_tokens\": event.input.maxTokens ?? \"\",\n };\n\n // Record input messages\n if (event.input.messages.length > 0) {\n attrs[\"llm.input_messages\"] = JSON.stringify(event.input.messages);\n }\n\n // Record schema if present\n if (event.input.schema) {\n try {\n attrs[\"llm.schema\"] = JSON.stringify(event.input.schema);\n } catch {\n // Ignore schema serialization errors\n }\n }\n\n // Record output\n if (event.output) {\n attrs[\"output.value\"] = event.output.content;\n attrs[\"llm.structured_output\"] = event.output.structured ?? false;\n\n // Record token usage\n if (event.output.usage) {\n this.setTokenUsageAttrs(attrs, event.output.usage);\n }\n }\n\n attrs[\"latency_ms\"] = event.latencyMs;\n\n if (event.error) {\n span.recordException(event.error);\n }\n\n span.setAttributes(attrs);\n }\n\n private setTokenUsageAttrs(attrs: Record<string, string | number | boolean>, usage: TokenUsage): void {\n attrs[\"llm.token_count.prompt\"] = usage.input;\n attrs[\"llm.token_count.completion\"] = usage.output;\n attrs[\"llm.token_count.total\"] = usage.total;\n }\n\n private recordValidation(span: OtelSpan, event: ValidationEvent): void {\n const attrs: Record<string, string | number | boolean> = {\n \"validation.attempt\": event.attempt,\n \"validation.max_attempts\": event.maxAttempts,\n \"validation.success\": event.success,\n };\n\n if (event.errors && event.errors.length > 0) {\n attrs[\"validation.errors\"] = JSON.stringify(event.errors);\n }\n\n if (event.latencyMs !== undefined) {\n attrs[\"latency_ms\"] = event.latencyMs;\n }\n\n span.setAttributes(attrs);\n }\n\n private recordChunk(span: OtelSpan, event: ChunkEvent): void {\n span.setAttributes({\n \"chunk.index\": event.chunkIndex,\n \"chunk.total\": event.totalChunks,\n \"chunk.tokens\": event.tokens,\n \"chunk.images\": event.images,\n });\n\n if (event.content) {\n span.setAttribute(\"chunk.content_preview\", event.content.slice(0, 1000));\n }\n }\n\n private recordToolCall(span: OtelSpan, event: ToolCallEvent): void {\n const attrs: Record<string, string | number | boolean> = {\n \"tool.name\": event.toolName,\n \"tool.args\": JSON.stringify(event.args),\n };\n\n if (event.result !== undefined) {\n try {\n attrs[\"tool.result\"] = JSON.stringify(event.result);\n } catch {\n attrs[\"tool.result\"] = \"[object]\";\n }\n }\n\n if (event.error) {\n attrs[\"tool.error\"] = event.error.message;\n }\n\n if (event.latencyMs !== undefined) {\n attrs[\"latency_ms\"] = event.latencyMs;\n }\n\n span.setAttributes(attrs);\n\n if (event.error) {\n span.recordException(event.error);\n }\n }\n\n private recordMerge(span: OtelSpan, event: MergeEvent): void {\n const attrs: Record<string, string | number | boolean> = {\n \"merge.strategy\": event.strategy,\n \"merge.input_count\": event.inputCount,\n \"merge.output_count\": event.outputCount,\n };\n\n if (event.deduped !== undefined) {\n attrs[\"merge.deduped\"] = event.deduped;\n }\n\n span.setAttributes(attrs);\n }\n\n private recordParse(span: OtelSpan, event: ParseEvent): void {\n span.setAttributes({\n \"parse.mime_type\": event.mimeType,\n \"parse.parser\": event.parser,\n \"parse.input_size\": event.inputSize,\n \"parse.output_tokens\": event.outputTokens,\n \"parse.output_images\": event.outputImages,\n \"latency_ms\": event.latencyMs,\n });\n }\n}\n\n/**\n * Create a Phoenix telemetry adapter\n * \n * @param config - Phoenix configuration\n * @returns Phoenix telemetry adapter\n */\nexport function createPhoenixAdapter(config: PhoenixConfig): PhoenixAdapter {\n return new PhoenixAdapter(config);\n}\n\nexport type { PhoenixConfig };\n"],"mappings":"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","names":[]}