0
# Tracing
1
2
Comprehensive tracing capabilities for observability in LLM applications. Langfuse provides hierarchical tracing with traces containing nested spans, generations (LLM calls), and events. All client classes are chainable for fluent API composition.
3
4
## Capabilities
5
6
### Creating Traces
7
8
The primary method for creating a new trace.
9
10
```typescript { .api }
11
/**
12
* Creates a new trace
13
* @param body - Optional trace configuration
14
* @returns Trace client for chaining operations
15
*/
16
trace(body?: CreateLangfuseTraceBody): LangfuseTraceClient;
17
18
interface CreateLangfuseTraceBody {
19
/** Custom trace ID */
20
id?: string;
21
/** Trace name */
22
name?: string;
23
/** Timestamp (defaults to now) */
24
timestamp?: Date | string;
25
/** Input data */
26
input?: any;
27
/** Output data */
28
output?: any;
29
/** Session ID for grouping related traces */
30
sessionId?: string;
31
/** User ID */
32
userId?: string;
33
/** Custom metadata */
34
metadata?: any;
35
/** Tags for filtering */
36
tags?: string[];
37
/** Release version */
38
release?: string;
39
/** Version identifier */
40
version?: string;
41
/** Make trace publicly accessible */
42
public?: boolean;
43
/** Environment name */
44
environment?: string;
45
}
46
```
47
48
**Usage Example:**
49
50
```typescript
51
import { Langfuse } from 'langfuse';
52
53
const langfuse = new Langfuse();
54
55
const trace = langfuse.trace({
56
name: 'chat-pipeline',
57
userId: 'user-123',
58
sessionId: 'session-456',
59
metadata: { platform: 'web' },
60
tags: ['production', 'chat'],
61
input: { message: 'Hello!' }
62
});
63
```
64
65
### LangfuseTraceClient
66
67
Client for interacting with a trace. Provides methods for updating the trace and creating child observations.
68
69
```typescript { .api }
70
class LangfuseTraceClient {
71
/** The parent Langfuse client */
72
client: LangfuseCore;
73
/** The trace ID */
74
id: string;
75
/** The trace ID (alias for id) */
76
traceId: string;
77
/** Always null for trace clients */
78
observationId: null;
79
80
/**
81
* Updates the trace with new data
82
* @param body - Trace update body (omit id)
83
* @returns This trace client for chaining
84
*/
85
update(body: Omit<CreateLangfuseTraceBody, "id">): this;
86
87
/**
88
* Creates a child span
89
* @param body - Span configuration (traceId and parentObservationId are auto-set)
90
* @returns Span client for chaining
91
*/
92
span(body: Omit<CreateLangfuseSpanBody, "traceId" | "parentObservationId">): LangfuseSpanClient;
93
94
/**
95
* Creates a child generation (LLM call)
96
* @param body - Generation configuration
97
* @returns Generation client for chaining
98
*/
99
generation(
100
body: Omit<CreateLangfuseGenerationBody, "traceId" | "parentObservationId" | "promptName" | "promptVersion"> & PromptInput
101
): LangfuseGenerationClient;
102
103
/**
104
* Creates a child event
105
* @param body - Event configuration
106
* @returns Event client for chaining
107
*/
108
event(body: Omit<CreateLangfuseEventBody, "traceId" | "parentObservationId">): LangfuseEventClient;
109
110
/**
111
* Adds a score to the trace
112
* @param body - Score configuration (traceId is auto-set)
113
* @returns This trace client for chaining
114
*/
115
score(body: Omit<CreateLangfuseScoreBody, "traceId" | "observationId">): this;
116
117
/**
118
* Returns the URL to view the trace in Langfuse UI
119
* @returns Trace URL
120
*/
121
getTraceUrl(): string;
122
}
123
```
124
125
**Usage Example:**
126
127
```typescript
128
const trace = langfuse.trace({ name: 'my-app' });
129
130
// Update trace with output
131
trace.update({
132
output: { success: true },
133
metadata: { duration: 1234 }
134
});
135
136
// Add a score
137
trace.score({
138
name: 'user-feedback',
139
value: 5,
140
comment: 'Excellent response'
141
});
142
143
// Get trace URL
144
console.log(trace.getTraceUrl());
145
```
146
147
### Creating Spans
148
149
Spans represent units of work within a trace (e.g., a function call, API request, or processing step).
150
151
```typescript { .api }
152
/**
153
* Creates a span observation
154
* @param body - Span configuration with traceId
155
* @returns Span client for chaining operations
156
*/
157
span(body: CreateLangfuseSpanBody): LangfuseSpanClient;
158
159
interface CreateLangfuseSpanBody {
160
/** Custom span ID */
161
id?: string;
162
/** Parent trace ID (required) */
163
traceId?: string;
164
/** Parent observation ID for nesting */
165
parentObservationId?: string;
166
/** Span name */
167
name?: string;
168
/** Start timestamp (defaults to now) */
169
startTime?: Date | string;
170
/** End timestamp */
171
endTime?: Date | string;
172
/** Custom metadata */
173
metadata?: any;
174
/** Input data */
175
input?: any;
176
/** Output data */
177
output?: any;
178
/** Log level: DEBUG, DEFAULT, WARNING, ERROR */
179
level?: ApiObservationLevel;
180
/** Status message */
181
statusMessage?: string;
182
/** Version identifier */
183
version?: string;
184
}
185
```
186
187
**Usage Example:**
188
189
```typescript
190
// Create span from trace
191
const span = trace.span({
192
name: 'data-processing',
193
input: { records: 100 },
194
metadata: { source: 'database' }
195
});
196
197
// Or create standalone span
198
const span2 = langfuse.span({
199
traceId: 'trace-123',
200
name: 'api-call'
201
});
202
```
203
204
### LangfuseSpanClient
205
206
Client for interacting with a span observation. Supports nesting and updating.
207
208
```typescript { .api }
209
class LangfuseSpanClient {
210
/** The parent Langfuse client */
211
client: LangfuseCore;
212
/** The span ID */
213
id: string;
214
/** The parent trace ID */
215
traceId: string;
216
/** The span ID (alias for id) */
217
observationId: string;
218
219
/**
220
* Updates the span with new data
221
* @param body - Span update body
222
* @returns This span client for chaining
223
*/
224
update(body: Omit<UpdateLangfuseSpanBody, "id" | "traceId">): this;
225
226
/**
227
* Ends the span by setting endTime to now
228
* @param body - Optional data to update when ending
229
* @returns This span client for chaining
230
*/
231
end(body?: Omit<UpdateLangfuseSpanBody, "id" | "endTime" | "traceId">): this;
232
233
/**
234
* Creates a nested span
235
* @param body - Span configuration
236
* @returns Nested span client
237
*/
238
span(body: Omit<CreateLangfuseSpanBody, "traceId" | "parentObservationId">): LangfuseSpanClient;
239
240
/**
241
* Creates a nested generation
242
* @param body - Generation configuration
243
* @returns Nested generation client
244
*/
245
generation(
246
body: Omit<CreateLangfuseGenerationBody, "traceId" | "parentObservationId" | "promptName" | "promptVersion"> & PromptInput
247
): LangfuseGenerationClient;
248
249
/**
250
* Creates a nested event
251
* @param body - Event configuration
252
* @returns Nested event client
253
*/
254
event(body: Omit<CreateLangfuseEventBody, "traceId" | "parentObservationId">): LangfuseEventClient;
255
256
/**
257
* Adds a score to the span
258
* @param body - Score configuration
259
* @returns This span client for chaining
260
*/
261
score(body: Omit<CreateLangfuseScoreBody, "traceId" | "observationId">): this;
262
263
/**
264
* Returns the URL to view the parent trace in Langfuse UI
265
* @returns Trace URL
266
*/
267
getTraceUrl(): string;
268
}
269
270
interface UpdateLangfuseSpanBody {
271
id?: string;
272
traceId?: string;
273
parentObservationId?: string;
274
name?: string;
275
startTime?: Date | string;
276
endTime?: Date | string;
277
metadata?: any;
278
input?: any;
279
output?: any;
280
level?: ApiObservationLevel;
281
statusMessage?: string;
282
version?: string;
283
}
284
```
285
286
**Usage Example:**
287
288
```typescript
289
const span = trace.span({ name: 'process-data' });
290
291
// Update span with results
292
span.update({
293
output: { processed: 100 },
294
metadata: { duration: 500 }
295
});
296
297
// End the span
298
span.end({ statusMessage: 'completed' });
299
300
// Create nested span
301
const nestedSpan = span.span({ name: 'sub-process' });
302
```
303
304
### Creating Generations
305
306
Generations represent LLM calls with token usage tracking and model information.
307
308
```typescript { .api }
309
/**
310
* Creates a generation observation (LLM call)
311
* @param body - Generation configuration
312
* @returns Generation client for chaining operations
313
*/
314
generation(body: CreateLangfuseGenerationBody): LangfuseGenerationClient;
315
316
interface CreateLangfuseGenerationBody extends CreateLangfuseSpanBody {
317
/** Model name (e.g., gpt-4, claude-3-opus) */
318
model?: string;
319
/** Model parameters (temperature, max_tokens, etc.) */
320
modelParameters?: any;
321
/** Token usage information */
322
usage?: Usage;
323
/** Detailed usage information with provider-specific schemas (OpenAI, etc.) */
324
usageDetails?: UsageDetails;
325
/** When completion started (for streaming) */
326
completionStartTime?: Date | string;
327
}
328
329
interface Usage {
330
/** Input tokens */
331
input?: number;
332
/** Output tokens */
333
output?: number;
334
/** Total tokens */
335
total?: number;
336
/** Usage unit (TOKENS, CHARACTERS, etc.) */
337
unit?: ApiModelUsageUnit;
338
/** Input cost in USD */
339
inputCost?: number;
340
/** Output cost in USD */
341
outputCost?: number;
342
/** Total cost in USD */
343
totalCost?: number;
344
}
345
346
type ApiModelUsageUnit =
347
| "CHARACTERS"
348
| "TOKENS"
349
| "MILLISECONDS"
350
| "SECONDS"
351
| "IMAGES"
352
| "REQUESTS";
353
354
type UsageDetails =
355
| { [key: string]: number }
356
| OpenAICompletionUsageSchema
357
| OpenAIResponseUsageSchema;
358
359
interface OpenAICompletionUsageSchema {
360
completion_tokens?: number;
361
prompt_tokens?: number;
362
total_tokens?: number;
363
}
364
365
interface OpenAIResponseUsageSchema {
366
completion_tokens?: number;
367
prompt_tokens?: number;
368
total_tokens?: number;
369
completion_tokens_details?: {
370
reasoning_tokens?: number;
371
accepted_prediction_tokens?: number;
372
rejected_prediction_tokens?: number;
373
};
374
prompt_tokens_details?: {
375
cached_tokens?: number;
376
audio_tokens?: number;
377
};
378
}
379
```
380
381
**Usage Example:**
382
383
```typescript
384
const generation = trace.generation({
385
name: 'chat-completion',
386
model: 'gpt-4',
387
input: [
388
{ role: 'system', content: 'You are a helpful assistant' },
389
{ role: 'user', content: 'Hello!' }
390
],
391
output: {
392
role: 'assistant',
393
content: 'Hi! How can I help you?'
394
},
395
usage: {
396
input: 25,
397
output: 15,
398
total: 40
399
},
400
modelParameters: {
401
temperature: 0.7,
402
max_tokens: 500
403
}
404
});
405
```
406
407
### LangfuseGenerationClient
408
409
Client for interacting with a generation observation. Includes prompt linking support.
410
411
```typescript { .api }
412
class LangfuseGenerationClient {
413
/** The parent Langfuse client */
414
client: LangfuseCore;
415
/** The generation ID */
416
id: string;
417
/** The parent trace ID */
418
traceId: string;
419
/** The generation ID (alias for id) */
420
observationId: string;
421
422
/**
423
* Updates the generation with new data
424
* @param body - Generation update body
425
* @returns This generation client for chaining
426
*/
427
update(
428
body: Omit<UpdateLangfuseGenerationBody, "id" | "traceId" | "promptName" | "promptVersion"> & PromptInput
429
): this;
430
431
/**
432
* Ends the generation by setting endTime to now
433
* @param body - Optional data to update when ending
434
* @returns This generation client for chaining
435
*/
436
end(
437
body?: Omit<UpdateLangfuseGenerationBody, "id" | "traceId" | "endTime" | "promptName" | "promptVersion"> & PromptInput
438
): this;
439
440
/**
441
* Creates a nested span
442
* @param body - Span configuration
443
* @returns Nested span client
444
*/
445
span(body: Omit<CreateLangfuseSpanBody, "traceId" | "parentObservationId">): LangfuseSpanClient;
446
447
/**
448
* Creates a nested generation
449
* @param body - Generation configuration
450
* @returns Nested generation client
451
*/
452
generation(
453
body: Omit<CreateLangfuseGenerationBody, "traceId" | "parentObservationId" | "promptName" | "promptVersion"> & PromptInput
454
): LangfuseGenerationClient;
455
456
/**
457
* Creates a nested event
458
* @param body - Event configuration
459
* @returns Nested event client
460
*/
461
event(body: Omit<CreateLangfuseEventBody, "traceId" | "parentObservationId">): LangfuseEventClient;
462
463
/**
464
* Adds a score to the generation
465
* @param body - Score configuration
466
* @returns This generation client for chaining
467
*/
468
score(body: Omit<CreateLangfuseScoreBody, "traceId" | "observationId">): this;
469
470
/**
471
* Returns the URL to view the parent trace in Langfuse UI
472
* @returns Trace URL
473
*/
474
getTraceUrl(): string;
475
}
476
477
interface UpdateLangfuseGenerationBody extends UpdateLangfuseSpanBody {
478
model?: string;
479
modelParameters?: any;
480
usage?: Usage;
481
completionStartTime?: Date | string;
482
}
483
484
interface PromptInput {
485
/** Link to a prompt client or record for automatic tracking */
486
prompt?: LangfusePromptClient | LangfusePromptRecord;
487
}
488
```
489
490
**Usage Example:**
491
492
```typescript
493
const generation = trace.generation({
494
name: 'gpt-call',
495
model: 'gpt-4'
496
});
497
498
// Stream response and update incrementally
499
generation.update({
500
output: partialResponse,
501
usage: { input: 25, output: 10 }
502
});
503
504
// Complete the generation
505
generation.end({
506
output: finalResponse,
507
usage: { input: 25, output: 50, total: 75 },
508
statusMessage: 'completed'
509
});
510
511
// Link a prompt
512
const promptClient = await langfuse.getPrompt('chat-template');
513
const gen = trace.generation({
514
name: 'templated-chat',
515
prompt: promptClient,
516
model: 'gpt-4'
517
});
518
```
519
520
### Creating Events
521
522
Events represent single-point observations (e.g., logs, errors, or notable occurrences).
523
524
```typescript { .api }
525
/**
526
* Creates an event observation
527
* @param body - Event configuration
528
* @returns Event client for chaining operations
529
*/
530
event(body: CreateLangfuseEventBody): LangfuseEventClient;
531
532
interface CreateLangfuseEventBody {
533
/** Custom event ID */
534
id?: string;
535
/** Parent trace ID */
536
traceId?: string;
537
/** Parent observation ID for nesting */
538
parentObservationId?: string;
539
/** Event name */
540
name?: string;
541
/** Timestamp (defaults to now) */
542
startTime?: Date | string;
543
/** Custom metadata */
544
metadata?: any;
545
/** Input data */
546
input?: any;
547
/** Output data */
548
output?: any;
549
/** Log level: DEBUG, DEFAULT, WARNING, ERROR */
550
level?: ApiObservationLevel;
551
/** Status message */
552
statusMessage?: string;
553
/** Version identifier */
554
version?: string;
555
}
556
557
type ApiObservationLevel = "DEBUG" | "DEFAULT" | "WARNING" | "ERROR";
558
```
559
560
**Usage Example:**
561
562
```typescript
563
// Create event from trace
564
const event = trace.event({
565
name: 'user-input-received',
566
input: { query: 'What is AI?' },
567
level: 'DEFAULT'
568
});
569
570
// Create error event
571
trace.event({
572
name: 'api-error',
573
level: 'ERROR',
574
statusMessage: 'Rate limit exceeded',
575
metadata: { errorCode: 429 }
576
});
577
```
578
579
### LangfuseEventClient
580
581
Client for interacting with an event observation. Events can also have nested observations.
582
583
```typescript { .api }
584
class LangfuseEventClient {
585
/** The parent Langfuse client */
586
client: LangfuseCore;
587
/** The event ID */
588
id: string;
589
/** The parent trace ID */
590
traceId: string;
591
/** The event ID (alias for id) */
592
observationId: string;
593
594
/**
595
* Creates a nested span
596
* @param body - Span configuration
597
* @returns Nested span client
598
*/
599
span(body: Omit<CreateLangfuseSpanBody, "traceId" | "parentObservationId">): LangfuseSpanClient;
600
601
/**
602
* Creates a nested generation
603
* @param body - Generation configuration
604
* @returns Nested generation client
605
*/
606
generation(
607
body: Omit<CreateLangfuseGenerationBody, "traceId" | "parentObservationId" | "promptName" | "promptVersion"> & PromptInput
608
): LangfuseGenerationClient;
609
610
/**
611
* Creates a nested event
612
* @param body - Event configuration
613
* @returns Nested event client
614
*/
615
event(body: Omit<CreateLangfuseEventBody, "traceId" | "parentObservationId">): LangfuseEventClient;
616
617
/**
618
* Adds a score to the event
619
* @param body - Score configuration
620
* @returns This event client for chaining
621
*/
622
score(body: Omit<CreateLangfuseScoreBody, "traceId" | "observationId">): this;
623
624
/**
625
* Returns the URL to view the parent trace in Langfuse UI
626
* @returns Trace URL
627
*/
628
getTraceUrl(): string;
629
}
630
```
631
632
### Creating Scores
633
634
Scores evaluate traces or observations with numeric, boolean, or categorical values.
635
636
```typescript { .api }
637
/**
638
* Creates a score for a trace or observation
639
* @param body - Score configuration
640
* @returns Langfuse instance for chaining
641
*/
642
score(body: CreateLangfuseScoreBody): this;
643
644
interface CreateLangfuseScoreBody {
645
/** Custom score ID */
646
id?: string;
647
/** Trace ID to score */
648
traceId: string;
649
/** Observation ID to score (if scoring an observation) */
650
observationId?: string;
651
/** Score name */
652
name: string;
653
/** Score value */
654
value: number | string | boolean;
655
/** Optional comment */
656
comment?: string;
657
/** Data type: NUMERIC, BOOLEAN, CATEGORICAL */
658
dataType?: ApiScoreDataType;
659
/** Score configuration ID */
660
configId?: string;
661
}
662
663
type ApiScoreDataType = "NUMERIC" | "BOOLEAN" | "CATEGORICAL";
664
```
665
666
**Usage Example:**
667
668
```typescript
669
// Score a trace
670
langfuse.score({
671
traceId: 'trace-123',
672
name: 'quality',
673
value: 0.95,
674
dataType: 'NUMERIC',
675
comment: 'High quality response'
676
});
677
678
// Score from trace client
679
trace.score({
680
name: 'user-satisfaction',
681
value: 5,
682
dataType: 'NUMERIC'
683
});
684
685
// Score an observation
686
generation.score({
687
name: 'accuracy',
688
value: true,
689
dataType: 'BOOLEAN'
690
});
691
```
692
693
### Fetching Traces and Observations
694
695
Retrieve existing traces and observations for analysis.
696
697
```typescript { .api }
698
/**
699
* Fetches traces with optional filtering
700
* @param query - Filter and pagination options
701
* @returns Paginated traces response
702
*/
703
fetchTraces(query?: GetLangfuseTracesQuery): Promise<GetLangfuseTracesResponse>;
704
705
/**
706
* Fetches a specific trace by ID
707
* @param traceId - Trace identifier
708
* @returns Trace with full details
709
*/
710
fetchTrace(traceId: string): Promise<{ data: GetLangfuseTraceResponse }>;
711
712
/**
713
* Fetches observations with optional filtering
714
* @param query - Filter and pagination options
715
* @returns Paginated observations response
716
*/
717
fetchObservations(query?: GetLangfuseObservationsQuery): Promise<GetLangfuseObservationsResponse>;
718
719
/**
720
* Fetches a specific observation by ID
721
* @param observationId - Observation identifier
722
* @returns Observation details
723
*/
724
fetchObservation(observationId: string): Promise<{ data: GetLangfuseObservationResponse }>;
725
726
/**
727
* Fetches sessions with optional filtering
728
* @param query - Filter and pagination options
729
* @returns Paginated sessions response
730
*/
731
fetchSessions(query?: GetLangfuseSessionsQuery): Promise<GetLangfuseSessionsResponse>;
732
733
interface GetLangfuseTracesQuery {
734
/** Page number */
735
page?: number;
736
/** Page size */
737
limit?: number;
738
/** Filter by user ID */
739
userId?: string;
740
/** Filter by trace name */
741
name?: string;
742
/** Filter by session ID */
743
sessionId?: string;
744
/** From timestamp (ISO 8601) */
745
fromTimestamp?: string;
746
/** To timestamp (ISO 8601) */
747
toTimestamp?: string;
748
/** Sort field */
749
orderBy?: string;
750
/** Filter by tags */
751
tags?: string[];
752
/** Filter by version */
753
version?: string;
754
}
755
756
interface GetLangfuseTracesResponse {
757
/** Array of traces */
758
data: ApiTraceWithDetails[];
759
/** Pagination metadata */
760
meta: {
761
page: number;
762
limit: number;
763
totalItems: number;
764
totalPages: number;
765
};
766
}
767
768
interface GetLangfuseObservationsQuery {
769
page?: number;
770
limit?: number;
771
userId?: string;
772
name?: string;
773
traceId?: string;
774
parentObservationId?: string;
775
fromStartTime?: string;
776
toStartTime?: string;
777
type?: ApiObservationType;
778
}
779
780
type ApiObservationType = "SPAN" | "GENERATION" | "EVENT";
781
782
interface GetLangfuseObservationsResponse {
783
data: ApiObservation[];
784
meta: {
785
page: number;
786
limit: number;
787
totalItems: number;
788
totalPages: number;
789
};
790
}
791
792
interface GetLangfuseSessionsQuery {
793
page?: number;
794
limit?: number;
795
fromTimestamp?: string;
796
toTimestamp?: string;
797
}
798
799
interface GetLangfuseSessionsResponse {
800
data: ApiSession[];
801
meta: {
802
page: number;
803
limit: number;
804
totalItems: number;
805
totalPages: number;
806
};
807
}
808
```
809
810
**Usage Example:**
811
812
```typescript
813
// Fetch recent traces
814
const traces = await langfuse.fetchTraces({
815
page: 1,
816
limit: 50,
817
userId: 'user-123',
818
tags: ['production']
819
});
820
821
// Fetch specific trace
822
const trace = await langfuse.fetchTrace('trace-id-123');
823
824
// Fetch observations for a trace
825
const observations = await langfuse.fetchObservations({
826
traceId: 'trace-id-123',
827
type: 'GENERATION'
828
});
829
```
830
831
## Complete Tracing Example
832
833
```typescript
834
import { Langfuse } from 'langfuse';
835
836
const langfuse = new Langfuse({
837
publicKey: 'pk-lf-...',
838
secretKey: 'sk-lf-...'
839
});
840
841
// Create a trace for a chat pipeline
842
const trace = langfuse.trace({
843
name: 'chat-pipeline',
844
userId: 'user-123',
845
sessionId: 'session-456',
846
tags: ['production']
847
});
848
849
// Add a span for retrieval
850
const retrievalSpan = trace.span({
851
name: 'document-retrieval',
852
input: { query: 'What is AI?' }
853
});
854
855
// Simulate retrieval
856
retrievalSpan.end({
857
output: { documents: [/* ... */] },
858
metadata: { count: 5 }
859
});
860
861
// Add a generation for LLM call
862
const generation = trace.generation({
863
name: 'answer-generation',
864
model: 'gpt-4',
865
input: [
866
{ role: 'system', content: 'You are a helpful assistant' },
867
{ role: 'user', content: 'What is AI?' }
868
],
869
modelParameters: {
870
temperature: 0.7,
871
max_tokens: 500
872
}
873
});
874
875
// Update with response
876
generation.end({
877
output: {
878
role: 'assistant',
879
content: 'AI is...'
880
},
881
usage: {
882
input: 150,
883
output: 200,
884
total: 350
885
}
886
});
887
888
// Add a score
889
trace.score({
890
name: 'user-feedback',
891
value: 5,
892
comment: 'Very helpful'
893
});
894
895
// Flush to send all events
896
await langfuse.flushAsync();
897
898
// Get trace URL
899
console.log(trace.getTraceUrl());
900
```
901