@langfuse/tracing 4.0.0-alpha.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.
package/dist/index.mjs ADDED
@@ -0,0 +1,460 @@
1
+ // src/index.ts
2
+ import { getGlobalLogger } from "@langfuse/core";
3
+ import {
4
+ trace as trace2,
5
+ context,
6
+ SpanStatusCode
7
+ } from "@opentelemetry/api";
8
+
9
+ // src/attributes.ts
10
+ import { LangfuseOtelSpanAttributes } from "@langfuse/core";
11
+ function createTraceAttributes({
12
+ name,
13
+ userId,
14
+ sessionId,
15
+ version,
16
+ release,
17
+ input,
18
+ output,
19
+ metadata,
20
+ tags,
21
+ environment,
22
+ public: isPublic
23
+ } = {}) {
24
+ const attributes = {
25
+ [LangfuseOtelSpanAttributes.TRACE_NAME]: name,
26
+ [LangfuseOtelSpanAttributes.TRACE_USER_ID]: userId,
27
+ [LangfuseOtelSpanAttributes.TRACE_SESSION_ID]: sessionId,
28
+ [LangfuseOtelSpanAttributes.VERSION]: version,
29
+ [LangfuseOtelSpanAttributes.RELEASE]: release,
30
+ [LangfuseOtelSpanAttributes.TRACE_INPUT]: _serialize(input),
31
+ [LangfuseOtelSpanAttributes.TRACE_OUTPUT]: _serialize(output),
32
+ [LangfuseOtelSpanAttributes.TRACE_TAGS]: tags,
33
+ [LangfuseOtelSpanAttributes.ENVIRONMENT]: environment,
34
+ [LangfuseOtelSpanAttributes.TRACE_PUBLIC]: isPublic,
35
+ ..._flattenAndSerializeMetadata(metadata, "trace")
36
+ };
37
+ return Object.fromEntries(
38
+ Object.entries(attributes).filter(([_, v]) => v != null)
39
+ );
40
+ }
41
+ function createSpanAttributes({
42
+ metadata,
43
+ input,
44
+ output,
45
+ level,
46
+ statusMessage,
47
+ version
48
+ }) {
49
+ const attributes = {
50
+ [LangfuseOtelSpanAttributes.OBSERVATION_TYPE]: "span",
51
+ [LangfuseOtelSpanAttributes.OBSERVATION_LEVEL]: level,
52
+ [LangfuseOtelSpanAttributes.OBSERVATION_STATUS_MESSAGE]: statusMessage,
53
+ [LangfuseOtelSpanAttributes.VERSION]: version,
54
+ [LangfuseOtelSpanAttributes.OBSERVATION_INPUT]: _serialize(input),
55
+ [LangfuseOtelSpanAttributes.OBSERVATION_OUTPUT]: _serialize(output),
56
+ ..._flattenAndSerializeMetadata(metadata, "observation")
57
+ };
58
+ return Object.fromEntries(
59
+ Object.entries(attributes).filter(([_, v]) => v != null)
60
+ );
61
+ }
62
+ function createGenerationAttributes({
63
+ completionStartTime,
64
+ metadata,
65
+ level,
66
+ statusMessage,
67
+ version,
68
+ model,
69
+ modelParameters,
70
+ input,
71
+ output,
72
+ usageDetails,
73
+ costDetails,
74
+ prompt
75
+ }) {
76
+ const attributes = {
77
+ [LangfuseOtelSpanAttributes.OBSERVATION_TYPE]: "generation",
78
+ [LangfuseOtelSpanAttributes.OBSERVATION_LEVEL]: level,
79
+ [LangfuseOtelSpanAttributes.OBSERVATION_STATUS_MESSAGE]: statusMessage,
80
+ [LangfuseOtelSpanAttributes.VERSION]: version,
81
+ [LangfuseOtelSpanAttributes.OBSERVATION_INPUT]: _serialize(input),
82
+ [LangfuseOtelSpanAttributes.OBSERVATION_OUTPUT]: _serialize(output),
83
+ [LangfuseOtelSpanAttributes.OBSERVATION_MODEL]: model,
84
+ [LangfuseOtelSpanAttributes.OBSERVATION_USAGE_DETAILS]: _serialize(usageDetails),
85
+ [LangfuseOtelSpanAttributes.OBSERVATION_COST_DETAILS]: _serialize(costDetails),
86
+ [LangfuseOtelSpanAttributes.OBSERVATION_COMPLETION_START_TIME]: _serialize(completionStartTime),
87
+ [LangfuseOtelSpanAttributes.OBSERVATION_MODEL_PARAMETERS]: _serialize(modelParameters),
88
+ ...prompt && !prompt.isFallback ? {
89
+ [LangfuseOtelSpanAttributes.OBSERVATION_PROMPT_NAME]: prompt.name,
90
+ [LangfuseOtelSpanAttributes.OBSERVATION_PROMPT_VERSION]: prompt.version
91
+ } : {},
92
+ ..._flattenAndSerializeMetadata(metadata, "observation")
93
+ };
94
+ return Object.fromEntries(
95
+ Object.entries(attributes).filter(([_, v]) => v != null)
96
+ );
97
+ }
98
+ function createEventAttributes({
99
+ metadata,
100
+ input,
101
+ output,
102
+ level,
103
+ statusMessage,
104
+ version
105
+ }) {
106
+ const attributes = {
107
+ [LangfuseOtelSpanAttributes.OBSERVATION_TYPE]: "event",
108
+ [LangfuseOtelSpanAttributes.OBSERVATION_LEVEL]: level,
109
+ [LangfuseOtelSpanAttributes.OBSERVATION_STATUS_MESSAGE]: statusMessage,
110
+ [LangfuseOtelSpanAttributes.VERSION]: version,
111
+ [LangfuseOtelSpanAttributes.OBSERVATION_INPUT]: _serialize(input),
112
+ [LangfuseOtelSpanAttributes.OBSERVATION_OUTPUT]: _serialize(output),
113
+ ..._flattenAndSerializeMetadata(metadata, "observation")
114
+ };
115
+ return Object.fromEntries(
116
+ Object.entries(attributes).filter(([_, v]) => v != null)
117
+ );
118
+ }
119
+ function _serialize(obj) {
120
+ try {
121
+ return obj != null ? JSON.stringify(obj) : void 0;
122
+ } catch {
123
+ return "<failed to serialize>";
124
+ }
125
+ }
126
+ function _flattenAndSerializeMetadata(metadata, type) {
127
+ const prefix = type === "observation" ? LangfuseOtelSpanAttributes.OBSERVATION_METADATA : LangfuseOtelSpanAttributes.TRACE_METADATA;
128
+ const metadataAttributes = {};
129
+ if (metadata === void 0 || metadata === null) {
130
+ return metadataAttributes;
131
+ }
132
+ if (typeof metadata !== "object" || Array.isArray(metadata)) {
133
+ const serialized = _serialize(metadata);
134
+ if (serialized) {
135
+ metadataAttributes[prefix] = serialized;
136
+ }
137
+ } else {
138
+ for (const [key, value] of Object.entries(metadata)) {
139
+ const serialized = typeof value === "string" ? value : _serialize(value);
140
+ if (serialized) {
141
+ metadataAttributes[`${prefix}.${key}`] = serialized;
142
+ }
143
+ }
144
+ }
145
+ return metadataAttributes;
146
+ }
147
+
148
+ // src/utils.ts
149
+ import { LANGFUSE_SDK_VERSION, LANGFUSE_TRACER_NAME } from "@langfuse/core";
150
+ import { trace } from "@opentelemetry/api";
151
+ function getLangfuseTracer() {
152
+ return trace.getTracer(LANGFUSE_TRACER_NAME, LANGFUSE_SDK_VERSION);
153
+ }
154
+
155
+ // src/spanWrapper.ts
156
+ var LangfuseSpanWrapper = class {
157
+ constructor(params) {
158
+ this.otelSpan = params.otelSpan;
159
+ this.id = params.otelSpan.spanContext().spanId;
160
+ this.traceId = params.otelSpan.spanContext().traceId;
161
+ }
162
+ get tracer() {
163
+ return getLangfuseTracer();
164
+ }
165
+ end(endTime) {
166
+ this.otelSpan.end(endTime);
167
+ }
168
+ updateTrace(attributes) {
169
+ this.otelSpan.setAttributes(createTraceAttributes(attributes));
170
+ return this;
171
+ }
172
+ };
173
+ var LangfuseSpan = class extends LangfuseSpanWrapper {
174
+ constructor(params) {
175
+ super(params);
176
+ if (params.attributes) {
177
+ this.otelSpan.setAttributes(createSpanAttributes(params.attributes));
178
+ }
179
+ }
180
+ update(attributes) {
181
+ this.otelSpan.setAttributes(createSpanAttributes(attributes));
182
+ return this;
183
+ }
184
+ startSpan(name, attributes) {
185
+ return startSpan(name, attributes, {
186
+ parentSpanContext: this.otelSpan.spanContext()
187
+ });
188
+ }
189
+ startGeneration(name, attributes) {
190
+ return startGeneration(name, attributes, {
191
+ parentSpanContext: this.otelSpan.spanContext()
192
+ });
193
+ }
194
+ createEvent(name, attributes) {
195
+ return createEvent(name, attributes, {
196
+ parentSpanContext: this.otelSpan.spanContext()
197
+ });
198
+ }
199
+ };
200
+ var LangfuseGeneration = class extends LangfuseSpanWrapper {
201
+ constructor(params) {
202
+ super(params);
203
+ if (params.attributes) {
204
+ this.otelSpan.setAttributes(
205
+ createGenerationAttributes(params.attributes)
206
+ );
207
+ }
208
+ }
209
+ update(attributes) {
210
+ this.otelSpan.setAttributes(createGenerationAttributes(attributes));
211
+ return this;
212
+ }
213
+ createEvent(name, attributes) {
214
+ return createEvent(name, attributes, {
215
+ parentSpanContext: this.otelSpan.spanContext()
216
+ });
217
+ }
218
+ };
219
+ var LangfuseEvent = class extends LangfuseSpanWrapper {
220
+ constructor(params) {
221
+ super(params);
222
+ if (params.attributes) {
223
+ this.otelSpan.setAttributes(createEventAttributes(params.attributes));
224
+ }
225
+ this.otelSpan.end(params.timestamp);
226
+ }
227
+ };
228
+
229
+ // src/index.ts
230
+ import { LangfuseOtelSpanAttributes as LangfuseOtelSpanAttributes2 } from "@langfuse/core";
231
+ function createOtelSpan(params) {
232
+ return getLangfuseTracer().startSpan(
233
+ params.name,
234
+ { startTime: params.startTime },
235
+ createParentContext(params.parentSpanContext)
236
+ );
237
+ }
238
+ function createParentContext(parentSpanContext) {
239
+ if (!parentSpanContext) return;
240
+ return trace2.setSpanContext(context.active(), parentSpanContext);
241
+ }
242
+ function wrapPromise(promise, span) {
243
+ return promise.then(
244
+ (value) => {
245
+ span.end();
246
+ return value;
247
+ },
248
+ (err) => {
249
+ span.setStatus({
250
+ code: SpanStatusCode.ERROR,
251
+ message: err instanceof Error ? err.message : "Unknown error"
252
+ }).end();
253
+ throw err;
254
+ }
255
+ );
256
+ }
257
+ function startSpan(name, attributes, options) {
258
+ const otelSpan = createOtelSpan({
259
+ name,
260
+ ...options
261
+ });
262
+ return new LangfuseSpan({ otelSpan, attributes });
263
+ }
264
+ function startGeneration(name, attributes, options) {
265
+ const otelSpan = createOtelSpan({
266
+ name,
267
+ ...options
268
+ });
269
+ return new LangfuseGeneration({ otelSpan, attributes });
270
+ }
271
+ function createEvent(name, attributes, options) {
272
+ var _a;
273
+ const timestamp = (_a = options == null ? void 0 : options.startTime) != null ? _a : /* @__PURE__ */ new Date();
274
+ const otelSpan = createOtelSpan({
275
+ name,
276
+ ...options,
277
+ startTime: timestamp
278
+ });
279
+ return new LangfuseEvent({ otelSpan, attributes, timestamp });
280
+ }
281
+ function startActiveSpan(name, fn, options) {
282
+ var _a;
283
+ return getLangfuseTracer().startActiveSpan(
284
+ name,
285
+ { startTime: options == null ? void 0 : options.startTime },
286
+ (_a = createParentContext(options == null ? void 0 : options.parentSpanContext)) != null ? _a : context.active(),
287
+ (span) => {
288
+ try {
289
+ const result = fn(new LangfuseSpan({ otelSpan: span }));
290
+ if (result instanceof Promise) {
291
+ return wrapPromise(result, span);
292
+ } else {
293
+ span.end();
294
+ return result;
295
+ }
296
+ } catch (err) {
297
+ span.setStatus({
298
+ code: SpanStatusCode.ERROR,
299
+ message: err instanceof Error ? err.message : "Unknown error"
300
+ }).end();
301
+ throw err;
302
+ }
303
+ }
304
+ );
305
+ }
306
+ function startActiveGeneration(name, fn, options) {
307
+ var _a;
308
+ return getLangfuseTracer().startActiveSpan(
309
+ name,
310
+ { startTime: options == null ? void 0 : options.startTime },
311
+ (_a = createParentContext(options == null ? void 0 : options.parentSpanContext)) != null ? _a : context.active(),
312
+ (span) => {
313
+ try {
314
+ const result = fn(new LangfuseGeneration({ otelSpan: span }));
315
+ if (result instanceof Promise) {
316
+ return wrapPromise(result, span);
317
+ } else {
318
+ span.end();
319
+ return result;
320
+ }
321
+ } catch (err) {
322
+ span.setStatus({
323
+ code: SpanStatusCode.ERROR,
324
+ message: err instanceof Error ? err.message : "Unknown error"
325
+ }).end();
326
+ throw err;
327
+ }
328
+ }
329
+ );
330
+ }
331
+ function updateActiveTrace(attributes) {
332
+ const span = trace2.getActiveSpan();
333
+ if (!span) {
334
+ getGlobalLogger().warn(
335
+ "No active OTEL span in context. Skipping trace update."
336
+ );
337
+ return;
338
+ }
339
+ span.setAttributes(createTraceAttributes(attributes));
340
+ }
341
+ function updateActiveSpan(attributes) {
342
+ const span = trace2.getActiveSpan();
343
+ if (!span) {
344
+ getGlobalLogger().warn(
345
+ "No active OTEL span in context. Skipping span update."
346
+ );
347
+ return;
348
+ }
349
+ span.setAttributes(createSpanAttributes(attributes));
350
+ }
351
+ function updateActiveGeneration(attributes) {
352
+ const span = trace2.getActiveSpan();
353
+ if (!span) {
354
+ getGlobalLogger().warn(
355
+ "No active OTEL span in context. Skipping generation update."
356
+ );
357
+ return;
358
+ }
359
+ span.setAttributes(createGenerationAttributes(attributes));
360
+ }
361
+ function observe(fn, options = {}) {
362
+ const {
363
+ name = fn.name || "anonymous-function",
364
+ asType = "span",
365
+ captureInput = true,
366
+ captureOutput = true
367
+ } = options;
368
+ const wrappedFunction = (...args) => {
369
+ const inputData = captureInput ? _captureArguments(args) : void 0;
370
+ const observation = asType === "generation" ? startGeneration(name, inputData ? { input: inputData } : {}) : startSpan(name, inputData ? { input: inputData } : {});
371
+ const activeContext = trace2.setSpan(context.active(), observation.otelSpan);
372
+ try {
373
+ const result = context.with(activeContext, () => fn(...args));
374
+ if (result instanceof Promise) {
375
+ return result.then(
376
+ (value) => {
377
+ if (captureOutput) {
378
+ observation.update({ output: _captureOutput(value) });
379
+ }
380
+ observation.end();
381
+ return value;
382
+ },
383
+ (error) => {
384
+ observation.update({
385
+ level: "ERROR",
386
+ statusMessage: (error instanceof Error ? error.message : String(error)) || "Function threw an error",
387
+ output: captureOutput ? { error: String(error) } : void 0
388
+ }).end();
389
+ throw error;
390
+ }
391
+ );
392
+ } else {
393
+ if (captureOutput) {
394
+ observation.update({ output: _captureOutput(result) });
395
+ }
396
+ observation.end();
397
+ return result;
398
+ }
399
+ } catch (error) {
400
+ observation.update({
401
+ level: "ERROR",
402
+ statusMessage: (error instanceof Error ? error.message : String(error)) || "Function threw an error",
403
+ output: captureOutput ? { error: String(error) } : void 0
404
+ }).end();
405
+ throw error;
406
+ }
407
+ };
408
+ return wrappedFunction;
409
+ }
410
+ function _captureArguments(args) {
411
+ try {
412
+ if (args.length === 0) return void 0;
413
+ if (args.length === 1) return args[0];
414
+ return args;
415
+ } catch {
416
+ return "<failed to capture arguments>";
417
+ }
418
+ }
419
+ function _captureOutput(value) {
420
+ try {
421
+ if (value === void 0 || value === null) return value;
422
+ if (typeof value !== "object") return value;
423
+ return value;
424
+ } catch {
425
+ return "<failed to capture output>";
426
+ }
427
+ }
428
+ async function createTraceId(seed) {
429
+ if (seed) {
430
+ const data = new TextEncoder().encode(seed);
431
+ const hashBuffer = await crypto.subtle.digest("SHA-256", data);
432
+ const hashArray = new Uint8Array(hashBuffer);
433
+ return uint8ArrayToHex(hashArray).slice(0, 32);
434
+ }
435
+ const randomValues = crypto.getRandomValues(new Uint8Array(16));
436
+ return uint8ArrayToHex(randomValues);
437
+ }
438
+ function uint8ArrayToHex(array) {
439
+ return Array.from(array).map((b) => b.toString(16).padStart(2, "0")).join("");
440
+ }
441
+ export {
442
+ LangfuseEvent,
443
+ LangfuseGeneration,
444
+ LangfuseOtelSpanAttributes2 as LangfuseOtelSpanAttributes,
445
+ LangfuseSpan,
446
+ createEvent,
447
+ createGenerationAttributes,
448
+ createSpanAttributes,
449
+ createTraceAttributes,
450
+ createTraceId,
451
+ observe,
452
+ startActiveGeneration,
453
+ startActiveSpan,
454
+ startGeneration,
455
+ startSpan,
456
+ updateActiveGeneration,
457
+ updateActiveSpan,
458
+ updateActiveTrace
459
+ };
460
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/attributes.ts","../src/utils.ts","../src/spanWrapper.ts"],"sourcesContent":["import { getGlobalLogger } from \"@langfuse/core\";\nimport {\n trace,\n context,\n TimeInput,\n SpanStatusCode,\n Span,\n Context,\n SpanContext,\n} from \"@opentelemetry/api\";\n\nimport {\n createGenerationAttributes,\n createSpanAttributes,\n createTraceAttributes,\n} from \"./attributes.js\";\nimport {\n LangfuseEvent,\n LangfuseGeneration,\n LangfuseSpan,\n} from \"./spanWrapper.js\";\nimport {\n LangfuseEventAttributes,\n LangfuseGenerationAttributes,\n LangfuseSpanAttributes,\n LangfuseTraceAttributes,\n} from \"./types.js\";\nimport { getLangfuseTracer } from \"./utils.js\";\n\nexport type {\n LangfuseObservationType,\n ObservationLevel,\n LangfuseSpanAttributes,\n LangfuseEventAttributes,\n LangfuseGenerationAttributes,\n LangfuseAttributes,\n LangfuseTraceAttributes,\n} from \"./types.js\";\n\nexport * from \"./spanWrapper.js\";\nexport {\n createTraceAttributes,\n createSpanAttributes,\n createGenerationAttributes,\n} from \"./attributes.js\";\n\nexport { LangfuseOtelSpanAttributes } from \"@langfuse/core\";\n\nexport type StartObservationOptions = {\n startTime?: Date;\n parentSpanContext?: SpanContext;\n};\n\nfunction createOtelSpan(params: {\n name: string;\n startTime?: TimeInput;\n parentSpanContext?: SpanContext;\n}): Span {\n return getLangfuseTracer().startSpan(\n params.name,\n { startTime: params.startTime },\n createParentContext(params.parentSpanContext),\n );\n}\n\nfunction createParentContext(\n parentSpanContext?: SpanContext,\n): Context | undefined {\n if (!parentSpanContext) return;\n\n return trace.setSpanContext(context.active(), parentSpanContext);\n}\n\nfunction wrapPromise<T>(promise: Promise<T>, span: Span): Promise<T> {\n return promise.then(\n (value) => {\n span.end(); // End span AFTER Promise resolves\n\n return value;\n },\n (err: unknown) => {\n span\n .setStatus({\n code: SpanStatusCode.ERROR,\n message: err instanceof Error ? err.message : \"Unknown error\",\n })\n .end(); // End span AFTER Promise rejects\n\n throw err;\n },\n );\n}\n\nexport function startSpan(\n name: string,\n attributes?: LangfuseSpanAttributes,\n options?: {\n startTime?: TimeInput;\n parentSpanContext?: SpanContext;\n },\n): LangfuseSpan {\n const otelSpan = createOtelSpan({\n name,\n ...options,\n });\n\n return new LangfuseSpan({ otelSpan, attributes });\n}\n\nexport function startGeneration(\n name: string,\n attributes?: LangfuseGenerationAttributes,\n options?: StartObservationOptions,\n): LangfuseGeneration {\n const otelSpan = createOtelSpan({\n name,\n ...options,\n });\n\n return new LangfuseGeneration({ otelSpan, attributes });\n}\n\nexport function createEvent(\n name: string,\n attributes?: LangfuseEventAttributes,\n options?: StartObservationOptions,\n) {\n const timestamp = options?.startTime ?? new Date();\n\n const otelSpan = createOtelSpan({\n name,\n ...options,\n startTime: timestamp,\n });\n\n return new LangfuseEvent({ otelSpan, attributes, timestamp });\n}\n\nexport function startActiveSpan<F extends (span: LangfuseSpan) => unknown>(\n name: string,\n fn: F,\n options?: StartObservationOptions,\n): ReturnType<F> {\n return getLangfuseTracer().startActiveSpan(\n name,\n { startTime: options?.startTime },\n createParentContext(options?.parentSpanContext) ?? context.active(),\n (span) => {\n try {\n const result = fn(new LangfuseSpan({ otelSpan: span }));\n\n if (result instanceof Promise) {\n return wrapPromise(result, span) as ReturnType<F>;\n } else {\n span.end();\n\n return result as ReturnType<F>;\n }\n } catch (err) {\n span\n .setStatus({\n code: SpanStatusCode.ERROR,\n message: err instanceof Error ? err.message : \"Unknown error\",\n })\n .end();\n\n throw err;\n }\n },\n );\n}\n\nexport function startActiveGeneration<\n F extends (span: LangfuseGeneration) => unknown,\n>(name: string, fn: F, options?: StartObservationOptions): ReturnType<F> {\n return getLangfuseTracer().startActiveSpan(\n name,\n { startTime: options?.startTime },\n createParentContext(options?.parentSpanContext) ?? context.active(),\n (span) => {\n try {\n const result = fn(new LangfuseGeneration({ otelSpan: span }));\n\n if (result instanceof Promise) {\n return wrapPromise(result, span) as ReturnType<F>;\n } else {\n span.end();\n\n return result as ReturnType<F>;\n }\n } catch (err) {\n span\n .setStatus({\n code: SpanStatusCode.ERROR,\n message: err instanceof Error ? err.message : \"Unknown error\",\n })\n .end();\n\n throw err;\n }\n },\n );\n}\n\nexport function updateActiveTrace(attributes: LangfuseTraceAttributes) {\n const span = trace.getActiveSpan();\n\n if (!span) {\n getGlobalLogger().warn(\n \"No active OTEL span in context. Skipping trace update.\",\n );\n\n return;\n }\n\n span.setAttributes(createTraceAttributes(attributes));\n}\n\nexport function updateActiveSpan(attributes: LangfuseSpanAttributes) {\n const span = trace.getActiveSpan();\n\n if (!span) {\n getGlobalLogger().warn(\n \"No active OTEL span in context. Skipping span update.\",\n );\n\n return;\n }\n\n span.setAttributes(createSpanAttributes(attributes));\n}\n\nexport function updateActiveGeneration(\n attributes: LangfuseGenerationAttributes,\n) {\n const span = trace.getActiveSpan();\n\n if (!span) {\n getGlobalLogger().warn(\n \"No active OTEL span in context. Skipping generation update.\",\n );\n\n return;\n }\n\n span.setAttributes(createGenerationAttributes(attributes));\n}\n\nexport interface ObserveOptions {\n name?: string;\n asType?: \"span\" | \"generation\";\n captureInput?: boolean;\n captureOutput?: boolean;\n}\n\nexport function observe<T extends (...args: unknown[]) => unknown>(\n fn: T,\n options: ObserveOptions = {},\n): T {\n const {\n name = fn.name || \"anonymous-function\",\n asType = \"span\",\n captureInput = true,\n captureOutput = true,\n } = options;\n\n const wrappedFunction = (...args: Parameters<T>): ReturnType<T> => {\n // Prepare input data\n const inputData = captureInput ? _captureArguments(args) : undefined;\n\n // Create the appropriate observation type\n const observation =\n asType === \"generation\"\n ? startGeneration(name, inputData ? { input: inputData } : {})\n : startSpan(name, inputData ? { input: inputData } : {});\n\n // Set the observation span as active in the context\n const activeContext = trace.setSpan(context.active(), observation.otelSpan);\n\n try {\n const result = context.with(activeContext, () => fn(...args));\n\n // Handle async functions - check if result is a Promise\n // TODO: handle returned generators for streamed responses\n if (result instanceof Promise) {\n return result.then(\n (value) => {\n if (captureOutput) {\n observation.update({ output: _captureOutput(value) });\n }\n observation.end();\n\n return value;\n },\n (error: unknown) => {\n observation\n .update({\n level: \"ERROR\",\n statusMessage:\n (error instanceof Error ? error.message : String(error)) ||\n \"Function threw an error\",\n output: captureOutput ? { error: String(error) } : undefined,\n })\n .end();\n\n throw error;\n },\n ) as ReturnType<T>;\n } else {\n // Handle sync functions\n if (captureOutput) {\n observation.update({ output: _captureOutput(result) });\n }\n observation.end();\n\n return result as ReturnType<T>;\n }\n } catch (error: unknown) {\n observation\n .update({\n level: \"ERROR\",\n statusMessage:\n (error instanceof Error ? error.message : String(error)) ||\n \"Function threw an error\",\n output: captureOutput ? { error: String(error) } : undefined,\n })\n .end();\n\n throw error;\n }\n };\n\n return wrappedFunction as T;\n}\n\n// Helper function to safely capture function arguments\nfunction _captureArguments(args: unknown[]): unknown {\n try {\n if (args.length === 0) return undefined;\n if (args.length === 1) return args[0];\n return args;\n } catch {\n return \"<failed to capture arguments>\";\n }\n}\n\n// Helper function to safely capture function output\nfunction _captureOutput(value: unknown): unknown {\n try {\n // Handle undefined/null\n if (value === undefined || value === null) return value;\n\n // For primitive types, return as-is\n if (typeof value !== \"object\") return value;\n\n // For objects, return them directly (serialization happens in span processor)\n return value;\n } catch {\n return \"<failed to capture output>\";\n }\n}\n\n/**\n * Creates a trace ID for OpenTelemetry spans.\n *\n * @param seed - A seed string for deterministic trace ID generation.\n * If provided (non-empty), the same seed will always generate the same trace ID.\n * If empty or falsy, generates a random trace ID.\n *\n * Using a seed is especially useful when trying to correlate external,\n * non-W3C compliant IDs with Langfuse trace IDs. This allows you to later\n * have a method available for scoring the Langfuse trace given only the\n * external ID by regenerating the same trace ID from the external ID.\n *\n * @returns A Promise that resolves to a 32-character lowercase hexadecimal string suitable for use as an OpenTelemetry trace ID.\n *\n * @example\n * ```typescript\n * // Deterministic trace ID from seed\n * const traceId1 = await createTraceId(\"my-session-123\");\n * const traceId2 = await createTraceId(\"my-session-123\");\n * console.log(traceId1 === traceId2); // true\n *\n * // Random trace ID\n * const randomId1 = await createTraceId(\"\");\n * const randomId2 = await createTraceId(\"\");\n * console.log(randomId1 === randomId2); // false\n *\n * // Use with spans\n * const span = startSpan(\"my-span\", {}, {\n * parentSpanContext: {\n * traceId: await createTraceId(\"session-456\"),\n * spanId: \"0123456789abcdef\",\n * traceFlags: 1\n * }\n * });\n *\n * // Correlating external IDs with Langfuse traces\n * const externalId = \"ext-12345-67890\";\n * const traceId = await createTraceId(externalId);\n *\n * // Later, when you need to score this trace, regenerate the same ID\n * const scoringTraceId = await createTraceId(externalId);\n * console.log(traceId === scoringTraceId); // true - can now find and score the trace\n * ```\n */\nexport async function createTraceId(seed?: string): Promise<string> {\n if (seed) {\n const data = new TextEncoder().encode(seed);\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", data);\n\n const hashArray = new Uint8Array(hashBuffer);\n\n return uint8ArrayToHex(hashArray).slice(0, 32);\n }\n\n const randomValues = crypto.getRandomValues(new Uint8Array(16));\n\n return uint8ArrayToHex(randomValues);\n}\n\nfunction uint8ArrayToHex(array: Uint8Array): string {\n return Array.from(array)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n","import { LangfuseOtelSpanAttributes } from \"@langfuse/core\";\nimport { type Attributes } from \"@opentelemetry/api\";\n\nimport {\n LangfuseGenerationAttributes,\n LangfuseSpanAttributes,\n LangfuseTraceAttributes,\n} from \"./types.js\";\n\nexport function createTraceAttributes({\n name,\n userId,\n sessionId,\n version,\n release,\n input,\n output,\n metadata,\n tags,\n environment,\n public: isPublic,\n}: LangfuseTraceAttributes = {}): Attributes {\n const attributes = {\n [LangfuseOtelSpanAttributes.TRACE_NAME]: name,\n [LangfuseOtelSpanAttributes.TRACE_USER_ID]: userId,\n [LangfuseOtelSpanAttributes.TRACE_SESSION_ID]: sessionId,\n [LangfuseOtelSpanAttributes.VERSION]: version,\n [LangfuseOtelSpanAttributes.RELEASE]: release,\n [LangfuseOtelSpanAttributes.TRACE_INPUT]: _serialize(input),\n [LangfuseOtelSpanAttributes.TRACE_OUTPUT]: _serialize(output),\n [LangfuseOtelSpanAttributes.TRACE_TAGS]: tags,\n [LangfuseOtelSpanAttributes.ENVIRONMENT]: environment,\n [LangfuseOtelSpanAttributes.TRACE_PUBLIC]: isPublic,\n ..._flattenAndSerializeMetadata(metadata, \"trace\"),\n };\n\n return Object.fromEntries(\n Object.entries(attributes).filter(([_, v]) => v != null),\n );\n}\n\nexport function createSpanAttributes({\n metadata,\n input,\n output,\n level,\n statusMessage,\n version,\n}: LangfuseSpanAttributes): Attributes {\n const attributes = {\n [LangfuseOtelSpanAttributes.OBSERVATION_TYPE]: \"span\",\n [LangfuseOtelSpanAttributes.OBSERVATION_LEVEL]: level,\n [LangfuseOtelSpanAttributes.OBSERVATION_STATUS_MESSAGE]: statusMessage,\n [LangfuseOtelSpanAttributes.VERSION]: version,\n [LangfuseOtelSpanAttributes.OBSERVATION_INPUT]: _serialize(input),\n [LangfuseOtelSpanAttributes.OBSERVATION_OUTPUT]: _serialize(output),\n ..._flattenAndSerializeMetadata(metadata, \"observation\"),\n };\n\n return Object.fromEntries(\n Object.entries(attributes).filter(([_, v]) => v != null),\n );\n}\n\nexport function createGenerationAttributes({\n completionStartTime,\n metadata,\n level,\n statusMessage,\n version,\n model,\n modelParameters,\n input,\n output,\n usageDetails,\n costDetails,\n prompt,\n}: LangfuseGenerationAttributes): Attributes {\n const attributes = {\n [LangfuseOtelSpanAttributes.OBSERVATION_TYPE]: \"generation\",\n [LangfuseOtelSpanAttributes.OBSERVATION_LEVEL]: level,\n [LangfuseOtelSpanAttributes.OBSERVATION_STATUS_MESSAGE]: statusMessage,\n [LangfuseOtelSpanAttributes.VERSION]: version,\n [LangfuseOtelSpanAttributes.OBSERVATION_INPUT]: _serialize(input),\n [LangfuseOtelSpanAttributes.OBSERVATION_OUTPUT]: _serialize(output),\n [LangfuseOtelSpanAttributes.OBSERVATION_MODEL]: model,\n [LangfuseOtelSpanAttributes.OBSERVATION_USAGE_DETAILS]:\n _serialize(usageDetails),\n [LangfuseOtelSpanAttributes.OBSERVATION_COST_DETAILS]:\n _serialize(costDetails),\n [LangfuseOtelSpanAttributes.OBSERVATION_COMPLETION_START_TIME]:\n _serialize(completionStartTime),\n [LangfuseOtelSpanAttributes.OBSERVATION_MODEL_PARAMETERS]:\n _serialize(modelParameters),\n ...(prompt && !prompt.isFallback\n ? {\n [LangfuseOtelSpanAttributes.OBSERVATION_PROMPT_NAME]: prompt.name,\n [LangfuseOtelSpanAttributes.OBSERVATION_PROMPT_VERSION]:\n prompt.version,\n }\n : {}),\n ..._flattenAndSerializeMetadata(metadata, \"observation\"),\n };\n\n return Object.fromEntries(\n Object.entries(attributes).filter(([_, v]) => v != null),\n ) as Attributes;\n}\n\nexport function createEventAttributes({\n metadata,\n input,\n output,\n level,\n statusMessage,\n version,\n}: LangfuseSpanAttributes): Attributes {\n const attributes = {\n [LangfuseOtelSpanAttributes.OBSERVATION_TYPE]: \"event\",\n [LangfuseOtelSpanAttributes.OBSERVATION_LEVEL]: level,\n [LangfuseOtelSpanAttributes.OBSERVATION_STATUS_MESSAGE]: statusMessage,\n [LangfuseOtelSpanAttributes.VERSION]: version,\n [LangfuseOtelSpanAttributes.OBSERVATION_INPUT]: _serialize(input),\n [LangfuseOtelSpanAttributes.OBSERVATION_OUTPUT]: _serialize(output),\n ..._flattenAndSerializeMetadata(metadata, \"observation\"),\n };\n\n return Object.fromEntries(\n Object.entries(attributes).filter(([_, v]) => v != null),\n );\n}\n\nfunction _serialize(obj: unknown): string | undefined {\n try {\n return obj != null ? JSON.stringify(obj) : undefined;\n } catch {\n return \"<failed to serialize>\";\n }\n}\n\nfunction _flattenAndSerializeMetadata(\n metadata: unknown,\n type: \"observation\" | \"trace\",\n): Record<string, string> {\n const prefix =\n type === \"observation\"\n ? LangfuseOtelSpanAttributes.OBSERVATION_METADATA\n : LangfuseOtelSpanAttributes.TRACE_METADATA;\n\n const metadataAttributes: Record<string, string> = {};\n\n if (metadata === undefined || metadata === null) {\n return metadataAttributes;\n }\n\n if (typeof metadata !== \"object\" || Array.isArray(metadata)) {\n const serialized = _serialize(metadata);\n if (serialized) {\n metadataAttributes[prefix] = serialized;\n }\n } else {\n for (const [key, value] of Object.entries(metadata)) {\n const serialized = typeof value === \"string\" ? value : _serialize(value);\n if (serialized) {\n metadataAttributes[`${prefix}.${key}`] = serialized;\n }\n }\n }\n\n return metadataAttributes;\n}\n","import { LANGFUSE_SDK_VERSION, LANGFUSE_TRACER_NAME } from \"@langfuse/core\";\nimport { trace } from \"@opentelemetry/api\";\n\nexport function getLangfuseTracer() {\n return trace.getTracer(LANGFUSE_TRACER_NAME, LANGFUSE_SDK_VERSION);\n}\n","import { Span, TimeInput } from \"@opentelemetry/api\";\n\nimport {\n createEventAttributes,\n createGenerationAttributes,\n createSpanAttributes,\n createTraceAttributes,\n} from \"./attributes.js\";\nimport {\n LangfuseGenerationAttributes,\n LangfuseSpanAttributes,\n LangfuseEventAttributes,\n LangfuseTraceAttributes,\n} from \"./types.js\";\nimport { getLangfuseTracer } from \"./utils.js\";\n\nimport { createEvent, startGeneration, startSpan } from \"./index.js\";\n\nexport type LangfuseObservation =\n | LangfuseSpan\n | LangfuseGeneration\n | LangfuseEvent;\n\ntype LangfuseSpanWrapperParams = {\n otelSpan: Span;\n attributes?:\n | LangfuseSpanAttributes\n | LangfuseGenerationAttributes\n | LangfuseEventAttributes;\n};\n\nabstract class LangfuseSpanWrapper {\n public readonly otelSpan: Span;\n public id: string;\n public traceId: string;\n\n constructor(params: LangfuseSpanWrapperParams) {\n this.otelSpan = params.otelSpan;\n this.id = params.otelSpan.spanContext().spanId;\n this.traceId = params.otelSpan.spanContext().traceId;\n }\n\n protected get tracer() {\n return getLangfuseTracer();\n }\n\n public end(endTime?: TimeInput) {\n this.otelSpan.end(endTime);\n }\n\n public updateTrace(attributes: LangfuseTraceAttributes) {\n this.otelSpan.setAttributes(createTraceAttributes(attributes));\n\n return this;\n }\n}\n\ntype LangfuseSpanParams = {\n otelSpan: Span;\n attributes?: LangfuseSpanAttributes;\n};\nexport class LangfuseSpan extends LangfuseSpanWrapper {\n constructor(params: LangfuseSpanParams) {\n super(params);\n if (params.attributes) {\n this.otelSpan.setAttributes(createSpanAttributes(params.attributes));\n }\n }\n\n public update(attributes: LangfuseSpanAttributes): LangfuseSpan {\n this.otelSpan.setAttributes(createSpanAttributes(attributes));\n\n return this;\n }\n\n public startSpan(\n name: string,\n attributes?: LangfuseSpanAttributes,\n ): LangfuseSpan {\n return startSpan(name, attributes, {\n parentSpanContext: this.otelSpan.spanContext(),\n });\n }\n\n public startGeneration(\n name: string,\n attributes?: LangfuseGenerationAttributes,\n ): LangfuseGeneration {\n return startGeneration(name, attributes, {\n parentSpanContext: this.otelSpan.spanContext(),\n });\n }\n\n public createEvent(\n name: string,\n attributes?: LangfuseEventAttributes,\n ): LangfuseEvent {\n return createEvent(name, attributes, {\n parentSpanContext: this.otelSpan.spanContext(),\n });\n }\n}\n\ntype LangfuseGenerationParams = {\n otelSpan: Span;\n attributes?: LangfuseGenerationAttributes;\n};\nexport class LangfuseGeneration extends LangfuseSpanWrapper {\n constructor(params: LangfuseGenerationParams) {\n super(params);\n if (params.attributes) {\n this.otelSpan.setAttributes(\n createGenerationAttributes(params.attributes),\n );\n }\n }\n\n update(attributes: LangfuseGenerationAttributes): LangfuseGeneration {\n this.otelSpan.setAttributes(createGenerationAttributes(attributes));\n\n return this;\n }\n\n createEvent(\n name: string,\n attributes?: LangfuseEventAttributes,\n ): LangfuseEvent {\n return createEvent(name, attributes, {\n parentSpanContext: this.otelSpan.spanContext(),\n });\n }\n}\n\ntype LangfuseEventParams = {\n otelSpan: Span;\n attributes?: LangfuseEventAttributes;\n timestamp: TimeInput;\n};\nexport class LangfuseEvent extends LangfuseSpanWrapper {\n constructor(params: LangfuseEventParams) {\n super(params);\n\n if (params.attributes) {\n this.otelSpan.setAttributes(createEventAttributes(params.attributes));\n }\n\n this.otelSpan.end(params.timestamp);\n }\n}\n"],"mappings":"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","names":["trace","LangfuseOtelSpanAttributes","trace"]}
@@ -0,0 +1,46 @@
1
+ import { Span, TimeInput } from "@opentelemetry/api";
2
+ import { LangfuseGenerationAttributes, LangfuseSpanAttributes, LangfuseEventAttributes, LangfuseTraceAttributes } from "./types.js";
3
+ export type LangfuseObservation = LangfuseSpan | LangfuseGeneration | LangfuseEvent;
4
+ type LangfuseSpanWrapperParams = {
5
+ otelSpan: Span;
6
+ attributes?: LangfuseSpanAttributes | LangfuseGenerationAttributes | LangfuseEventAttributes;
7
+ };
8
+ declare abstract class LangfuseSpanWrapper {
9
+ readonly otelSpan: Span;
10
+ id: string;
11
+ traceId: string;
12
+ constructor(params: LangfuseSpanWrapperParams);
13
+ protected get tracer(): import("@opentelemetry/api").Tracer;
14
+ end(endTime?: TimeInput): void;
15
+ updateTrace(attributes: LangfuseTraceAttributes): this;
16
+ }
17
+ type LangfuseSpanParams = {
18
+ otelSpan: Span;
19
+ attributes?: LangfuseSpanAttributes;
20
+ };
21
+ export declare class LangfuseSpan extends LangfuseSpanWrapper {
22
+ constructor(params: LangfuseSpanParams);
23
+ update(attributes: LangfuseSpanAttributes): LangfuseSpan;
24
+ startSpan(name: string, attributes?: LangfuseSpanAttributes): LangfuseSpan;
25
+ startGeneration(name: string, attributes?: LangfuseGenerationAttributes): LangfuseGeneration;
26
+ createEvent(name: string, attributes?: LangfuseEventAttributes): LangfuseEvent;
27
+ }
28
+ type LangfuseGenerationParams = {
29
+ otelSpan: Span;
30
+ attributes?: LangfuseGenerationAttributes;
31
+ };
32
+ export declare class LangfuseGeneration extends LangfuseSpanWrapper {
33
+ constructor(params: LangfuseGenerationParams);
34
+ update(attributes: LangfuseGenerationAttributes): LangfuseGeneration;
35
+ createEvent(name: string, attributes?: LangfuseEventAttributes): LangfuseEvent;
36
+ }
37
+ type LangfuseEventParams = {
38
+ otelSpan: Span;
39
+ attributes?: LangfuseEventAttributes;
40
+ timestamp: TimeInput;
41
+ };
42
+ export declare class LangfuseEvent extends LangfuseSpanWrapper {
43
+ constructor(params: LangfuseEventParams);
44
+ }
45
+ export {};
46
+ //# sourceMappingURL=spanWrapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spanWrapper.d.ts","sourceRoot":"","sources":["../src/spanWrapper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAQrD,OAAO,EACL,4BAA4B,EAC5B,sBAAsB,EACtB,uBAAuB,EACvB,uBAAuB,EACxB,MAAM,YAAY,CAAC;AAKpB,MAAM,MAAM,mBAAmB,GAC3B,YAAY,GACZ,kBAAkB,GAClB,aAAa,CAAC;AAElB,KAAK,yBAAyB,GAAG;IAC/B,QAAQ,EAAE,IAAI,CAAC;IACf,UAAU,CAAC,EACP,sBAAsB,GACtB,4BAA4B,GAC5B,uBAAuB,CAAC;CAC7B,CAAC;AAEF,uBAAe,mBAAmB;IAChC,SAAgB,QAAQ,EAAE,IAAI,CAAC;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;gBAEX,MAAM,EAAE,yBAAyB;IAM7C,SAAS,KAAK,MAAM,wCAEnB;IAEM,GAAG,CAAC,OAAO,CAAC,EAAE,SAAS;IAIvB,WAAW,CAAC,UAAU,EAAE,uBAAuB;CAKvD;AAED,KAAK,kBAAkB,GAAG;IACxB,QAAQ,EAAE,IAAI,CAAC;IACf,UAAU,CAAC,EAAE,sBAAsB,CAAC;CACrC,CAAC;AACF,qBAAa,YAAa,SAAQ,mBAAmB;gBACvC,MAAM,EAAE,kBAAkB;IAO/B,MAAM,CAAC,UAAU,EAAE,sBAAsB,GAAG,YAAY;IAMxD,SAAS,CACd,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,sBAAsB,GAClC,YAAY;IAMR,eAAe,CACpB,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,4BAA4B,GACxC,kBAAkB;IAMd,WAAW,CAChB,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,uBAAuB,GACnC,aAAa;CAKjB;AAED,KAAK,wBAAwB,GAAG;IAC9B,QAAQ,EAAE,IAAI,CAAC;IACf,UAAU,CAAC,EAAE,4BAA4B,CAAC;CAC3C,CAAC;AACF,qBAAa,kBAAmB,SAAQ,mBAAmB;gBAC7C,MAAM,EAAE,wBAAwB;IAS5C,MAAM,CAAC,UAAU,EAAE,4BAA4B,GAAG,kBAAkB;IAMpE,WAAW,CACT,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,uBAAuB,GACnC,aAAa;CAKjB;AAED,KAAK,mBAAmB,GAAG;IACzB,QAAQ,EAAE,IAAI,CAAC;IACf,UAAU,CAAC,EAAE,uBAAuB,CAAC;IACrC,SAAS,EAAE,SAAS,CAAC;CACtB,CAAC;AACF,qBAAa,aAAc,SAAQ,mBAAmB;gBACxC,MAAM,EAAE,mBAAmB;CASxC"}
@@ -0,0 +1,73 @@
1
+ import { createEventAttributes, createGenerationAttributes, createSpanAttributes, createTraceAttributes, } from "./attributes.js";
2
+ import { getLangfuseTracer } from "./utils.js";
3
+ import { createEvent, startGeneration, startSpan } from "./index.js";
4
+ class LangfuseSpanWrapper {
5
+ constructor(params) {
6
+ this.otelSpan = params.otelSpan;
7
+ this.id = params.otelSpan.spanContext().spanId;
8
+ this.traceId = params.otelSpan.spanContext().traceId;
9
+ }
10
+ get tracer() {
11
+ return getLangfuseTracer();
12
+ }
13
+ end(endTime) {
14
+ this.otelSpan.end(endTime);
15
+ }
16
+ updateTrace(attributes) {
17
+ this.otelSpan.setAttributes(createTraceAttributes(attributes));
18
+ return this;
19
+ }
20
+ }
21
+ export class LangfuseSpan extends LangfuseSpanWrapper {
22
+ constructor(params) {
23
+ super(params);
24
+ if (params.attributes) {
25
+ this.otelSpan.setAttributes(createSpanAttributes(params.attributes));
26
+ }
27
+ }
28
+ update(attributes) {
29
+ this.otelSpan.setAttributes(createSpanAttributes(attributes));
30
+ return this;
31
+ }
32
+ startSpan(name, attributes) {
33
+ return startSpan(name, attributes, {
34
+ parentSpanContext: this.otelSpan.spanContext(),
35
+ });
36
+ }
37
+ startGeneration(name, attributes) {
38
+ return startGeneration(name, attributes, {
39
+ parentSpanContext: this.otelSpan.spanContext(),
40
+ });
41
+ }
42
+ createEvent(name, attributes) {
43
+ return createEvent(name, attributes, {
44
+ parentSpanContext: this.otelSpan.spanContext(),
45
+ });
46
+ }
47
+ }
48
+ export class LangfuseGeneration extends LangfuseSpanWrapper {
49
+ constructor(params) {
50
+ super(params);
51
+ if (params.attributes) {
52
+ this.otelSpan.setAttributes(createGenerationAttributes(params.attributes));
53
+ }
54
+ }
55
+ update(attributes) {
56
+ this.otelSpan.setAttributes(createGenerationAttributes(attributes));
57
+ return this;
58
+ }
59
+ createEvent(name, attributes) {
60
+ return createEvent(name, attributes, {
61
+ parentSpanContext: this.otelSpan.spanContext(),
62
+ });
63
+ }
64
+ }
65
+ export class LangfuseEvent extends LangfuseSpanWrapper {
66
+ constructor(params) {
67
+ super(params);
68
+ if (params.attributes) {
69
+ this.otelSpan.setAttributes(createEventAttributes(params.attributes));
70
+ }
71
+ this.otelSpan.end(params.timestamp);
72
+ }
73
+ }