foam-ruby 0.1.0.alpha8 → 0.1.0.alpha10

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: a4435b32248c007790701a7de2054f702398a2f1881bcaa571f20f209825d5e8
4
- data.tar.gz: 82a9836aa895f5b1b70ace7b441dd288997ff7e2772a5c1e5f7742a2fa22dcc6
3
+ metadata.gz: 71780521715f934380dd5f95a3a37dcb08f20080da5cd1c118323b436e96c2bb
4
+ data.tar.gz: fac0121d3b535c4e36d75cedb35fe5e74fc0bbb286f8ed168485f8e2b20abd7b
5
5
  SHA512:
6
- metadata.gz: 8e3792c185a39b7470ddf0b0037580fcf45ed9f906d4834ea28bd837422df5fbb365109f9525fae66e7cb68121844ad119f38228d83bcfb0946965fbf6b005d2
7
- data.tar.gz: 4fab2024d4ef4e8fe3601e3836e8af28544feaefd41d80e929721f651ac7ba84c034810dc923d90bf9a540ac335dd6c25db7d4567ea30b3c039f61abd9115a84
6
+ metadata.gz: 2b2e862134bc9f576ee91f1e7343af59ca31889392c959929f0bc8fcc931ea748b3b9f0796629eecf1bbd243f8927caacb456b0304b4bc1429bcd5e6493d0d3c
7
+ data.tar.gz: 40d3e22371d54dad030036a5a552718b391c3112e7c114e49c5741e3c63906de62d459fb7bff0471be84f81fe6a795c35b7352613649f2e4362d54287ca285f5
@@ -9,7 +9,7 @@ module Foam
9
9
 
10
10
  def initialize
11
11
  @token = ENV["FOAM_API_TOKEN"]
12
- @service_name = ENV.fetch("OTEL_SERVICE_NAME", "rails-app")
12
+ @service_name = ENV["OTEL_SERVICE_NAME"]
13
13
  @endpoint = ENV.fetch("FOAM_OTEL_ENDPOINT", FOAM_OTEL_ENDPOINT)
14
14
  end
15
15
 
@@ -26,7 +26,13 @@ module Foam
26
26
  end
27
27
 
28
28
  def valid?
29
- !token.nil? && !token.empty?
29
+ present?(token) && present?(service_name)
30
+ end
31
+
32
+ private
33
+
34
+ def present?(val)
35
+ !val.nil? && !val.empty?
30
36
  end
31
37
  end
32
38
  end
@@ -24,13 +24,14 @@ module Foam
24
24
  }.freeze
25
25
 
26
26
  def initialize
27
- @otel_logger = OpenTelemetry.logger_provider.logger(name: "foam-ruby")
27
+ @logger_name = "foam-ruby"
28
28
  end
29
29
 
30
30
  def emit(severity, message)
31
31
  return if message.nil? || (message.respond_to?(:empty?) && message.empty?)
32
32
 
33
- @otel_logger.on_emit(
33
+ otel_logger = OpenTelemetry.logger_provider.logger(name: @logger_name)
34
+ otel_logger.on_emit(
34
35
  body: message.to_s,
35
36
  severity_number: SEVERITY_MAP.fetch(severity, OpenTelemetry::Logs::SeverityNumber::SEVERITY_NUMBER_INFO),
36
37
  severity_text: SEVERITY_TEXT.fetch(severity, "INFO"),
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Foam
4
+ module Ruby
5
+ class Middleware
6
+ def initialize(app)
7
+ @app = app
8
+ end
9
+
10
+ def call(env)
11
+ Foam::Ruby.ensure_worker_setup!
12
+ @app.call(env)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -27,6 +27,7 @@ module Foam
27
27
  existing = OpenTelemetry.tracer_provider
28
28
  if existing.is_a?(OpenTelemetry::SDK::Trace::TracerProvider)
29
29
  existing.add_span_processor(@foam_span_processor)
30
+ install_instrumentations!
30
31
  else
31
32
  OpenTelemetry::SDK.configure do |c|
32
33
  c.service_name = config.service_name
@@ -38,6 +39,15 @@ module Foam
38
39
  @attached_provider = OpenTelemetry.tracer_provider
39
40
  end
40
41
 
42
+ def install_instrumentations!
43
+ registry = OpenTelemetry::Instrumentation.registry
44
+ return unless registry
45
+
46
+ registry.each do |instrumentation|
47
+ instrumentation.install unless instrumentation.installed?
48
+ end
49
+ end
50
+
41
51
  def ensure_processor_attached!
42
52
  return unless @foam_span_processor
43
53
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Foam
4
4
  module Ruby
5
- VERSION = "0.1.0.alpha8"
5
+ VERSION = "0.1.0.alpha10"
6
6
  end
7
7
  end
data/lib/foam/ruby.rb CHANGED
@@ -11,6 +11,7 @@ module Foam
11
11
  end
12
12
 
13
13
  def init(token: nil, service_name: nil)
14
+ return if initialized?
14
15
  return unless production?
15
16
 
16
17
  config = configuration
@@ -18,16 +19,17 @@ module Foam
18
19
  config.service_name = service_name if service_name
19
20
 
20
21
  unless config.valid?
21
- warn "[foam-ruby] Missing token — set FOAM_API_TOKEN or pass token: to Foam::Ruby.init"
22
+ warn "[foam-ruby] Missing required config — set OTEL_FOAM_COLLECTOR_BEARER_TOKEN and OTEL_SERVICE_NAME, " \
23
+ "or pass token: and service_name: to Foam::Ruby.init"
22
24
  return
23
25
  end
24
26
 
25
27
  require_relative "ruby/otel_setup"
26
28
  require_relative "ruby/log_subscriber"
29
+ require_relative "ruby/middleware"
27
30
 
28
31
  OtelSetup.configure!(config)
29
- schedule_trace_reattach!
30
- schedule_logger_attach!
32
+ insert_middleware!
31
33
  bridge_sentry!
32
34
  @initialized = true
33
35
  rescue Exception => e # rubocop:disable Lint/RescueException
@@ -35,6 +37,24 @@ module Foam
35
37
  @initialized = false
36
38
  end
37
39
 
40
+ # Ensures Foam's processors and logger broadcast are attached in the
41
+ # current process. Called by Middleware on the first request per worker
42
+ # PID — a single integer comparison on every subsequent request.
43
+ # Public so non-Rails apps can call it from custom fork hooks.
44
+ def ensure_worker_setup!
45
+ return unless initialized?
46
+
47
+ pid = Process.pid
48
+ return if @worker_pid == pid
49
+ @worker_pid = pid
50
+
51
+ OtelSetup.ensure_processor_attached!
52
+ OtelSetup.ensure_log_processor_attached!
53
+ attach_otel_logger!
54
+ rescue Exception # rubocop:disable Lint/RescueException
55
+ nil
56
+ end
57
+
38
58
  def capture_exception(error, attributes: {})
39
59
  return unless initialized?
40
60
 
@@ -72,14 +92,10 @@ module Foam
72
92
  false
73
93
  end
74
94
 
75
- def schedule_logger_attach!
76
- return unless defined?(::Rails)
95
+ def insert_middleware!
96
+ return unless defined?(::Rails) && ::Rails.respond_to?(:application) && ::Rails.application
77
97
 
78
- if ::Rails.respond_to?(:application) && ::Rails.application
79
- ::Rails.application.config.after_initialize { do_attach_otel_logger! }
80
- else
81
- do_attach_otel_logger!
82
- end
98
+ ::Rails.application.middleware.insert(0, Foam::Ruby::Middleware)
83
99
  rescue Exception # rubocop:disable Lint/RescueException
84
100
  nil
85
101
  end
@@ -101,31 +117,30 @@ module Foam
101
117
  nil
102
118
  end
103
119
 
104
- def schedule_trace_reattach!
105
- return unless defined?(::Rails) && ::Rails.respond_to?(:application) && ::Rails.application
120
+ def attach_otel_logger!
121
+ return unless defined?(::Rails) && ::Rails.respond_to?(:logger) && ::Rails.logger
106
122
 
107
- ::Rails.application.config.after_initialize do
108
- OtelSetup.ensure_processor_attached!
109
- OtelSetup.ensure_log_processor_attached!
123
+ unless OpenTelemetry.logger_provider.is_a?(OpenTelemetry::SDK::Logs::LoggerProvider)
124
+ return
110
125
  end
111
- rescue Exception # rubocop:disable Lint/RescueException
112
- nil
113
- end
114
126
 
115
- def do_attach_otel_logger!
116
- return unless ::Rails.respond_to?(:logger) && ::Rails.logger
127
+ logger = ::Rails.logger
117
128
 
118
- unless OpenTelemetry.logger_provider.is_a?(OpenTelemetry::SDK::Logs::LoggerProvider)
119
- return
129
+ if logger.respond_to?(:broadcasts)
130
+ return if logger.broadcasts.any? { |l| l.is_a?(OtelLogger) }
131
+ else
132
+ return if logger.equal?(@attached_rails_logger)
120
133
  end
121
134
 
122
135
  otel_logger = OtelLogger.new
123
136
 
124
- if ::Rails.logger.respond_to?(:broadcast_to)
125
- ::Rails.logger.broadcast_to(otel_logger)
137
+ if logger.respond_to?(:broadcast_to)
138
+ logger.broadcast_to(otel_logger)
126
139
  elsif defined?(::ActiveSupport::Logger) && ::ActiveSupport::Logger.respond_to?(:broadcast)
127
- ::Rails.logger.extend(::ActiveSupport::Logger.broadcast(otel_logger))
140
+ logger.extend(::ActiveSupport::Logger.broadcast(otel_logger))
128
141
  end
142
+
143
+ @attached_rails_logger = logger
129
144
  rescue Exception # rubocop:disable Lint/RescueException
130
145
  nil
131
146
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foam-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.alpha8
4
+ version: 0.1.0.alpha10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Foam
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-04-15 00:00:00.000000000 Z
11
+ date: 2026-04-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: opentelemetry-api
@@ -218,6 +218,7 @@ files:
218
218
  - lib/foam/ruby.rb
219
219
  - lib/foam/ruby/configuration.rb
220
220
  - lib/foam/ruby/log_subscriber.rb
221
+ - lib/foam/ruby/middleware.rb
221
222
  - lib/foam/ruby/otel_setup.rb
222
223
  - lib/foam/ruby/version.rb
223
224
  homepage: https://github.com/nicktesh/packages