Skip to content

Implement Langfuse::OtelAttributes module for converting domain models to OTel span attributes #7

@kxzk

Description

@kxzk

Overview

Create serialization layer that converts Langfuse domain models to OpenTelemetry span attributes format.

Context

  • JS SDK has createObservationAttributes() and createTraceAttributes() (in attributes.ts)
  • These convert user-friendly objects to OTel attribute format
  • Need Ruby equivalent that serializes domain objects to OTel span attributes

Technical Implementation

Create lib/langfuse/otel_attributes.rb with:

Attribute Key Constants

module Langfuse
  module OtelAttributes
    # Trace attributes
    TRACE_NAME = "langfuse.trace.name"
    TRACE_USER_ID = "langfuse.trace.userId"
    TRACE_SESSION_ID = "langfuse.trace.sessionId"
    TRACE_INPUT = "langfuse.trace.input"
    TRACE_OUTPUT = "langfuse.trace.output"
    TRACE_METADATA = "langfuse.trace.metadata"
    TRACE_TAGS = "langfuse.trace.tags"
    TRACE_PUBLIC = "langfuse.trace.public"

    # Observation attributes
    OBSERVATION_TYPE = "langfuse.observation.type"
    OBSERVATION_INPUT = "langfuse.observation.input"
    OBSERVATION_OUTPUT = "langfuse.observation.output"
    OBSERVATION_METADATA = "langfuse.observation.metadata"
    OBSERVATION_LEVEL = "langfuse.observation.level"
    OBSERVATION_STATUS_MESSAGE = "langfuse.observation.statusMessage"
    OBSERVATION_MODEL = "langfuse.observation.model"
    OBSERVATION_MODEL_PARAMETERS = "langfuse.observation.modelParameters"
    OBSERVATION_USAGE_DETAILS = "langfuse.observation.usageDetails"
    OBSERVATION_COST_DETAILS = "langfuse.observation.costDetails"
    OBSERVATION_PROMPT_NAME = "langfuse.observation.promptName"
    OBSERVATION_PROMPT_VERSION = "langfuse.observation.promptVersion"

    # Common attributes
    VERSION = "langfuse.version"
    RELEASE = "langfuse.release"
    ENVIRONMENT = "langfuse.environment"
  end
end

Core Methods

create_trace_attributes(attrs)

  • Accepts TraceAttributes object or hash
  • Maps to OTel attribute keys
  • Flattens metadata to dot-notation
  • Removes nil values

create_observation_attributes(type, attrs)

  • Accepts observation type string and attributes
  • Maps common attributes
  • Handles generation-specific attributes for generation and embedding types
  • Implements prompt linking (skips if is_fallback: true)
  • Flattens metadata

serialize(obj)

  • Converts objects to JSON strings
  • Returns strings as-is
  • Returns "<failed to serialize>" on error

flatten_metadata(metadata, prefix)

  • Flattens nested hash to dot-notation
  • Example: { user: { id: 123 } }{ "langfuse.trace.metadata.user.id": "123" }
  • Non-hash metadata serialized as-is

Acceptance Criteria

  • OtelAttributes.create_trace_attributes(attrs) converts trace attrs to OTel format
  • OtelAttributes.create_observation_attributes(type, attrs) converts observation attrs
  • Metadata is flattened to dot-notation (e.g., langfuse.trace.metadata.key)
  • JSON serialization handles objects, arrays, strings
  • Nil values are removed from final hash
  • Prompt linking works for generations/embeddings
  • Unit tests for all conversion methods

Files to Create

  • lib/langfuse/otel_attributes.rb - Serialization logic
  • spec/langfuse/otel_attributes_spec.rb - Tests

Dependencies

Requires: Step 0.1 (uses Types module)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions