ask-opentelemetry 0.1.0 → 0.1.2
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 -1
- data/README.md +29 -133
- data/lib/ask/open_telemetry/subscriber.rb +6 -3
- data/lib/ask/open_telemetry/version.rb +1 -1
- data/lib/ask/open_telemetry.rb +5 -0
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8a559471a836955c42ed5be1518e1170dcb328aaac0de21500f40154e9df885c
|
|
4
|
+
data.tar.gz: 63d774f21be7b6cc3db2ab8030e68869ffa4ef93c8d91899000009a4bcceeb93
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: de08a12ab4339fd888dee358fc38def836e44037d8530489ab041829976df25ef96fa60881c4023cafd82545ac84671ce9105a225075fb04117e04f963ada3fd
|
|
7
|
+
data.tar.gz: 89f1e1816a5cc13df01f77ecfb740d6d0c0687818e61873c582c37a7e2879398e4f3c4d3e6ea13982eb868688e9bbc093a5fad317eb20824fa714993a92b13a3
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
|
+
## [0.1.2] - 2026-08-06
|
|
2
|
+
|
|
3
|
+
### Fixed
|
|
4
|
+
- `llm.input_tokens`/`llm.output_tokens` span attributes read from the nested
|
|
5
|
+
`usage` payload hash (ask-agent enriches it after the call returns; the
|
|
6
|
+
instrumenter shallow-copies the top-level payload). Top-level keys still
|
|
7
|
+
work for other emitters. `llm.duration_ms` now reflects the real LLM call
|
|
8
|
+
duration thanks to the ask-agent event fix.
|
|
9
|
+
|
|
10
|
+
## [0.1.1] - 2026-06-25
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
- Railtie test (3 tests), subscriber install idempotency. Infrastructure: rubocop, overcommit, bin/setup, CI matrix, gemspec test.
|
|
1
14
|
# Changelog
|
|
2
15
|
|
|
3
|
-
## [0.1.0] -
|
|
16
|
+
## [0.1.0] - 2026-06-21
|
|
4
17
|
|
|
5
18
|
### Added
|
|
6
19
|
- Initial release
|
data/README.md
CHANGED
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
|
|
6
6
|
OpenTelemetry tracing for the ask-rb ecosystem. Subscribes to
|
|
7
7
|
`ask-instrumentation` events and creates OpenTelemetry spans for chat
|
|
8
|
-
completions, tool calls, embeddings, and image generation.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
completions, tool calls, embeddings, and image generation. Backend-agnostic:
|
|
9
|
+
the exporter is configured with the standard OpenTelemetry SDK, so spans go
|
|
10
|
+
to any OpenTelemetry-compatible backend (Langfuse, Datadog, Honeycomb, Jaeger,
|
|
11
|
+
Arize Phoenix, and more).
|
|
12
12
|
|
|
13
13
|
## Installation
|
|
14
14
|
|
|
@@ -22,66 +22,37 @@ gem "ask-instrumentation"
|
|
|
22
22
|
```ruby
|
|
23
23
|
require "ask/open_telemetry"
|
|
24
24
|
|
|
25
|
-
# Subscribe to all ask events and create OpenTelemetry spans
|
|
26
25
|
Ask::OpenTelemetry.install
|
|
27
26
|
```
|
|
28
27
|
|
|
29
|
-
|
|
28
|
+
That's it. Every `Ask::Instrumentation` event is now wrapped in a span. The
|
|
29
|
+
call is idempotent; subsequent calls are no-ops.
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
```ruby
|
|
34
|
-
# Gemfile
|
|
35
|
-
gem "ask-opentelemetry"
|
|
36
|
-
gem "ask-instrumentation"
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
That's it. Spans are created automatically for every LLM operation.
|
|
31
|
+
In a Rails app, the Railtie calls `Ask::OpenTelemetry.install` automatically:
|
|
32
|
+
no manual setup required.
|
|
40
33
|
|
|
41
34
|
## Spans Created
|
|
42
35
|
|
|
43
|
-
| Event | Span
|
|
44
|
-
|
|
45
|
-
| `chat.ask` | `llm.chat` |
|
|
46
|
-
| `
|
|
47
|
-
| `
|
|
48
|
-
| `
|
|
49
|
-
| `image.ask` | `llm.image` | provider, model, image.size, duration_ms |
|
|
50
|
-
|
|
51
|
-
### Standard Attributes
|
|
52
|
-
|
|
53
|
-
All spans include:
|
|
36
|
+
| Event | Span |
|
|
37
|
+
|---|---|
|
|
38
|
+
| `chat.ask`, `chat.stream.ask` | `llm.chat` |
|
|
39
|
+
| `tool.ask` | `llm.tool` |
|
|
40
|
+
| `embedding.ask` | `llm.embedding` |
|
|
41
|
+
| `image.ask` | `llm.image` |
|
|
54
42
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
43
|
+
Span attributes use the `llm.*` namespace: `llm.provider`, `llm.model`,
|
|
44
|
+
`llm.input_tokens`, `llm.output_tokens`, `llm.duration_ms`, `llm.tool`,
|
|
45
|
+
`llm.tool_args`, and `llm.image.size` when present. Any context set via
|
|
46
|
+
`Ask::Instrumentation.with_metadata` is forwarded as `llm.metadata.*`
|
|
47
|
+
attributes.
|
|
60
48
|
|
|
61
|
-
|
|
49
|
+
## Configuration
|
|
62
50
|
|
|
63
|
-
|
|
64
|
-
|
|
51
|
+
`Ask::OpenTelemetry.install` is the entire public API; there is no exporter
|
|
52
|
+
configuration on the gem itself. Configure the exporter once with the standard
|
|
53
|
+
OpenTelemetry SDK before calling `install`:
|
|
65
54
|
|
|
66
55
|
```ruby
|
|
67
|
-
Ask::Instrumentation.with_metadata(user_id: 42, session_id: "abc") do
|
|
68
|
-
# The resulting span has:
|
|
69
|
-
# llm.metadata.user_id = 42
|
|
70
|
-
# llm.metadata.session_id = "abc"
|
|
71
|
-
end
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
## Backend Examples
|
|
75
|
-
|
|
76
|
-
### Langfuse
|
|
77
|
-
|
|
78
|
-
[Langfuse](https://langfuse.com) provides LLM observability (cost tracking,
|
|
79
|
-
evaluations, prompt management) via OpenTelemetry.
|
|
80
|
-
|
|
81
|
-
**Using Langfuse Cloud:**
|
|
82
|
-
|
|
83
|
-
```ruby
|
|
84
|
-
require "ask/open_telemetry"
|
|
85
56
|
require "opentelemetry-sdk"
|
|
86
57
|
require "opentelemetry-exporter-otlp"
|
|
87
58
|
|
|
@@ -89,12 +60,7 @@ OpenTelemetry::SDK.configure do |c|
|
|
|
89
60
|
c.service_name = "my-app"
|
|
90
61
|
c.add_span_processor(
|
|
91
62
|
OpenTelemetry::SDK::Trace::Export::BatchSpanProcessor.new(
|
|
92
|
-
OpenTelemetry::Exporter::OTLP::Exporter.new(
|
|
93
|
-
endpoint: "https://cloud.langfuse.com/api/public/otel/v1/traces",
|
|
94
|
-
headers: {
|
|
95
|
-
"Authorization" => "Basic #{Base64.strict_encode64("#{LANGFUSE_PUBLIC_KEY}:#{LANGFUSE_SECRET_KEY}")}"
|
|
96
|
-
}
|
|
97
|
-
)
|
|
63
|
+
OpenTelemetry::Exporter::OTLP::Exporter.new(endpoint: "https://otlp.example.com")
|
|
98
64
|
)
|
|
99
65
|
)
|
|
100
66
|
end
|
|
@@ -102,87 +68,17 @@ end
|
|
|
102
68
|
Ask::OpenTelemetry.install
|
|
103
69
|
```
|
|
104
70
|
|
|
105
|
-
|
|
71
|
+
## Full documentation
|
|
106
72
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
OpenTelemetry::SDK::Trace::Export::BatchSpanProcessor.new(
|
|
112
|
-
OpenTelemetry::Exporter::OTLP::Exporter.new(
|
|
113
|
-
endpoint: "https://your-instance.langfuse.com/api/public/otel/v1/traces",
|
|
114
|
-
headers: {
|
|
115
|
-
"Authorization" => "Basic #{Base64.strict_encode64("#{LANGFUSE_PUBLIC_KEY}:#{LANGFUSE_SECRET_KEY}")}"
|
|
116
|
-
}
|
|
117
|
-
)
|
|
118
|
-
)
|
|
119
|
-
)
|
|
120
|
-
end
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
### Datadog
|
|
124
|
-
|
|
125
|
-
```ruby
|
|
126
|
-
require "ask/open_telemetry"
|
|
127
|
-
require "opentelemetry-sdk"
|
|
128
|
-
require "opentelemetry-exporter-otlp"
|
|
129
|
-
|
|
130
|
-
OpenTelemetry::SDK.configure do |c|
|
|
131
|
-
c.service_name = "my-app"
|
|
132
|
-
c.add_span_processor(
|
|
133
|
-
OpenTelemetry::SDK::Trace::Export::BatchSpanProcessor.new(
|
|
134
|
-
OpenTelemetry::Exporter::OTLP::Exporter.new(
|
|
135
|
-
endpoint: "https://otlp.datadoghq.com",
|
|
136
|
-
headers: { "DD-API-KEY" => ENV["DD_API_KEY"] }
|
|
137
|
-
)
|
|
138
|
-
)
|
|
139
|
-
)
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
Ask::OpenTelemetry.install
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
### Honeycomb
|
|
146
|
-
|
|
147
|
-
```ruby
|
|
148
|
-
require "ask/open_telemetry"
|
|
149
|
-
require "opentelemetry-sdk"
|
|
150
|
-
require "opentelemetry-exporter-otlp"
|
|
151
|
-
|
|
152
|
-
OpenTelemetry::SDK.configure do |c|
|
|
153
|
-
c.service_name = "my-app"
|
|
154
|
-
c.add_span_processor(
|
|
155
|
-
OpenTelemetry::SDK::Trace::Export::BatchSpanProcessor.new(
|
|
156
|
-
OpenTelemetry::Exporter::OTLP::Exporter.new(
|
|
157
|
-
endpoint: "https://api.honeycomb.io:443",
|
|
158
|
-
headers: { "x-honeycomb-team" => ENV["HONEYCOMB_API_KEY"] }
|
|
159
|
-
)
|
|
160
|
-
)
|
|
161
|
-
)
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
Ask::OpenTelemetry.install
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
## API
|
|
168
|
-
|
|
169
|
-
### `.install`
|
|
170
|
-
|
|
171
|
-
Subscribe to all `.ask` events and start creating spans. Idempotent — calling
|
|
172
|
-
multiple times only subscribes once.
|
|
173
|
-
|
|
174
|
-
```ruby
|
|
175
|
-
Ask::OpenTelemetry.install
|
|
176
|
-
```
|
|
73
|
+
The full ask-rb documentation lives at https://ask-rb.github.io/ask-docs.
|
|
74
|
+
https://ask-rb.github.io/ask-docs/production/opentelemetry covers
|
|
75
|
+
ask-opentelemetry in depth, including per-backend setup examples. API
|
|
76
|
+
reference: https://ask-rb.github.io/ask-docs/reference/api.
|
|
177
77
|
|
|
178
78
|
## Development
|
|
179
79
|
|
|
180
|
-
```bash
|
|
181
|
-
git clone https://github.com/ask-rb/ask-opentelemetry.git
|
|
182
|
-
cd ask-opentelemetry
|
|
183
80
|
bundle install
|
|
184
81
|
bundle exec rake test
|
|
185
|
-
```
|
|
186
82
|
|
|
187
83
|
## License
|
|
188
84
|
|
|
@@ -44,9 +44,12 @@ module Ask
|
|
|
44
44
|
attrs["llm.provider"] = payload[:provider] if payload[:provider]
|
|
45
45
|
attrs["llm.model"] = payload[:model] if payload[:model]
|
|
46
46
|
|
|
47
|
-
# Token tracking (when available)
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
# Token tracking (when available). Chat events emitted by ask-agent
|
|
48
|
+
# enrich a shared nested +usage+ hash after the call returns (tokens
|
|
49
|
+
# are only known then); other emitters pass them at the top level.
|
|
50
|
+
usage = payload[:usage] || payload
|
|
51
|
+
attrs["llm.input_tokens"] = usage[:input_tokens] if usage[:input_tokens]
|
|
52
|
+
attrs["llm.output_tokens"] = usage[:output_tokens] if usage[:output_tokens]
|
|
50
53
|
|
|
51
54
|
# Tool-specific
|
|
52
55
|
attrs["llm.tool"] = payload[:tool_name] if payload[:tool_name]
|
data/lib/ask/open_telemetry.rb
CHANGED
|
@@ -2,6 +2,11 @@ require "ask/instrumentation"
|
|
|
2
2
|
require "opentelemetry-api"
|
|
3
3
|
require_relative "open_telemetry/version"
|
|
4
4
|
|
|
5
|
+
# Rails discovers gem railties only when they are required, so load the
|
|
6
|
+
# railtie from the entry file once Rails itself is on the stack (the
|
|
7
|
+
# documented pattern: "require my_gem/railtie if defined?(Rails::Railtie)").
|
|
8
|
+
require_relative "open_telemetry/railtie" if defined?(Rails::Railtie)
|
|
9
|
+
|
|
5
10
|
module Ask
|
|
6
11
|
# OpenTelemetry tracing for the ask-rb ecosystem.
|
|
7
12
|
#
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ask-opentelemetry
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kaka Ruto
|
|
@@ -13,14 +13,14 @@ dependencies:
|
|
|
13
13
|
name: ask-instrumentation
|
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
|
15
15
|
requirements:
|
|
16
|
-
- - "
|
|
16
|
+
- - ">="
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
18
|
version: '0.1'
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
|
-
- - "
|
|
23
|
+
- - ">="
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
25
|
version: '0.1'
|
|
26
26
|
- !ruby/object:Gem::Dependency
|