Module: PlatformSdk::Observability::Langfuse
- Defined in:
- lib/platform_sdk/observability/langfuse.rb,
lib/platform_sdk/observability/langfuse.rb,
lib/platform_sdk/observability/langfuse/recorder.rb,
lib/platform_sdk/observability/langfuse/coercions.rb,
lib/platform_sdk/observability/langfuse/traceable.rb,
lib/platform_sdk/observability/langfuse/spec_support.rb,
lib/platform_sdk/observability/langfuse/configuration.rb,
lib/platform_sdk/observability/langfuse/openai_adapter.rb,
lib/platform_sdk/observability/langfuse/ruby_llm_adapter.rb,
lib/platform_sdk/observability/langfuse/sidekiq_lifecycle.rb,
lib/platform_sdk/observability/langfuse/null_span_exporter.rb,
lib/platform_sdk/observability/langfuse/trace_summarizable.rb,
lib/platform_sdk/observability/langfuse/bedrock_claude_adapter.rb,
lib/platform_sdk/observability/langfuse/notification_subscriber.rb
Defined Under Namespace
Modules: BedrockClaudeAdapter, Coercions, NotificationSubscriber, OpenAIAdapter, Recorder, RubyLLMAdapter, SidekiqLifecycle, SpecSupport, TraceSummarizable, Traceable Classes: Configuration, ConfigurationError, Error, NullSpanExporter
Constant Summary collapse
- LLM_CALL_EVENT =
ActiveSupport::Notifications event name for LLM calls. Owned by the ‘Langfuse` namespace (rather than `NotificationSubscriber`) so the adapter can emit without requiring the subscriber to be loaded.
'llm_call.platform_sdk'- OWNED_THREAD_LOCALS_KEY =
:platform_sdk_langfuse_owned_thread_locals
Class Attribute Summary collapse
-
.configuration ⇒ Object
readonly
Returns the value of attribute configuration.
Class Method Summary collapse
-
.clear_tracked_thread_locals! ⇒ Object
Clear every thread-local registered via ‘track_thread_local` on this thread, then drop the registry itself.
- .configure(app_name:, environment: nil, prompt_label: nil, exporter: nil, autosubscribe: true) ⇒ Object
- .enabled? ⇒ Boolean
- .record_generation(**kwargs) ⇒ Object
- .reset! ⇒ Object
-
.set_trace_output(value) ⇒ Object
Set the trace-level output on the active parent span.
- .tracer ⇒ Object
-
.track_thread_local(*keys) ⇒ Object
Register thread-local keys that should be cleared at the next Traceable job boundary.
Class Attribute Details
.configuration ⇒ Object (readonly)
Returns the value of attribute configuration.
37 38 39 |
# File 'lib/platform_sdk/observability/langfuse.rb', line 37 def configuration @configuration end |
Class Method Details
.clear_tracked_thread_locals! ⇒ Object
Clear every thread-local registered via ‘track_thread_local` on this thread, then drop the registry itself. Called from the Traceable wrapper’s ‘ensure` block.
130 131 132 133 134 135 136 |
# File 'lib/platform_sdk/observability/langfuse.rb', line 130 def clear_tracked_thread_locals! owned = Thread.current[OWNED_THREAD_LOCALS_KEY] return unless owned owned.each { |k| Thread.current[k] = nil } Thread.current[OWNED_THREAD_LOCALS_KEY] = nil end |
.configure(app_name:, environment: nil, prompt_label: nil, exporter: nil, autosubscribe: true) ⇒ Object
39 40 41 42 43 44 45 46 47 |
# File 'lib/platform_sdk/observability/langfuse.rb', line 39 def configure(app_name:, environment: nil, prompt_label: nil, exporter: nil, autosubscribe: true) @configuration&.force_flush_and_shutdown @configuration = Configuration.new(app_name:, environment:, prompt_label:, exporter:) if @configuration.enabled? SidekiqLifecycle.install! NotificationSubscriber.install! if autosubscribe end @configuration end |
.enabled? ⇒ Boolean
49 50 51 |
# File 'lib/platform_sdk/observability/langfuse.rb', line 49 def enabled? !@configuration.nil? && @configuration.enabled? end |
.record_generation(**kwargs) ⇒ Object
59 60 61 |
# File 'lib/platform_sdk/observability/langfuse.rb', line 59 def record_generation(**kwargs) Recorder.record_generation(**kwargs) end |
.reset! ⇒ Object
101 102 103 104 105 106 |
# File 'lib/platform_sdk/observability/langfuse.rb', line 101 def reset! @configuration&.force_flush_and_shutdown @configuration = nil SidekiqLifecycle.reset! NotificationSubscriber.reset! end |
.set_trace_output(value) ⇒ Object
Set the trace-level output on the active parent span. Application code calls this from inside a Traceable job (or any block running under an active span) to record a meaningful summary of the job’s result.
Why this is opt-in rather than auto-captured from ‘perform`’s return value: Sidekiq’s ‘perform` return is incidental — it’s often nil, an AR transaction callback array, or otherwise unrelated to anything a human reading a trace would find useful. Only the application knows what’s meaningful (e.g. a generated record’s ID).
Example:
class MyJob
include Sidekiq::Job
include PlatformSdk::Observability::Langfuse::Traceable
def perform(args)
component = generate_component(args)
PlatformSdk::Observability::Langfuse.set_trace_output(
{ component_id: component.id, status: component.status }
)
end
end
No-ops when the SDK is disabled or no span is currently active. Never raises — observability failures must not break callers.
89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/platform_sdk/observability/langfuse.rb', line 89 def set_trace_output(value) return unless enabled? span = OpenTelemetry::Trace.current_span return unless span.context.valid? span.set_attribute('langfuse.trace.output', Recorder.stringify(value)) rescue StandardError, SystemStackError => e OpenTelemetry.handle_error(message: "Langfuse set_trace_output failed: #{e.class}: #{e.[0, 200]}") nil end |
.tracer ⇒ Object
53 54 55 56 57 |
# File 'lib/platform_sdk/observability/langfuse.rb', line 53 def tracer return nil unless enabled? @configuration.tracer end |
.track_thread_local(*keys) ⇒ Object
Register thread-local keys that should be cleared at the next Traceable job boundary. Consumers call this when they store per-trace state on ‘Thread.current` (e.g. the ID of the last recorded message) so the value can’t leak into the next job that lands on this Sidekiq thread.
Example:
PlatformSdk::Observability::Langfuse.track_thread_local(:my_app_last_message_id)
Thread.current[:my_app_last_message_id] = msg.id
Compared to a name-prefix convention, this requires explicit opt-in (so consumers can’t accidentally have unrelated state zeroed) and is O(owned keys) instead of O(all thread locals).
121 122 123 124 125 |
# File 'lib/platform_sdk/observability/langfuse.rb', line 121 def track_thread_local(*keys) list = (Thread.current[OWNED_THREAD_LOCALS_KEY] ||= []) keys.each { |k| list << k unless list.include?(k) } nil end |