@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/LICENSE +21 -0
- package/dist/attributes.d.ts +7 -0
- package/dist/attributes.d.ts.map +1 -0
- package/dist/attributes.js +96 -0
- package/dist/index.cjs +497 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +166 -0
- package/dist/index.d.ts +75 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +271 -0
- package/dist/index.mjs +460 -0
- package/dist/index.mjs.map +1 -0
- package/dist/spanWrapper.d.ts +46 -0
- package/dist/spanWrapper.d.ts.map +1 -0
- package/dist/spanWrapper.js +73 -0
- package/dist/types.d.ts +50 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/dist/utils.d.ts +2 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +5 -0
- package/package.json +39 -0
|
@@ -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":["import_core","import_api","import_core","import_core"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import * as _opentelemetry_api from '@opentelemetry/api';
|
|
2
|
+
import { Span, TimeInput, Attributes, SpanContext } from '@opentelemetry/api';
|
|
3
|
+
import { OpenAiUsage } from '@langfuse/core';
|
|
4
|
+
export { LangfuseOtelSpanAttributes } from '@langfuse/core';
|
|
5
|
+
|
|
6
|
+
type LangfuseObservationType = "span" | "generation" | "event";
|
|
7
|
+
type ObservationLevel = "DEBUG" | "DEFAULT" | "WARNING" | "ERROR";
|
|
8
|
+
type LangfuseSpanAttributes = {
|
|
9
|
+
input?: unknown;
|
|
10
|
+
output?: unknown;
|
|
11
|
+
metadata?: Record<string, unknown>;
|
|
12
|
+
level?: ObservationLevel;
|
|
13
|
+
statusMessage?: string;
|
|
14
|
+
version?: string;
|
|
15
|
+
environment?: string;
|
|
16
|
+
};
|
|
17
|
+
type LangfuseEventAttributes = LangfuseSpanAttributes;
|
|
18
|
+
type LangfuseGenerationAttributes = LangfuseSpanAttributes & {
|
|
19
|
+
completionStartTime?: Date;
|
|
20
|
+
model?: string | null;
|
|
21
|
+
modelParameters?: {
|
|
22
|
+
[key: string]: string | number | null;
|
|
23
|
+
};
|
|
24
|
+
usageDetails?: {
|
|
25
|
+
[key: string]: number;
|
|
26
|
+
} | OpenAiUsage;
|
|
27
|
+
costDetails?: {
|
|
28
|
+
[key: string]: number;
|
|
29
|
+
};
|
|
30
|
+
prompt?: {
|
|
31
|
+
name: string;
|
|
32
|
+
version: number;
|
|
33
|
+
isFallback: boolean;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
type LangfuseAttributes = LangfuseSpanAttributes | LangfuseGenerationAttributes | LangfuseEventAttributes;
|
|
37
|
+
type LangfuseTraceAttributes = {
|
|
38
|
+
name?: string;
|
|
39
|
+
userId?: string;
|
|
40
|
+
sessionId?: string;
|
|
41
|
+
version?: string;
|
|
42
|
+
release?: string;
|
|
43
|
+
input?: unknown;
|
|
44
|
+
output?: unknown;
|
|
45
|
+
metadata?: unknown;
|
|
46
|
+
tags?: string[];
|
|
47
|
+
public?: boolean;
|
|
48
|
+
environment?: string;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
type LangfuseObservation = LangfuseSpan | LangfuseGeneration | LangfuseEvent;
|
|
52
|
+
type LangfuseSpanWrapperParams = {
|
|
53
|
+
otelSpan: Span;
|
|
54
|
+
attributes?: LangfuseSpanAttributes | LangfuseGenerationAttributes | LangfuseEventAttributes;
|
|
55
|
+
};
|
|
56
|
+
declare abstract class LangfuseSpanWrapper {
|
|
57
|
+
readonly otelSpan: Span;
|
|
58
|
+
id: string;
|
|
59
|
+
traceId: string;
|
|
60
|
+
constructor(params: LangfuseSpanWrapperParams);
|
|
61
|
+
protected get tracer(): _opentelemetry_api.Tracer;
|
|
62
|
+
end(endTime?: TimeInput): void;
|
|
63
|
+
updateTrace(attributes: LangfuseTraceAttributes): this;
|
|
64
|
+
}
|
|
65
|
+
type LangfuseSpanParams = {
|
|
66
|
+
otelSpan: Span;
|
|
67
|
+
attributes?: LangfuseSpanAttributes;
|
|
68
|
+
};
|
|
69
|
+
declare class LangfuseSpan extends LangfuseSpanWrapper {
|
|
70
|
+
constructor(params: LangfuseSpanParams);
|
|
71
|
+
update(attributes: LangfuseSpanAttributes): LangfuseSpan;
|
|
72
|
+
startSpan(name: string, attributes?: LangfuseSpanAttributes): LangfuseSpan;
|
|
73
|
+
startGeneration(name: string, attributes?: LangfuseGenerationAttributes): LangfuseGeneration;
|
|
74
|
+
createEvent(name: string, attributes?: LangfuseEventAttributes): LangfuseEvent;
|
|
75
|
+
}
|
|
76
|
+
type LangfuseGenerationParams = {
|
|
77
|
+
otelSpan: Span;
|
|
78
|
+
attributes?: LangfuseGenerationAttributes;
|
|
79
|
+
};
|
|
80
|
+
declare class LangfuseGeneration extends LangfuseSpanWrapper {
|
|
81
|
+
constructor(params: LangfuseGenerationParams);
|
|
82
|
+
update(attributes: LangfuseGenerationAttributes): LangfuseGeneration;
|
|
83
|
+
createEvent(name: string, attributes?: LangfuseEventAttributes): LangfuseEvent;
|
|
84
|
+
}
|
|
85
|
+
type LangfuseEventParams = {
|
|
86
|
+
otelSpan: Span;
|
|
87
|
+
attributes?: LangfuseEventAttributes;
|
|
88
|
+
timestamp: TimeInput;
|
|
89
|
+
};
|
|
90
|
+
declare class LangfuseEvent extends LangfuseSpanWrapper {
|
|
91
|
+
constructor(params: LangfuseEventParams);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
declare function createTraceAttributes({ name, userId, sessionId, version, release, input, output, metadata, tags, environment, public: isPublic, }?: LangfuseTraceAttributes): Attributes;
|
|
95
|
+
declare function createSpanAttributes({ metadata, input, output, level, statusMessage, version, }: LangfuseSpanAttributes): Attributes;
|
|
96
|
+
declare function createGenerationAttributes({ completionStartTime, metadata, level, statusMessage, version, model, modelParameters, input, output, usageDetails, costDetails, prompt, }: LangfuseGenerationAttributes): Attributes;
|
|
97
|
+
|
|
98
|
+
type StartObservationOptions = {
|
|
99
|
+
startTime?: Date;
|
|
100
|
+
parentSpanContext?: SpanContext;
|
|
101
|
+
};
|
|
102
|
+
declare function startSpan(name: string, attributes?: LangfuseSpanAttributes, options?: {
|
|
103
|
+
startTime?: TimeInput;
|
|
104
|
+
parentSpanContext?: SpanContext;
|
|
105
|
+
}): LangfuseSpan;
|
|
106
|
+
declare function startGeneration(name: string, attributes?: LangfuseGenerationAttributes, options?: StartObservationOptions): LangfuseGeneration;
|
|
107
|
+
declare function createEvent(name: string, attributes?: LangfuseEventAttributes, options?: StartObservationOptions): LangfuseEvent;
|
|
108
|
+
declare function startActiveSpan<F extends (span: LangfuseSpan) => unknown>(name: string, fn: F, options?: StartObservationOptions): ReturnType<F>;
|
|
109
|
+
declare function startActiveGeneration<F extends (span: LangfuseGeneration) => unknown>(name: string, fn: F, options?: StartObservationOptions): ReturnType<F>;
|
|
110
|
+
declare function updateActiveTrace(attributes: LangfuseTraceAttributes): void;
|
|
111
|
+
declare function updateActiveSpan(attributes: LangfuseSpanAttributes): void;
|
|
112
|
+
declare function updateActiveGeneration(attributes: LangfuseGenerationAttributes): void;
|
|
113
|
+
interface ObserveOptions {
|
|
114
|
+
name?: string;
|
|
115
|
+
asType?: "span" | "generation";
|
|
116
|
+
captureInput?: boolean;
|
|
117
|
+
captureOutput?: boolean;
|
|
118
|
+
}
|
|
119
|
+
declare function observe<T extends (...args: unknown[]) => unknown>(fn: T, options?: ObserveOptions): T;
|
|
120
|
+
/**
|
|
121
|
+
* Creates a trace ID for OpenTelemetry spans.
|
|
122
|
+
*
|
|
123
|
+
* @param seed - A seed string for deterministic trace ID generation.
|
|
124
|
+
* If provided (non-empty), the same seed will always generate the same trace ID.
|
|
125
|
+
* If empty or falsy, generates a random trace ID.
|
|
126
|
+
*
|
|
127
|
+
* Using a seed is especially useful when trying to correlate external,
|
|
128
|
+
* non-W3C compliant IDs with Langfuse trace IDs. This allows you to later
|
|
129
|
+
* have a method available for scoring the Langfuse trace given only the
|
|
130
|
+
* external ID by regenerating the same trace ID from the external ID.
|
|
131
|
+
*
|
|
132
|
+
* @returns A Promise that resolves to a 32-character lowercase hexadecimal string suitable for use as an OpenTelemetry trace ID.
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
* ```typescript
|
|
136
|
+
* // Deterministic trace ID from seed
|
|
137
|
+
* const traceId1 = await createTraceId("my-session-123");
|
|
138
|
+
* const traceId2 = await createTraceId("my-session-123");
|
|
139
|
+
* console.log(traceId1 === traceId2); // true
|
|
140
|
+
*
|
|
141
|
+
* // Random trace ID
|
|
142
|
+
* const randomId1 = await createTraceId("");
|
|
143
|
+
* const randomId2 = await createTraceId("");
|
|
144
|
+
* console.log(randomId1 === randomId2); // false
|
|
145
|
+
*
|
|
146
|
+
* // Use with spans
|
|
147
|
+
* const span = startSpan("my-span", {}, {
|
|
148
|
+
* parentSpanContext: {
|
|
149
|
+
* traceId: await createTraceId("session-456"),
|
|
150
|
+
* spanId: "0123456789abcdef",
|
|
151
|
+
* traceFlags: 1
|
|
152
|
+
* }
|
|
153
|
+
* });
|
|
154
|
+
*
|
|
155
|
+
* // Correlating external IDs with Langfuse traces
|
|
156
|
+
* const externalId = "ext-12345-67890";
|
|
157
|
+
* const traceId = await createTraceId(externalId);
|
|
158
|
+
*
|
|
159
|
+
* // Later, when you need to score this trace, regenerate the same ID
|
|
160
|
+
* const scoringTraceId = await createTraceId(externalId);
|
|
161
|
+
* console.log(traceId === scoringTraceId); // true - can now find and score the trace
|
|
162
|
+
* ```
|
|
163
|
+
*/
|
|
164
|
+
declare function createTraceId(seed?: string): Promise<string>;
|
|
165
|
+
|
|
166
|
+
export { type LangfuseAttributes, LangfuseEvent, type LangfuseEventAttributes, LangfuseGeneration, type LangfuseGenerationAttributes, type LangfuseObservation, type LangfuseObservationType, LangfuseSpan, type LangfuseSpanAttributes, type LangfuseTraceAttributes, type ObservationLevel, type ObserveOptions, type StartObservationOptions, createEvent, createGenerationAttributes, createSpanAttributes, createTraceAttributes, createTraceId, observe, startActiveGeneration, startActiveSpan, startGeneration, startSpan, updateActiveGeneration, updateActiveSpan, updateActiveTrace };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { TimeInput, SpanContext } from "@opentelemetry/api";
|
|
2
|
+
import { LangfuseEvent, LangfuseGeneration, LangfuseSpan } from "./spanWrapper.js";
|
|
3
|
+
import { LangfuseEventAttributes, LangfuseGenerationAttributes, LangfuseSpanAttributes, LangfuseTraceAttributes } from "./types.js";
|
|
4
|
+
export type { LangfuseObservationType, ObservationLevel, LangfuseSpanAttributes, LangfuseEventAttributes, LangfuseGenerationAttributes, LangfuseAttributes, LangfuseTraceAttributes, } from "./types.js";
|
|
5
|
+
export * from "./spanWrapper.js";
|
|
6
|
+
export { createTraceAttributes, createSpanAttributes, createGenerationAttributes, } from "./attributes.js";
|
|
7
|
+
export { LangfuseOtelSpanAttributes } from "@langfuse/core";
|
|
8
|
+
export type StartObservationOptions = {
|
|
9
|
+
startTime?: Date;
|
|
10
|
+
parentSpanContext?: SpanContext;
|
|
11
|
+
};
|
|
12
|
+
export declare function startSpan(name: string, attributes?: LangfuseSpanAttributes, options?: {
|
|
13
|
+
startTime?: TimeInput;
|
|
14
|
+
parentSpanContext?: SpanContext;
|
|
15
|
+
}): LangfuseSpan;
|
|
16
|
+
export declare function startGeneration(name: string, attributes?: LangfuseGenerationAttributes, options?: StartObservationOptions): LangfuseGeneration;
|
|
17
|
+
export declare function createEvent(name: string, attributes?: LangfuseEventAttributes, options?: StartObservationOptions): LangfuseEvent;
|
|
18
|
+
export declare function startActiveSpan<F extends (span: LangfuseSpan) => unknown>(name: string, fn: F, options?: StartObservationOptions): ReturnType<F>;
|
|
19
|
+
export declare function startActiveGeneration<F extends (span: LangfuseGeneration) => unknown>(name: string, fn: F, options?: StartObservationOptions): ReturnType<F>;
|
|
20
|
+
export declare function updateActiveTrace(attributes: LangfuseTraceAttributes): void;
|
|
21
|
+
export declare function updateActiveSpan(attributes: LangfuseSpanAttributes): void;
|
|
22
|
+
export declare function updateActiveGeneration(attributes: LangfuseGenerationAttributes): void;
|
|
23
|
+
export interface ObserveOptions {
|
|
24
|
+
name?: string;
|
|
25
|
+
asType?: "span" | "generation";
|
|
26
|
+
captureInput?: boolean;
|
|
27
|
+
captureOutput?: boolean;
|
|
28
|
+
}
|
|
29
|
+
export declare function observe<T extends (...args: unknown[]) => unknown>(fn: T, options?: ObserveOptions): T;
|
|
30
|
+
/**
|
|
31
|
+
* Creates a trace ID for OpenTelemetry spans.
|
|
32
|
+
*
|
|
33
|
+
* @param seed - A seed string for deterministic trace ID generation.
|
|
34
|
+
* If provided (non-empty), the same seed will always generate the same trace ID.
|
|
35
|
+
* If empty or falsy, generates a random trace ID.
|
|
36
|
+
*
|
|
37
|
+
* Using a seed is especially useful when trying to correlate external,
|
|
38
|
+
* non-W3C compliant IDs with Langfuse trace IDs. This allows you to later
|
|
39
|
+
* have a method available for scoring the Langfuse trace given only the
|
|
40
|
+
* external ID by regenerating the same trace ID from the external ID.
|
|
41
|
+
*
|
|
42
|
+
* @returns A Promise that resolves to a 32-character lowercase hexadecimal string suitable for use as an OpenTelemetry trace ID.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* // Deterministic trace ID from seed
|
|
47
|
+
* const traceId1 = await createTraceId("my-session-123");
|
|
48
|
+
* const traceId2 = await createTraceId("my-session-123");
|
|
49
|
+
* console.log(traceId1 === traceId2); // true
|
|
50
|
+
*
|
|
51
|
+
* // Random trace ID
|
|
52
|
+
* const randomId1 = await createTraceId("");
|
|
53
|
+
* const randomId2 = await createTraceId("");
|
|
54
|
+
* console.log(randomId1 === randomId2); // false
|
|
55
|
+
*
|
|
56
|
+
* // Use with spans
|
|
57
|
+
* const span = startSpan("my-span", {}, {
|
|
58
|
+
* parentSpanContext: {
|
|
59
|
+
* traceId: await createTraceId("session-456"),
|
|
60
|
+
* spanId: "0123456789abcdef",
|
|
61
|
+
* traceFlags: 1
|
|
62
|
+
* }
|
|
63
|
+
* });
|
|
64
|
+
*
|
|
65
|
+
* // Correlating external IDs with Langfuse traces
|
|
66
|
+
* const externalId = "ext-12345-67890";
|
|
67
|
+
* const traceId = await createTraceId(externalId);
|
|
68
|
+
*
|
|
69
|
+
* // Later, when you need to score this trace, regenerate the same ID
|
|
70
|
+
* const scoringTraceId = await createTraceId(externalId);
|
|
71
|
+
* console.log(traceId === scoringTraceId); // true - can now find and score the trace
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
export declare function createTraceId(seed?: string): Promise<string>;
|
|
75
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,SAAS,EAIT,WAAW,EACZ,MAAM,oBAAoB,CAAC;AAO5B,OAAO,EACL,aAAa,EACb,kBAAkB,EAClB,YAAY,EACb,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,uBAAuB,EACvB,4BAA4B,EAC5B,sBAAsB,EACtB,uBAAuB,EACxB,MAAM,YAAY,CAAC;AAGpB,YAAY,EACV,uBAAuB,EACvB,gBAAgB,EAChB,sBAAsB,EACtB,uBAAuB,EACvB,4BAA4B,EAC5B,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,YAAY,CAAC;AAEpB,cAAc,kBAAkB,CAAC;AACjC,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,0BAA0B,GAC3B,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AAE5D,MAAM,MAAM,uBAAuB,GAAG;IACpC,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,iBAAiB,CAAC,EAAE,WAAW,CAAC;CACjC,CAAC;AA0CF,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,sBAAsB,EACnC,OAAO,CAAC,EAAE;IACR,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,iBAAiB,CAAC,EAAE,WAAW,CAAC;CACjC,GACA,YAAY,CAOd;AAED,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,4BAA4B,EACzC,OAAO,CAAC,EAAE,uBAAuB,GAChC,kBAAkB,CAOpB;AAED,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,uBAAuB,EACpC,OAAO,CAAC,EAAE,uBAAuB,iBAWlC;AAED,wBAAgB,eAAe,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,EACvE,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,CAAC,EACL,OAAO,CAAC,EAAE,uBAAuB,GAChC,UAAU,CAAC,CAAC,CAAC,CA4Bf;AAED,wBAAgB,qBAAqB,CACnC,CAAC,SAAS,CAAC,IAAI,EAAE,kBAAkB,KAAK,OAAO,EAC/C,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,uBAAuB,GAAG,UAAU,CAAC,CAAC,CAAC,CA4BvE;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,uBAAuB,QAYpE;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,sBAAsB,QAYlE;AAED,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,4BAA4B,QAazC;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,GAAG,YAAY,CAAC;IAC/B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,wBAAgB,OAAO,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,EAC/D,EAAE,EAAE,CAAC,EACL,OAAO,GAAE,cAAmB,GAC3B,CAAC,CA2EH;AA6BD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAsB,aAAa,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAalE"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import { getGlobalLogger } from "@langfuse/core";
|
|
2
|
+
import { trace, context, SpanStatusCode, } from "@opentelemetry/api";
|
|
3
|
+
import { createGenerationAttributes, createSpanAttributes, createTraceAttributes, } from "./attributes.js";
|
|
4
|
+
import { LangfuseEvent, LangfuseGeneration, LangfuseSpan, } from "./spanWrapper.js";
|
|
5
|
+
import { getLangfuseTracer } from "./utils.js";
|
|
6
|
+
export * from "./spanWrapper.js";
|
|
7
|
+
export { createTraceAttributes, createSpanAttributes, createGenerationAttributes, } from "./attributes.js";
|
|
8
|
+
export { LangfuseOtelSpanAttributes } from "@langfuse/core";
|
|
9
|
+
function createOtelSpan(params) {
|
|
10
|
+
return getLangfuseTracer().startSpan(params.name, { startTime: params.startTime }, createParentContext(params.parentSpanContext));
|
|
11
|
+
}
|
|
12
|
+
function createParentContext(parentSpanContext) {
|
|
13
|
+
if (!parentSpanContext)
|
|
14
|
+
return;
|
|
15
|
+
return trace.setSpanContext(context.active(), parentSpanContext);
|
|
16
|
+
}
|
|
17
|
+
function wrapPromise(promise, span) {
|
|
18
|
+
return promise.then((value) => {
|
|
19
|
+
span.end(); // End span AFTER Promise resolves
|
|
20
|
+
return value;
|
|
21
|
+
}, (err) => {
|
|
22
|
+
span
|
|
23
|
+
.setStatus({
|
|
24
|
+
code: SpanStatusCode.ERROR,
|
|
25
|
+
message: err instanceof Error ? err.message : "Unknown error",
|
|
26
|
+
})
|
|
27
|
+
.end(); // End span AFTER Promise rejects
|
|
28
|
+
throw err;
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
export function startSpan(name, attributes, options) {
|
|
32
|
+
const otelSpan = createOtelSpan({
|
|
33
|
+
name,
|
|
34
|
+
...options,
|
|
35
|
+
});
|
|
36
|
+
return new LangfuseSpan({ otelSpan, attributes });
|
|
37
|
+
}
|
|
38
|
+
export function startGeneration(name, attributes, options) {
|
|
39
|
+
const otelSpan = createOtelSpan({
|
|
40
|
+
name,
|
|
41
|
+
...options,
|
|
42
|
+
});
|
|
43
|
+
return new LangfuseGeneration({ otelSpan, attributes });
|
|
44
|
+
}
|
|
45
|
+
export function createEvent(name, attributes, options) {
|
|
46
|
+
var _a;
|
|
47
|
+
const timestamp = (_a = options === null || options === void 0 ? void 0 : options.startTime) !== null && _a !== void 0 ? _a : new Date();
|
|
48
|
+
const otelSpan = createOtelSpan({
|
|
49
|
+
name,
|
|
50
|
+
...options,
|
|
51
|
+
startTime: timestamp,
|
|
52
|
+
});
|
|
53
|
+
return new LangfuseEvent({ otelSpan, attributes, timestamp });
|
|
54
|
+
}
|
|
55
|
+
export function startActiveSpan(name, fn, options) {
|
|
56
|
+
var _a;
|
|
57
|
+
return getLangfuseTracer().startActiveSpan(name, { startTime: options === null || options === void 0 ? void 0 : options.startTime }, (_a = createParentContext(options === null || options === void 0 ? void 0 : options.parentSpanContext)) !== null && _a !== void 0 ? _a : context.active(), (span) => {
|
|
58
|
+
try {
|
|
59
|
+
const result = fn(new LangfuseSpan({ otelSpan: span }));
|
|
60
|
+
if (result instanceof Promise) {
|
|
61
|
+
return wrapPromise(result, span);
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
span.end();
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
span
|
|
70
|
+
.setStatus({
|
|
71
|
+
code: SpanStatusCode.ERROR,
|
|
72
|
+
message: err instanceof Error ? err.message : "Unknown error",
|
|
73
|
+
})
|
|
74
|
+
.end();
|
|
75
|
+
throw err;
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
export function startActiveGeneration(name, fn, options) {
|
|
80
|
+
var _a;
|
|
81
|
+
return getLangfuseTracer().startActiveSpan(name, { startTime: options === null || options === void 0 ? void 0 : options.startTime }, (_a = createParentContext(options === null || options === void 0 ? void 0 : options.parentSpanContext)) !== null && _a !== void 0 ? _a : context.active(), (span) => {
|
|
82
|
+
try {
|
|
83
|
+
const result = fn(new LangfuseGeneration({ otelSpan: span }));
|
|
84
|
+
if (result instanceof Promise) {
|
|
85
|
+
return wrapPromise(result, span);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
span.end();
|
|
89
|
+
return result;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
span
|
|
94
|
+
.setStatus({
|
|
95
|
+
code: SpanStatusCode.ERROR,
|
|
96
|
+
message: err instanceof Error ? err.message : "Unknown error",
|
|
97
|
+
})
|
|
98
|
+
.end();
|
|
99
|
+
throw err;
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
export function updateActiveTrace(attributes) {
|
|
104
|
+
const span = trace.getActiveSpan();
|
|
105
|
+
if (!span) {
|
|
106
|
+
getGlobalLogger().warn("No active OTEL span in context. Skipping trace update.");
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
span.setAttributes(createTraceAttributes(attributes));
|
|
110
|
+
}
|
|
111
|
+
export function updateActiveSpan(attributes) {
|
|
112
|
+
const span = trace.getActiveSpan();
|
|
113
|
+
if (!span) {
|
|
114
|
+
getGlobalLogger().warn("No active OTEL span in context. Skipping span update.");
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
span.setAttributes(createSpanAttributes(attributes));
|
|
118
|
+
}
|
|
119
|
+
export function updateActiveGeneration(attributes) {
|
|
120
|
+
const span = trace.getActiveSpan();
|
|
121
|
+
if (!span) {
|
|
122
|
+
getGlobalLogger().warn("No active OTEL span in context. Skipping generation update.");
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
span.setAttributes(createGenerationAttributes(attributes));
|
|
126
|
+
}
|
|
127
|
+
export function observe(fn, options = {}) {
|
|
128
|
+
const { name = fn.name || "anonymous-function", asType = "span", captureInput = true, captureOutput = true, } = options;
|
|
129
|
+
const wrappedFunction = (...args) => {
|
|
130
|
+
// Prepare input data
|
|
131
|
+
const inputData = captureInput ? _captureArguments(args) : undefined;
|
|
132
|
+
// Create the appropriate observation type
|
|
133
|
+
const observation = asType === "generation"
|
|
134
|
+
? startGeneration(name, inputData ? { input: inputData } : {})
|
|
135
|
+
: startSpan(name, inputData ? { input: inputData } : {});
|
|
136
|
+
// Set the observation span as active in the context
|
|
137
|
+
const activeContext = trace.setSpan(context.active(), observation.otelSpan);
|
|
138
|
+
try {
|
|
139
|
+
const result = context.with(activeContext, () => fn(...args));
|
|
140
|
+
// Handle async functions - check if result is a Promise
|
|
141
|
+
// TODO: handle returned generators for streamed responses
|
|
142
|
+
if (result instanceof Promise) {
|
|
143
|
+
return result.then((value) => {
|
|
144
|
+
if (captureOutput) {
|
|
145
|
+
observation.update({ output: _captureOutput(value) });
|
|
146
|
+
}
|
|
147
|
+
observation.end();
|
|
148
|
+
return value;
|
|
149
|
+
}, (error) => {
|
|
150
|
+
observation
|
|
151
|
+
.update({
|
|
152
|
+
level: "ERROR",
|
|
153
|
+
statusMessage: (error instanceof Error ? error.message : String(error)) ||
|
|
154
|
+
"Function threw an error",
|
|
155
|
+
output: captureOutput ? { error: String(error) } : undefined,
|
|
156
|
+
})
|
|
157
|
+
.end();
|
|
158
|
+
throw error;
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
// Handle sync functions
|
|
163
|
+
if (captureOutput) {
|
|
164
|
+
observation.update({ output: _captureOutput(result) });
|
|
165
|
+
}
|
|
166
|
+
observation.end();
|
|
167
|
+
return result;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
observation
|
|
172
|
+
.update({
|
|
173
|
+
level: "ERROR",
|
|
174
|
+
statusMessage: (error instanceof Error ? error.message : String(error)) ||
|
|
175
|
+
"Function threw an error",
|
|
176
|
+
output: captureOutput ? { error: String(error) } : undefined,
|
|
177
|
+
})
|
|
178
|
+
.end();
|
|
179
|
+
throw error;
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
return wrappedFunction;
|
|
183
|
+
}
|
|
184
|
+
// Helper function to safely capture function arguments
|
|
185
|
+
function _captureArguments(args) {
|
|
186
|
+
try {
|
|
187
|
+
if (args.length === 0)
|
|
188
|
+
return undefined;
|
|
189
|
+
if (args.length === 1)
|
|
190
|
+
return args[0];
|
|
191
|
+
return args;
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
return "<failed to capture arguments>";
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
// Helper function to safely capture function output
|
|
198
|
+
function _captureOutput(value) {
|
|
199
|
+
try {
|
|
200
|
+
// Handle undefined/null
|
|
201
|
+
if (value === undefined || value === null)
|
|
202
|
+
return value;
|
|
203
|
+
// For primitive types, return as-is
|
|
204
|
+
if (typeof value !== "object")
|
|
205
|
+
return value;
|
|
206
|
+
// For objects, return them directly (serialization happens in span processor)
|
|
207
|
+
return value;
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
return "<failed to capture output>";
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Creates a trace ID for OpenTelemetry spans.
|
|
215
|
+
*
|
|
216
|
+
* @param seed - A seed string for deterministic trace ID generation.
|
|
217
|
+
* If provided (non-empty), the same seed will always generate the same trace ID.
|
|
218
|
+
* If empty or falsy, generates a random trace ID.
|
|
219
|
+
*
|
|
220
|
+
* Using a seed is especially useful when trying to correlate external,
|
|
221
|
+
* non-W3C compliant IDs with Langfuse trace IDs. This allows you to later
|
|
222
|
+
* have a method available for scoring the Langfuse trace given only the
|
|
223
|
+
* external ID by regenerating the same trace ID from the external ID.
|
|
224
|
+
*
|
|
225
|
+
* @returns A Promise that resolves to a 32-character lowercase hexadecimal string suitable for use as an OpenTelemetry trace ID.
|
|
226
|
+
*
|
|
227
|
+
* @example
|
|
228
|
+
* ```typescript
|
|
229
|
+
* // Deterministic trace ID from seed
|
|
230
|
+
* const traceId1 = await createTraceId("my-session-123");
|
|
231
|
+
* const traceId2 = await createTraceId("my-session-123");
|
|
232
|
+
* console.log(traceId1 === traceId2); // true
|
|
233
|
+
*
|
|
234
|
+
* // Random trace ID
|
|
235
|
+
* const randomId1 = await createTraceId("");
|
|
236
|
+
* const randomId2 = await createTraceId("");
|
|
237
|
+
* console.log(randomId1 === randomId2); // false
|
|
238
|
+
*
|
|
239
|
+
* // Use with spans
|
|
240
|
+
* const span = startSpan("my-span", {}, {
|
|
241
|
+
* parentSpanContext: {
|
|
242
|
+
* traceId: await createTraceId("session-456"),
|
|
243
|
+
* spanId: "0123456789abcdef",
|
|
244
|
+
* traceFlags: 1
|
|
245
|
+
* }
|
|
246
|
+
* });
|
|
247
|
+
*
|
|
248
|
+
* // Correlating external IDs with Langfuse traces
|
|
249
|
+
* const externalId = "ext-12345-67890";
|
|
250
|
+
* const traceId = await createTraceId(externalId);
|
|
251
|
+
*
|
|
252
|
+
* // Later, when you need to score this trace, regenerate the same ID
|
|
253
|
+
* const scoringTraceId = await createTraceId(externalId);
|
|
254
|
+
* console.log(traceId === scoringTraceId); // true - can now find and score the trace
|
|
255
|
+
* ```
|
|
256
|
+
*/
|
|
257
|
+
export async function createTraceId(seed) {
|
|
258
|
+
if (seed) {
|
|
259
|
+
const data = new TextEncoder().encode(seed);
|
|
260
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
|
|
261
|
+
const hashArray = new Uint8Array(hashBuffer);
|
|
262
|
+
return uint8ArrayToHex(hashArray).slice(0, 32);
|
|
263
|
+
}
|
|
264
|
+
const randomValues = crypto.getRandomValues(new Uint8Array(16));
|
|
265
|
+
return uint8ArrayToHex(randomValues);
|
|
266
|
+
}
|
|
267
|
+
function uint8ArrayToHex(array) {
|
|
268
|
+
return Array.from(array)
|
|
269
|
+
.map((b) => b.toString(16).padStart(2, "0"))
|
|
270
|
+
.join("");
|
|
271
|
+
}
|