Langfuse instrumentation methods based on OpenTelemetry
The LangfuseOtelSpanAttributes enum provides constant keys for OpenTelemetry span attributes used by Langfuse. These constants are primarily used internally by the createTraceAttributes() and createObservationAttributes() functions but are exported for advanced use cases where you need direct access to the underlying OpenTelemetry attribute keys.
import { LangfuseOtelSpanAttributes } from '@langfuse/tracing';
import { trace } from '@opentelemetry/api';
// Advanced: Directly set OpenTelemetry attributes
const span = trace.getActiveSpan();
if (span) {
span.setAttribute(
LangfuseOtelSpanAttributes.TRACE_USER_ID,
'user-123'
);
}Constants for trace-level attributes:
enum LangfuseOtelSpanAttributes {
/** Trace name attribute key */
TRACE_NAME = "langfuse.trace.name",
/** User ID attribute key (OpenTelemetry standard) */
TRACE_USER_ID = "user.id",
/** Session ID attribute key (OpenTelemetry standard) */
TRACE_SESSION_ID = "session.id",
/** Trace tags attribute key */
TRACE_TAGS = "langfuse.trace.tags",
/** Trace public visibility attribute key */
TRACE_PUBLIC = "langfuse.trace.public",
/** Trace metadata prefix key */
TRACE_METADATA = "langfuse.trace.metadata",
/** Trace input attribute key */
TRACE_INPUT = "langfuse.trace.input",
/** Trace output attribute key */
TRACE_OUTPUT = "langfuse.trace.output",
}Constants for observation-level attributes:
enum LangfuseOtelSpanAttributes {
/** Observation type attribute key */
OBSERVATION_TYPE = "langfuse.observation.type",
/** Observation metadata prefix key */
OBSERVATION_METADATA = "langfuse.observation.metadata",
/** Observation severity level attribute key */
OBSERVATION_LEVEL = "langfuse.observation.level",
/** Observation status message attribute key */
OBSERVATION_STATUS_MESSAGE = "langfuse.observation.status_message",
/** Observation input attribute key */
OBSERVATION_INPUT = "langfuse.observation.input",
/** Observation output attribute key */
OBSERVATION_OUTPUT = "langfuse.observation.output",
}Constants for generation-specific (LLM) attributes:
enum LangfuseOtelSpanAttributes {
/** Completion start time attribute key */
OBSERVATION_COMPLETION_START_TIME = "langfuse.observation.completion_start_time",
/** Model name attribute key */
OBSERVATION_MODEL = "langfuse.observation.model.name",
/** Model parameters attribute key */
OBSERVATION_MODEL_PARAMETERS = "langfuse.observation.model.parameters",
/** Usage details attribute key */
OBSERVATION_USAGE_DETAILS = "langfuse.observation.usage_details",
/** Cost details attribute key */
OBSERVATION_COST_DETAILS = "langfuse.observation.cost_details",
/** Prompt name attribute key */
OBSERVATION_PROMPT_NAME = "langfuse.observation.prompt.name",
/** Prompt version attribute key */
OBSERVATION_PROMPT_VERSION = "langfuse.observation.prompt.version",
}Constants for general attributes applicable to both traces and observations:
enum LangfuseOtelSpanAttributes {
/** Environment attribute key */
ENVIRONMENT = "langfuse.environment",
/** Release identifier attribute key */
RELEASE = "langfuse.release",
/** Version attribute key */
VERSION = "langfuse.version",
}Constants for internal use:
enum LangfuseOtelSpanAttributes {
/** Internal flag for root span marking */
AS_ROOT = "langfuse.internal.as_root",
}Legacy attribute keys maintained for backward compatibility:
enum LangfuseOtelSpanAttributes {
/** Legacy user ID attribute key */
TRACE_COMPAT_USER_ID = "langfuse.user.id",
/** Legacy session ID attribute key */
TRACE_COMPAT_SESSION_ID = "langfuse.session.id",
}Use the high-level Langfuse functions which handle attribute keys automatically:
import { startObservation } from '@langfuse/tracing';
// Recommended: Use high-level API
const span = startObservation('my-operation', {
input: { userId: '123' },
metadata: { source: 'api' }
});
span.updateTrace({
userId: 'user-123',
sessionId: 'session-456'
});Use attribute constants when working directly with OpenTelemetry spans:
import { LangfuseOtelSpanAttributes } from '@langfuse/tracing';
import { trace } from '@opentelemetry/api';
// Advanced: Direct OpenTelemetry span manipulation
const activeSpan = trace.getActiveSpan();
if (activeSpan) {
// Set Langfuse-specific attributes directly
activeSpan.setAttributes({
[LangfuseOtelSpanAttributes.TRACE_USER_ID]: 'user-123',
[LangfuseOtelSpanAttributes.OBSERVATION_LEVEL]: 'DEFAULT',
[LangfuseOtelSpanAttributes.ENVIRONMENT]: 'production'
});
}Use constants when implementing custom OpenTelemetry span processors:
import { LangfuseOtelSpanAttributes } from '@langfuse/tracing';
import { SpanProcessor, ReadableSpan } from '@opentelemetry/sdk-trace-base';
class CustomSpanProcessor implements SpanProcessor {
onStart(span: Span): void {
// Add default environment to all spans
span.setAttribute(
LangfuseOtelSpanAttributes.ENVIRONMENT,
process.env.NODE_ENV || 'development'
);
}
onEnd(span: ReadableSpan): void {
const attributes = span.attributes;
// Read Langfuse-specific attributes
const userId = attributes[LangfuseOtelSpanAttributes.TRACE_USER_ID];
const observationType = attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE];
// Custom processing logic
if (observationType === 'generation') {
const model = attributes[LangfuseOtelSpanAttributes.OBSERVATION_MODEL];
console.log(`LLM call with model: ${model}`);
}
}
forceFlush(): Promise<void> {
return Promise.resolve();
}
shutdown(): Promise<void> {
return Promise.resolve();
}
}Metadata attributes use a dot-notation naming convention:
// Metadata is flattened with dot notation
// For observation metadata:
// { metadata: { database: { host: 'localhost', port: 5432 } } }
// becomes:
// {
// 'langfuse.observation.metadata.database.host': 'localhost',
// 'langfuse.observation.metadata.database.port': '5432'
// }
// For trace metadata:
// { metadata: { apiVersion: '2.1.0' } }
// becomes:
// {
// 'langfuse.trace.metadata.apiVersion': '2.1.0'
// }The TRACE_METADATA and OBSERVATION_METADATA constants provide the base prefix for all metadata keys. Individual metadata fields are appended with dot notation.
Langfuse uses OpenTelemetry semantic conventions where applicable:
User ID: Uses the standard OpenTelemetry user.id attribute key rather than a custom Langfuse-specific key, ensuring compatibility with other OpenTelemetry tools.
Session ID: Uses the standard OpenTelemetry session.id attribute key for consistency with the broader ecosystem.
For attributes without established semantic conventions, Langfuse uses the langfuse.* namespace.
// Good: Use high-level API
import { updateActiveTrace } from '@langfuse/tracing';
updateActiveTrace({
userId: 'user-123',
environment: 'production'
});
// Avoid: Direct attribute manipulation (unless necessary)
import { LangfuseOtelSpanAttributes } from '@langfuse/tracing';
import { trace } from '@opentelemetry/api';
trace.getActiveSpan()?.setAttributes({
[LangfuseOtelSpanAttributes.TRACE_USER_ID]: 'user-123',
[LangfuseOtelSpanAttributes.ENVIRONMENT]: 'production'
});// Good: Use enum constants
activeSpan.setAttribute(
LangfuseOtelSpanAttributes.OBSERVATION_LEVEL,
'ERROR'
);
// Avoid: Magic strings
activeSpan.setAttribute('langfuse.observation.level', 'ERROR');import { trace } from '@opentelemetry/api';
import { LangfuseOtelSpanAttributes } from '@langfuse/tracing';
const span = trace.getActiveSpan();
if (span) {
span.setAttribute(
LangfuseOtelSpanAttributes.ENVIRONMENT,
'production'
);
} else {
console.warn('No active span found');
}Install with Tessl CLI
npx tessl i tessl/npm-langfuse--tracing