0
# Constants and OpenTelemetry Attributes
1
2
SDK identifiers and standardized OpenTelemetry span attribute keys for integrating Langfuse tracing with OpenTelemetry instrumentation.
3
4
## Capabilities
5
6
### SDK Constants
7
8
Core constants identifying the Langfuse SDK and tracer.
9
10
```typescript { .api }
11
const LANGFUSE_TRACER_NAME: string;
12
const LANGFUSE_SDK_VERSION: string;
13
const LANGFUSE_SDK_NAME: string;
14
```
15
16
**Import:**
17
18
```typescript
19
import {
20
LANGFUSE_TRACER_NAME,
21
LANGFUSE_SDK_VERSION,
22
LANGFUSE_SDK_NAME
23
} from '@langfuse/core';
24
```
25
26
#### LANGFUSE_TRACER_NAME
27
28
The name identifier for the Langfuse tracer used in OpenTelemetry instrumentation.
29
30
```typescript { .api }
31
const LANGFUSE_TRACER_NAME: string; // Value: "langfuse-sdk"
32
```
33
34
**Usage Example:**
35
36
```typescript
37
import { trace } from '@opentelemetry/api';
38
import { LANGFUSE_TRACER_NAME } from '@langfuse/core';
39
40
const tracer = trace.getTracer(LANGFUSE_TRACER_NAME);
41
const span = tracer.startSpan('operation-name');
42
```
43
44
#### LANGFUSE_SDK_VERSION
45
46
The current version of the Langfuse SDK, dynamically loaded from package.json.
47
48
```typescript { .api }
49
const LANGFUSE_SDK_VERSION: string; // Value: "4.2.0" (current version)
50
```
51
52
**Usage Example:**
53
54
```typescript
55
import { LANGFUSE_SDK_VERSION } from '@langfuse/core';
56
57
console.log(`Langfuse SDK version: ${LANGFUSE_SDK_VERSION}`);
58
59
// Used in API client headers
60
const client = new LangfuseAPIClient({
61
environment: 'https://cloud.langfuse.com',
62
xLangfuseSdkVersion: LANGFUSE_SDK_VERSION
63
});
64
```
65
66
#### LANGFUSE_SDK_NAME
67
68
The platform/language identifier for the SDK.
69
70
```typescript { .api }
71
const LANGFUSE_SDK_NAME: string; // Value: "javascript"
72
```
73
74
**Usage Example:**
75
76
```typescript
77
import { LANGFUSE_SDK_NAME } from '@langfuse/core';
78
79
const client = new LangfuseAPIClient({
80
environment: 'https://cloud.langfuse.com',
81
xLangfuseSdkName: LANGFUSE_SDK_NAME
82
});
83
```
84
85
### OpenTelemetry Span Attributes
86
87
Standardized attribute keys for annotating OpenTelemetry spans with Langfuse trace and observation metadata.
88
89
```typescript { .api }
90
enum LangfuseOtelSpanAttributes {
91
// Trace attributes
92
TRACE_NAME = "langfuse.trace.name",
93
TRACE_USER_ID = "user.id",
94
TRACE_SESSION_ID = "session.id",
95
TRACE_TAGS = "langfuse.trace.tags",
96
TRACE_PUBLIC = "langfuse.trace.public",
97
TRACE_METADATA = "langfuse.trace.metadata",
98
TRACE_INPUT = "langfuse.trace.input",
99
TRACE_OUTPUT = "langfuse.trace.output",
100
101
// Observation attributes
102
OBSERVATION_TYPE = "langfuse.observation.type",
103
OBSERVATION_METADATA = "langfuse.observation.metadata",
104
OBSERVATION_LEVEL = "langfuse.observation.level",
105
OBSERVATION_STATUS_MESSAGE = "langfuse.observation.status_message",
106
OBSERVATION_INPUT = "langfuse.observation.input",
107
OBSERVATION_OUTPUT = "langfuse.observation.output",
108
109
// Generation attributes (for LLM generations)
110
OBSERVATION_COMPLETION_START_TIME = "langfuse.observation.completion_start_time",
111
OBSERVATION_MODEL = "langfuse.observation.model.name",
112
OBSERVATION_MODEL_PARAMETERS = "langfuse.observation.model.parameters",
113
OBSERVATION_USAGE_DETAILS = "langfuse.observation.usage_details",
114
OBSERVATION_COST_DETAILS = "langfuse.observation.cost_details",
115
OBSERVATION_PROMPT_NAME = "langfuse.observation.prompt.name",
116
OBSERVATION_PROMPT_VERSION = "langfuse.observation.prompt.version",
117
118
// General attributes
119
ENVIRONMENT = "langfuse.environment",
120
RELEASE = "langfuse.release",
121
VERSION = "langfuse.version",
122
123
// Internal attributes
124
AS_ROOT = "langfuse.internal.as_root",
125
126
// Compatibility attributes (legacy)
127
TRACE_COMPAT_USER_ID = "langfuse.user.id",
128
TRACE_COMPAT_SESSION_ID = "langfuse.session.id"
129
}
130
```
131
132
**Import:**
133
134
```typescript
135
import { LangfuseOtelSpanAttributes } from '@langfuse/core';
136
```
137
138
#### Trace Attributes
139
140
Attributes for trace-level metadata and lifecycle information.
141
142
```typescript { .api }
143
enum LangfuseOtelSpanAttributes {
144
TRACE_NAME = "langfuse.trace.name", // Name of the trace
145
TRACE_USER_ID = "user.id", // User identifier (OpenTelemetry standard)
146
TRACE_SESSION_ID = "session.id", // Session identifier (OpenTelemetry standard)
147
TRACE_TAGS = "langfuse.trace.tags", // Array of tags
148
TRACE_PUBLIC = "langfuse.trace.public", // Public visibility flag (boolean)
149
TRACE_METADATA = "langfuse.trace.metadata", // Trace metadata (JSON object)
150
TRACE_INPUT = "langfuse.trace.input", // Trace input data (JSON)
151
TRACE_OUTPUT = "langfuse.trace.output", // Trace output data (JSON)
152
}
153
```
154
155
**Usage Example:**
156
157
```typescript
158
import { trace } from '@opentelemetry/api';
159
import { LangfuseOtelSpanAttributes } from '@langfuse/core';
160
161
const span = tracer.startSpan('user-request');
162
163
// Set trace attributes
164
span.setAttribute(LangfuseOtelSpanAttributes.TRACE_NAME, 'chat-completion');
165
span.setAttribute(LangfuseOtelSpanAttributes.TRACE_USER_ID, 'user-123');
166
span.setAttribute(LangfuseOtelSpanAttributes.TRACE_SESSION_ID, 'session-456');
167
span.setAttribute(LangfuseOtelSpanAttributes.TRACE_TAGS, JSON.stringify(['production', 'api']));
168
span.setAttribute(LangfuseOtelSpanAttributes.TRACE_PUBLIC, false);
169
span.setAttribute(LangfuseOtelSpanAttributes.TRACE_METADATA, JSON.stringify({
170
region: 'us-east-1',
171
version: 'v2'
172
}));
173
span.setAttribute(LangfuseOtelSpanAttributes.TRACE_INPUT, JSON.stringify({
174
prompt: 'Hello, world!'
175
}));
176
span.setAttribute(LangfuseOtelSpanAttributes.TRACE_OUTPUT, JSON.stringify({
177
response: 'Hi there!'
178
}));
179
```
180
181
#### Observation Attributes
182
183
Attributes for observation-level metadata (spans, generations, events).
184
185
```typescript { .api }
186
enum LangfuseOtelSpanAttributes {
187
OBSERVATION_TYPE = "langfuse.observation.type", // Type (SPAN, GENERATION, EVENT, etc.)
188
OBSERVATION_METADATA = "langfuse.observation.metadata", // Observation metadata (JSON)
189
OBSERVATION_LEVEL = "langfuse.observation.level", // Level (DEBUG, DEFAULT, WARNING, ERROR)
190
OBSERVATION_STATUS_MESSAGE = "langfuse.observation.status_message", // Status message
191
OBSERVATION_INPUT = "langfuse.observation.input", // Input data (JSON)
192
OBSERVATION_OUTPUT = "langfuse.observation.output", // Output data (JSON)
193
}
194
```
195
196
**Usage Example:**
197
198
```typescript
199
import { LangfuseOtelSpanAttributes } from '@langfuse/core';
200
201
// Set observation attributes
202
span.setAttribute(LangfuseOtelSpanAttributes.OBSERVATION_TYPE, 'GENERATION');
203
span.setAttribute(LangfuseOtelSpanAttributes.OBSERVATION_LEVEL, 'DEFAULT');
204
span.setAttribute(LangfuseOtelSpanAttributes.OBSERVATION_METADATA, JSON.stringify({
205
retryCount: 0,
206
cacheHit: false
207
}));
208
span.setAttribute(LangfuseOtelSpanAttributes.OBSERVATION_INPUT, JSON.stringify({
209
messages: [{ role: 'user', content: 'Hello' }]
210
}));
211
span.setAttribute(LangfuseOtelSpanAttributes.OBSERVATION_OUTPUT, JSON.stringify({
212
message: { role: 'assistant', content: 'Hi!' }
213
}));
214
span.setAttribute(LangfuseOtelSpanAttributes.OBSERVATION_STATUS_MESSAGE, 'Success');
215
```
216
217
#### Generation Attributes
218
219
Specialized attributes for LLM generation observations.
220
221
```typescript { .api }
222
enum LangfuseOtelSpanAttributes {
223
OBSERVATION_COMPLETION_START_TIME = "langfuse.observation.completion_start_time", // ISO 8601 timestamp
224
OBSERVATION_MODEL = "langfuse.observation.model.name", // Model name (e.g., "gpt-4")
225
OBSERVATION_MODEL_PARAMETERS = "langfuse.observation.model.parameters", // Model parameters (JSON)
226
OBSERVATION_USAGE_DETAILS = "langfuse.observation.usage_details", // Usage metrics (JSON)
227
OBSERVATION_COST_DETAILS = "langfuse.observation.cost_details", // Cost metrics (JSON)
228
OBSERVATION_PROMPT_NAME = "langfuse.observation.prompt.name", // Prompt template name
229
OBSERVATION_PROMPT_VERSION = "langfuse.observation.prompt.version", // Prompt version number
230
}
231
```
232
233
**Usage Example:**
234
235
```typescript
236
import { LangfuseOtelSpanAttributes } from '@langfuse/core';
237
238
// LLM generation tracking
239
const generationSpan = tracer.startSpan('openai-completion');
240
241
generationSpan.setAttribute(LangfuseOtelSpanAttributes.OBSERVATION_TYPE, 'GENERATION');
242
generationSpan.setAttribute(LangfuseOtelSpanAttributes.OBSERVATION_MODEL, 'gpt-4-turbo');
243
generationSpan.setAttribute(LangfuseOtelSpanAttributes.OBSERVATION_COMPLETION_START_TIME,
244
new Date().toISOString()
245
);
246
247
// Model parameters
248
generationSpan.setAttribute(LangfuseOtelSpanAttributes.OBSERVATION_MODEL_PARAMETERS,
249
JSON.stringify({
250
temperature: 0.7,
251
max_tokens: 1000,
252
top_p: 1
253
})
254
);
255
256
// Usage tracking
257
generationSpan.setAttribute(LangfuseOtelSpanAttributes.OBSERVATION_USAGE_DETAILS,
258
JSON.stringify({
259
promptTokens: 50,
260
completionTokens: 100,
261
totalTokens: 150
262
})
263
);
264
265
// Cost tracking
266
generationSpan.setAttribute(LangfuseOtelSpanAttributes.OBSERVATION_COST_DETAILS,
267
JSON.stringify({
268
promptCost: 0.0005,
269
completionCost: 0.002,
270
totalCost: 0.0025
271
})
272
);
273
274
// Prompt tracking
275
generationSpan.setAttribute(LangfuseOtelSpanAttributes.OBSERVATION_PROMPT_NAME, 'chat-assistant');
276
generationSpan.setAttribute(LangfuseOtelSpanAttributes.OBSERVATION_PROMPT_VERSION, '3');
277
```
278
279
#### General Attributes
280
281
Environment and release identification attributes.
282
283
```typescript { .api }
284
enum LangfuseOtelSpanAttributes {
285
ENVIRONMENT = "langfuse.environment", // Environment identifier (e.g., "production")
286
RELEASE = "langfuse.release", // Release identifier (e.g., "v1.2.3")
287
VERSION = "langfuse.version", // Version identifier
288
}
289
```
290
291
**Usage Example:**
292
293
```typescript
294
import { LangfuseOtelSpanAttributes } from '@langfuse/core';
295
296
// Set environment and release
297
span.setAttribute(LangfuseOtelSpanAttributes.ENVIRONMENT, 'production');
298
span.setAttribute(LangfuseOtelSpanAttributes.RELEASE, 'v1.2.3');
299
span.setAttribute(LangfuseOtelSpanAttributes.VERSION, '2024.10');
300
```
301
302
**Note**: Environment identifiers must be lowercase alphanumeric with hyphens/underscores and cannot start with 'langfuse'.
303
304
#### Internal Attributes
305
306
Internal attributes for SDK implementation details.
307
308
```typescript { .api }
309
enum LangfuseOtelSpanAttributes {
310
AS_ROOT = "langfuse.internal.as_root", // Internal flag for root spans (boolean)
311
}
312
```
313
314
#### Compatibility Attributes
315
316
Legacy attribute keys for backward compatibility.
317
318
```typescript { .api }
319
enum LangfuseOtelSpanAttributes {
320
TRACE_COMPAT_USER_ID = "langfuse.user.id", // Legacy user ID attribute
321
TRACE_COMPAT_SESSION_ID = "langfuse.session.id", // Legacy session ID attribute
322
}
323
```
324
325
**Note**: Prefer the standard OpenTelemetry attributes (`TRACE_USER_ID`, `TRACE_SESSION_ID`) for new implementations.
326
327
## Usage Patterns
328
329
### Complete Trace Instrumentation
330
331
```typescript
332
import { trace } from '@opentelemetry/api';
333
import {
334
LANGFUSE_TRACER_NAME,
335
LangfuseOtelSpanAttributes
336
} from '@langfuse/core';
337
338
const tracer = trace.getTracer(LANGFUSE_TRACER_NAME);
339
340
async function handleUserRequest(userId: string, sessionId: string, input: any) {
341
const span = tracer.startSpan('user-request');
342
343
try {
344
// Set trace-level attributes
345
span.setAttribute(LangfuseOtelSpanAttributes.TRACE_NAME, 'user-chat-request');
346
span.setAttribute(LangfuseOtelSpanAttributes.TRACE_USER_ID, userId);
347
span.setAttribute(LangfuseOtelSpanAttributes.TRACE_SESSION_ID, sessionId);
348
span.setAttribute(LangfuseOtelSpanAttributes.TRACE_TAGS, JSON.stringify(['chat', 'api']));
349
span.setAttribute(LangfuseOtelSpanAttributes.TRACE_INPUT, JSON.stringify(input));
350
span.setAttribute(LangfuseOtelSpanAttributes.ENVIRONMENT, 'production');
351
span.setAttribute(LangfuseOtelSpanAttributes.RELEASE, 'v1.2.3');
352
353
// Process request...
354
const output = await processRequest(input);
355
356
span.setAttribute(LangfuseOtelSpanAttributes.TRACE_OUTPUT, JSON.stringify(output));
357
span.end();
358
359
return output;
360
} catch (error) {
361
span.recordException(error);
362
span.end();
363
throw error;
364
}
365
}
366
```
367
368
### LLM Generation Tracking
369
370
```typescript
371
import { trace } from '@opentelemetry/api';
372
import { LangfuseOtelSpanAttributes } from '@langfuse/core';
373
374
async function trackLLMGeneration(prompt: string) {
375
const tracer = trace.getTracer('langfuse-sdk');
376
const span = tracer.startSpan('llm-generation');
377
378
// Mark as generation type
379
span.setAttribute(LangfuseOtelSpanAttributes.OBSERVATION_TYPE, 'GENERATION');
380
span.setAttribute(LangfuseOtelSpanAttributes.OBSERVATION_MODEL, 'gpt-4');
381
span.setAttribute(LangfuseOtelSpanAttributes.OBSERVATION_COMPLETION_START_TIME,
382
new Date().toISOString()
383
);
384
385
// Model configuration
386
span.setAttribute(LangfuseOtelSpanAttributes.OBSERVATION_MODEL_PARAMETERS,
387
JSON.stringify({
388
temperature: 0.7,
389
max_tokens: 1000
390
})
391
);
392
393
// Input
394
span.setAttribute(LangfuseOtelSpanAttributes.OBSERVATION_INPUT,
395
JSON.stringify({ messages: [{ role: 'user', content: prompt }] })
396
);
397
398
try {
399
// Call LLM...
400
const response = await callOpenAI(prompt);
401
402
// Output
403
span.setAttribute(LangfuseOtelSpanAttributes.OBSERVATION_OUTPUT,
404
JSON.stringify({ message: response })
405
);
406
407
// Usage and cost
408
span.setAttribute(LangfuseOtelSpanAttributes.OBSERVATION_USAGE_DETAILS,
409
JSON.stringify({
410
promptTokens: response.usage.prompt_tokens,
411
completionTokens: response.usage.completion_tokens,
412
totalTokens: response.usage.total_tokens
413
})
414
);
415
416
span.setAttribute(LangfuseOtelSpanAttributes.OBSERVATION_COST_DETAILS,
417
JSON.stringify({
418
promptCost: response.usage.prompt_tokens * 0.00001,
419
completionCost: response.usage.completion_tokens * 0.00003,
420
totalCost: (response.usage.prompt_tokens * 0.00001) +
421
(response.usage.completion_tokens * 0.00003)
422
})
423
);
424
425
span.end();
426
return response;
427
} catch (error) {
428
span.setAttribute(LangfuseOtelSpanAttributes.OBSERVATION_LEVEL, 'ERROR');
429
span.setAttribute(LangfuseOtelSpanAttributes.OBSERVATION_STATUS_MESSAGE,
430
error.message
431
);
432
span.recordException(error);
433
span.end();
434
throw error;
435
}
436
}
437
```
438
439
### Nested Observations
440
441
```typescript
442
import { trace } from '@opentelemetry/api';
443
import { LangfuseOtelSpanAttributes } from '@langfuse/core';
444
445
const tracer = trace.getTracer('langfuse-sdk');
446
447
async function processWithSteps(input: any) {
448
// Root span (trace)
449
const rootSpan = tracer.startSpan('processing-pipeline');
450
rootSpan.setAttribute(LangfuseOtelSpanAttributes.TRACE_NAME, 'data-pipeline');
451
452
return trace.with(trace.setSpan(trace.active(), rootSpan), async () => {
453
// Child span 1
454
const retrieveSpan = tracer.startSpan('retrieve-data');
455
retrieveSpan.setAttribute(LangfuseOtelSpanAttributes.OBSERVATION_TYPE, 'SPAN');
456
const data = await retrieveData(input);
457
retrieveSpan.end();
458
459
// Child span 2 (LLM generation)
460
const generateSpan = tracer.startSpan('generate-response');
461
generateSpan.setAttribute(LangfuseOtelSpanAttributes.OBSERVATION_TYPE, 'GENERATION');
462
generateSpan.setAttribute(LangfuseOtelSpanAttributes.OBSERVATION_MODEL, 'gpt-4');
463
const response = await generateResponse(data);
464
generateSpan.end();
465
466
rootSpan.end();
467
return response;
468
});
469
}
470
```
471
472
### Metadata and Tags
473
474
```typescript
475
import { LangfuseOtelSpanAttributes } from '@langfuse/core';
476
477
// Rich metadata
478
span.setAttribute(LangfuseOtelSpanAttributes.TRACE_METADATA, JSON.stringify({
479
userId: 'user-123',
480
region: 'us-east-1',
481
tier: 'premium',
482
requestId: 'req-456',
483
features: ['feature-a', 'feature-b']
484
}));
485
486
// Tags for filtering
487
span.setAttribute(LangfuseOtelSpanAttributes.TRACE_TAGS,
488
JSON.stringify(['production', 'api', 'v2'])
489
);
490
491
// Observation metadata
492
span.setAttribute(LangfuseOtelSpanAttributes.OBSERVATION_METADATA, JSON.stringify({
493
cacheHit: false,
494
retryCount: 0,
495
processingTime: 1250
496
}));
497
```
498
499
## Type Definitions
500
501
```typescript { .api }
502
const LANGFUSE_TRACER_NAME: string;
503
const LANGFUSE_SDK_VERSION: string;
504
const LANGFUSE_SDK_NAME: string;
505
506
enum LangfuseOtelSpanAttributes {
507
TRACE_NAME = "langfuse.trace.name",
508
TRACE_USER_ID = "user.id",
509
TRACE_SESSION_ID = "session.id",
510
TRACE_TAGS = "langfuse.trace.tags",
511
TRACE_PUBLIC = "langfuse.trace.public",
512
TRACE_METADATA = "langfuse.trace.metadata",
513
TRACE_INPUT = "langfuse.trace.input",
514
TRACE_OUTPUT = "langfuse.trace.output",
515
OBSERVATION_TYPE = "langfuse.observation.type",
516
OBSERVATION_METADATA = "langfuse.observation.metadata",
517
OBSERVATION_LEVEL = "langfuse.observation.level",
518
OBSERVATION_STATUS_MESSAGE = "langfuse.observation.status_message",
519
OBSERVATION_INPUT = "langfuse.observation.input",
520
OBSERVATION_OUTPUT = "langfuse.observation.output",
521
OBSERVATION_COMPLETION_START_TIME = "langfuse.observation.completion_start_time",
522
OBSERVATION_MODEL = "langfuse.observation.model.name",
523
OBSERVATION_MODEL_PARAMETERS = "langfuse.observation.model.parameters",
524
OBSERVATION_USAGE_DETAILS = "langfuse.observation.usage_details",
525
OBSERVATION_COST_DETAILS = "langfuse.observation.cost_details",
526
OBSERVATION_PROMPT_NAME = "langfuse.observation.prompt.name",
527
OBSERVATION_PROMPT_VERSION = "langfuse.observation.prompt.version",
528
ENVIRONMENT = "langfuse.environment",
529
RELEASE = "langfuse.release",
530
VERSION = "langfuse.version",
531
AS_ROOT = "langfuse.internal.as_root",
532
TRACE_COMPAT_USER_ID = "langfuse.user.id",
533
TRACE_COMPAT_SESSION_ID = "langfuse.session.id"
534
}
535
```
536
537
## Best Practices
538
539
1. **Use Standard Attributes**: Prefer `TRACE_USER_ID` and `TRACE_SESSION_ID` over compatibility versions
540
2. **JSON Serialization**: Always stringify objects/arrays when setting metadata, tags, or complex attributes
541
3. **Timestamp Format**: Use ISO 8601 format for all timestamp attributes
542
4. **Environment Naming**: Use lowercase alphanumeric with hyphens/underscores, avoid 'langfuse' prefix
543
5. **Cost Tracking**: Include detailed cost breakdown in `OBSERVATION_COST_DETAILS` for accurate billing
544
6. **Usage Metrics**: Track all relevant usage metrics (tokens, characters, API calls) in `OBSERVATION_USAGE_DETAILS`
545
7. **Error Handling**: Set `OBSERVATION_LEVEL` to 'ERROR' and include `OBSERVATION_STATUS_MESSAGE` for failures
546
8. **Prompt Versioning**: Always track `OBSERVATION_PROMPT_NAME` and `OBSERVATION_PROMPT_VERSION` for generations
547
9. **Type Identification**: Set `OBSERVATION_TYPE` appropriately (SPAN, GENERATION, EVENT, etc.)
548
10. **Metadata Structure**: Keep metadata objects flat and simple for better queryability in Langfuse UI
549