Class: Langfuse::BaseObservation Abstract

Inherits:
Object
  • Object
show all
Defined in:
lib/langfuse/observations.rb

Overview

This class is abstract.

Subclass and pass type: to super to create concrete observation types

Base class for all Langfuse observation wrappers.

Provides unified functionality for spans, generations, events, and specialized observation types. Wraps OpenTelemetry spans with Langfuse-specific functionality. Uses unified ‘start_observation()` method with `as_type` parameter, aligning with langfuse-js architecture.

Examples:

Block-based API (auto-ends)

Langfuse.observe("parent-operation", input: { query: "test" }) do |span|
  # Child span
  span.start_observation("data-processing", input: { step: "fetch" }) do |child|
    result = fetch_data
    child.update(output: result)
  end

  # Child generation (LLM call)
  span.start_observation("llm-call", { model: "gpt-4", input: [{ role: "user", content: "Hello" }] }, as_type: :generation) do |gen|
    response = call_llm
    gen.update(output: response, usage_details: { prompt_tokens: 100, completion_tokens: 50 })
  end
end

Stateful API (manual end)

span = Langfuse.start_observation("parent-operation", { input: { query: "test" } })

# Child span
child_span = span.start_observation("data-validation", { input: { data: result } })
validate_data
child_span.update(output: { valid: true })
child_span.end

# Child generation (LLM call)
gen = span.start_observation("llm-summary", {
  model: "gpt-3.5-turbo",
  input: [{ role: "user", content: "Summarize" }]
}, as_type: :generation)
summary = call_llm
gen.update(output: summary, usage_details: { prompt_tokens: 50, completion_tokens: 25 })
gen.end

span.end

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(otel_span, otel_tracer, attributes: nil, type: nil) ⇒ BaseObservation

Returns a new instance of BaseObservation.

Parameters:

  • otel_span (OpenTelemetry::SDK::Trace::Span)

    The underlying OTel span

  • otel_tracer (OpenTelemetry::SDK::Trace::Tracer)

    The OTel tracer

  • attributes (Hash, Types::SpanAttributes, Types::GenerationAttributes, nil) (defaults to: nil)

    Optional initial attributes

  • type (String) (defaults to: nil)

    Observation type (e.g., “span”, “generation”, “event”)



74
75
76
77
78
79
80
81
82
83
# File 'lib/langfuse/observations.rb', line 74

def initialize(otel_span, otel_tracer, attributes: nil, type: nil)
  @otel_span = otel_span
  @otel_tracer = otel_tracer
  @type = type || raise(ArgumentError, "type must be provided")

  # Set initial attributes if provided
  return unless attributes

  update_observation_attributes(attributes.to_h)
end

Instance Attribute Details

#otel_spanOpenTelemetry::SDK::Trace::Span (readonly)

Returns The underlying OTel span.

Returns:

  • (OpenTelemetry::SDK::Trace::Span)

    The underlying OTel span



62
63
64
# File 'lib/langfuse/observations.rb', line 62

def otel_span
  @otel_span
end

#otel_tracerOpenTelemetry::SDK::Trace::Tracer (readonly)

Returns The OTel tracer.

Returns:

  • (OpenTelemetry::SDK::Trace::Tracer)

    The OTel tracer



65
66
67
# File 'lib/langfuse/observations.rb', line 65

def otel_tracer
  @otel_tracer
end

#typeString (readonly)

Returns Observation type (e.g., “span”, “generation”, “event”).

Returns:

  • (String)

    Observation type (e.g., “span”, “generation”, “event”)



68
69
70
# File 'lib/langfuse/observations.rb', line 68

def type
  @type
end

Instance Method Details

#current_spanOpenTelemetry::SDK::Trace::Span

Returns:

  • (OpenTelemetry::SDK::Trace::Span)


194
195
196
# File 'lib/langfuse/observations.rb', line 194

def current_span
  @otel_span
end

#end(end_time: nil) ⇒ void

This method returns an undefined value.

Ends the observation span.

Parameters:

  • end_time (Time, Integer, nil) (defaults to: nil)

    Optional end time (Time object or Unix timestamp in nanoseconds)



109
110
111
# File 'lib/langfuse/observations.rb', line 109

def end(end_time: nil)
  @otel_span.finish(end_timestamp: end_time)
end

#event(name:, input: nil, level: "default") ⇒ void

This method returns an undefined value.

Adds an event to this observation’s span.

Parameters:

  • name (String)

    Event name

  • input (Object, nil) (defaults to: nil)

    Optional event data

  • level (String) (defaults to: "default")

    Log level (debug, default, warning, error)



183
184
185
186
187
188
189
190
191
# File 'lib/langfuse/observations.rb', line 183

def event(name:, input: nil, level: "default")
  masked_input = Masking.apply(input, mask: Langfuse.configuration.mask)
  attributes = {
    OtelAttributes::OBSERVATION_INPUT => masked_input&.to_json,
    OtelAttributes::OBSERVATION_LEVEL => level
  }.compact

  @otel_span.add_event(name, attributes: attributes)
end

#idString

Returns Hex-encoded span ID (16 hex characters).

Returns:

  • (String)

    Hex-encoded span ID (16 hex characters)



86
87
88
# File 'lib/langfuse/observations.rb', line 86

def id
  @otel_span.context.span_id.unpack1("H*")
end

#input=(value) ⇒ void

This method returns an undefined value.

Sets observation-level input attributes.

Parameters:

  • value (Object)

    Input value (will be JSON-encoded)



153
154
155
# File 'lib/langfuse/observations.rb', line 153

def input=(value)
  update_observation_attributes(input: value)
end

#level=(value) ⇒ void

This method returns an undefined value.

Parameters:

  • value (String)

    Level (DEBUG, DEFAULT, WARNING, ERROR)



173
174
175
# File 'lib/langfuse/observations.rb', line 173

def level=(value)
  update_observation_attributes(level: value)
end

#metadata=(value) ⇒ void

This method returns an undefined value.

Parameters:

  • value (Hash)

    Metadata hash (expanded into individual langfuse.observation.metadata.* attributes)



167
168
169
# File 'lib/langfuse/observations.rb', line 167

def metadata=(value)
  update_observation_attributes(metadata: value)
end

#output=(value) ⇒ void

This method returns an undefined value.

Sets observation-level output attributes.

Parameters:

  • value (Object)

    Output value (will be JSON-encoded)



161
162
163
# File 'lib/langfuse/observations.rb', line 161

def output=(value)
  update_observation_attributes(output: value)
end

#score_trace(name:, value:, comment: nil, metadata: nil, data_type: :numeric) ⇒ Hash

Create a score for the trace this observation belongs to

Parameters:

  • name (String)

    score name

  • value (Numeric, String, Boolean)

    score value

  • comment (String, nil) (defaults to: nil)

    optional comment

  • metadata (Hash, nil) (defaults to: nil)

    optional metadata

  • data_type (Symbol) (defaults to: :numeric)

    one of :numeric, :boolean, :categorical

Returns:

  • (Hash)

    created score data from the API



206
207
208
209
210
211
212
213
214
215
# File 'lib/langfuse/observations.rb', line 206

def score_trace(name:, value:, comment: nil, metadata: nil, data_type: :numeric)
  Langfuse.create_score(
    name: name,
    value: value,
    trace_id: trace_id,
    comment: comment,
    metadata: ,
    data_type: data_type
  )
end

#start_observation(name, attrs = {}, as_type: :span) {|observation| ... } ⇒ BaseObservation, Object

Creates a child observation within this observation’s context.

Supports block-based (auto-ends) and stateful (manual end) APIs. Events auto-end when created without a block.

Parameters:

  • name (String)

    Descriptive name for the child observation

  • attrs (Hash, Types::SpanAttributes, Types::GenerationAttributes, nil) (defaults to: {})

    Observation attributes

  • as_type (Symbol, String) (defaults to: :span)

    Observation type (:span, :generation, :event, etc.). Defaults to ‘:span`.

Yields:

  • (observation)

    Optional block that receives the observation object

Returns:

  • (BaseObservation, Object)

    The child observation (or block return value if block given)



135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/langfuse/observations.rb', line 135

def start_observation(name, attrs = {}, as_type: :span, &block)
  # Skip validation so unknown types fall back to Span in the factory.
  child = Langfuse.start_observation(
    name,
    attrs,
    as_type: as_type,
    parent_span_context: @otel_span.context,
    skip_validation: true
  )
  return child unless block

  child.send(:run_in_context, &block)
end

#trace_idString

Returns Hex-encoded trace ID (32 hex characters).

Returns:

  • (String)

    Hex-encoded trace ID (32 hex characters)



91
92
93
# File 'lib/langfuse/observations.rb', line 91

def trace_id
  @otel_span.context.trace_id.unpack1("H*")
end

#trace_urlString

Returns URL to view this trace in Langfuse UI.

Examples:

span = Langfuse.observe("operation") do |obs|
  puts "View trace: #{obs.trace_url}"
end

Returns:

  • (String)

    URL to view this trace in Langfuse UI



101
102
103
# File 'lib/langfuse/observations.rb', line 101

def trace_url
  Langfuse.client.trace_url(trace_id)
end

#update_trace(attrs) ⇒ self

Updates trace-level attributes (user_id, session_id, tags, etc.) for the entire trace. Tags exceeding 200 characters are silently dropped with a warning log.

Parameters:

Returns:

  • (self)


118
119
120
121
122
123
124
# File 'lib/langfuse/observations.rb', line 118

def update_trace(attrs)
  return self unless @otel_span.recording?

  otel_attrs = OtelAttributes.create_trace_attributes(attrs.to_h, mask: Langfuse.configuration.mask)
  otel_attrs.each { |key, value| @otel_span.set_attribute(key, value) }
  self
end