langfuse-rb 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -2
- data/lib/langfuse/cache_warmer.rb +1 -1
- data/lib/langfuse/observations.rb +24 -19
- data/lib/langfuse/trace_id.rb +88 -0
- data/lib/langfuse/version.rb +1 -1
- data/lib/langfuse.rb +67 -39
- metadata +7 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2bf0fdf8f1b31f237397c90d8db3fc61c40bc8a69e20111a949aa0bdffc8dd3e
|
|
4
|
+
data.tar.gz: b6b83329218d23b3ebd53562a4eb5bb1cd01179f07fdbf5d90b2b1c97fc192ef
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a0bda13a371bcc93d37d4ae17548f04c65f1cc8fdf4982756eebac468d280f5b3a44d51ecb5ed5406e2ffee204a958988b3423860916471d8eb1a9e728fcf51c
|
|
7
|
+
data.tar.gz: a2bebff2e84e94c5fa30b6774c89c35f63ed4d2af214a76348a370ddbd9326ff0c8346fac9b3601e9bf9427bdb56f73a3f309f7eb71d439bd31b70426461ae3d
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.7.0] - 2026-04-14
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Custom/deterministic trace ID support (#74)
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
- Bump faraday, json, and addressable to patch CVEs (#75)
|
|
17
|
+
|
|
18
|
+
### Documentation
|
|
19
|
+
- Align docs with implementation (#70, #76)
|
|
20
|
+
|
|
10
21
|
## [0.6.0] - 2026-03-06
|
|
11
22
|
|
|
12
23
|
### Added
|
|
@@ -69,7 +80,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
69
80
|
- OpenTelemetry-based tracing with OTLP export
|
|
70
81
|
- Distributed caching with Rails.cache backend and stampede protection
|
|
71
82
|
- Prompt management (text and chat) with Mustache templating
|
|
72
|
-
- In-memory caching with TTL and
|
|
83
|
+
- In-memory caching with TTL and bounded expiration-ordered eviction
|
|
73
84
|
- Fallback prompt support
|
|
74
85
|
- Global configuration pattern with `Langfuse.configure`
|
|
75
86
|
|
|
@@ -77,7 +88,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
77
88
|
- Migrated from legacy ingestion API to OTLP endpoint
|
|
78
89
|
- Removed `tracing_enabled` configuration flag (#2)
|
|
79
90
|
|
|
80
|
-
[Unreleased]: https://github.com/simplepractice/langfuse-rb/compare/v0.
|
|
91
|
+
[Unreleased]: https://github.com/simplepractice/langfuse-rb/compare/v0.7.0...HEAD
|
|
92
|
+
[0.7.0]: https://github.com/simplepractice/langfuse-rb/compare/v0.6.0...v0.7.0
|
|
81
93
|
[0.6.0]: https://github.com/simplepractice/langfuse-rb/compare/v0.5.0...v0.6.0
|
|
82
94
|
[0.5.0]: https://github.com/simplepractice/langfuse-rb/compare/v0.4.0...v0.5.0
|
|
83
95
|
[0.4.0]: https://github.com/simplepractice/langfuse-rb/compare/v0.3.0...v0.4.0
|
|
@@ -85,7 +85,7 @@ module Langfuse
|
|
|
85
85
|
# @example Warm with a different default label
|
|
86
86
|
# results = warmer.warm_all(default_label: "staging")
|
|
87
87
|
#
|
|
88
|
-
# @example Warm without any label (
|
|
88
|
+
# @example Warm without any label (API-determined selection)
|
|
89
89
|
# results = warmer.warm_all(default_label: nil)
|
|
90
90
|
#
|
|
91
91
|
# @example With specific versions for some prompts
|
|
@@ -133,8 +133,7 @@ module Langfuse
|
|
|
133
133
|
# @yield [observation] Optional block that receives the observation object
|
|
134
134
|
# @return [BaseObservation, Object] The child observation (or block return value if block given)
|
|
135
135
|
def start_observation(name, attrs = {}, as_type: :span, &block)
|
|
136
|
-
#
|
|
137
|
-
# Skip validation to allow unknown types to fall back to Span
|
|
136
|
+
# Skip validation so unknown types fall back to Span in the factory.
|
|
138
137
|
child = Langfuse.start_observation(
|
|
139
138
|
name,
|
|
140
139
|
attrs,
|
|
@@ -142,24 +141,9 @@ module Langfuse
|
|
|
142
141
|
parent_span_context: @otel_span.context,
|
|
143
142
|
skip_validation: true
|
|
144
143
|
)
|
|
144
|
+
return child unless block
|
|
145
145
|
|
|
146
|
-
|
|
147
|
-
# Block-based API: auto-ends when block completes
|
|
148
|
-
# Set context and execute block
|
|
149
|
-
current_context = OpenTelemetry::Context.current
|
|
150
|
-
result = OpenTelemetry::Context.with_current(
|
|
151
|
-
OpenTelemetry::Trace.context_with_span(child.otel_span, parent_context: current_context)
|
|
152
|
-
) do
|
|
153
|
-
block.call(child)
|
|
154
|
-
end
|
|
155
|
-
# Only end if not already ended (events auto-end in start_observation)
|
|
156
|
-
child.end unless as_type.to_s == OBSERVATION_TYPES[:event]
|
|
157
|
-
result
|
|
158
|
-
else
|
|
159
|
-
# Stateful API - return observation
|
|
160
|
-
# Events already auto-ended in start_observation
|
|
161
|
-
child
|
|
162
|
-
end
|
|
146
|
+
child.send(:run_in_context, &block)
|
|
163
147
|
end
|
|
164
148
|
|
|
165
149
|
# Sets observation-level input attributes.
|
|
@@ -261,6 +245,27 @@ module Langfuse
|
|
|
261
245
|
prompt
|
|
262
246
|
end
|
|
263
247
|
end
|
|
248
|
+
|
|
249
|
+
private
|
|
250
|
+
|
|
251
|
+
# Runs the block with this observation as the active OTel span,
|
|
252
|
+
# then ends the span in ensure (events excluded — they auto-end).
|
|
253
|
+
# @api private
|
|
254
|
+
def run_in_context
|
|
255
|
+
parent_ctx = OpenTelemetry::Context.current
|
|
256
|
+
span_ctx = OpenTelemetry::Trace.context_with_span(@otel_span, parent_context: parent_ctx)
|
|
257
|
+
OpenTelemetry::Context.with_current(span_ctx) { yield self }
|
|
258
|
+
ensure
|
|
259
|
+
safe_end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
# Ends the span, swallowing errors so ensure never masks a block exception.
|
|
263
|
+
# @api private
|
|
264
|
+
def safe_end
|
|
265
|
+
self.end unless @type == OBSERVATION_TYPES[:event]
|
|
266
|
+
rescue StandardError
|
|
267
|
+
nil
|
|
268
|
+
end
|
|
264
269
|
end
|
|
265
270
|
|
|
266
271
|
# General-purpose observation for tracking operations, functions, or logical units of work.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "digest"
|
|
4
|
+
|
|
5
|
+
module Langfuse
|
|
6
|
+
# Deterministic and random trace/observation ID generation.
|
|
7
|
+
#
|
|
8
|
+
# Mirrors the Python and JS SDK helpers so the same seed produces the same
|
|
9
|
+
# trace ID across all three SDKs. This lets callers correlate Langfuse traces
|
|
10
|
+
# with external system identifiers (database primary keys, request IDs, etc.)
|
|
11
|
+
# and score or reference traces later without having to persist the generated
|
|
12
|
+
# Langfuse ID.
|
|
13
|
+
#
|
|
14
|
+
# @example Deterministic from an external ID
|
|
15
|
+
# trace_id = Langfuse::TraceId.create(seed: "order-12345")
|
|
16
|
+
# Langfuse.observe("process-order", trace_id: trace_id) { |span| ... }
|
|
17
|
+
# Langfuse.create_score(name: "quality", value: 0.9, trace_id: trace_id)
|
|
18
|
+
#
|
|
19
|
+
# @example Random (no seed)
|
|
20
|
+
# trace_id = Langfuse::TraceId.create
|
|
21
|
+
module TraceId
|
|
22
|
+
TRACE_ID_PATTERN = /\A[0-9a-f]{32}\z/
|
|
23
|
+
INVALID_TRACE_ID = ("0" * 32)
|
|
24
|
+
|
|
25
|
+
private_constant :TRACE_ID_PATTERN, :INVALID_TRACE_ID
|
|
26
|
+
|
|
27
|
+
class << self
|
|
28
|
+
# Generate a W3C trace ID (32 lowercase hex chars).
|
|
29
|
+
#
|
|
30
|
+
# With no seed, delegates to OpenTelemetry's random trace ID generator.
|
|
31
|
+
# With a seed, takes the first 16 bytes of SHA-256(seed) so the same
|
|
32
|
+
# input always produces the same trace ID.
|
|
33
|
+
#
|
|
34
|
+
# @note Avoid passing PII, secrets, or credentials as seeds — the raw seed
|
|
35
|
+
# value appears in application code and may leak through logs/backtraces.
|
|
36
|
+
# Use stable external identifiers (database PKs, UUIDs, request IDs).
|
|
37
|
+
# @param seed [String, nil] Optional seed for deterministic generation.
|
|
38
|
+
# Must be a String if provided; non-String values raise ArgumentError
|
|
39
|
+
# for cross-SDK parity (Python/JS both reject non-strings).
|
|
40
|
+
# @return [String] 32-character lowercase hex trace ID
|
|
41
|
+
# @raise [ArgumentError] if seed is not nil and not a String
|
|
42
|
+
def create(seed: nil)
|
|
43
|
+
return OpenTelemetry::Trace.generate_trace_id.unpack1("H*") if seed.nil?
|
|
44
|
+
|
|
45
|
+
Digest::SHA256.digest(validate_seed!(seed))[0, 16].unpack1("H*")
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
private
|
|
49
|
+
|
|
50
|
+
# @api private
|
|
51
|
+
def validate_seed!(seed)
|
|
52
|
+
raise ArgumentError, "seed must be a String, got #{seed.class}" unless seed.is_a?(String)
|
|
53
|
+
|
|
54
|
+
# ASCII-8BIT strings (binary) often already hold valid UTF-8 bytes
|
|
55
|
+
# but can't be transcoded — re-tag them instead.
|
|
56
|
+
return seed.dup.force_encoding("UTF-8") if seed.encoding == Encoding::ASCII_8BIT
|
|
57
|
+
|
|
58
|
+
seed.encode("UTF-8")
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# @api private
|
|
62
|
+
def valid?(trace_id)
|
|
63
|
+
return false unless trace_id.is_a?(String) && TRACE_ID_PATTERN.match?(trace_id)
|
|
64
|
+
|
|
65
|
+
trace_id != INVALID_TRACE_ID
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Build a sampled OpenTelemetry SpanContext carrying the given hex trace ID.
|
|
69
|
+
#
|
|
70
|
+
# A random span_id is generated as a placeholder — only the trace_id is
|
|
71
|
+
# consumed by the child span that gets created.
|
|
72
|
+
#
|
|
73
|
+
# @api private
|
|
74
|
+
def to_span_context(trace_id)
|
|
75
|
+
raise ArgumentError, "Invalid trace_id: #{trace_id.inspect}" unless valid?(trace_id)
|
|
76
|
+
|
|
77
|
+
OpenTelemetry::Trace::SpanContext.new(
|
|
78
|
+
trace_id: [trace_id].pack("H*"),
|
|
79
|
+
span_id: OpenTelemetry::Trace.generate_span_id,
|
|
80
|
+
trace_flags: OpenTelemetry::Trace::TraceFlags::SAMPLED,
|
|
81
|
+
# Cross-SDK parity: Python uses is_remote=False (_create_remote_parent_span).
|
|
82
|
+
# Changing this would alter ParentBased sampler behavior across SDKs.
|
|
83
|
+
remote: false
|
|
84
|
+
)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
data/lib/langfuse/version.rb
CHANGED
data/lib/langfuse.rb
CHANGED
|
@@ -50,6 +50,7 @@ require_relative "langfuse/otel_attributes"
|
|
|
50
50
|
require_relative "langfuse/propagation"
|
|
51
51
|
require_relative "langfuse/span_processor"
|
|
52
52
|
require_relative "langfuse/observations"
|
|
53
|
+
require_relative "langfuse/trace_id"
|
|
53
54
|
require_relative "langfuse/score_client"
|
|
54
55
|
require_relative "langfuse/text_prompt_client"
|
|
55
56
|
require_relative "langfuse/chat_prompt_client"
|
|
@@ -296,6 +297,24 @@ module Langfuse
|
|
|
296
297
|
client.flush_scores if @client
|
|
297
298
|
end
|
|
298
299
|
|
|
300
|
+
# Generate a trace ID (deterministic when seeded, random otherwise).
|
|
301
|
+
#
|
|
302
|
+
# Use this to correlate Langfuse traces with external identifiers. The
|
|
303
|
+
# same seed always produces the same trace ID across the Ruby, Python,
|
|
304
|
+
# and JS SDKs (SHA-256 of the seed, first 16 bytes, as 32 hex chars).
|
|
305
|
+
#
|
|
306
|
+
# @note Avoid PII or secrets as seeds. See {TraceId.create} for details.
|
|
307
|
+
# @param seed [String, nil] Optional deterministic seed
|
|
308
|
+
# @return [String] 32-character lowercase hex trace ID
|
|
309
|
+
# @raise [ArgumentError] if seed is not nil and not a String
|
|
310
|
+
#
|
|
311
|
+
# @example
|
|
312
|
+
# trace_id = Langfuse.create_trace_id(seed: "order-12345")
|
|
313
|
+
# Langfuse.observe("process", trace_id: trace_id) { |span| ... }
|
|
314
|
+
def create_trace_id(seed: nil)
|
|
315
|
+
TraceId.create(seed: seed)
|
|
316
|
+
end
|
|
317
|
+
|
|
299
318
|
# Reset global configuration and client (useful for testing)
|
|
300
319
|
#
|
|
301
320
|
# @return [void]
|
|
@@ -319,11 +338,14 @@ module Langfuse
|
|
|
319
338
|
# @param name [String] Descriptive name for the observation
|
|
320
339
|
# @param attrs [Hash, Types::SpanAttributes, Types::GenerationAttributes, nil] Observation attributes
|
|
321
340
|
# @param as_type [Symbol, String] Observation type (:span, :generation, :event, etc.)
|
|
341
|
+
# @param trace_id [String, nil] Optional 32-char lowercase hex trace ID to attach the observation to.
|
|
342
|
+
# Mutually exclusive with `parent_span_context`. Use {Langfuse.create_trace_id} to generate one.
|
|
322
343
|
# @param parent_span_context [OpenTelemetry::Trace::SpanContext, nil] Parent span context for child observations
|
|
323
344
|
# @param start_time [Time, Integer, nil] Optional start time (Time object or Unix timestamp in nanoseconds)
|
|
324
345
|
# @param skip_validation [Boolean] Skip validation (for internal use). Defaults to false.
|
|
325
346
|
# @return [BaseObservation] The observation wrapper (Span, Generation, or Event)
|
|
326
|
-
# @raise [ArgumentError] if an invalid observation type is provided
|
|
347
|
+
# @raise [ArgumentError] if an invalid observation type is provided, an invalid `trace_id` is given,
|
|
348
|
+
# or both `trace_id` and `parent_span_context` are provided
|
|
327
349
|
#
|
|
328
350
|
# @example Create root span
|
|
329
351
|
# span = Langfuse.start_observation("root-operation", { input: {...} })
|
|
@@ -332,14 +354,16 @@ module Langfuse
|
|
|
332
354
|
# child = Langfuse.start_observation("llm-call", { model: "gpt-4" },
|
|
333
355
|
# as_type: :generation,
|
|
334
356
|
# parent_span_context: parent.otel_span.context)
|
|
335
|
-
|
|
336
|
-
|
|
357
|
+
#
|
|
358
|
+
# @example Attach to a deterministic trace ID
|
|
359
|
+
# trace_id = Langfuse.create_trace_id(seed: "order-123")
|
|
360
|
+
# root = Langfuse.start_observation("process-order", trace_id: trace_id)
|
|
361
|
+
# rubocop:disable Metrics/ParameterLists
|
|
362
|
+
def start_observation(name, attrs = {}, as_type: :span, trace_id: nil, parent_span_context: nil,
|
|
363
|
+
start_time: nil, skip_validation: false)
|
|
364
|
+
parent_span_context = resolve_trace_context(trace_id, parent_span_context)
|
|
337
365
|
type_str = as_type.to_s
|
|
338
|
-
|
|
339
|
-
unless skip_validation || valid_observation_type?(as_type)
|
|
340
|
-
valid_types = OBSERVATION_TYPES.values.sort.join(", ")
|
|
341
|
-
raise ArgumentError, "Invalid observation type: #{type_str}. Valid types: #{valid_types}"
|
|
342
|
-
end
|
|
366
|
+
validate_observation_type!(as_type, type_str) unless skip_validation
|
|
343
367
|
|
|
344
368
|
otel_tracer = otel_tracer()
|
|
345
369
|
otel_span = create_otel_span(
|
|
@@ -348,32 +372,27 @@ module Langfuse
|
|
|
348
372
|
parent_span_context: parent_span_context,
|
|
349
373
|
otel_tracer: otel_tracer
|
|
350
374
|
)
|
|
375
|
+
apply_observation_attributes(otel_span, type_str, attrs)
|
|
351
376
|
|
|
352
|
-
# Serialize attributes
|
|
353
|
-
# Only set attributes if span is still recording (should always be true here, but guard for safety)
|
|
354
|
-
if otel_span.recording?
|
|
355
|
-
otel_attrs = OtelAttributes.create_observation_attributes(type_str, attrs.to_h, mask: configuration.mask)
|
|
356
|
-
otel_attrs.each { |key, value| otel_span.set_attribute(key, value) }
|
|
357
|
-
end
|
|
358
|
-
|
|
359
|
-
# Wrap in appropriate class (attributes already set on span above — pass nil to avoid double-masking)
|
|
360
377
|
observation = wrap_otel_span(otel_span, type_str, otel_tracer)
|
|
361
|
-
|
|
362
378
|
# Events auto-end immediately when created
|
|
363
379
|
observation.end if type_str == OBSERVATION_TYPES[:event]
|
|
364
|
-
|
|
365
380
|
observation
|
|
366
381
|
end
|
|
382
|
+
# rubocop:enable Metrics/ParameterLists
|
|
367
383
|
|
|
368
384
|
# User-facing convenience method for creating root observations
|
|
369
385
|
#
|
|
370
386
|
# @param name [String] Descriptive name for the observation
|
|
371
387
|
# @param attrs [Hash] Observation attributes (optional positional or keyword)
|
|
372
388
|
# @param as_type [Symbol, String] Observation type (:span, :generation, :event, etc.)
|
|
389
|
+
# @param trace_id [String, nil] Optional 32-char lowercase hex trace ID to attach the observation to.
|
|
390
|
+
# Use {Langfuse.create_trace_id} to generate one. Forwarded to {.start_observation}.
|
|
373
391
|
# @param kwargs [Hash] Additional keyword arguments merged into observation attributes (e.g., input:, output:, metadata:)
|
|
374
392
|
# @yield [observation] Optional block that receives the observation object
|
|
375
393
|
# @yieldparam observation [BaseObservation] The observation object
|
|
376
394
|
# @return [BaseObservation, Object] The observation (or block return value if block given)
|
|
395
|
+
# @raise [ArgumentError] if an invalid `trace_id` is provided
|
|
377
396
|
#
|
|
378
397
|
# @example Block-based API (auto-ends)
|
|
379
398
|
# Langfuse.observe("operation") do |obs|
|
|
@@ -385,28 +404,12 @@ module Langfuse
|
|
|
385
404
|
# obs = Langfuse.observe("operation", input: { data: "test" })
|
|
386
405
|
# obs.update(output: { result: "success" })
|
|
387
406
|
# obs.end
|
|
388
|
-
def observe(name, attrs = {}, as_type: :span, **kwargs, &block)
|
|
389
|
-
# Merge positional attrs and keyword kwargs
|
|
407
|
+
def observe(name, attrs = {}, as_type: :span, trace_id: nil, **kwargs, &block)
|
|
390
408
|
merged_attrs = attrs.to_h.merge(kwargs)
|
|
391
|
-
observation = start_observation(name, merged_attrs, as_type: as_type)
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
# Set context and execute block
|
|
396
|
-
current_context = OpenTelemetry::Context.current
|
|
397
|
-
result = OpenTelemetry::Context.with_current(
|
|
398
|
-
OpenTelemetry::Trace.context_with_span(observation.otel_span, parent_context: current_context)
|
|
399
|
-
) do
|
|
400
|
-
block.call(observation)
|
|
401
|
-
end
|
|
402
|
-
# Only end if not already ended (events auto-end in start_observation)
|
|
403
|
-
observation.end unless as_type.to_s == OBSERVATION_TYPES[:event]
|
|
404
|
-
result
|
|
405
|
-
else
|
|
406
|
-
# Stateful API - return observation
|
|
407
|
-
# Events already auto-ended in start_observation
|
|
408
|
-
observation
|
|
409
|
-
end
|
|
409
|
+
observation = start_observation(name, merged_attrs, as_type: as_type, trace_id: trace_id)
|
|
410
|
+
return observation unless block
|
|
411
|
+
|
|
412
|
+
observation.send(:run_in_context, &block)
|
|
410
413
|
end
|
|
411
414
|
|
|
412
415
|
# Registry mapping observation type strings to their wrapper classes
|
|
@@ -425,6 +428,31 @@ module Langfuse
|
|
|
425
428
|
|
|
426
429
|
private
|
|
427
430
|
|
|
431
|
+
# @api private
|
|
432
|
+
def resolve_trace_context(trace_id, parent_span_context)
|
|
433
|
+
return parent_span_context unless trace_id
|
|
434
|
+
raise ArgumentError, "Cannot specify both trace_id and parent_span_context" if parent_span_context
|
|
435
|
+
|
|
436
|
+
TraceId.send(:to_span_context, trace_id)
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
# @api private
|
|
440
|
+
def validate_observation_type!(as_type, type_str)
|
|
441
|
+
return if valid_observation_type?(as_type)
|
|
442
|
+
|
|
443
|
+
valid_types = OBSERVATION_TYPES.values.sort.join(", ")
|
|
444
|
+
raise ArgumentError, "Invalid observation type: #{type_str}. Valid types: #{valid_types}"
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
# @api private
|
|
448
|
+
def apply_observation_attributes(otel_span, type_str, attrs)
|
|
449
|
+
# Guard against ended spans — should always be recording here, but safe.
|
|
450
|
+
return unless otel_span.recording?
|
|
451
|
+
|
|
452
|
+
otel_attrs = OtelAttributes.create_observation_attributes(type_str, attrs.to_h, mask: configuration.mask)
|
|
453
|
+
otel_attrs.each { |key, value| otel_span.set_attribute(key, value) }
|
|
454
|
+
end
|
|
455
|
+
|
|
428
456
|
# Validates that an observation type is valid
|
|
429
457
|
#
|
|
430
458
|
# Checks if the provided type (symbol or string) matches a valid observation type
|
metadata
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: langfuse-rb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- SimplePractice
|
|
8
|
+
autorequire:
|
|
8
9
|
bindir: bin
|
|
9
10
|
cert_chain: []
|
|
10
|
-
date:
|
|
11
|
+
date: 2026-04-14 00:00:00.000000000 Z
|
|
11
12
|
dependencies:
|
|
12
13
|
- !ruby/object:Gem::Dependency
|
|
13
14
|
name: faraday
|
|
@@ -183,6 +184,7 @@ files:
|
|
|
183
184
|
- lib/langfuse/stale_while_revalidate.rb
|
|
184
185
|
- lib/langfuse/text_prompt_client.rb
|
|
185
186
|
- lib/langfuse/timestamp_parser.rb
|
|
187
|
+
- lib/langfuse/trace_id.rb
|
|
186
188
|
- lib/langfuse/traced_execution.rb
|
|
187
189
|
- lib/langfuse/types.rb
|
|
188
190
|
- lib/langfuse/version.rb
|
|
@@ -194,6 +196,7 @@ metadata:
|
|
|
194
196
|
source_code_uri: https://github.com/simplepractice/langfuse-rb
|
|
195
197
|
changelog_uri: https://github.com/simplepractice/langfuse-rb/blob/main/CHANGELOG.md
|
|
196
198
|
rubygems_mfa_required: 'true'
|
|
199
|
+
post_install_message:
|
|
197
200
|
rdoc_options: []
|
|
198
201
|
require_paths:
|
|
199
202
|
- lib
|
|
@@ -208,7 +211,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
208
211
|
- !ruby/object:Gem::Version
|
|
209
212
|
version: '0'
|
|
210
213
|
requirements: []
|
|
211
|
-
rubygems_version: 4.
|
|
214
|
+
rubygems_version: 3.4.1
|
|
215
|
+
signing_key:
|
|
212
216
|
specification_version: 4
|
|
213
217
|
summary: Ruby SDK for Langfuse - LLM observability and prompt management
|
|
214
218
|
test_files: []
|