or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

active-observations.mdattribute-creation.mdcontext-management.mdindex.mdmanual-observations.mdobservation-types.mdobserve-decorator.mdotel-span-attributes.mdtrace-id-generation.mdtracer-provider.md

tracer-provider.mddocs/

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