0
# Utilities
1
2
Cross-platform utility functions for UUID generation, base64 encoding/decoding, environment variable access, and safe timeouts. All utilities work in both Node.js and browser environments.
3
4
## Capabilities
5
6
### UUID Generation
7
8
```typescript { .api }
9
/**
10
* Generates a UUID v4 string
11
* @param globalThis - Optional global object (for testing/customization)
12
* @returns A UUID v4 string in the format "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"
13
*/
14
function generateUUID(globalThis?: any): string;
15
```
16
17
**Import:**
18
19
```typescript
20
import { generateUUID } from '@langfuse/core';
21
```
22
23
**Description**: Generates a random UUID v4 compliant with RFC 4122. Uses a timestamp-based random number generation algorithm for cross-platform compatibility in both Node.js and browser environments.
24
25
**Usage Examples:**
26
27
```typescript
28
import { generateUUID } from '@langfuse/core';
29
30
// Generate a UUID
31
const id = generateUUID();
32
console.log(id); // "a3bb189e-8bf9-3888-9912-ace4e6543002"
33
34
// Use for trace IDs
35
const traceId = generateUUID();
36
await client.ingestion.batch({
37
batch: [{
38
type: 'trace-create',
39
id: generateUUID(), // Event ID
40
timestamp: new Date().toISOString(),
41
body: {
42
id: traceId,
43
name: 'My Trace'
44
}
45
}]
46
});
47
48
// Generate multiple unique IDs
49
const ids = Array.from({ length: 10 }, () => generateUUID());
50
console.log(ids); // Array of 10 unique UUIDs
51
```
52
53
### Environment Variables
54
55
```typescript { .api }
56
/**
57
* Gets environment variable values from process.env or globalThis
58
* @param key - The environment variable name
59
* @returns The environment variable value or undefined
60
*/
61
function getEnv(key: LangfuseEnvVar): string | undefined;
62
63
type LangfuseEnvVar =
64
| "LANGFUSE_PUBLIC_KEY"
65
| "LANGFUSE_SECRET_KEY"
66
| "LANGFUSE_BASE_URL"
67
| "LANGFUSE_BASEURL" // Legacy v2
68
| "LANGFUSE_TIMEOUT"
69
| "LANGFUSE_FLUSH_AT"
70
| "LANGFUSE_FLUSH_INTERVAL"
71
| "LANGFUSE_LOG_LEVEL"
72
| "LANGFUSE_RELEASE"
73
| "LANGFUSE_TRACING_ENVIRONMENT";
74
```
75
76
**Import:**
77
78
```typescript
79
import { getEnv } from '@langfuse/core';
80
```
81
82
**Description**: Safely retrieves Langfuse environment variables from either `process.env` (Node.js) or `globalThis` (browser). Returns undefined if the variable is not set.
83
84
**Supported Environment Variables:**
85
- `LANGFUSE_PUBLIC_KEY` - Public API key for authentication
86
- `LANGFUSE_SECRET_KEY` - Secret API key for authentication
87
- `LANGFUSE_BASE_URL` - Base API URL (e.g., "https://cloud.langfuse.com")
88
- `LANGFUSE_BASEURL` - Legacy base URL (v2 compatibility)
89
- `LANGFUSE_TIMEOUT` - Request timeout in milliseconds
90
- `LANGFUSE_FLUSH_AT` - Batch size for flushing operations
91
- `LANGFUSE_FLUSH_INTERVAL` - Flush interval in milliseconds
92
- `LANGFUSE_LOG_LEVEL` - Logging level (DEBUG, INFO, WARN, ERROR)
93
- `LANGFUSE_RELEASE` - Release identifier for traces
94
- `LANGFUSE_TRACING_ENVIRONMENT` - Environment identifier for traces
95
96
**Usage Examples:**
97
98
```typescript
99
import { getEnv, LangfuseAPIClient } from '@langfuse/core';
100
101
// Get API keys from environment
102
const publicKey = getEnv('LANGFUSE_PUBLIC_KEY');
103
const secretKey = getEnv('LANGFUSE_SECRET_KEY');
104
105
if (!publicKey || !secretKey) {
106
throw new Error('Missing Langfuse API keys');
107
}
108
109
// Initialize client with environment variables
110
const client = new LangfuseAPIClient({
111
environment: getEnv('LANGFUSE_BASE_URL') || 'https://cloud.langfuse.com',
112
username: publicKey,
113
password: secretKey
114
});
115
116
// Get configuration values
117
const timeout = parseInt(getEnv('LANGFUSE_TIMEOUT') || '60000');
118
const logLevel = getEnv('LANGFUSE_LOG_LEVEL') || 'INFO';
119
const release = getEnv('LANGFUSE_RELEASE');
120
121
console.log(`Using timeout: ${timeout}ms, log level: ${logLevel}`);
122
```
123
124
### Base64 Encoding/Decoding
125
126
Cross-platform base64 utilities that work in Node.js, browsers, and edge runtimes.
127
128
```typescript { .api }
129
/**
130
* Encodes a UTF-8 string to base64
131
* @param input - UTF-8 string to encode
132
* @returns Base64 encoded string
133
*/
134
function base64Encode(input: string): string;
135
136
/**
137
* Decodes a base64 string to UTF-8
138
* @param input - Base64 encoded string
139
* @returns Decoded UTF-8 string
140
*/
141
function base64Decode(input: string): string;
142
143
/**
144
* Converts a base64 string to a Uint8Array of bytes
145
* @param base64 - Base64 encoded string
146
* @returns Uint8Array of decoded bytes
147
*/
148
function base64ToBytes(base64: string): Uint8Array;
149
150
/**
151
* Converts a Uint8Array of bytes to a base64 string
152
* @param bytes - Byte array to encode
153
* @returns Base64 encoded string
154
*/
155
function bytesToBase64(bytes: Uint8Array): string;
156
```
157
158
**Import:**
159
160
```typescript
161
import {
162
base64Encode,
163
base64Decode,
164
base64ToBytes,
165
bytesToBase64
166
} from '@langfuse/core';
167
```
168
169
#### base64Encode()
170
171
Encodes a UTF-8 string to base64. Works in both Node.js and browser environments.
172
173
**Usage Examples:**
174
175
```typescript
176
import { base64Encode } from '@langfuse/core';
177
178
// Encode simple string
179
const encoded = base64Encode('Hello, World!');
180
console.log(encoded); // "SGVsbG8sIFdvcmxkIQ=="
181
182
// Encode JSON
183
const data = { name: 'Alice', age: 30 };
184
const encodedJson = base64Encode(JSON.stringify(data));
185
console.log(encodedJson); // "eyJuYW1lIjoiQWxpY2UiLCJhZ2UiOjMwfQ=="
186
187
// Encode Unicode
188
const unicode = base64Encode('Hello ไธ็ ๐');
189
console.log(unicode); // Properly encoded UTF-8
190
```
191
192
#### base64Decode()
193
194
Decodes a base64 string to UTF-8.
195
196
**Usage Examples:**
197
198
```typescript
199
import { base64Decode } from '@langfuse/core';
200
201
// Decode simple string
202
const decoded = base64Decode('SGVsbG8sIFdvcmxkIQ==');
203
console.log(decoded); // "Hello, World!"
204
205
// Decode JSON
206
const encodedJson = 'eyJuYW1lIjoiQWxpY2UiLCJhZ2UiOjMwfQ==';
207
const decodedJson = base64Decode(encodedJson);
208
const data = JSON.parse(decodedJson);
209
console.log(data); // { name: 'Alice', age: 30 }
210
211
// Decode Unicode
212
const unicode = base64Decode('SGVsbG8g5LiW55WMIPCfjI0=');
213
console.log(unicode); // "Hello ไธ็ ๐"
214
```
215
216
#### base64ToBytes()
217
218
Converts a base64 string to a Uint8Array of bytes.
219
220
**Usage Examples:**
221
222
```typescript
223
import { base64ToBytes } from '@langfuse/core';
224
225
// Decode to bytes
226
const base64 = 'SGVsbG8=';
227
const bytes = base64ToBytes(base64);
228
console.log(bytes); // Uint8Array(5) [72, 101, 108, 108, 111]
229
230
// Convert to string
231
const text = new TextDecoder().decode(bytes);
232
console.log(text); // "Hello"
233
234
// Use with binary data
235
const imageBase64 = 'iVBORw0KGgoAAAA...';
236
const imageBytes = base64ToBytes(imageBase64);
237
console.log(`Image size: ${imageBytes.length} bytes`);
238
```
239
240
#### bytesToBase64()
241
242
Converts a Uint8Array of bytes to a base64 string.
243
244
**Usage Examples:**
245
246
```typescript
247
import { bytesToBase64 } from '@langfuse/core';
248
249
// Encode bytes
250
const bytes = new Uint8Array([72, 101, 108, 108, 111]);
251
const base64 = bytesToBase64(bytes);
252
console.log(base64); // "SGVsbG8="
253
254
// Encode binary data
255
const binaryData = new Uint8Array([0xFF, 0xD8, 0xFF, 0xE0]);
256
const encoded = bytesToBase64(binaryData);
257
console.log(encoded); // "/9j/4A=="
258
259
// Round-trip conversion
260
const original = new Uint8Array([1, 2, 3, 4, 5]);
261
const encoded2 = bytesToBase64(original);
262
const decoded = base64ToBytes(encoded2);
263
console.log(decoded); // Uint8Array(5) [1, 2, 3, 4, 5]
264
```
265
266
### Safe Timeout
267
268
```typescript { .api }
269
/**
270
* Sets a timeout that unref's itself in Node.js environments to prevent hanging on exit
271
* @param fn - Function to execute after timeout
272
* @param timeout - Timeout duration in milliseconds
273
* @returns The timeout handle
274
*/
275
function safeSetTimeout(fn: () => void, timeout: number): any;
276
```
277
278
**Import:**
279
280
```typescript
281
import { safeSetTimeout } from '@langfuse/core';
282
```
283
284
**Description**: Creates a timeout that automatically unref's itself in Node.js environments. This prevents the timeout from keeping the process alive if it's the only pending operation, allowing for clean process exits.
285
286
**Usage Examples:**
287
288
```typescript
289
import { safeSetTimeout } from '@langfuse/core';
290
291
// Schedule a delayed operation
292
safeSetTimeout(() => {
293
console.log('This runs after 5 seconds');
294
}, 5000);
295
296
// In a long-running service
297
class BatchProcessor {
298
private timeoutHandle: any;
299
300
scheduleNextFlush() {
301
// Clear existing timeout
302
if (this.timeoutHandle) {
303
clearTimeout(this.timeoutHandle);
304
}
305
306
// Schedule next flush (won't prevent process exit)
307
this.timeoutHandle = safeSetTimeout(() => {
308
this.flush();
309
this.scheduleNextFlush();
310
}, 30000); // 30 seconds
311
}
312
313
flush() {
314
console.log('Flushing batch...');
315
// Flush logic
316
}
317
318
shutdown() {
319
if (this.timeoutHandle) {
320
clearTimeout(this.timeoutHandle);
321
}
322
}
323
}
324
325
// Retry logic with safe timeout
326
async function retryWithBackoff<T>(
327
fn: () => Promise<T>,
328
maxRetries: number = 3
329
): Promise<T> {
330
let lastError: Error | undefined;
331
332
for (let i = 0; i < maxRetries; i++) {
333
try {
334
return await fn();
335
} catch (error) {
336
lastError = error as Error;
337
338
if (i < maxRetries - 1) {
339
const delay = Math.pow(2, i) * 1000; // Exponential backoff
340
await new Promise(resolve => safeSetTimeout(resolve, delay));
341
}
342
}
343
}
344
345
throw lastError;
346
}
347
```
348
349
## Usage Patterns
350
351
### Complete Client Initialization
352
353
```typescript
354
import {
355
LangfuseAPIClient,
356
getEnv,
357
configureGlobalLogger,
358
LogLevel
359
} from '@langfuse/core';
360
361
// Configure logger from environment
362
const logLevelMap: Record<string, LogLevel> = {
363
'DEBUG': LogLevel.DEBUG,
364
'INFO': LogLevel.INFO,
365
'WARN': LogLevel.WARN,
366
'ERROR': LogLevel.ERROR
367
};
368
369
const logLevel = logLevelMap[getEnv('LANGFUSE_LOG_LEVEL') || 'INFO'];
370
configureGlobalLogger({
371
level: logLevel,
372
prefix: 'Langfuse',
373
enableTimestamp: true
374
});
375
376
// Initialize client with environment variables
377
const client = new LangfuseAPIClient({
378
environment: getEnv('LANGFUSE_BASE_URL') || 'https://cloud.langfuse.com',
379
username: getEnv('LANGFUSE_PUBLIC_KEY'),
380
password: getEnv('LANGFUSE_SECRET_KEY')
381
});
382
```
383
384
### Data URI Construction
385
386
```typescript
387
import { bytesToBase64 } from '@langfuse/core';
388
389
function createDataUri(bytes: Uint8Array, mimeType: string): string {
390
const base64 = bytesToBase64(bytes);
391
return `data:${mimeType};base64,${base64}`;
392
}
393
394
// Usage
395
const imageBytes = new Uint8Array([/* ... */]);
396
const dataUri = createDataUri(imageBytes, 'image/png');
397
console.log(dataUri); // "data:image/png;base64,..."
398
```
399
400
### Secure Token Encoding
401
402
```typescript
403
import { base64Encode, base64Decode } from '@langfuse/core';
404
405
interface Token {
406
userId: string;
407
sessionId: string;
408
expires: number;
409
}
410
411
function encodeToken(token: Token): string {
412
const json = JSON.stringify(token);
413
return base64Encode(json);
414
}
415
416
function decodeToken(encoded: string): Token {
417
const json = base64Decode(encoded);
418
return JSON.parse(json);
419
}
420
421
// Usage
422
const token = {
423
userId: 'user-123',
424
sessionId: 'session-456',
425
expires: Date.now() + 3600000
426
};
427
428
const encoded = encodeToken(token);
429
console.log(encoded); // Base64 encoded token
430
431
const decoded = decodeToken(encoded);
432
console.log(decoded); // Original token object
433
```
434
435
### Batch Processing with Safe Timeouts
436
437
```typescript
438
import { safeSetTimeout, generateUUID } from '@langfuse/core';
439
440
class EventBatcher<T> {
441
private batch: Array<{ id: string; data: T }> = [];
442
private flushHandle: any;
443
444
constructor(
445
private onFlush: (batch: Array<{ id: string; data: T }>) => Promise<void>,
446
private flushInterval: number = 5000,
447
private maxBatchSize: number = 100
448
) {
449
this.scheduleFlush();
450
}
451
452
add(data: T) {
453
this.batch.push({
454
id: generateUUID(),
455
data
456
});
457
458
if (this.batch.length >= this.maxBatchSize) {
459
this.flush();
460
}
461
}
462
463
private scheduleFlush() {
464
this.flushHandle = safeSetTimeout(() => {
465
this.flush();
466
}, this.flushInterval);
467
}
468
469
private async flush() {
470
if (this.flushHandle) {
471
clearTimeout(this.flushHandle);
472
}
473
474
if (this.batch.length === 0) {
475
this.scheduleFlush();
476
return;
477
}
478
479
const toFlush = this.batch;
480
this.batch = [];
481
482
try {
483
await this.onFlush(toFlush);
484
} catch (error) {
485
console.error('Flush failed', error);
486
// Re-add to batch or handle error
487
}
488
489
this.scheduleFlush();
490
}
491
492
async shutdown() {
493
if (this.flushHandle) {
494
clearTimeout(this.flushHandle);
495
}
496
await this.flush();
497
}
498
}
499
500
// Usage
501
const batcher = new EventBatcher(
502
async (batch) => {
503
console.log(`Flushing ${batch.length} events`);
504
// Send to API
505
},
506
5000, // Flush every 5 seconds
507
100 // Or when 100 events
508
);
509
510
batcher.add({ type: 'trace', data: { /* ... */ } });
511
```
512
513
### Environment-Based Configuration
514
515
```typescript
516
import { getEnv } from '@langfuse/core';
517
518
interface Config {
519
apiUrl: string;
520
publicKey: string;
521
secretKey: string;
522
timeout: number;
523
flushInterval: number;
524
flushAt: number;
525
release?: string;
526
environment?: string;
527
logLevel: string;
528
}
529
530
function loadConfig(): Config {
531
const publicKey = getEnv('LANGFUSE_PUBLIC_KEY');
532
const secretKey = getEnv('LANGFUSE_SECRET_KEY');
533
534
if (!publicKey || !secretKey) {
535
throw new Error(
536
'Missing required environment variables: LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY'
537
);
538
}
539
540
return {
541
apiUrl: getEnv('LANGFUSE_BASE_URL') || 'https://cloud.langfuse.com',
542
publicKey,
543
secretKey,
544
timeout: parseInt(getEnv('LANGFUSE_TIMEOUT') || '60000'),
545
flushInterval: parseInt(getEnv('LANGFUSE_FLUSH_INTERVAL') || '5000'),
546
flushAt: parseInt(getEnv('LANGFUSE_FLUSH_AT') || '100'),
547
release: getEnv('LANGFUSE_RELEASE'),
548
environment: getEnv('LANGFUSE_TRACING_ENVIRONMENT'),
549
logLevel: getEnv('LANGFUSE_LOG_LEVEL') || 'INFO'
550
};
551
}
552
553
// Usage
554
const config = loadConfig();
555
console.log(`Connecting to ${config.apiUrl}`);
556
console.log(`Flush interval: ${config.flushInterval}ms`);
557
```
558
559
### Binary Data Handling
560
561
```typescript
562
import { base64ToBytes, bytesToBase64 } from '@langfuse/core';
563
564
async function downloadAndEncode(url: string): Promise<string> {
565
const response = await fetch(url);
566
const arrayBuffer = await response.arrayBuffer();
567
const bytes = new Uint8Array(arrayBuffer);
568
return bytesToBase64(bytes);
569
}
570
571
async function decodeAndDisplay(base64: string, mimeType: string) {
572
const bytes = base64ToBytes(base64);
573
const blob = new Blob([bytes], { type: mimeType });
574
const url = URL.createObjectURL(blob);
575
576
const img = document.createElement('img');
577
img.src = url;
578
document.body.appendChild(img);
579
}
580
581
// Usage
582
const encoded = await downloadAndEncode('https://example.com/image.png');
583
await decodeAndDisplay(encoded, 'image/png');
584
```
585
586
## Type Definitions
587
588
```typescript { .api }
589
function generateUUID(globalThis?: any): string;
590
591
function getEnv(key: LangfuseEnvVar): string | undefined;
592
593
type LangfuseEnvVar =
594
| "LANGFUSE_PUBLIC_KEY"
595
| "LANGFUSE_SECRET_KEY"
596
| "LANGFUSE_BASE_URL"
597
| "LANGFUSE_BASEURL"
598
| "LANGFUSE_TIMEOUT"
599
| "LANGFUSE_FLUSH_AT"
600
| "LANGFUSE_FLUSH_INTERVAL"
601
| "LANGFUSE_LOG_LEVEL"
602
| "LANGFUSE_RELEASE"
603
| "LANGFUSE_TRACING_ENVIRONMENT";
604
605
function base64Encode(input: string): string;
606
function base64Decode(input: string): string;
607
function base64ToBytes(base64: string): Uint8Array;
608
function bytesToBase64(bytes: Uint8Array): string;
609
610
function safeSetTimeout(fn: () => void, timeout: number): any;
611
```
612
613
## Best Practices
614
615
1. **Environment Variables**: Always validate required environment variables at startup
616
2. **UUID Generation**: Use `generateUUID()` for all ID generation to ensure RFC 4122 compliance
617
3. **Base64 Encoding**: Prefer `base64Encode`/`base64Decode` over direct Buffer/btoa/atob for cross-platform compatibility
618
4. **Binary Data**: Use `base64ToBytes`/`bytesToBase64` when working with raw binary data
619
5. **Safe Timeouts**: Always use `safeSetTimeout` for background operations to prevent process hanging
620
6. **Error Handling**: Wrap base64 operations in try-catch blocks for malformed input
621
7. **Memory Management**: For large binary data, process in chunks rather than loading entirely
622
8. **Configuration**: Centralize environment variable reading in a config module
623
9. **Type Safety**: Use the `LangfuseEnvVar` type for environment variable keys
624
10. **Cleanup**: Always clear timeouts in cleanup/shutdown handlers
625