verica-observability 0.1.8 → 0.1.9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9b2286c95c84642a8961ca9521858ce47f8cdff3d764e7269a278acd6a78284c
4
- data.tar.gz: bb471935256948e92255edf0b4c92ef97f245544890fe4de09b9862b92d2c092
3
+ metadata.gz: 87dae5be3d2d8bb4abc605dce2d2338735d12cc3686ed92e9cb3cb185beb1c19
4
+ data.tar.gz: 243179f8c98115b7c59cf1f6089abb2a9ea2eec90e666407f006c6c510d18f6b
5
5
  SHA512:
6
- metadata.gz: e2765905d27ac2b2d5b94f59d79ebda8fab9b42aeb9e677cd97eeff9e1fb9021567b68b249d58a65ccc423f76997fcf6274320b205b220f18d60c8c9b73acdfb
7
- data.tar.gz: d1d66aa9cf309ac254c4bcfde0dadbc4ecfdbad75aa85da8f98b88ccb143f3058fea5d2586946168bdfacc7f33fc61867cb400da690b18a069fad22011851f95
6
+ metadata.gz: 400f082d4df041fa02d68087a29fe15e7716fc2c69cabd04a4ffaf6e00843d571cd99a11e4c4ca63daed5310e2e93bbf2474ec9e7657bd211ee9a12a973b5329
7
+ data.tar.gz: 99859f6abe8329b733074a913e928b5e3839c01b95b4acc65521c8b730db54521fb034edcb2b5163f954cfea2234580c7aacdcc5580110cd2d53c11ff95644c2
data/README.md CHANGED
@@ -107,6 +107,32 @@ Per-request tags UNION with the globals (dedup, order preserved); nested blocks
107
107
  accumulate; the scope is thread-local and restored even if the block raises.
108
108
  Values are coerced with `to_s`; the server caps at 20 tags x 120 chars.
109
109
 
110
+ ## Agent loops
111
+
112
+ An agent run is more than one LLM call: it interleaves model turns with tool
113
+ executions. `Verica.with_span(name)` opens `name` as the active span for the
114
+ block, so wrapped-client calls and nested `with_span`/`with_tool` blocks become
115
+ its children. The whole run lands as ONE trace with a span tree instead of a
116
+ handful of disconnected spans. `Verica.with_tool(name)` is the same, plus the
117
+ OTel GenAI semconv tool attributes (`gen_ai.operation.name = execute_tool`,
118
+ `gen_ai.tool.name = name`), so tool spans are matchable by `span_check`.
119
+
120
+ ```ruby
121
+ Verica.with_span('agent.run') do
122
+ client.chat.completions.create(model: 'gpt-4o-mini', messages: plan_messages)
123
+ weather = Verica.with_tool('lookup_weather') { lookup_weather('Cordoba') }
124
+ client.chat.completions.create(model: 'gpt-4o-mini', messages: reply_messages(weather))
125
+ end
126
+ ```
127
+
128
+ The span name is `name` verbatim (that is what `span_check` patterns match).
129
+ Both return the block's value, so you can wrap an existing method body and keep
130
+ its return unchanged. An exception raised inside the block marks the span as
131
+ error and propagates untouched (rescue it outside if the loop should continue).
132
+ Before `Verica.init` both are transparent no-ops that still run the block, so
133
+ instrumentation never changes control flow. See `examples/agent.rb` for a full
134
+ two-call, two-tool run (one tool fails on purpose).
135
+
110
136
  ## Streaming (`wrap_openai_compatible`)
111
137
 
112
138
  Streaming calls (a `stream:` proc in `parameters`) are fully captured: the
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Verica
4
- VERSION = '0.1.8'
4
+ VERSION = '0.1.9'
5
5
  end
data/lib/verica.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'json'
3
4
  require 'verica/version'
4
5
  require 'verica/config'
5
6
  require 'verica/providers'
@@ -68,6 +69,27 @@ module Verica
68
69
  merge_tags(@config&.tags || [], Thread.current[TAGS_KEY] || [])
69
70
  end
70
71
 
72
+ # Opens `name` as the active span for the block: wrapped-client calls and
73
+ # nested with_span/with_tool inside become children, so a whole agent run
74
+ # lands as ONE trace with a span tree. The span name is `name` verbatim
75
+ # (what span_check patterns match). Exceptions mark the span as error and
76
+ # propagate untouched. No-op before init (fail-open). Returns the block's
77
+ # value.
78
+ #
79
+ # Verica.with_span("agent.run") { ...loop... }
80
+ def with_span(name, &block)
81
+ manual_span(name.to_s, {}, &block)
82
+ end
83
+
84
+ # with_span + the OTel GenAI semconv tool attributes
85
+ # (gen_ai.operation.name = execute_tool, gen_ai.tool.name).
86
+ #
87
+ # Verica.with_tool("search_exercises") { execute(...) }
88
+ def with_tool(name, &block)
89
+ n = name.to_s
90
+ manual_span(n, { 'gen_ai.operation.name' => 'execute_tool', 'gen_ai.tool.name' => n }, &block)
91
+ end
92
+
71
93
  def init(**options)
72
94
  if @initialized
73
95
  warn '[verica] init called twice; ignoring the second call.'
@@ -149,5 +171,28 @@ module Verica
149
171
  end
150
172
  out
151
173
  end
174
+
175
+ # Ruby has no stamping span processor (the wrappers stamp per span), so
176
+ # manual spans stamp conversation/tags themselves for cross-SDK parity.
177
+ def manual_span(name, attributes)
178
+ tracer = @initialized && safely { OpenTelemetry.tracer_provider.tracer('verica-observability', Verica::VERSION) }
179
+ return yield unless tracer
180
+
181
+ attrs = attributes.dup
182
+ safely do
183
+ cid = conversation_id
184
+ attrs['gen_ai.conversation.id'] = cid if cid
185
+ tags = current_tags
186
+ attrs['verica.tags'] = JSON.generate(tags) unless tags.empty?
187
+ end
188
+ # in_span records the exception, sets error status, re-raises, finishes.
189
+ tracer.in_span(name, attributes: attrs) { yield }
190
+ end
191
+
192
+ def safely
193
+ yield
194
+ rescue StandardError
195
+ nil
196
+ end
152
197
  end
153
198
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: verica-observability
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.8
4
+ version: 0.1.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Verica
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-07-06 00:00:00.000000000 Z
11
+ date: 2026-07-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: opentelemetry-exporter-otlp