otlp_rails 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 +7 -0
- data/CHANGELOG.md +18 -0
- data/LICENSE.txt +21 -0
- data/lib/otlp_rails/configuration.rb +43 -0
- data/lib/otlp_rails/meter_provider_resolver.rb +73 -0
- data/lib/otlp_rails/railtie.rb +8 -0
- data/lib/otlp_rails/subscriber.rb +62 -0
- data/lib/otlp_rails/subscriber_registry.rb +40 -0
- data/lib/otlp_rails/subscribers/action_controller_subscriber.rb +37 -0
- data/lib/otlp_rails/subscribers/active_job_subscriber.rb +71 -0
- data/lib/otlp_rails/subscribers/active_record_subscriber.rb +52 -0
- data/lib/otlp_rails/version.rb +3 -0
- data/lib/otlp_rails.rb +48 -0
- metadata +150 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 4777fd19cdf39779247e804d59bec7b1f0bab16a9954f1b331501583fbae5f4f
|
|
4
|
+
data.tar.gz: 4c48473532ca764aba7fd5cf96d78da9c85331403479b58f847b6bf6b3bb17f9
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: a0ecffbb198ff471731f47a5ed722d29120af32e7493c58f698883672328a94070099f88f51ac9c8ccde63159b0bd8af64689f397287eb7a31d05d9306188987
|
|
7
|
+
data.tar.gz: b1a650a217462df121bd6d12d092a68be276fa6a42691bbe5f3b25175e3497b2f1ead05d2d0215e03eee8a1d5735db9be3e1b85fe00cb59f0fddfee5bc1198c6
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.2.0](https://github.com/endoze/otlp_rails/compare/otlp_rails-v0.1.0...otlp_rails/v0.2.0) (2026-04-03)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* initial release of otlp_rails ([#7](https://github.com/endoze/otlp_rails/issues/7)) ([45a791b](https://github.com/endoze/otlp_rails/commit/45a791bd3194a0b9172959f581f16ee499dbea09))
|
|
9
|
+
|
|
10
|
+
## [0.1.0] - Unreleased
|
|
11
|
+
|
|
12
|
+
- Initial release
|
|
13
|
+
- ActionController request metrics (duration histogram, request counter)
|
|
14
|
+
- ActiveRecord query metrics (duration histogram, query counter)
|
|
15
|
+
- ActiveJob job metrics (perform duration/count, enqueue count)
|
|
16
|
+
- Hybrid MeterProvider discovery (reuse existing or provision standalone)
|
|
17
|
+
- Pluggable subscriber architecture for custom metrics
|
|
18
|
+
- Rails Railtie for zero-config integration
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Endoze
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module OTLPRails
|
|
2
|
+
class Configuration
|
|
3
|
+
attr_accessor :metric_prefix,
|
|
4
|
+
:otlp_endpoint,
|
|
5
|
+
:export_interval_millis,
|
|
6
|
+
:export_timeout_millis,
|
|
7
|
+
:resource_attributes
|
|
8
|
+
|
|
9
|
+
attr_reader :subscriber_settings, :custom_subscribers
|
|
10
|
+
|
|
11
|
+
def initialize
|
|
12
|
+
@metric_prefix = "rails"
|
|
13
|
+
@otlp_endpoint = nil
|
|
14
|
+
@export_interval_millis = 60_000
|
|
15
|
+
@export_timeout_millis = 30_000
|
|
16
|
+
@resource_attributes = {}
|
|
17
|
+
|
|
18
|
+
@subscriber_settings = {
|
|
19
|
+
action_controller: {enabled: true},
|
|
20
|
+
active_record: {enabled: true},
|
|
21
|
+
active_job: {enabled: true}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@custom_subscribers = []
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def enable_subscriber(name)
|
|
28
|
+
@subscriber_settings[name][:enabled] = true if @subscriber_settings.key?(name)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def disable_subscriber(name)
|
|
32
|
+
@subscriber_settings[name][:enabled] = false if @subscriber_settings.key?(name)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def subscriber_enabled?(name)
|
|
36
|
+
@subscriber_settings.dig(name, :enabled) != false
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def add_subscriber(subscriber_class)
|
|
40
|
+
@custom_subscribers << subscriber_class
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
require "opentelemetry-metrics-api"
|
|
2
|
+
|
|
3
|
+
module OTLPRails
|
|
4
|
+
class MeterProviderResolver
|
|
5
|
+
def initialize(configuration)
|
|
6
|
+
@configuration = configuration
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def resolve
|
|
10
|
+
existing = detect_existing_provider
|
|
11
|
+
return existing if existing
|
|
12
|
+
|
|
13
|
+
provision_standalone_provider
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def detect_existing_provider
|
|
19
|
+
provider = OpenTelemetry.meter_provider
|
|
20
|
+
|
|
21
|
+
return if !provider.is_a?(OpenTelemetry::SDK::Metrics::MeterProvider)
|
|
22
|
+
return if provider.metric_readers.none?
|
|
23
|
+
|
|
24
|
+
log(:info,
|
|
25
|
+
"Discovered existing SDK MeterProvider " \
|
|
26
|
+
"with #{provider.metric_readers.size} reader(s); reusing it.")
|
|
27
|
+
|
|
28
|
+
provider
|
|
29
|
+
rescue NameError
|
|
30
|
+
nil
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def provision_standalone_provider
|
|
34
|
+
require "opentelemetry/sdk"
|
|
35
|
+
require "opentelemetry-metrics-sdk"
|
|
36
|
+
require "opentelemetry/exporter/otlp_metrics"
|
|
37
|
+
|
|
38
|
+
resource = build_resource
|
|
39
|
+
provider = OpenTelemetry::SDK::Metrics::MeterProvider.new(resource: resource)
|
|
40
|
+
|
|
41
|
+
exporter_opts = {}
|
|
42
|
+
exporter_opts[:endpoint] = @configuration.otlp_endpoint if @configuration.otlp_endpoint
|
|
43
|
+
exporter = OpenTelemetry::Exporter::OTLP::Metrics::MetricsExporter.new(**exporter_opts)
|
|
44
|
+
|
|
45
|
+
periodic_reader = OpenTelemetry::SDK::Metrics::Export::PeriodicMetricReader.new(
|
|
46
|
+
exporter: exporter,
|
|
47
|
+
export_interval_millis: @configuration.export_interval_millis,
|
|
48
|
+
export_timeout_millis: @configuration.export_timeout_millis
|
|
49
|
+
)
|
|
50
|
+
provider.add_metric_reader(periodic_reader)
|
|
51
|
+
|
|
52
|
+
OpenTelemetry.meter_provider = provider
|
|
53
|
+
|
|
54
|
+
log(:info,
|
|
55
|
+
"Provisioned standalone MeterProvider " \
|
|
56
|
+
"exporting to #{@configuration.otlp_endpoint || "default OTLP endpoint"}.")
|
|
57
|
+
|
|
58
|
+
provider
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def log(level, message)
|
|
62
|
+
Rails.logger.send(level, "[otlp_rails] #{message}") if defined?(Rails) && Rails.respond_to?(:logger) && Rails.logger
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def build_resource
|
|
66
|
+
attrs = {
|
|
67
|
+
"service.name" => ENV.fetch("OTEL_SERVICE_NAME", "rails-app")
|
|
68
|
+
}.merge(@configuration.resource_attributes)
|
|
69
|
+
|
|
70
|
+
OpenTelemetry::SDK::Resources::Resource.create(attrs)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
module OTLPRails
|
|
2
|
+
class Subscriber
|
|
3
|
+
attr_reader :meter, :subscriptions
|
|
4
|
+
|
|
5
|
+
def initialize(meter)
|
|
6
|
+
@meter = meter
|
|
7
|
+
@instruments = {}
|
|
8
|
+
@subscriptions = []
|
|
9
|
+
setup_instruments
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.events
|
|
13
|
+
raise NotImplementedError, "#{name} must implement .events"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def setup_instruments
|
|
17
|
+
raise NotImplementedError, "#{self.class.name} must implement #setup_instruments"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def on_event(name, started, finished, unique_id, payload)
|
|
21
|
+
raise NotImplementedError, "#{self.class.name} must implement #on_event"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def subscribe!
|
|
25
|
+
return if self.class.events.none?
|
|
26
|
+
|
|
27
|
+
self.class.events.each do |event_name|
|
|
28
|
+
subscription = ActiveSupport::Notifications.subscribe(event_name) do |name, started, finished, unique_id, payload|
|
|
29
|
+
on_event(name, started, finished, unique_id, payload)
|
|
30
|
+
rescue => e
|
|
31
|
+
if !defined?(Rails) || !Rails.respond_to?(:logger) || !Rails.logger
|
|
32
|
+
next
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
Rails.logger.warn(
|
|
36
|
+
"[otlp_rails] Error in #{self.class.name} " \
|
|
37
|
+
"handling #{name}: #{e.message}"
|
|
38
|
+
)
|
|
39
|
+
end
|
|
40
|
+
@subscriptions << subscription
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def unsubscribe!
|
|
45
|
+
@subscriptions.each do |subscription|
|
|
46
|
+
ActiveSupport::Notifications.unsubscribe(subscription)
|
|
47
|
+
end
|
|
48
|
+
@subscriptions.clear
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
private
|
|
52
|
+
|
|
53
|
+
def duration_ms(started, finished)
|
|
54
|
+
(finished - started) * 1000.0
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def metric_name(suffix)
|
|
58
|
+
prefix = OTLPRails.configuration.metric_prefix
|
|
59
|
+
"#{prefix}.#{suffix}"
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require "singleton"
|
|
2
|
+
|
|
3
|
+
module OTLPRails
|
|
4
|
+
class SubscriberRegistry
|
|
5
|
+
include Singleton
|
|
6
|
+
|
|
7
|
+
BUILT_IN_SUBSCRIBERS = {
|
|
8
|
+
action_controller: Subscribers::ActionControllerSubscriber,
|
|
9
|
+
active_record: Subscribers::ActiveRecordSubscriber,
|
|
10
|
+
active_job: Subscribers::ActiveJobSubscriber
|
|
11
|
+
}.freeze
|
|
12
|
+
|
|
13
|
+
def initialize
|
|
14
|
+
@active_subscribers = []
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def subscribe_all(meter)
|
|
18
|
+
config = OTLPRails.configuration
|
|
19
|
+
|
|
20
|
+
BUILT_IN_SUBSCRIBERS.each do |name, klass|
|
|
21
|
+
next if !config.subscriber_enabled?(name)
|
|
22
|
+
|
|
23
|
+
subscriber = klass.new(meter)
|
|
24
|
+
subscriber.subscribe!
|
|
25
|
+
@active_subscribers << subscriber
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
config.custom_subscribers.each do |klass|
|
|
29
|
+
subscriber = klass.new(meter)
|
|
30
|
+
subscriber.subscribe!
|
|
31
|
+
@active_subscribers << subscriber
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def unsubscribe_all
|
|
36
|
+
@active_subscribers.each(&:unsubscribe!)
|
|
37
|
+
@active_subscribers.clear
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module OTLPRails
|
|
2
|
+
module Subscribers
|
|
3
|
+
class ActionControllerSubscriber < Subscriber
|
|
4
|
+
def self.events
|
|
5
|
+
["process_action.action_controller"]
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def setup_instruments
|
|
9
|
+
@instruments[:request_duration] = meter.create_histogram(
|
|
10
|
+
metric_name("http.request.duration"),
|
|
11
|
+
unit: "ms",
|
|
12
|
+
description: "Duration of HTTP requests processed by Rails controllers"
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
@instruments[:request_count] = meter.create_counter(
|
|
16
|
+
metric_name("http.request.count"),
|
|
17
|
+
unit: "requests",
|
|
18
|
+
description: "Total number of HTTP requests processed by Rails controllers"
|
|
19
|
+
)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def on_event(_name, started, finished, _unique_id, payload)
|
|
23
|
+
attributes = {
|
|
24
|
+
"controller" => payload[:controller].to_s,
|
|
25
|
+
"action" => payload[:action].to_s,
|
|
26
|
+
"status" => payload[:status].to_s,
|
|
27
|
+
"method" => payload[:method].to_s
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
duration = duration_ms(started, finished)
|
|
31
|
+
|
|
32
|
+
@instruments[:request_duration].record(duration, attributes: attributes)
|
|
33
|
+
@instruments[:request_count].add(1, attributes: attributes)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
module OTLPRails
|
|
2
|
+
module Subscribers
|
|
3
|
+
class ActiveJobSubscriber < Subscriber
|
|
4
|
+
def self.events
|
|
5
|
+
[
|
|
6
|
+
"perform.active_job",
|
|
7
|
+
"enqueue.active_job",
|
|
8
|
+
"enqueue_at.active_job"
|
|
9
|
+
]
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def setup_instruments
|
|
13
|
+
@instruments[:perform_duration] = meter.create_histogram(
|
|
14
|
+
metric_name("job.perform.duration"),
|
|
15
|
+
unit: "ms",
|
|
16
|
+
description: "Duration of ActiveJob job execution"
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
@instruments[:perform_count] = meter.create_counter(
|
|
20
|
+
metric_name("job.perform.count"),
|
|
21
|
+
unit: "jobs",
|
|
22
|
+
description: "Total number of ActiveJob jobs performed"
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
@instruments[:enqueue_count] = meter.create_counter(
|
|
26
|
+
metric_name("job.enqueue.count"),
|
|
27
|
+
unit: "jobs",
|
|
28
|
+
description: "Total number of ActiveJob jobs enqueued"
|
|
29
|
+
)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def on_event(name, started, finished, _unique_id, payload)
|
|
33
|
+
case name
|
|
34
|
+
when "perform.active_job"
|
|
35
|
+
record_perform(started, finished, payload)
|
|
36
|
+
when "enqueue.active_job", "enqueue_at.active_job"
|
|
37
|
+
record_enqueue(payload)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def record_perform(started, finished, payload)
|
|
44
|
+
job = payload[:job]
|
|
45
|
+
status = payload[:exception_object] ? "error" : "success"
|
|
46
|
+
|
|
47
|
+
attributes = {
|
|
48
|
+
"job_class" => job.class.name,
|
|
49
|
+
"queue_name" => job.queue_name.to_s,
|
|
50
|
+
"status" => status
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
duration = duration_ms(started, finished)
|
|
54
|
+
|
|
55
|
+
@instruments[:perform_duration].record(duration, attributes: attributes)
|
|
56
|
+
@instruments[:perform_count].add(1, attributes: attributes)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def record_enqueue(payload)
|
|
60
|
+
job = payload[:job]
|
|
61
|
+
|
|
62
|
+
attributes = {
|
|
63
|
+
"job_class" => job.class.name,
|
|
64
|
+
"queue_name" => job.queue_name.to_s
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@instruments[:enqueue_count].add(1, attributes: attributes)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
module OTLPRails
|
|
2
|
+
module Subscribers
|
|
3
|
+
class ActiveRecordSubscriber < Subscriber
|
|
4
|
+
OPERATION_REGEX = /\A\s*(SELECT|INSERT|UPDATE|DELETE)/i
|
|
5
|
+
SKIP_NAMES = ["SCHEMA", "EXPLAIN"].freeze
|
|
6
|
+
|
|
7
|
+
def self.events
|
|
8
|
+
["sql.active_record"]
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def setup_instruments
|
|
12
|
+
@instruments[:query_duration] = meter.create_histogram(
|
|
13
|
+
metric_name("db.query.duration"),
|
|
14
|
+
unit: "ms",
|
|
15
|
+
description: "Duration of SQL queries executed by ActiveRecord"
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
@instruments[:query_count] = meter.create_counter(
|
|
19
|
+
metric_name("db.query.count"),
|
|
20
|
+
unit: "queries",
|
|
21
|
+
description: "Total number of SQL queries executed by ActiveRecord"
|
|
22
|
+
)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def on_event(_name, started, finished, _unique_id, payload)
|
|
26
|
+
return if payload[:name].nil? || payload[:name].to_s.empty?
|
|
27
|
+
return if SKIP_NAMES.include?(payload[:name])
|
|
28
|
+
return if payload[:sql].nil? || payload[:sql].to_s.empty?
|
|
29
|
+
|
|
30
|
+
operation = extract_operation(payload[:sql])
|
|
31
|
+
return if !operation
|
|
32
|
+
|
|
33
|
+
attributes = {
|
|
34
|
+
"operation" => operation,
|
|
35
|
+
"name" => payload[:name].to_s
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
duration = duration_ms(started, finished)
|
|
39
|
+
|
|
40
|
+
@instruments[:query_duration].record(duration, attributes: attributes)
|
|
41
|
+
@instruments[:query_count].add(1, attributes: attributes)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
def extract_operation(sql)
|
|
47
|
+
match = sql.match(OPERATION_REGEX)
|
|
48
|
+
match ? match[1].upcase : nil
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
data/lib/otlp_rails.rb
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
require "otlp_rails/version"
|
|
2
|
+
require "otlp_rails/configuration"
|
|
3
|
+
require "otlp_rails/meter_provider_resolver"
|
|
4
|
+
require "otlp_rails/subscriber"
|
|
5
|
+
require "otlp_rails/subscribers/action_controller_subscriber"
|
|
6
|
+
require "otlp_rails/subscribers/active_record_subscriber"
|
|
7
|
+
require "otlp_rails/subscribers/active_job_subscriber"
|
|
8
|
+
require "otlp_rails/subscriber_registry"
|
|
9
|
+
require "otlp_rails/railtie" if defined?(Rails::Railtie)
|
|
10
|
+
|
|
11
|
+
module OTLPRails
|
|
12
|
+
class Error < StandardError; end
|
|
13
|
+
|
|
14
|
+
class << self
|
|
15
|
+
attr_accessor :meter
|
|
16
|
+
|
|
17
|
+
def configuration
|
|
18
|
+
@configuration ||= Configuration.new
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def configure
|
|
22
|
+
yield(configuration) if block_given?
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def reset!
|
|
26
|
+
@configuration = Configuration.new
|
|
27
|
+
@meter = nil
|
|
28
|
+
|
|
29
|
+
SubscriberRegistry.instance.unsubscribe_all
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def subscribe!
|
|
33
|
+
resolver = MeterProviderResolver.new(configuration)
|
|
34
|
+
meter_provider = resolver.resolve
|
|
35
|
+
|
|
36
|
+
self.meter = meter_provider.meter(
|
|
37
|
+
"otlp_rails",
|
|
38
|
+
version: VERSION
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
SubscriberRegistry.instance.subscribe_all(meter)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def unsubscribe!
|
|
45
|
+
SubscriberRegistry.instance.unsubscribe_all
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: otlp_rails
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.2.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Endoze
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: railties
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '7.0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '7.0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: activesupport
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '7.0'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '7.0'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: opentelemetry-api
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '1.0'
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '1.0'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: opentelemetry-metrics-api
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '0.2'
|
|
61
|
+
type: :runtime
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '0.2'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: opentelemetry-sdk
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - "~>"
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '1.0'
|
|
75
|
+
type: :runtime
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - "~>"
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '1.0'
|
|
82
|
+
- !ruby/object:Gem::Dependency
|
|
83
|
+
name: opentelemetry-metrics-sdk
|
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - "~>"
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: '0.12'
|
|
89
|
+
type: :runtime
|
|
90
|
+
prerelease: false
|
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
92
|
+
requirements:
|
|
93
|
+
- - "~>"
|
|
94
|
+
- !ruby/object:Gem::Version
|
|
95
|
+
version: '0.12'
|
|
96
|
+
- !ruby/object:Gem::Dependency
|
|
97
|
+
name: opentelemetry-exporter-otlp-metrics
|
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - "~>"
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: '0.7'
|
|
103
|
+
type: :runtime
|
|
104
|
+
prerelease: false
|
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - "~>"
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: '0.7'
|
|
110
|
+
description: Subscribes to Rails instrumentation events and records OpenTelemetry
|
|
111
|
+
metrics, pushing them via OTLP. Works standalone or alongside an existing OpenTelemetry
|
|
112
|
+
SDK setup.
|
|
113
|
+
executables: []
|
|
114
|
+
extensions: []
|
|
115
|
+
extra_rdoc_files: []
|
|
116
|
+
files:
|
|
117
|
+
- CHANGELOG.md
|
|
118
|
+
- LICENSE.txt
|
|
119
|
+
- lib/otlp_rails.rb
|
|
120
|
+
- lib/otlp_rails/configuration.rb
|
|
121
|
+
- lib/otlp_rails/meter_provider_resolver.rb
|
|
122
|
+
- lib/otlp_rails/railtie.rb
|
|
123
|
+
- lib/otlp_rails/subscriber.rb
|
|
124
|
+
- lib/otlp_rails/subscriber_registry.rb
|
|
125
|
+
- lib/otlp_rails/subscribers/action_controller_subscriber.rb
|
|
126
|
+
- lib/otlp_rails/subscribers/active_job_subscriber.rb
|
|
127
|
+
- lib/otlp_rails/subscribers/active_record_subscriber.rb
|
|
128
|
+
- lib/otlp_rails/version.rb
|
|
129
|
+
homepage: https://github.com/endoze/otlp_rails
|
|
130
|
+
licenses:
|
|
131
|
+
- MIT
|
|
132
|
+
metadata: {}
|
|
133
|
+
rdoc_options: []
|
|
134
|
+
require_paths:
|
|
135
|
+
- lib
|
|
136
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
137
|
+
requirements:
|
|
138
|
+
- - ">="
|
|
139
|
+
- !ruby/object:Gem::Version
|
|
140
|
+
version: '3.2'
|
|
141
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
142
|
+
requirements:
|
|
143
|
+
- - ">="
|
|
144
|
+
- !ruby/object:Gem::Version
|
|
145
|
+
version: '0'
|
|
146
|
+
requirements: []
|
|
147
|
+
rubygems_version: 3.6.9
|
|
148
|
+
specification_version: 4
|
|
149
|
+
summary: Rails ActiveSupport::Notifications to OpenTelemetry metrics via OTLP push
|
|
150
|
+
test_files: []
|