0
# Tracer Provider
1
2
Tracer provider functions enable configuration of OpenTelemetry tracer instances for Langfuse tracing operations. These utilities allow you to isolate Langfuse tracing from other OpenTelemetry instrumentation in your application.
3
4
## Core Functions
5
6
### setLangfuseTracerProvider
7
8
Sets an isolated TracerProvider for Langfuse tracing operations, separate from the global OpenTelemetry TracerProvider.
9
10
```typescript { .api }
11
/**
12
* Sets an isolated TracerProvider for Langfuse tracing operations.
13
*
14
* This allows Langfuse to use its own TracerProvider instance, separate from
15
* the global OpenTelemetry TracerProvider. This is useful for avoiding conflicts
16
* with other OpenTelemetry instrumentation in the application.
17
*
18
* ⚠️ Limitation: Span Context Sharing
19
*
20
* While this function isolates span processing and export, it does NOT provide
21
* complete trace isolation. OpenTelemetry context (trace IDs, parent spans) is
22
* still shared between the global and isolated providers.
23
*
24
* @param provider - The TracerProvider instance to use, or null to clear
25
*/
26
function setLangfuseTracerProvider(provider: TracerProvider | null): void;
27
```
28
29
**Usage:**
30
31
```typescript
32
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
33
import { LangfuseSpanProcessor } from '@langfuse/otel';
34
import { setLangfuseTracerProvider } from '@langfuse/tracing';
35
36
// Create provider with Langfuse span processor
37
const langfuseProvider = new NodeTracerProvider({
38
spanProcessors: [new LangfuseSpanProcessor()]
39
});
40
41
// Set as isolated provider for Langfuse
42
setLangfuseTracerProvider(langfuseProvider);
43
44
// Now all Langfuse tracing uses this provider
45
import { startObservation } from '@langfuse/tracing';
46
const span = startObservation('my-operation');
47
```
48
49
### getLangfuseTracerProvider
50
51
Gets the TracerProvider for Langfuse tracing operations, returning the isolated provider if set, otherwise the global provider.
52
53
```typescript { .api }
54
/**
55
* Gets the TracerProvider for Langfuse tracing operations.
56
*
57
* Returns the isolated TracerProvider if one has been set via setLangfuseTracerProvider(),
58
* otherwise falls back to the global OpenTelemetry TracerProvider.
59
*
60
* @returns The TracerProvider instance to use for Langfuse tracing
61
*/
62
function getLangfuseTracerProvider(): TracerProvider;
63
```
64
65
**Usage:**
66
67
```typescript
68
import { getLangfuseTracerProvider } from '@langfuse/tracing';
69
70
const provider = getLangfuseTracerProvider();
71
72
// Use provider directly if needed
73
const tracer = provider.getTracer('my-tracer', '1.0.0');
74
const span = tracer.startSpan('custom-span');
75
```
76
77
### getLangfuseTracer
78
79
Gets the OpenTelemetry tracer instance specifically configured for Langfuse with the correct tracer name and version.
80
81
```typescript { .api }
82
/**
83
* Gets the OpenTelemetry tracer instance for Langfuse.
84
*
85
* This function returns a tracer specifically configured for Langfuse
86
* with the correct tracer name and version. Used internally by all
87
* Langfuse tracing functions to ensure consistent trace creation.
88
*
89
* @returns The Langfuse OpenTelemetry tracer instance
90
*/
91
function getLangfuseTracer(): Tracer;
92
```
93
94
**Usage:**
95
96
```typescript
97
import { getLangfuseTracer } from '@langfuse/tracing';
98
99
const tracer = getLangfuseTracer();
100
101
// Create custom span using Langfuse tracer
102
const span = tracer.startSpan('custom-operation', {
103
startTime: new Date()
104
});
105
106
// Perform operation
107
span.setAttributes({
108
'custom.attribute': 'value'
109
});
110
111
span.end();
112
```
113
114
## Use Cases
115
116
### Isolating Langfuse Tracing
117
118
Separate Langfuse traces from other OpenTelemetry instrumentation in your application.
119
120
```typescript
121
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
122
import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';
123
import { LangfuseSpanProcessor } from '@langfuse/otel';
124
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
125
import { setLangfuseTracerProvider } from '@langfuse/tracing';
126
import { trace } from '@opentelemetry/api';
127
128
// Global provider for general application tracing
129
const globalProvider = new NodeTracerProvider();
130
globalProvider.addSpanProcessor(
131
new BatchSpanProcessor(new OTLPTraceExporter({
132
url: 'https://your-otel-collector.com/v1/traces'
133
}))
134
);
135
trace.setGlobalTracerProvider(globalProvider);
136
137
// Isolated provider for Langfuse tracing
138
const langfuseProvider = new NodeTracerProvider({
139
spanProcessors: [
140
new LangfuseSpanProcessor({
141
publicKey: process.env.LANGFUSE_PUBLIC_KEY,
142
secretKey: process.env.LANGFUSE_SECRET_KEY
143
})
144
]
145
});
146
147
setLangfuseTracerProvider(langfuseProvider);
148
149
// Now application traces go to OTLP, Langfuse traces go to Langfuse
150
import { startObservation } from '@langfuse/tracing';
151
const langfuseSpan = startObservation('langfuse-operation');
152
153
const appTracer = trace.getTracer('app');
154
const appSpan = appTracer.startSpan('app-operation');
155
```
156
157
### Multiple Span Processors
158
159
Configure multiple span processors for Langfuse provider.
160
161
```typescript
162
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
163
import { BatchSpanProcessor, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base';
164
import { LangfuseSpanProcessor } from '@langfuse/otel';
165
import { ConsoleSpanExporter } from '@opentelemetry/sdk-trace-base';
166
import { setLangfuseTracerProvider } from '@langfuse/tracing';
167
168
const provider = new NodeTracerProvider();
169
170
// Add Langfuse processor
171
provider.addSpanProcessor(
172
new LangfuseSpanProcessor({
173
publicKey: process.env.LANGFUSE_PUBLIC_KEY,
174
secretKey: process.env.LANGFUSE_SECRET_KEY,
175
baseUrl: 'https://cloud.langfuse.com'
176
})
177
);
178
179
// Add console exporter for debugging
180
if (process.env.DEBUG) {
181
provider.addSpanProcessor(
182
new SimpleSpanProcessor(new ConsoleSpanExporter())
183
);
184
}
185
186
setLangfuseTracerProvider(provider);
187
```
188
189
### Environment-Based Configuration
190
191
Configure tracer provider based on environment.
192
193
```typescript
194
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
195
import { LangfuseSpanProcessor } from '@langfuse/otel';
196
import { setLangfuseTracerProvider } from '@langfuse/tracing';
197
198
function configureLangfuseTracing() {
199
if (process.env.LANGFUSE_ENABLED !== 'true') {
200
// Disable Langfuse tracing
201
setLangfuseTracerProvider(null);
202
return;
203
}
204
205
const provider = new NodeTracerProvider({
206
spanProcessors: [
207
new LangfuseSpanProcessor({
208
publicKey: process.env.LANGFUSE_PUBLIC_KEY,
209
secretKey: process.env.LANGFUSE_SECRET_KEY,
210
baseUrl: process.env.LANGFUSE_BASE_URL,
211
flushAt: process.env.NODE_ENV === 'production' ? 15 : 1,
212
flushInterval: process.env.NODE_ENV === 'production' ? 10000 : 1000
213
})
214
]
215
});
216
217
setLangfuseTracerProvider(provider);
218
}
219
220
configureLangfuseTracing();
221
```
222
223
### Custom Sampling
224
225
Implement custom sampling strategies for Langfuse traces.
226
227
```typescript
228
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
229
import { ParentBasedSampler, TraceIdRatioBasedSampler } from '@opentelemetry/sdk-trace-base';
230
import { LangfuseSpanProcessor } from '@langfuse/otel';
231
import { setLangfuseTracerProvider } from '@langfuse/tracing';
232
233
// Sample 10% of traces in production, 100% in development
234
const samplingRatio = process.env.NODE_ENV === 'production' ? 0.1 : 1.0;
235
236
const provider = new NodeTracerProvider({
237
sampler: new ParentBasedSampler({
238
root: new TraceIdRatioBasedSampler(samplingRatio)
239
}),
240
spanProcessors: [
241
new LangfuseSpanProcessor({
242
publicKey: process.env.LANGFUSE_PUBLIC_KEY,
243
secretKey: process.env.LANGFUSE_SECRET_KEY
244
})
245
]
246
});
247
248
setLangfuseTracerProvider(provider);
249
```
250
251
### Custom Resource Attributes
252
253
Add custom resource attributes to all Langfuse traces.
254
255
```typescript
256
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
257
import { Resource } from '@opentelemetry/resources';
258
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions';
259
import { LangfuseSpanProcessor } from '@langfuse/otel';
260
import { setLangfuseTracerProvider } from '@langfuse/tracing';
261
262
const provider = new NodeTracerProvider({
263
resource: new Resource({
264
[SemanticResourceAttributes.SERVICE_NAME]: 'my-ai-service',
265
[SemanticResourceAttributes.SERVICE_VERSION]: '1.2.3',
266
[SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]: process.env.NODE_ENV,
267
'custom.attribute': 'custom-value'
268
}),
269
spanProcessors: [
270
new LangfuseSpanProcessor({
271
publicKey: process.env.LANGFUSE_PUBLIC_KEY,
272
secretKey: process.env.LANGFUSE_SECRET_KEY
273
})
274
]
275
});
276
277
setLangfuseTracerProvider(provider);
278
```
279
280
### Graceful Shutdown
281
282
Properly shutdown tracer provider on application exit.
283
284
```typescript
285
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
286
import { LangfuseSpanProcessor } from '@langfuse/otel';
287
import { setLangfuseTracerProvider, getLangfuseTracerProvider } from '@langfuse/tracing';
288
289
const provider = new NodeTracerProvider({
290
spanProcessors: [
291
new LangfuseSpanProcessor({
292
publicKey: process.env.LANGFUSE_PUBLIC_KEY,
293
secretKey: process.env.LANGFUSE_SECRET_KEY
294
})
295
]
296
});
297
298
setLangfuseTracerProvider(provider);
299
300
// Graceful shutdown
301
async function shutdown() {
302
const provider = getLangfuseTracerProvider();
303
304
if (provider && 'shutdown' in provider) {
305
await (provider as NodeTracerProvider).shutdown();
306
console.log('Tracer provider shut down successfully');
307
}
308
}
309
310
// Register shutdown handlers
311
process.on('SIGTERM', async () => {
312
await shutdown();
313
process.exit(0);
314
});
315
316
process.on('SIGINT', async () => {
317
await shutdown();
318
process.exit(0);
319
});
320
```
321
322
### Testing Configuration
323
324
Configure different providers for testing environments.
325
326
```typescript
327
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
328
import { InMemorySpanExporter, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base';
329
import { LangfuseSpanProcessor } from '@langfuse/otel';
330
import { setLangfuseTracerProvider } from '@langfuse/tracing';
331
332
function setupTracingForTesting() {
333
if (process.env.NODE_ENV === 'test') {
334
// Use in-memory exporter for tests
335
const exporter = new InMemorySpanExporter();
336
const provider = new NodeTracerProvider({
337
spanProcessors: [new SimpleSpanProcessor(exporter)]
338
});
339
340
setLangfuseTracerProvider(provider);
341
342
// Return exporter for assertions in tests
343
return exporter;
344
} else {
345
// Production configuration
346
const provider = new NodeTracerProvider({
347
spanProcessors: [
348
new LangfuseSpanProcessor({
349
publicKey: process.env.LANGFUSE_PUBLIC_KEY,
350
secretKey: process.env.LANGFUSE_SECRET_KEY
351
})
352
]
353
});
354
355
setLangfuseTracerProvider(provider);
356
return null;
357
}
358
}
359
360
const testExporter = setupTracingForTesting();
361
362
// In tests
363
if (testExporter) {
364
const spans = testExporter.getFinishedSpans();
365
// Assert on captured spans
366
}
367
```
368
369
## Advanced Patterns
370
371
### Provider Registry
372
373
Manage multiple tracer providers for different purposes.
374
375
```typescript
376
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
377
import { LangfuseSpanProcessor } from '@langfuse/otel';
378
import { setLangfuseTracerProvider } from '@langfuse/tracing';
379
380
class TracerProviderRegistry {
381
private providers: Map<string, NodeTracerProvider> = new Map();
382
383
register(name: string, provider: NodeTracerProvider) {
384
this.providers.set(name, provider);
385
}
386
387
get(name: string): NodeTracerProvider | undefined {
388
return this.providers.get(name);
389
}
390
391
async shutdownAll() {
392
for (const [name, provider] of this.providers) {
393
await provider.shutdown();
394
console.log(`Shutdown provider: ${name}`);
395
}
396
}
397
}
398
399
const registry = new TracerProviderRegistry();
400
401
// Register Langfuse provider
402
const langfuseProvider = new NodeTracerProvider({
403
spanProcessors: [new LangfuseSpanProcessor()]
404
});
405
registry.register('langfuse', langfuseProvider);
406
setLangfuseTracerProvider(langfuseProvider);
407
408
// Shutdown all on exit
409
process.on('SIGTERM', async () => {
410
await registry.shutdownAll();
411
});
412
```
413
414
### Dynamic Provider Switching
415
416
Switch tracer providers based on runtime conditions.
417
418
```typescript
419
import { getLangfuseTracerProvider, setLangfuseTracerProvider } from '@langfuse/tracing';
420
421
let currentProvider: NodeTracerProvider | null = null;
422
423
async function switchProvider(config: {
424
publicKey: string;
425
secretKey: string;
426
baseUrl?: string;
427
}) {
428
// Shutdown current provider
429
if (currentProvider) {
430
await currentProvider.shutdown();
431
}
432
433
// Create new provider
434
const provider = new NodeTracerProvider({
435
spanProcessors: [
436
new LangfuseSpanProcessor({
437
publicKey: config.publicKey,
438
secretKey: config.secretKey,
439
baseUrl: config.baseUrl
440
})
441
]
442
});
443
444
setLangfuseTracerProvider(provider);
445
currentProvider = provider;
446
447
console.log('Switched to new tracer provider');
448
}
449
450
// Switch providers at runtime
451
await switchProvider({
452
publicKey: process.env.NEW_PUBLIC_KEY,
453
secretKey: process.env.NEW_SECRET_KEY
454
});
455
```
456
457
## Context Sharing Limitation
458
459
The isolated tracer provider shares OpenTelemetry context with the global provider.
460
461
```typescript
462
import { trace } from '@opentelemetry/api';
463
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
464
import { setLangfuseTracerProvider } from '@langfuse/tracing';
465
import { startObservation } from '@langfuse/tracing';
466
467
// Setup isolated Langfuse provider
468
const langfuseProvider = new NodeTracerProvider();
469
setLangfuseTracerProvider(langfuseProvider);
470
471
// Setup global provider
472
const globalProvider = new NodeTracerProvider();
473
trace.setGlobalTracerProvider(globalProvider);
474
475
// Create global span
476
const globalTracer = trace.getTracer('global');
477
const globalSpan = globalTracer.startSpan('global-operation');
478
479
// Set global span as active
480
const ctx = trace.setSpan(trace.context.active(), globalSpan);
481
482
// Langfuse span created within global span context
483
trace.context.with(ctx, () => {
484
// This Langfuse span inherits the trace ID from globalSpan
485
const langfuseSpan = startObservation('langfuse-operation');
486
console.log('Same trace ID:', langfuseSpan.traceId === globalSpan.spanContext().traceId);
487
langfuseSpan.end();
488
});
489
490
globalSpan.end();
491
```
492
493
## Best Practices
494
495
### Initialize Early
496
497
Set up the tracer provider early in application lifecycle, before creating any observations.
498
499
```typescript
500
// app.ts or index.ts
501
import { initializeLangfuseTracing } from './tracing-setup';
502
503
// Initialize before any imports that use tracing
504
initializeLangfuseTracing();
505
506
// Now import and use application code
507
import { startServer } from './server';
508
startServer();
509
```
510
511
### Single Provider Instance
512
513
Create only one tracer provider instance for Langfuse in your application.
514
515
```typescript
516
// tracing-config.ts
517
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
518
import { LangfuseSpanProcessor } from '@langfuse/otel';
519
import { setLangfuseTracerProvider } from '@langfuse/tracing';
520
521
let providerInitialized = false;
522
523
export function initializeLangfuseTracing() {
524
if (providerInitialized) {
525
console.warn('Langfuse tracer provider already initialized');
526
return;
527
}
528
529
const provider = new NodeTracerProvider({
530
spanProcessors: [new LangfuseSpanProcessor()]
531
});
532
533
setLangfuseTracerProvider(provider);
534
providerInitialized = true;
535
}
536
```
537
538
### Configuration Validation
539
540
Validate configuration before creating provider.
541
542
```typescript
543
function validateConfig() {
544
const required = ['LANGFUSE_PUBLIC_KEY', 'LANGFUSE_SECRET_KEY'];
545
const missing = required.filter(key => !process.env[key]);
546
547
if (missing.length > 0) {
548
throw new Error(`Missing required env vars: ${missing.join(', ')}`);
549
}
550
}
551
552
try {
553
validateConfig();
554
555
const provider = new NodeTracerProvider({
556
spanProcessors: [
557
new LangfuseSpanProcessor({
558
publicKey: process.env.LANGFUSE_PUBLIC_KEY!,
559
secretKey: process.env.LANGFUSE_SECRET_KEY!
560
})
561
]
562
});
563
564
setLangfuseTracerProvider(provider);
565
} catch (error) {
566
console.error('Failed to initialize Langfuse tracing:', error);
567
// Decide whether to exit or continue without tracing
568
}
569
```
570
571
### Proper Cleanup
572
573
Always register shutdown handlers for tracer providers.
574
575
```typescript
576
import { getLangfuseTracerProvider } from '@langfuse/tracing';
577
578
async function gracefulShutdown(signal: string) {
579
console.log(`Received ${signal}, shutting down gracefully`);
580
581
const provider = getLangfuseTracerProvider();
582
if (provider && 'shutdown' in provider) {
583
try {
584
await (provider as NodeTracerProvider).shutdown();
585
console.log('Tracer provider shut down successfully');
586
} catch (error) {
587
console.error('Error shutting down tracer provider:', error);
588
}
589
}
590
591
process.exit(0);
592
}
593
594
process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
595
process.on('SIGINT', () => gracefulShutdown('SIGINT'));
596
```
597