Class: LLM::Tracer::Telemetry
- Inherits:
-
LLM::Tracer
- Object
- LLM::Tracer
- LLM::Tracer::Telemetry
- Defined in:
- lib/llm/tracer/telemetry.rb
Overview
The LLM::Tracer::Telemetry tracer provides telemetry support through the opentelemetry-ruby RubyGem. The gem should be installed separately since this feature is opt-in and disabled by default.
Direct Known Subclasses
Constant Summary
Constants inherited from LLM::Tracer
Instance Method Summary collapse
-
#flush! ⇒
nil
Flushes queued telemetry to the configured exporter.
-
#start_trace(trace_group_id:
nil, name: "llm", attributes: {}, metadata: nil) ⇒ self
When +trace_group_id+ is provided, it is converted to an OpenTelemetry trace_id (via a deterministic 16-byte hash) so all spans until #stop_trace share that trace_id and appear as one trace in OTLP/Langfuse.
- #stop_trace ⇒ self
- #on_request_start(operation:, model: nil, inputs: nil) ⇒ Object
- #on_request_finish(operation:, res:, model: nil, span: nil, outputs: nil, metadata: nil) ⇒ Object
- #on_request_error(ex:, span:) ⇒ Object
- #on_tool_start(id:, name:, arguments:, model:) ⇒ void
- #on_tool_finish(result:, span:) ⇒ void
- #on_tool_error(ex:, span:) ⇒ void
-
#spans ⇒
Array<OpenTelemetry::SDK::Trace::SpanData>
This method returns an empty array for exporters that do not implement 'finished_spans' such as the OTLP exporter.
-
#initialize(provider,
options = {}) ⇒ LLM::Tracer::Telemetry constructor
param [LLM::Provider] provider An LLM provider.
Methods inherited from LLM::Tracer
#consume_extra_inputs, #consume_extra_outputs, #consume_request_metadata, #current_extra, #inspect, #merge_extra, #set_finish_metadata_proc, #set_request_metadata
Constructor Details
#initialize(provider, options = {}) ⇒ LLM::Tracer::Telemetry
param [LLM::Provider] provider An LLM provider
47 48 49 50 51 |
# File 'lib/llm/tracer/telemetry.rb', line 47 def initialize(provider, = {}) super @exporter = .delete(:exporter) setup! end |
Instance Method Details
#flush! ⇒ nil
Exports are batched in the background by default. Long-lived processes usually do not need to call this method. Short-lived scripts should call #flush! before exit to reduce the risk of losing spans that are still buffered.
Flushes queued telemetry to the configured exporter.
188 189 190 191 |
# File 'lib/llm/tracer/telemetry.rb', line 188 def flush! @tracer_provider.force_flush nil end |
#start_trace(trace_group_id: nil, name: "llm", attributes: {}, metadata: nil) ⇒ self
When +trace_group_id+ is provided, it is converted to an OpenTelemetry trace_id (via a deterministic 16-byte hash) so all spans until #stop_trace share that trace_id and appear as one trace in OTLP/Langfuse.
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/llm/tracer/telemetry.rb', line 60 def start_trace(trace_group_id: nil, name: "llm", attributes: {}, metadata: nil) return self if trace_group_id.to_s.empty? span_context = span_context_from_trace_group_id(trace_group_id.to_s) parent_ctx = ::OpenTelemetry::Trace.context_with_span( ::OpenTelemetry::Trace.non_recording_span(span_context) ) attrs = attributes.compact attrs["llm.trace_group_id"] = trace_group_id.to_s root_span = @tracer.start_span( name, kind: :server, attributes: attrs, with_parent: parent_ctx ) @root_span = root_span @root_context = ::OpenTelemetry::Trace.context_with_span(root_span) self end |
#stop_trace ⇒ self
82 83 84 85 86 87 |
# File 'lib/llm/tracer/telemetry.rb', line 82 def stop_trace @root_span&.finish @root_span = nil @root_context = nil self end |
#on_request_start(operation:, model: nil, inputs: nil) ⇒ Object
91 92 93 94 95 96 97 |
# File 'lib/llm/tracer/telemetry.rb', line 91 def on_request_start(operation:, model: nil, inputs: nil) case operation when "chat" then start_chat(operation:, model:, inputs:) when "retrieval" then start_retrieval(operation:) else nil end end |
#on_request_finish(operation:, res:, model: nil, span: nil, outputs: nil, metadata: nil) ⇒ Object
101 102 103 104 105 106 107 108 |
# File 'lib/llm/tracer/telemetry.rb', line 101 def on_request_finish(operation:, res:, model: nil, span: nil, outputs: nil, metadata: nil) return nil unless span case operation when "chat" then finish_chat(operation:, model:, res:, span:, outputs:, metadata:) when "retrieval" then finish_retrieval(operation:, res:, span:) else nil end end |
#on_request_error(ex:, span:) ⇒ Object
112 113 114 115 116 117 118 119 |
# File 'lib/llm/tracer/telemetry.rb', line 112 def on_request_error(ex:, span:) return nil unless span attributes = {"error.type" => ex.class.to_s}.compact attributes.each { span.set_attribute(_1, _2) } span.add_event("gen_ai.request.finish") span.status = ::OpenTelemetry::Trace::Status.error(ex.) span.tap(&:finish) end |
#on_tool_start(id:, name:, arguments:, model:) ⇒ void
This method returns an undefined value.
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/llm/tracer/telemetry.rb', line 124 def on_tool_start(id:, name:, arguments:, model:) attributes = { "gen_ai.operation.name" => "execute_tool", "gen_ai.request.model" => model, "gen_ai.tool.call.id" => id, "gen_ai.tool.name" => name, "gen_ai.tool.call.arguments" => LLM.json.dump(arguments), "gen_ai.provider.name" => provider_name, "server.address" => provider_host, "server.port" => provider_port }.merge!(trace_attributes(span_kind: "tool")).compact span_name = ["execute_tool", name].compact.join(" ") span = create_span(span_name.empty? ? "gen_ai.tool" : span_name, attributes:) span.add_event("gen_ai.tool.start") span end |
#on_tool_finish(result:, span:) ⇒ void
This method returns an undefined value.
144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/llm/tracer/telemetry.rb', line 144 def on_tool_finish(result:, span:) return nil unless span attributes = { "gen_ai.tool.call.id" => result.id, "gen_ai.tool.name" => result.name, "gen_ai.tool.call.result" => LLM.json.dump(result.value) }.compact attributes.each { span.set_attribute(_1, _2) } span.add_event("gen_ai.tool.finish") span.tap(&:finish) end |
#on_tool_error(ex:, span:) ⇒ void
This method returns an undefined value.
159 160 161 162 163 164 165 166 |
# File 'lib/llm/tracer/telemetry.rb', line 159 def on_tool_error(ex:, span:) return nil unless span attributes = {"error.type" => ex.class.to_s}.compact attributes.each { span.set_attribute(_1, _2) } span.add_event("gen_ai.tool.finish") span.status = ::OpenTelemetry::Trace::Status.error(ex.) span.tap(&:finish) end |
#spans ⇒ Array<OpenTelemetry::SDK::Trace::SpanData>
This method returns an empty array for exporters that do not implement 'finished_spans' such as the OTLP exporter
174 175 176 177 178 |
# File 'lib/llm/tracer/telemetry.rb', line 174 def spans return [] unless @exporter.respond_to?(:finished_spans) flush! @exporter.finished_spans end |