ruby_llm-instrumentation 0.1.1 → 0.2.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 +12 -0
- data/README.md +52 -2
- data/lib/ruby_llm/instrumentation/chat.rb +6 -4
- data/lib/ruby_llm/instrumentation/embedding.rb +3 -2
- data/lib/ruby_llm/instrumentation/image.rb +3 -2
- data/lib/ruby_llm/instrumentation/moderation.rb +3 -2
- data/lib/ruby_llm/instrumentation/transcription.rb +3 -2
- data/lib/ruby_llm/instrumentation/version.rb +1 -1
- data/lib/ruby_llm/instrumentation.rb +16 -0
- metadata +5 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 40d0077ab75737f0cc26a40df7249d3a1c0b2907504adbf753dc1b5d97dc249c
|
|
4
|
+
data.tar.gz: eb7d1694584584c1f0e9cea0fe8161e53e34e02a9f38aa6676cb2c66d7c4ae26
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 77b54c9936dc4fe603c59c1525202af80d31c317fdf9ea22fe3b04914c76c501bfbdb5ae1785a2a314ee57da65685184ddcb680d9f5c39d3e53460bd806d56bd
|
|
7
|
+
data.tar.gz: 1885dec884b5396c1ff055af82a5c40253e3339f53bd2f02c43945d6304be1176cac2d95135662627d6551ea29a5c7efe4d2d660362ad0effecbdaf7bdf013ce
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.2.0] - 2026-01-20
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Custom metadata support via `RubyLLM::Instrumentation.with` block method. [#10](https://github.com/sinaptia/ruby_llm-instrumentation/pull/10) [@marckohlbrugge](https://github.com/marckohlbrugge)
|
data/README.md
CHANGED
|
@@ -20,7 +20,9 @@ Now, RubyLLM will instrument all calls to your configured LLM.
|
|
|
20
20
|
|
|
21
21
|
## Usage
|
|
22
22
|
|
|
23
|
-
RubyLLM::Instrumentation uses ActiveSupport::Notifications to publish events. You can subscribe to these events to build custom monitoring, logging, or analytics
|
|
23
|
+
RubyLLM::Instrumentation uses ActiveSupport::Notifications to publish events. You can subscribe to these events to build custom monitoring, logging, or analytics.
|
|
24
|
+
|
|
25
|
+
### Subscribing to events
|
|
24
26
|
|
|
25
27
|
```ruby
|
|
26
28
|
# Subscribe to all LLM events
|
|
@@ -31,6 +33,48 @@ ActiveSupport::Notifications.subscribe(/ruby_llm/) do |name, start, finish, id,
|
|
|
31
33
|
Rails.logger.info "Duration: #{duration}ms"
|
|
32
34
|
Rails.logger.info "Input tokens: #{payload[:input_tokens]}"
|
|
33
35
|
Rails.logger.info "Output tokens: #{payload[:output_tokens]}"
|
|
36
|
+
Rails.logger.info "Metadata: #{payload[:metadata]}" if payload[:metadata]
|
|
37
|
+
end
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Metadata
|
|
41
|
+
|
|
42
|
+
You can attach custom metadata to any RubyLLM call for tracking, attribution, or analytics purposes. Metadata is included in the event payload under the `metadata` key.
|
|
43
|
+
|
|
44
|
+
```ruby
|
|
45
|
+
# Block form - great for controller around_actions
|
|
46
|
+
RubyLLM::Instrumentation.with(user_id: current_user.id, feature: "chat_assistant") do
|
|
47
|
+
RubyLLM.chat.ask("Hello")
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# One-liners work too
|
|
51
|
+
RubyLLM::Instrumentation.with(feature: "search") { RubyLLM.embed("text") }
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
The block form is particularly useful for setting request-level context:
|
|
55
|
+
|
|
56
|
+
```ruby
|
|
57
|
+
class ApplicationController < ActionController::Base
|
|
58
|
+
around_action :instrument_llm_calls
|
|
59
|
+
|
|
60
|
+
private
|
|
61
|
+
|
|
62
|
+
def instrument_llm_calls
|
|
63
|
+
RubyLLM::Instrumentation.with(user_id: current_user&.id, request_id: request.uuid) do
|
|
64
|
+
yield
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Nested blocks merge metadata, so you can set global context and add specific metadata per-call:
|
|
71
|
+
|
|
72
|
+
```ruby
|
|
73
|
+
RubyLLM::Instrumentation.with(user_id: 123) do
|
|
74
|
+
RubyLLM::Instrumentation.with(feature: "chat") do
|
|
75
|
+
RubyLLM.chat.ask("Hello")
|
|
76
|
+
# metadata: { user_id: 123, feature: "chat" }
|
|
77
|
+
end
|
|
34
78
|
end
|
|
35
79
|
```
|
|
36
80
|
|
|
@@ -53,6 +97,7 @@ Triggered when `#ask` is called.
|
|
|
53
97
|
| output_tokens | Output tokens consumed |
|
|
54
98
|
| cached_tokens | Cache reads tokens (if supported) |
|
|
55
99
|
| cache_creation_tokens | Cache write tokens (if supported) |
|
|
100
|
+
| metadata | Custom metadata hash (if provided) |
|
|
56
101
|
|
|
57
102
|
#### execute_tool.ruby_llm
|
|
58
103
|
|
|
@@ -67,6 +112,7 @@ Triggered when `#execute_tool` is called.
|
|
|
67
112
|
| arguments | The arguments |
|
|
68
113
|
| chat | The chat, a RubyLLM::Chat instance |
|
|
69
114
|
| halted | Indicates if the tool stopped the conversation loop |
|
|
115
|
+
| metadata | Custom metadata hash (if provided) |
|
|
70
116
|
|
|
71
117
|
### RubyLLM::Embedding
|
|
72
118
|
|
|
@@ -82,6 +128,7 @@ Triggered when `.embed` is called.
|
|
|
82
128
|
| dimensions | Number of embedding dimensions (or array of sizes if multiple) |
|
|
83
129
|
| input_tokens | Input tokens consumed |
|
|
84
130
|
| vector_count | Number of vectors generated |
|
|
131
|
+
| metadata | Custom metadata hash (if provided) |
|
|
85
132
|
|
|
86
133
|
### RubyLLM::Image
|
|
87
134
|
|
|
@@ -93,8 +140,9 @@ Triggered when `.paint` is called.
|
|
|
93
140
|
| -------- | -------------------------------------------- |
|
|
94
141
|
| provider | Provider slug |
|
|
95
142
|
| size | Image dimensions |
|
|
96
|
-
| image | The
|
|
143
|
+
| image | The image generated, a RubyLLM::Image object |
|
|
97
144
|
| model | Model ID |
|
|
145
|
+
| metadata | Custom metadata hash (if provided) |
|
|
98
146
|
|
|
99
147
|
### RubyLLM::Moderation
|
|
100
148
|
|
|
@@ -108,6 +156,7 @@ Triggered when `.moderate` is called.
|
|
|
108
156
|
| moderation | The moderation, a RubyLLM::Moderation object |
|
|
109
157
|
| model | Model ID |
|
|
110
158
|
| flagged | Whether the text was flagged |
|
|
159
|
+
| metadata | Custom metadata hash (if provided) |
|
|
111
160
|
|
|
112
161
|
### RubyLLM::Transcription
|
|
113
162
|
|
|
@@ -123,6 +172,7 @@ Triggered when `.transcribe` is called.
|
|
|
123
172
|
| input_tokens | Input tokens consumed |
|
|
124
173
|
| output_tokens | Output tokens consumed |
|
|
125
174
|
| duration | Audio duration in seconds (if available) |
|
|
175
|
+
| metadata | Custom metadata hash (if provided) |
|
|
126
176
|
|
|
127
177
|
## Contributing
|
|
128
178
|
|
|
@@ -9,8 +9,9 @@ module RubyLLM
|
|
|
9
9
|
raw_payload = {
|
|
10
10
|
provider: @provider.slug,
|
|
11
11
|
model: @model.id,
|
|
12
|
-
streaming: block_given
|
|
13
|
-
|
|
12
|
+
streaming: block_given?,
|
|
13
|
+
metadata: RubyLLM::Instrumentation.current_metadata.presence
|
|
14
|
+
}.compact
|
|
14
15
|
|
|
15
16
|
ActiveSupport::Notifications.instrument("complete_chat.ruby_llm", raw_payload) do |payload|
|
|
16
17
|
original_complete(&).tap do |response|
|
|
@@ -32,8 +33,9 @@ module RubyLLM
|
|
|
32
33
|
model: @model.id,
|
|
33
34
|
tool_call: tool_call,
|
|
34
35
|
tool_name: tool_call.name,
|
|
35
|
-
arguments: tool_call.arguments
|
|
36
|
-
|
|
36
|
+
arguments: tool_call.arguments,
|
|
37
|
+
metadata: RubyLLM::Instrumentation.current_metadata.presence
|
|
38
|
+
}.compact
|
|
37
39
|
|
|
38
40
|
ActiveSupport::Notifications.instrument("execute_tool.ruby_llm", raw_payload) do |payload|
|
|
39
41
|
original_execute_tool(tool_call).tap do |response|
|
|
@@ -8,8 +8,9 @@ module RubyLLM
|
|
|
8
8
|
alias_method :original_embed, :embed
|
|
9
9
|
def embed(text, model: nil, provider: nil, assume_model_exists: false, context: nil, dimensions: nil)
|
|
10
10
|
raw_payload = {
|
|
11
|
-
provider
|
|
12
|
-
|
|
11
|
+
provider:,
|
|
12
|
+
metadata: RubyLLM::Instrumentation.current_metadata.presence
|
|
13
|
+
}.compact
|
|
13
14
|
|
|
14
15
|
ActiveSupport::Notifications.instrument("embed_text.ruby_llm", raw_payload) do |payload|
|
|
15
16
|
original_embed(text, model:, provider:, assume_model_exists:, context:, dimensions:).tap do |response|
|
|
@@ -9,8 +9,9 @@ module RubyLLM
|
|
|
9
9
|
def paint(prompt, model: nil, provider: nil, assume_model_exists: false, size: "1024x1024", context: nil)
|
|
10
10
|
raw_payload = {
|
|
11
11
|
provider:,
|
|
12
|
-
size
|
|
13
|
-
|
|
12
|
+
size:,
|
|
13
|
+
metadata: RubyLLM::Instrumentation.current_metadata.presence
|
|
14
|
+
}.compact
|
|
14
15
|
|
|
15
16
|
ActiveSupport::Notifications.instrument("paint_image.ruby_llm", raw_payload) do |payload|
|
|
16
17
|
original_paint(prompt, model:, provider:, assume_model_exists:, size:, context:).tap do |response|
|
|
@@ -8,8 +8,9 @@ module RubyLLM
|
|
|
8
8
|
alias_method :original_moderate, :moderate
|
|
9
9
|
def moderate(input, model: nil, provider: nil, assume_model_exists: false, context: nil)
|
|
10
10
|
raw_payload = {
|
|
11
|
-
provider
|
|
12
|
-
|
|
11
|
+
provider:,
|
|
12
|
+
metadata: RubyLLM::Instrumentation.current_metadata.presence
|
|
13
|
+
}.compact
|
|
13
14
|
|
|
14
15
|
ActiveSupport::Notifications.instrument("moderate_text.ruby_llm", raw_payload) do |payload|
|
|
15
16
|
original_moderate(input, model:, provider:, assume_model_exists:, context:).tap do |response|
|
|
@@ -8,8 +8,9 @@ module RubyLLM
|
|
|
8
8
|
alias_method :original_transcribe, :transcribe
|
|
9
9
|
def transcribe(audio_file, **kwargs)
|
|
10
10
|
raw_payload = {
|
|
11
|
-
provider: kwargs[:provider]
|
|
12
|
-
|
|
11
|
+
provider: kwargs[:provider],
|
|
12
|
+
metadata: RubyLLM::Instrumentation.current_metadata.presence
|
|
13
|
+
}.compact
|
|
13
14
|
|
|
14
15
|
ActiveSupport::Notifications.instrument("transcribe_audio.ruby_llm", raw_payload) do |payload|
|
|
15
16
|
original_transcribe(audio_file, **kwargs).tap do |response|
|
|
@@ -4,11 +4,27 @@ require "ruby_llm/instrumentation/railtie"
|
|
|
4
4
|
|
|
5
5
|
module RubyLLM
|
|
6
6
|
module Instrumentation
|
|
7
|
+
METADATA_KEY = :ruby_llm_instrumentation_metadata
|
|
8
|
+
|
|
7
9
|
autoload :Chat, "ruby_llm/instrumentation/chat"
|
|
8
10
|
autoload :Embedding, "ruby_llm/instrumentation/embedding"
|
|
9
11
|
autoload :Image, "ruby_llm/instrumentation/image"
|
|
10
12
|
autoload :Transcription, "ruby_llm/instrumentation/transcription"
|
|
11
13
|
autoload :Moderation, "ruby_llm/instrumentation/moderation"
|
|
14
|
+
|
|
15
|
+
class << self
|
|
16
|
+
def with(metadata = {})
|
|
17
|
+
previous_metadata = Thread.current[METADATA_KEY]
|
|
18
|
+
Thread.current[METADATA_KEY] = (previous_metadata || {}).merge(metadata)
|
|
19
|
+
yield
|
|
20
|
+
ensure
|
|
21
|
+
Thread.current[METADATA_KEY] = previous_metadata
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def current_metadata
|
|
25
|
+
Thread.current[METADATA_KEY] || {}
|
|
26
|
+
end
|
|
27
|
+
end
|
|
12
28
|
end
|
|
13
29
|
end
|
|
14
30
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ruby_llm-instrumentation
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Patricio Mac Adden
|
|
@@ -15,14 +15,14 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - ">="
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 7.
|
|
18
|
+
version: 7.2.0
|
|
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
|
-
version: 7.
|
|
25
|
+
version: 7.2.0
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: ruby_llm
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -44,6 +44,7 @@ executables: []
|
|
|
44
44
|
extensions: []
|
|
45
45
|
extra_rdoc_files: []
|
|
46
46
|
files:
|
|
47
|
+
- CHANGELOG.md
|
|
47
48
|
- README.md
|
|
48
49
|
- Rakefile
|
|
49
50
|
- lib/ruby_llm/instrumentation.rb
|
|
@@ -60,6 +61,7 @@ licenses: []
|
|
|
60
61
|
metadata:
|
|
61
62
|
homepage_uri: https://github.com/sinaptia/ruby_llm-instrumentation
|
|
62
63
|
source_code_uri: https://github.com/sinaptia/ruby_llm-instrumentation
|
|
64
|
+
changelog_uri: https://github.com/sinaptia/ruby_llm-instrumentation/blob/main/CHANGELOG.md
|
|
63
65
|
rdoc_options: []
|
|
64
66
|
require_paths:
|
|
65
67
|
- lib
|