Skip to content

Commit d9124b0

Browse files
committed
Add Proof of Concept instrumentation for Solid Process
1 parent 9dc61ce commit d9124b0

File tree

6 files changed

+301
-21
lines changed

6 files changed

+301
-21
lines changed

Gemfile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ gem "tzinfo-data", platforms: %i[windows jruby]
3030
# Reduces boot times through caching; required in config/boot.rb
3131
gem "bootsnap", require: false
3232

33+
# OpenTelemetry tracing
34+
gem "opentelemetry-sdk"
35+
gem "opentelemetry-instrumentation-all"
36+
gem "opentelemetry-exporter-otlp"
37+
3338
group :development, :test do
3439
# See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
3540
gem "debug", platforms: %i[mri windows]

Gemfile.lock

Lines changed: 209 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,9 @@ GEM
176176
formtastic_i18n (0.7.0)
177177
globalid (1.2.1)
178178
activesupport (>= 6.1)
179+
google-protobuf (3.25.3-x86_64-linux)
180+
googleapis-common-protos-types (1.14.0)
181+
google-protobuf (~> 3.18)
179182
has_scope (0.8.2)
180183
actionpack (>= 5.2)
181184
activesupport (>= 5.2)
@@ -239,18 +242,211 @@ GEM
239242
net-smtp (0.5.0)
240243
net-protocol
241244
nio4r (2.7.1)
242-
nokogiri (1.16.4-aarch64-linux)
243-
racc (~> 1.4)
244-
nokogiri (1.16.4-arm-linux)
245-
racc (~> 1.4)
246-
nokogiri (1.16.4-arm64-darwin)
247-
racc (~> 1.4)
248-
nokogiri (1.16.4-x86-linux)
249-
racc (~> 1.4)
250-
nokogiri (1.16.4-x86_64-darwin)
251-
racc (~> 1.4)
252245
nokogiri (1.16.4-x86_64-linux)
253246
racc (~> 1.4)
247+
opentelemetry-api (1.2.5)
248+
opentelemetry-common (0.20.1)
249+
opentelemetry-api (~> 1.0)
250+
opentelemetry-exporter-otlp (0.26.3)
251+
google-protobuf (~> 3.14)
252+
googleapis-common-protos-types (~> 1.3)
253+
opentelemetry-api (~> 1.1)
254+
opentelemetry-common (~> 0.20)
255+
opentelemetry-sdk (~> 1.2)
256+
opentelemetry-semantic_conventions
257+
opentelemetry-helpers-mysql (0.1.0)
258+
opentelemetry-api (~> 1.0)
259+
opentelemetry-common (~> 0.20)
260+
opentelemetry-helpers-sql-obfuscation (0.1.0)
261+
opentelemetry-common (~> 0.20)
262+
opentelemetry-instrumentation-action_pack (0.9.0)
263+
opentelemetry-api (~> 1.0)
264+
opentelemetry-instrumentation-base (~> 0.22.1)
265+
opentelemetry-instrumentation-rack (~> 0.21)
266+
opentelemetry-instrumentation-action_view (0.7.0)
267+
opentelemetry-api (~> 1.0)
268+
opentelemetry-instrumentation-active_support (~> 0.1)
269+
opentelemetry-instrumentation-base (~> 0.22.1)
270+
opentelemetry-instrumentation-active_job (0.7.1)
271+
opentelemetry-api (~> 1.0)
272+
opentelemetry-instrumentation-base (~> 0.22.1)
273+
opentelemetry-instrumentation-active_model_serializers (0.20.1)
274+
opentelemetry-api (~> 1.0)
275+
opentelemetry-instrumentation-base (~> 0.22.1)
276+
opentelemetry-instrumentation-active_record (0.7.1)
277+
opentelemetry-api (~> 1.0)
278+
opentelemetry-instrumentation-base (~> 0.22.1)
279+
opentelemetry-instrumentation-active_support (0.5.1)
280+
opentelemetry-api (~> 1.0)
281+
opentelemetry-instrumentation-base (~> 0.22.1)
282+
opentelemetry-instrumentation-all (0.60.0)
283+
opentelemetry-instrumentation-active_model_serializers (~> 0.20.1)
284+
opentelemetry-instrumentation-aws_sdk (~> 0.5.0)
285+
opentelemetry-instrumentation-bunny (~> 0.21.0)
286+
opentelemetry-instrumentation-concurrent_ruby (~> 0.21.1)
287+
opentelemetry-instrumentation-dalli (~> 0.25.0)
288+
opentelemetry-instrumentation-delayed_job (~> 0.22.0)
289+
opentelemetry-instrumentation-ethon (~> 0.21.1)
290+
opentelemetry-instrumentation-excon (~> 0.22.0)
291+
opentelemetry-instrumentation-faraday (~> 0.24.0)
292+
opentelemetry-instrumentation-grape (~> 0.1.3)
293+
opentelemetry-instrumentation-graphql (~> 0.28.0)
294+
opentelemetry-instrumentation-gruf (~> 0.2.0)
295+
opentelemetry-instrumentation-http (~> 0.23.1)
296+
opentelemetry-instrumentation-http_client (~> 0.22.1)
297+
opentelemetry-instrumentation-koala (~> 0.20.1)
298+
opentelemetry-instrumentation-lmdb (~> 0.22.1)
299+
opentelemetry-instrumentation-mongo (~> 0.22.1)
300+
opentelemetry-instrumentation-mysql2 (~> 0.27.0)
301+
opentelemetry-instrumentation-net_http (~> 0.22.1)
302+
opentelemetry-instrumentation-pg (~> 0.27.0)
303+
opentelemetry-instrumentation-que (~> 0.8.0)
304+
opentelemetry-instrumentation-racecar (~> 0.3.0)
305+
opentelemetry-instrumentation-rack (~> 0.24.0)
306+
opentelemetry-instrumentation-rails (~> 0.30.0)
307+
opentelemetry-instrumentation-rake (~> 0.2.1)
308+
opentelemetry-instrumentation-rdkafka (~> 0.4.0)
309+
opentelemetry-instrumentation-redis (~> 0.25.1)
310+
opentelemetry-instrumentation-resque (~> 0.5.0)
311+
opentelemetry-instrumentation-restclient (~> 0.22.1)
312+
opentelemetry-instrumentation-ruby_kafka (~> 0.21.0)
313+
opentelemetry-instrumentation-sidekiq (~> 0.25.0)
314+
opentelemetry-instrumentation-sinatra (~> 0.23.1)
315+
opentelemetry-instrumentation-trilogy (~> 0.59.0)
316+
opentelemetry-instrumentation-aws_sdk (0.5.1)
317+
opentelemetry-api (~> 1.0)
318+
opentelemetry-instrumentation-base (~> 0.22.1)
319+
opentelemetry-instrumentation-base (0.22.3)
320+
opentelemetry-api (~> 1.0)
321+
opentelemetry-registry (~> 0.1)
322+
opentelemetry-instrumentation-bunny (0.21.2)
323+
opentelemetry-api (~> 1.0)
324+
opentelemetry-instrumentation-base (~> 0.22.1)
325+
opentelemetry-instrumentation-concurrent_ruby (0.21.2)
326+
opentelemetry-api (~> 1.0)
327+
opentelemetry-instrumentation-base (~> 0.22.1)
328+
opentelemetry-instrumentation-dalli (0.25.0)
329+
opentelemetry-api (~> 1.0)
330+
opentelemetry-common (~> 0.20.0)
331+
opentelemetry-instrumentation-base (~> 0.22.1)
332+
opentelemetry-instrumentation-delayed_job (0.22.1)
333+
opentelemetry-api (~> 1.0)
334+
opentelemetry-instrumentation-base (~> 0.22.1)
335+
opentelemetry-instrumentation-ethon (0.21.3)
336+
opentelemetry-api (~> 1.0)
337+
opentelemetry-common (~> 0.20.0)
338+
opentelemetry-instrumentation-base (~> 0.22.1)
339+
opentelemetry-instrumentation-excon (0.22.0)
340+
opentelemetry-api (~> 1.0)
341+
opentelemetry-common (~> 0.20.0)
342+
opentelemetry-instrumentation-base (~> 0.22.1)
343+
opentelemetry-instrumentation-faraday (0.24.1)
344+
opentelemetry-api (~> 1.0)
345+
opentelemetry-common (~> 0.20.0)
346+
opentelemetry-instrumentation-base (~> 0.22.1)
347+
opentelemetry-instrumentation-grape (0.1.6)
348+
opentelemetry-api (~> 1.0)
349+
opentelemetry-instrumentation-base (~> 0.22.1)
350+
opentelemetry-instrumentation-rack (~> 0.21)
351+
opentelemetry-instrumentation-graphql (0.28.1)
352+
opentelemetry-api (~> 1.0)
353+
opentelemetry-instrumentation-base (~> 0.22.1)
354+
opentelemetry-instrumentation-gruf (0.2.0)
355+
opentelemetry-api (>= 1.0.0)
356+
opentelemetry-instrumentation-base (~> 0.22.1)
357+
opentelemetry-instrumentation-http (0.23.2)
358+
opentelemetry-api (~> 1.0)
359+
opentelemetry-instrumentation-base (~> 0.22.1)
360+
opentelemetry-instrumentation-http_client (0.22.3)
361+
opentelemetry-api (~> 1.0)
362+
opentelemetry-common (~> 0.20.0)
363+
opentelemetry-instrumentation-base (~> 0.22.1)
364+
opentelemetry-instrumentation-koala (0.20.2)
365+
opentelemetry-api (~> 1.0)
366+
opentelemetry-common (~> 0.20.0)
367+
opentelemetry-instrumentation-base (~> 0.22.1)
368+
opentelemetry-instrumentation-lmdb (0.22.1)
369+
opentelemetry-api (~> 1.0)
370+
opentelemetry-instrumentation-base (~> 0.22.1)
371+
opentelemetry-instrumentation-mongo (0.22.2)
372+
opentelemetry-api (~> 1.0)
373+
opentelemetry-instrumentation-base (~> 0.22.1)
374+
opentelemetry-instrumentation-mysql2 (0.27.0)
375+
opentelemetry-api (~> 1.0)
376+
opentelemetry-helpers-mysql
377+
opentelemetry-helpers-sql-obfuscation
378+
opentelemetry-instrumentation-base (~> 0.22.1)
379+
opentelemetry-instrumentation-net_http (0.22.4)
380+
opentelemetry-api (~> 1.0)
381+
opentelemetry-common (~> 0.20.0)
382+
opentelemetry-instrumentation-base (~> 0.22.1)
383+
opentelemetry-instrumentation-pg (0.27.1)
384+
opentelemetry-api (~> 1.0)
385+
opentelemetry-helpers-sql-obfuscation
386+
opentelemetry-instrumentation-base (~> 0.22.1)
387+
opentelemetry-instrumentation-que (0.8.0)
388+
opentelemetry-api (~> 1.0)
389+
opentelemetry-instrumentation-base (~> 0.22.1)
390+
opentelemetry-instrumentation-racecar (0.3.1)
391+
opentelemetry-api (~> 1.0)
392+
opentelemetry-instrumentation-base (~> 0.22.1)
393+
opentelemetry-instrumentation-rack (0.24.1)
394+
opentelemetry-api (~> 1.0)
395+
opentelemetry-common (~> 0.20.0)
396+
opentelemetry-instrumentation-base (~> 0.22.1)
397+
opentelemetry-instrumentation-rails (0.30.0)
398+
opentelemetry-api (~> 1.0)
399+
opentelemetry-instrumentation-action_pack (~> 0.9.0)
400+
opentelemetry-instrumentation-action_view (~> 0.7.0)
401+
opentelemetry-instrumentation-active_job (~> 0.7.0)
402+
opentelemetry-instrumentation-active_record (~> 0.7.0)
403+
opentelemetry-instrumentation-active_support (~> 0.5.0)
404+
opentelemetry-instrumentation-base (~> 0.22.1)
405+
opentelemetry-instrumentation-rake (0.2.1)
406+
opentelemetry-api (~> 1.0)
407+
opentelemetry-instrumentation-base (~> 0.22.1)
408+
opentelemetry-instrumentation-rdkafka (0.4.3)
409+
opentelemetry-api (~> 1.0)
410+
opentelemetry-common (~> 0.20.0)
411+
opentelemetry-instrumentation-base (~> 0.22.1)
412+
opentelemetry-instrumentation-redis (0.25.3)
413+
opentelemetry-api (~> 1.0)
414+
opentelemetry-common (~> 0.20.0)
415+
opentelemetry-instrumentation-base (~> 0.22.1)
416+
opentelemetry-instrumentation-resque (0.5.1)
417+
opentelemetry-api (~> 1.0)
418+
opentelemetry-instrumentation-base (~> 0.22.1)
419+
opentelemetry-instrumentation-restclient (0.22.3)
420+
opentelemetry-api (~> 1.0)
421+
opentelemetry-common (~> 0.20.0)
422+
opentelemetry-instrumentation-base (~> 0.22.1)
423+
opentelemetry-instrumentation-ruby_kafka (0.21.0)
424+
opentelemetry-api (~> 1.0)
425+
opentelemetry-instrumentation-base (~> 0.22.1)
426+
opentelemetry-instrumentation-sidekiq (0.25.2)
427+
opentelemetry-api (~> 1.0)
428+
opentelemetry-common (~> 0.20.0)
429+
opentelemetry-instrumentation-base (~> 0.22.1)
430+
opentelemetry-instrumentation-sinatra (0.23.2)
431+
opentelemetry-api (~> 1.0)
432+
opentelemetry-common (~> 0.20.0)
433+
opentelemetry-instrumentation-base (~> 0.22.1)
434+
opentelemetry-instrumentation-rack (~> 0.21)
435+
opentelemetry-instrumentation-trilogy (0.59.2)
436+
opentelemetry-api (~> 1.0)
437+
opentelemetry-helpers-mysql
438+
opentelemetry-helpers-sql-obfuscation
439+
opentelemetry-instrumentation-base (~> 0.22.1)
440+
opentelemetry-semantic_conventions (>= 1.8.0)
441+
opentelemetry-registry (0.3.1)
442+
opentelemetry-api (~> 1.1)
443+
opentelemetry-sdk (1.4.1)
444+
opentelemetry-api (~> 1.1)
445+
opentelemetry-common (~> 0.20)
446+
opentelemetry-registry (~> 0.2)
447+
opentelemetry-semantic_conventions
448+
opentelemetry-semantic_conventions (1.10.0)
449+
opentelemetry-api (~> 1.0)
254450
parallel (1.24.0)
255451
parser (3.3.0.5)
256452
ast (~> 2.4.1)
@@ -376,11 +572,6 @@ GEM
376572
simplecov-html (0.12.3)
377573
simplecov_json_formatter (0.1.4)
378574
solid-result (2.0.0)
379-
sqlite3 (1.7.3-aarch64-linux)
380-
sqlite3 (1.7.3-arm-linux)
381-
sqlite3 (1.7.3-arm64-darwin)
382-
sqlite3 (1.7.3-x86-linux)
383-
sqlite3 (1.7.3-x86_64-darwin)
384575
sqlite3 (1.7.3-x86_64-linux)
385576
standard (1.35.1)
386577
language_server-protocol (~> 3.17.0.2)
@@ -424,11 +615,6 @@ GEM
424615
zeitwerk (2.6.13)
425616

426617
PLATFORMS
427-
aarch64-linux
428-
arm-linux
429-
arm64-darwin
430-
x86-linux
431-
x86_64-darwin
432618
x86_64-linux
433619

434620
DEPENDENCIES
@@ -440,6 +626,9 @@ DEPENDENCIES
440626
debug
441627
importmap-rails
442628
letter_opener (~> 1.9)
629+
opentelemetry-exporter-otlp
630+
opentelemetry-instrumentation-all
631+
opentelemetry-sdk
443632
propshaft (~> 0.8.0)
444633
puma (>= 5.0)
445634
rails (~> 7.1.3, >= 7.1.3.2)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
require "opentelemetry/sdk"
2+
require "opentelemetry/instrumentation/all"
3+
require "opentelemetry-exporter-otlp"
4+
5+
OpenTelemetry::SDK.configure do |c|
6+
c.service_name = "solid-rails-app"
7+
c.use_all # enables all instrumentation!
8+
end

config/initializers/solid_process.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,17 @@
99
require "solid/process/event_logs/json_logger_listener"
1010
# require "solid/process/event_logs/basic_logger_listener"
1111

12+
require "solid/process/active_support_publisher"
13+
14+
require "open_telemetry_tracer"
15+
OpenTelemetryTracer.subscribe
16+
1217
# Solid::Process::EventLogs::BasicLoggerListener.logger = Rails.logger
1318

1419
Solid::Result.configuration do |config|
1520
config.event_logs.listener = Solid::Result::EventLogs::Listeners[
1621
Solid::Process::EventLogs::JsonLoggerListener,
17-
Solid::Process::EventLogs::Record::Listener
22+
Solid::Process::EventLogs::Record::Listener,
23+
Solid::Process::ActiveSupportPublisher
1824
]
1925
end

lib/open_telemetry_tracer.rb

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
module OpenTelemetryTracer
2+
SolidResultTracer = ::OpenTelemetry.tracer_provider.tracer("solid-result")
3+
4+
module ProcessListener
5+
def self.start(name, _id, payload)
6+
scope = payload[:scope]
7+
8+
span = SolidResultTracer.start_span("#{scope[:name]}#call", attributes: {
9+
"desc" => scope[:desc].inspect
10+
})
11+
12+
token = OpenTelemetry::Context.attach(::OpenTelemetry::Trace.context_with_span(span))
13+
payload.merge!(__otel: {span:, token:})
14+
end
15+
16+
def self.finish(_name, _id, payload)
17+
otel = payload.delete(:__otel)
18+
19+
otel => { span:, token: }
20+
21+
span.finish
22+
OpenTelemetry::Context.detach(token)
23+
end
24+
end
25+
26+
module AndThenListener
27+
def self.start(name, _id, payload)
28+
payload => { scope:, and_then: }
29+
30+
span = SolidResultTracer.start_span("#{scope[:name]}##{and_then[:method_name] || "block"}", attributes: {
31+
"type" => and_then[:type].to_s,
32+
"arg" => and_then[:arg].inspect
33+
})
34+
35+
token = OpenTelemetry::Context.attach(::OpenTelemetry::Trace.context_with_span(span))
36+
payload.merge!(__otel: {span:, token:})
37+
end
38+
39+
def self.finish(_name, _id, payload)
40+
otel = payload.delete(:__otel)
41+
42+
otel => { span:, token: }
43+
44+
span.finish
45+
OpenTelemetry::Context.detach(token)
46+
end
47+
end
48+
49+
def self.subscribe
50+
ActiveSupport::Notifications.monotonic_subscribe("start_process.solid_process", ProcessListener)
51+
ActiveSupport::Notifications.monotonic_subscribe("and_then.solid_process", AndThenListener)
52+
end
53+
end
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
class Solid::Process::ActiveSupportPublisher
2+
include Solid::Result::EventLogs::Listener
3+
4+
def self.around_event_logs?
5+
true
6+
end
7+
8+
def self.around_and_then?
9+
true
10+
end
11+
12+
def around_event_logs(scope:, &)
13+
ActiveSupport::Notifications.instrument("start_process.solid_process", scope:, &)
14+
end
15+
16+
def around_and_then(scope:, and_then:, **, &)
17+
ActiveSupport::Notifications.instrument("and_then.solid_process", scope:, and_then:, &)
18+
end
19+
end

0 commit comments

Comments
 (0)