@langfuse/otel 4.0.0-beta.0 → 4.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -0
- package/dist/index.cjs +145 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +297 -1
- package/dist/index.d.ts +297 -1
- package/dist/index.mjs +147 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -2,26 +2,140 @@ import { ReadableSpan, SpanExporter, BatchSpanProcessor, Span } from '@opentelem
|
|
|
2
2
|
import { MediaContentType } from '@langfuse/core';
|
|
3
3
|
export { MediaContentType } from '@langfuse/core';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Function type for masking sensitive data in spans before export.
|
|
7
|
+
*
|
|
8
|
+
* @param params - Object containing the data to be masked
|
|
9
|
+
* @param params.data - The data that should be masked
|
|
10
|
+
* @returns The masked data (can be of any type)
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const maskFunction: MaskFunction = ({ data }) => {
|
|
15
|
+
* if (typeof data === 'string') {
|
|
16
|
+
* return data.replace(/password=\w+/g, 'password=***');
|
|
17
|
+
* }
|
|
18
|
+
* return data;
|
|
19
|
+
* };
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
5
24
|
type MaskFunction = (params: {
|
|
6
25
|
data: any;
|
|
7
26
|
}) => any;
|
|
27
|
+
/**
|
|
28
|
+
* Function type for determining whether a span should be exported to Langfuse.
|
|
29
|
+
*
|
|
30
|
+
* @param params - Object containing the span to evaluate
|
|
31
|
+
* @param params.otelSpan - The OpenTelemetry span to evaluate
|
|
32
|
+
* @returns `true` if the span should be exported, `false` otherwise
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```typescript
|
|
36
|
+
* const shouldExportSpan: ShouldExportSpan = ({ otelSpan }) => {
|
|
37
|
+
* // Only export spans that took longer than 100ms
|
|
38
|
+
* return otelSpan.duration[0] * 1000 + otelSpan.duration[1] / 1000000 > 100;
|
|
39
|
+
* };
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* @public
|
|
43
|
+
*/
|
|
8
44
|
type ShouldExportSpan = (params: {
|
|
9
45
|
otelSpan: ReadableSpan;
|
|
10
46
|
}) => boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Configuration parameters for the LangfuseSpanProcessor.
|
|
49
|
+
*
|
|
50
|
+
* @public
|
|
51
|
+
*/
|
|
11
52
|
interface LangfuseSpanProcessorParams {
|
|
53
|
+
/**
|
|
54
|
+
* Custom OpenTelemetry span exporter. If not provided, a default OTLP exporter will be used.
|
|
55
|
+
*/
|
|
12
56
|
exporter?: SpanExporter;
|
|
57
|
+
/**
|
|
58
|
+
* Langfuse public API key. Can also be set via LANGFUSE_PUBLIC_KEY environment variable.
|
|
59
|
+
*/
|
|
13
60
|
publicKey?: string;
|
|
61
|
+
/**
|
|
62
|
+
* Langfuse secret API key. Can also be set via LANGFUSE_SECRET_KEY environment variable.
|
|
63
|
+
*/
|
|
14
64
|
secretKey?: string;
|
|
65
|
+
/**
|
|
66
|
+
* Langfuse instance base URL. Can also be set via LANGFUSE_BASE_URL environment variable.
|
|
67
|
+
* @defaultValue "https://cloud.langfuse.com"
|
|
68
|
+
*/
|
|
15
69
|
baseUrl?: string;
|
|
70
|
+
/**
|
|
71
|
+
* Number of spans to batch before flushing. Can also be set via LANGFUSE_FLUSH_AT environment variable.
|
|
72
|
+
*/
|
|
16
73
|
flushAt?: number;
|
|
74
|
+
/**
|
|
75
|
+
* Flush interval in seconds. Can also be set via LANGFUSE_FLUSH_INTERVAL environment variable.
|
|
76
|
+
*/
|
|
17
77
|
flushInterval?: number;
|
|
78
|
+
/**
|
|
79
|
+
* Function to mask sensitive data in spans before export.
|
|
80
|
+
*/
|
|
18
81
|
mask?: MaskFunction;
|
|
82
|
+
/**
|
|
83
|
+
* Function to determine whether a span should be exported to Langfuse.
|
|
84
|
+
*/
|
|
19
85
|
shouldExportSpan?: ShouldExportSpan;
|
|
86
|
+
/**
|
|
87
|
+
* Environment identifier for the traces. Can also be set via LANGFUSE_TRACING_ENVIRONMENT environment variable.
|
|
88
|
+
*/
|
|
20
89
|
environment?: string;
|
|
90
|
+
/**
|
|
91
|
+
* Release identifier for the traces. Can also be set via LANGFUSE_RELEASE environment variable.
|
|
92
|
+
*/
|
|
21
93
|
release?: string;
|
|
94
|
+
/**
|
|
95
|
+
* Request timeout in seconds. Can also be set via LANGFUSE_TIMEOUT environment variable.
|
|
96
|
+
* @defaultValue 5
|
|
97
|
+
*/
|
|
22
98
|
timeout?: number;
|
|
99
|
+
/**
|
|
100
|
+
* Additional HTTP headers to include with requests.
|
|
101
|
+
*/
|
|
23
102
|
additionalHeaders?: Record<string, string>;
|
|
24
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* OpenTelemetry span processor for sending spans to Langfuse.
|
|
106
|
+
*
|
|
107
|
+
* This processor extends the standard BatchSpanProcessor to provide:
|
|
108
|
+
* - Automatic batching and flushing of spans to Langfuse
|
|
109
|
+
* - Media content extraction and upload from base64 data URIs
|
|
110
|
+
* - Data masking capabilities for sensitive information
|
|
111
|
+
* - Conditional span export based on custom logic
|
|
112
|
+
* - Environment and release tagging
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```typescript
|
|
116
|
+
* import { NodeSDK } from '@opentelemetry/sdk-node';
|
|
117
|
+
* import { LangfuseSpanProcessor } from '@langfuse/otel';
|
|
118
|
+
*
|
|
119
|
+
* const sdk = new NodeSDK({
|
|
120
|
+
* spanProcessors: [
|
|
121
|
+
* new LangfuseSpanProcessor({
|
|
122
|
+
* publicKey: 'pk_...',
|
|
123
|
+
* secretKey: 'sk_...',
|
|
124
|
+
* baseUrl: 'https://cloud.langfuse.com',
|
|
125
|
+
* environment: 'production',
|
|
126
|
+
* mask: ({ data }) => {
|
|
127
|
+
* // Mask sensitive data
|
|
128
|
+
* return data.replace(/api_key=\w+/g, 'api_key=***');
|
|
129
|
+
* }
|
|
130
|
+
* })
|
|
131
|
+
* ]
|
|
132
|
+
* });
|
|
133
|
+
*
|
|
134
|
+
* sdk.start();
|
|
135
|
+
* ```
|
|
136
|
+
*
|
|
137
|
+
* @public
|
|
138
|
+
*/
|
|
25
139
|
declare class LangfuseSpanProcessor extends BatchSpanProcessor {
|
|
26
140
|
private pendingMediaUploads;
|
|
27
141
|
private publicKey?;
|
|
@@ -31,12 +145,74 @@ declare class LangfuseSpanProcessor extends BatchSpanProcessor {
|
|
|
31
145
|
private mask?;
|
|
32
146
|
private shouldExportSpan?;
|
|
33
147
|
private apiClient;
|
|
148
|
+
/**
|
|
149
|
+
* Creates a new LangfuseSpanProcessor instance.
|
|
150
|
+
*
|
|
151
|
+
* @param params - Configuration parameters for the processor
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* ```typescript
|
|
155
|
+
* const processor = new LangfuseSpanProcessor({
|
|
156
|
+
* publicKey: 'pk_...',
|
|
157
|
+
* secretKey: 'sk_...',
|
|
158
|
+
* environment: 'staging',
|
|
159
|
+
* flushAt: 10,
|
|
160
|
+
* flushInterval: 2,
|
|
161
|
+
* mask: ({ data }) => {
|
|
162
|
+
* // Custom masking logic
|
|
163
|
+
* return typeof data === 'string'
|
|
164
|
+
* ? data.replace(/secret_\w+/g, 'secret_***')
|
|
165
|
+
* : data;
|
|
166
|
+
* },
|
|
167
|
+
* shouldExportSpan: ({ otelSpan }) => {
|
|
168
|
+
* // Only export spans from specific services
|
|
169
|
+
* return otelSpan.name.startsWith('my-service');
|
|
170
|
+
* }
|
|
171
|
+
* });
|
|
172
|
+
* ```
|
|
173
|
+
*/
|
|
34
174
|
constructor(params?: LangfuseSpanProcessorParams);
|
|
35
175
|
private get logger();
|
|
176
|
+
/**
|
|
177
|
+
* Called when a span is started. Adds environment and release attributes to the span.
|
|
178
|
+
*
|
|
179
|
+
* @param span - The span that was started
|
|
180
|
+
* @param parentContext - The parent context
|
|
181
|
+
*
|
|
182
|
+
* @override
|
|
183
|
+
*/
|
|
36
184
|
onStart(span: Span, parentContext: any): void;
|
|
185
|
+
/**
|
|
186
|
+
* Called when a span ends. Processes the span for export to Langfuse.
|
|
187
|
+
*
|
|
188
|
+
* This method:
|
|
189
|
+
* 1. Checks if the span should be exported using the shouldExportSpan function
|
|
190
|
+
* 2. Applies data masking to sensitive attributes
|
|
191
|
+
* 3. Handles media content extraction and upload
|
|
192
|
+
* 4. Logs span details in debug mode
|
|
193
|
+
* 5. Passes the span to the parent processor for export
|
|
194
|
+
*
|
|
195
|
+
* @param span - The span that ended
|
|
196
|
+
*
|
|
197
|
+
* @override
|
|
198
|
+
*/
|
|
37
199
|
onEnd(span: ReadableSpan): void;
|
|
38
200
|
private flush;
|
|
201
|
+
/**
|
|
202
|
+
* Forces an immediate flush of all pending spans and media uploads.
|
|
203
|
+
*
|
|
204
|
+
* @returns Promise that resolves when all pending operations are complete
|
|
205
|
+
*
|
|
206
|
+
* @override
|
|
207
|
+
*/
|
|
39
208
|
forceFlush(): Promise<void>;
|
|
209
|
+
/**
|
|
210
|
+
* Gracefully shuts down the processor, ensuring all pending operations are completed.
|
|
211
|
+
*
|
|
212
|
+
* @returns Promise that resolves when shutdown is complete
|
|
213
|
+
*
|
|
214
|
+
* @override
|
|
215
|
+
*/
|
|
40
216
|
shutdown(): Promise<void>;
|
|
41
217
|
private handleMediaInPlace;
|
|
42
218
|
private applyMaskInPlace;
|
|
@@ -45,31 +221,151 @@ declare class LangfuseSpanProcessor extends BatchSpanProcessor {
|
|
|
45
221
|
private uploadMediaWithBackoff;
|
|
46
222
|
}
|
|
47
223
|
|
|
224
|
+
/**
|
|
225
|
+
* Parameters for creating a LangfuseMedia instance.
|
|
226
|
+
*
|
|
227
|
+
* Supports two input formats:
|
|
228
|
+
* - Base64 data URI (e.g., "data:image/png;base64,...")
|
|
229
|
+
* - Raw bytes with explicit content type
|
|
230
|
+
*
|
|
231
|
+
* @public
|
|
232
|
+
*/
|
|
48
233
|
type LangfuseMediaParams = {
|
|
234
|
+
/** Indicates the media is provided as a base64 data URI */
|
|
49
235
|
source: "base64_data_uri";
|
|
236
|
+
/** The complete base64 data URI string */
|
|
50
237
|
base64DataUri: string;
|
|
51
238
|
} | {
|
|
239
|
+
/** Indicates the media is provided as raw bytes */
|
|
52
240
|
source: "bytes";
|
|
241
|
+
/** The raw content bytes */
|
|
53
242
|
contentBytes: Buffer;
|
|
243
|
+
/** The MIME type of the content */
|
|
54
244
|
contentType: MediaContentType;
|
|
55
245
|
};
|
|
56
246
|
/**
|
|
57
247
|
* A class for wrapping media objects for upload to Langfuse.
|
|
58
248
|
*
|
|
59
249
|
* This class handles the preparation and formatting of media content for Langfuse,
|
|
60
|
-
* supporting both base64 data URIs and raw content bytes.
|
|
250
|
+
* supporting both base64 data URIs and raw content bytes. It automatically:
|
|
251
|
+
* - Parses base64 data URIs to extract content type and bytes
|
|
252
|
+
* - Generates SHA-256 hashes for content integrity
|
|
253
|
+
* - Creates unique media IDs based on content hash
|
|
254
|
+
* - Formats media references for embedding in traces
|
|
255
|
+
*
|
|
256
|
+
* @example
|
|
257
|
+
* ```typescript
|
|
258
|
+
* // From base64 data URI
|
|
259
|
+
* const media1 = new LangfuseMedia({
|
|
260
|
+
* source: "base64_data_uri",
|
|
261
|
+
* base64DataUri: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=="
|
|
262
|
+
* });
|
|
263
|
+
*
|
|
264
|
+
* // From raw bytes
|
|
265
|
+
* const media2 = new LangfuseMedia({
|
|
266
|
+
* source: "bytes",
|
|
267
|
+
* contentBytes: Buffer.from("Hello World"),
|
|
268
|
+
* contentType: "text/plain"
|
|
269
|
+
* });
|
|
270
|
+
*
|
|
271
|
+
* console.log(media1.id); // Unique media ID
|
|
272
|
+
* console.log(media1.tag); // Media reference tag
|
|
273
|
+
* ```
|
|
274
|
+
*
|
|
275
|
+
* @public
|
|
61
276
|
*/
|
|
62
277
|
declare class LangfuseMedia {
|
|
63
278
|
_contentBytes?: Buffer;
|
|
64
279
|
_contentType?: MediaContentType;
|
|
65
280
|
_source?: string;
|
|
281
|
+
/**
|
|
282
|
+
* Creates a new LangfuseMedia instance.
|
|
283
|
+
*
|
|
284
|
+
* @param params - Media parameters specifying the source and content
|
|
285
|
+
*
|
|
286
|
+
* @example
|
|
287
|
+
* ```typescript
|
|
288
|
+
* // Create from base64 data URI
|
|
289
|
+
* const media = new LangfuseMedia({
|
|
290
|
+
* source: "base64_data_uri",
|
|
291
|
+
* base64DataUri: "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQ..."
|
|
292
|
+
* });
|
|
293
|
+
* ```
|
|
294
|
+
*/
|
|
66
295
|
constructor(params: LangfuseMediaParams);
|
|
296
|
+
/**
|
|
297
|
+
* Parses a base64 data URI to extract content bytes and type.
|
|
298
|
+
*
|
|
299
|
+
* @param data - The base64 data URI string
|
|
300
|
+
* @returns Tuple of [contentBytes, contentType] or [undefined, undefined] on error
|
|
301
|
+
* @private
|
|
302
|
+
*/
|
|
67
303
|
private parseBase64DataUri;
|
|
304
|
+
/**
|
|
305
|
+
* Gets a unique identifier for this media based on its content hash.
|
|
306
|
+
*
|
|
307
|
+
* The ID is derived from the first 22 characters of the URL-safe base64-encoded
|
|
308
|
+
* SHA-256 hash of the content.
|
|
309
|
+
*
|
|
310
|
+
* @returns The unique media ID, or null if hash generation failed
|
|
311
|
+
*
|
|
312
|
+
* @example
|
|
313
|
+
* ```typescript
|
|
314
|
+
* const media = new LangfuseMedia({...});
|
|
315
|
+
* console.log(media.id); // "A1B2C3D4E5F6G7H8I9J0K1"
|
|
316
|
+
* ```
|
|
317
|
+
*/
|
|
68
318
|
get id(): string | null;
|
|
319
|
+
/**
|
|
320
|
+
* Gets the length of the media content in bytes.
|
|
321
|
+
*
|
|
322
|
+
* @returns The content length in bytes, or undefined if no content is available
|
|
323
|
+
*/
|
|
69
324
|
get contentLength(): number | undefined;
|
|
325
|
+
/**
|
|
326
|
+
* Gets the SHA-256 hash of the media content.
|
|
327
|
+
*
|
|
328
|
+
* The hash is used for content integrity verification and generating unique media IDs.
|
|
329
|
+
* Returns undefined if crypto is not available or hash generation fails.
|
|
330
|
+
*
|
|
331
|
+
* @returns The base64-encoded SHA-256 hash, or undefined if unavailable
|
|
332
|
+
*/
|
|
70
333
|
get contentSha256Hash(): string | undefined;
|
|
334
|
+
/**
|
|
335
|
+
* Gets the media reference tag for embedding in trace data.
|
|
336
|
+
*
|
|
337
|
+
* The tag format is: `@@@langfuseMedia:type=<contentType>|id=<mediaId>|source=<source>@@@`
|
|
338
|
+
* This tag can be embedded in trace attributes and will be replaced with actual
|
|
339
|
+
* media content when the trace is viewed in Langfuse.
|
|
340
|
+
*
|
|
341
|
+
* @returns The media reference tag, or null if required data is missing
|
|
342
|
+
*
|
|
343
|
+
* @example
|
|
344
|
+
* ```typescript
|
|
345
|
+
* const media = new LangfuseMedia({...});
|
|
346
|
+
* console.log(media.tag);
|
|
347
|
+
* // "@@@langfuseMedia:type=image/png|id=A1B2C3D4E5F6G7H8I9J0K1|source=base64_data_uri@@@"
|
|
348
|
+
* ```
|
|
349
|
+
*/
|
|
71
350
|
get tag(): string | null;
|
|
351
|
+
/**
|
|
352
|
+
* Gets the media content as a base64 data URI.
|
|
353
|
+
*
|
|
354
|
+
* @returns The complete data URI string, or null if no content is available
|
|
355
|
+
*
|
|
356
|
+
* @example
|
|
357
|
+
* ```typescript
|
|
358
|
+
* const media = new LangfuseMedia({...});
|
|
359
|
+
* console.log(media.base64DataUri);
|
|
360
|
+
* // "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAB..."
|
|
361
|
+
* ```
|
|
362
|
+
*/
|
|
72
363
|
get base64DataUri(): string | null;
|
|
364
|
+
/**
|
|
365
|
+
* Serializes the media to JSON (returns the base64 data URI).
|
|
366
|
+
*
|
|
367
|
+
* @returns The base64 data URI, or null if no content is available
|
|
368
|
+
*/
|
|
73
369
|
toJSON(): string | null;
|
|
74
370
|
}
|
|
75
371
|
|
package/dist/index.mjs
CHANGED
|
@@ -12,7 +12,8 @@ import {
|
|
|
12
12
|
LangfuseAPIClient,
|
|
13
13
|
LANGFUSE_SDK_VERSION,
|
|
14
14
|
LangfuseOtelSpanAttributes,
|
|
15
|
-
getEnv
|
|
15
|
+
getEnv,
|
|
16
|
+
uint8ArrayToBase64 as uint8ArrayToBase642
|
|
16
17
|
} from "@langfuse/core";
|
|
17
18
|
import { hrTimeToMilliseconds } from "@opentelemetry/core";
|
|
18
19
|
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
|
|
@@ -60,6 +61,20 @@ function getSha256HashFromBytes(data) {
|
|
|
60
61
|
// src/media.ts
|
|
61
62
|
import { getGlobalLogger as getGlobalLogger2 } from "@langfuse/core";
|
|
62
63
|
var LangfuseMedia = class {
|
|
64
|
+
/**
|
|
65
|
+
* Creates a new LangfuseMedia instance.
|
|
66
|
+
*
|
|
67
|
+
* @param params - Media parameters specifying the source and content
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```typescript
|
|
71
|
+
* // Create from base64 data URI
|
|
72
|
+
* const media = new LangfuseMedia({
|
|
73
|
+
* source: "base64_data_uri",
|
|
74
|
+
* base64DataUri: "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQ..."
|
|
75
|
+
* });
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
63
78
|
constructor(params) {
|
|
64
79
|
const { source } = params;
|
|
65
80
|
this._source = source;
|
|
@@ -74,6 +89,13 @@ var LangfuseMedia = class {
|
|
|
74
89
|
this._contentType = params.contentType;
|
|
75
90
|
}
|
|
76
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* Parses a base64 data URI to extract content bytes and type.
|
|
94
|
+
*
|
|
95
|
+
* @param data - The base64 data URI string
|
|
96
|
+
* @returns Tuple of [contentBytes, contentType] or [undefined, undefined] on error
|
|
97
|
+
* @private
|
|
98
|
+
*/
|
|
77
99
|
parseBase64DataUri(data) {
|
|
78
100
|
try {
|
|
79
101
|
if (!data || typeof data !== "string") {
|
|
@@ -103,15 +125,42 @@ var LangfuseMedia = class {
|
|
|
103
125
|
return [void 0, void 0];
|
|
104
126
|
}
|
|
105
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* Gets a unique identifier for this media based on its content hash.
|
|
130
|
+
*
|
|
131
|
+
* The ID is derived from the first 22 characters of the URL-safe base64-encoded
|
|
132
|
+
* SHA-256 hash of the content.
|
|
133
|
+
*
|
|
134
|
+
* @returns The unique media ID, or null if hash generation failed
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```typescript
|
|
138
|
+
* const media = new LangfuseMedia({...});
|
|
139
|
+
* console.log(media.id); // "A1B2C3D4E5F6G7H8I9J0K1"
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
106
142
|
get id() {
|
|
107
143
|
if (!this.contentSha256Hash) return null;
|
|
108
144
|
const urlSafeContentHash = this.contentSha256Hash.replaceAll("+", "-").replaceAll("/", "_");
|
|
109
145
|
return urlSafeContentHash.slice(0, 22);
|
|
110
146
|
}
|
|
147
|
+
/**
|
|
148
|
+
* Gets the length of the media content in bytes.
|
|
149
|
+
*
|
|
150
|
+
* @returns The content length in bytes, or undefined if no content is available
|
|
151
|
+
*/
|
|
111
152
|
get contentLength() {
|
|
112
153
|
var _a2;
|
|
113
154
|
return (_a2 = this._contentBytes) == null ? void 0 : _a2.length;
|
|
114
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* Gets the SHA-256 hash of the media content.
|
|
158
|
+
*
|
|
159
|
+
* The hash is used for content integrity verification and generating unique media IDs.
|
|
160
|
+
* Returns undefined if crypto is not available or hash generation fails.
|
|
161
|
+
*
|
|
162
|
+
* @returns The base64-encoded SHA-256 hash, or undefined if unavailable
|
|
163
|
+
*/
|
|
115
164
|
get contentSha256Hash() {
|
|
116
165
|
if (!this._contentBytes || !isCryptoAvailable) {
|
|
117
166
|
return void 0;
|
|
@@ -126,14 +175,47 @@ var LangfuseMedia = class {
|
|
|
126
175
|
return void 0;
|
|
127
176
|
}
|
|
128
177
|
}
|
|
178
|
+
/**
|
|
179
|
+
* Gets the media reference tag for embedding in trace data.
|
|
180
|
+
*
|
|
181
|
+
* The tag format is: `@@@langfuseMedia:type=<contentType>|id=<mediaId>|source=<source>@@@`
|
|
182
|
+
* This tag can be embedded in trace attributes and will be replaced with actual
|
|
183
|
+
* media content when the trace is viewed in Langfuse.
|
|
184
|
+
*
|
|
185
|
+
* @returns The media reference tag, or null if required data is missing
|
|
186
|
+
*
|
|
187
|
+
* @example
|
|
188
|
+
* ```typescript
|
|
189
|
+
* const media = new LangfuseMedia({...});
|
|
190
|
+
* console.log(media.tag);
|
|
191
|
+
* // "@@@langfuseMedia:type=image/png|id=A1B2C3D4E5F6G7H8I9J0K1|source=base64_data_uri@@@"
|
|
192
|
+
* ```
|
|
193
|
+
*/
|
|
129
194
|
get tag() {
|
|
130
195
|
if (!this._contentType || !this._source || !this.id) return null;
|
|
131
196
|
return `@@@langfuseMedia:type=${this._contentType}|id=${this.id}|source=${this._source}@@@`;
|
|
132
197
|
}
|
|
198
|
+
/**
|
|
199
|
+
* Gets the media content as a base64 data URI.
|
|
200
|
+
*
|
|
201
|
+
* @returns The complete data URI string, or null if no content is available
|
|
202
|
+
*
|
|
203
|
+
* @example
|
|
204
|
+
* ```typescript
|
|
205
|
+
* const media = new LangfuseMedia({...});
|
|
206
|
+
* console.log(media.base64DataUri);
|
|
207
|
+
* // "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAB..."
|
|
208
|
+
* ```
|
|
209
|
+
*/
|
|
133
210
|
get base64DataUri() {
|
|
134
211
|
if (!this._contentBytes) return null;
|
|
135
212
|
return `data:${this._contentType};base64,${Buffer.from(this._contentBytes).toString("base64")}`;
|
|
136
213
|
}
|
|
214
|
+
/**
|
|
215
|
+
* Serializes the media to JSON (returns the base64 data URI).
|
|
216
|
+
*
|
|
217
|
+
* @returns The base64 data URI, or null if no content is available
|
|
218
|
+
*/
|
|
137
219
|
toJSON() {
|
|
138
220
|
return this.base64DataUri;
|
|
139
221
|
}
|
|
@@ -141,6 +223,32 @@ var LangfuseMedia = class {
|
|
|
141
223
|
|
|
142
224
|
// src/span-processor.ts
|
|
143
225
|
var LangfuseSpanProcessor = class extends BatchSpanProcessor {
|
|
226
|
+
/**
|
|
227
|
+
* Creates a new LangfuseSpanProcessor instance.
|
|
228
|
+
*
|
|
229
|
+
* @param params - Configuration parameters for the processor
|
|
230
|
+
*
|
|
231
|
+
* @example
|
|
232
|
+
* ```typescript
|
|
233
|
+
* const processor = new LangfuseSpanProcessor({
|
|
234
|
+
* publicKey: 'pk_...',
|
|
235
|
+
* secretKey: 'sk_...',
|
|
236
|
+
* environment: 'staging',
|
|
237
|
+
* flushAt: 10,
|
|
238
|
+
* flushInterval: 2,
|
|
239
|
+
* mask: ({ data }) => {
|
|
240
|
+
* // Custom masking logic
|
|
241
|
+
* return typeof data === 'string'
|
|
242
|
+
* ? data.replace(/secret_\w+/g, 'secret_***')
|
|
243
|
+
* : data;
|
|
244
|
+
* },
|
|
245
|
+
* shouldExportSpan: ({ otelSpan }) => {
|
|
246
|
+
* // Only export spans from specific services
|
|
247
|
+
* return otelSpan.name.startsWith('my-service');
|
|
248
|
+
* }
|
|
249
|
+
* });
|
|
250
|
+
* ```
|
|
251
|
+
*/
|
|
144
252
|
constructor(params) {
|
|
145
253
|
var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
|
|
146
254
|
const logger = getGlobalLogger3();
|
|
@@ -162,8 +270,8 @@ var LangfuseSpanProcessor = class extends BatchSpanProcessor {
|
|
|
162
270
|
}
|
|
163
271
|
const flushAt = (_f = params == null ? void 0 : params.flushAt) != null ? _f : getEnv("LANGFUSE_FLUSH_AT");
|
|
164
272
|
const flushIntervalSeconds = (_g = params == null ? void 0 : params.flushInterval) != null ? _g : getEnv("LANGFUSE_FLUSH_INTERVAL");
|
|
165
|
-
const authHeaderValue =
|
|
166
|
-
|
|
273
|
+
const authHeaderValue = uint8ArrayToBase642(
|
|
274
|
+
new TextEncoder().encode(`${publicKey}:${secretKey}`)
|
|
167
275
|
);
|
|
168
276
|
const timeoutSeconds = (_i = params == null ? void 0 : params.timeout) != null ? _i : Number((_h = getEnv("LANGFUSE_TIMEOUT")) != null ? _h : 5);
|
|
169
277
|
const exporter = (_j = params == null ? void 0 : params.exporter) != null ? _j : new OTLPTraceExporter({
|
|
@@ -217,6 +325,14 @@ var LangfuseSpanProcessor = class extends BatchSpanProcessor {
|
|
|
217
325
|
get logger() {
|
|
218
326
|
return getGlobalLogger3();
|
|
219
327
|
}
|
|
328
|
+
/**
|
|
329
|
+
* Called when a span is started. Adds environment and release attributes to the span.
|
|
330
|
+
*
|
|
331
|
+
* @param span - The span that was started
|
|
332
|
+
* @param parentContext - The parent context
|
|
333
|
+
*
|
|
334
|
+
* @override
|
|
335
|
+
*/
|
|
220
336
|
onStart(span, parentContext) {
|
|
221
337
|
span.setAttributes({
|
|
222
338
|
[LangfuseOtelSpanAttributes.ENVIRONMENT]: this.environment,
|
|
@@ -224,6 +340,20 @@ var LangfuseSpanProcessor = class extends BatchSpanProcessor {
|
|
|
224
340
|
});
|
|
225
341
|
return super.onStart(span, parentContext);
|
|
226
342
|
}
|
|
343
|
+
/**
|
|
344
|
+
* Called when a span ends. Processes the span for export to Langfuse.
|
|
345
|
+
*
|
|
346
|
+
* This method:
|
|
347
|
+
* 1. Checks if the span should be exported using the shouldExportSpan function
|
|
348
|
+
* 2. Applies data masking to sensitive attributes
|
|
349
|
+
* 3. Handles media content extraction and upload
|
|
350
|
+
* 4. Logs span details in debug mode
|
|
351
|
+
* 5. Passes the span to the parent processor for export
|
|
352
|
+
*
|
|
353
|
+
* @param span - The span that ended
|
|
354
|
+
*
|
|
355
|
+
* @override
|
|
356
|
+
*/
|
|
227
357
|
onEnd(span) {
|
|
228
358
|
var _a2, _b;
|
|
229
359
|
if (this.shouldExportSpan) {
|
|
@@ -269,10 +399,24 @@ ${JSON.stringify(
|
|
|
269
399
|
);
|
|
270
400
|
});
|
|
271
401
|
}
|
|
402
|
+
/**
|
|
403
|
+
* Forces an immediate flush of all pending spans and media uploads.
|
|
404
|
+
*
|
|
405
|
+
* @returns Promise that resolves when all pending operations are complete
|
|
406
|
+
*
|
|
407
|
+
* @override
|
|
408
|
+
*/
|
|
272
409
|
async forceFlush() {
|
|
273
410
|
await this.flush();
|
|
274
411
|
return super.forceFlush();
|
|
275
412
|
}
|
|
413
|
+
/**
|
|
414
|
+
* Gracefully shuts down the processor, ensuring all pending operations are completed.
|
|
415
|
+
*
|
|
416
|
+
* @returns Promise that resolves when shutdown is complete
|
|
417
|
+
*
|
|
418
|
+
* @override
|
|
419
|
+
*/
|
|
276
420
|
async shutdown() {
|
|
277
421
|
await this.flush();
|
|
278
422
|
return super.shutdown();
|