Module: Phlex::Reactive::APM
- Defined in:
- lib/phlex/reactive/apm.rb,
lib/phlex/reactive/apm/sentry.rb,
lib/phlex/reactive/apm/adapter.rb,
lib/phlex/reactive/apm/datadog.rb,
lib/phlex/reactive/apm/appsignal.rb,
lib/phlex/reactive/apm/subscriber.rb
Overview
Turnkey APM integration (issue #207). The gem already emits *.phlex_reactive
ActiveSupport::Notifications events (issue #107); this namespace turns them
into per-component visibility in AppSignal / Sentry / Datadog with ONE config
line — Phlex::Reactive.apm = :appsignal — instead of every app hand-writing
the subscribe block and each vendor's transaction-naming / error-tagging API.
The vendor adapters are RUNTIME capability-detected (defined?(::Appsignal)
etc.), never a gemspec dependency — the same optionality invariant as pgbus.
A set-but-absent SDK logs one warning and no-ops.
Defined Under Namespace
Classes: Adapter, Appsignal, Datadog, Sentry, Subscriber
Constant Summary collapse
- BUILT_INS =
Symbol => built-in adapter class. Resolved lazily (at attach time), so the adapter class is only referenced when an app actually opts into it.
{ appsignal: "Phlex::Reactive::APM::Appsignal", sentry: "Phlex::Reactive::APM::Sentry", datadog: "Phlex::Reactive::APM::Datadog" }.freeze
Class Method Summary collapse
-
.attach!(apm = Phlex::Reactive.apm) ⇒ Object
Attach the APM Subscriber to the notification bus if an adapter resolves.
-
.detect(apm) ⇒ Object
Resolve
Phlex::Reactive.apmto a live adapter instance, or nil. -
.reset! ⇒ Object
Drop the installed subscriber + adapter AND the memoized built-in instances.
Class Method Details
.attach!(apm = Phlex::Reactive.apm) ⇒ Object
Attach the APM Subscriber to the notification bus if an adapter resolves. Called once from the engine's after_initialize when Phlex::Reactive.apm is set. Idempotent within a boot: a second call with the SAME adapter is a no-op. Returns the attached adapter (or nil when nothing resolved).
54 55 56 57 58 59 60 61 62 63 |
# File 'lib/phlex/reactive/apm.rb', line 54 def attach!(apm = Phlex::Reactive.apm) adapter = detect(apm) return nil unless adapter Subscriber.install(adapter) # Hold the adapter so the endpoint's error seam (report_error) can reach # record_error without re-running detection per request. Phlex::Reactive.resolved_apm_adapter = adapter adapter end |
.detect(apm) ⇒ Object
Resolve Phlex::Reactive.apm to a live adapter instance, or nil.
- nil -> nil (off; no warning)
- an object -> returned verbatim (a custom adapter)
- a known Symbol -> the built-in adapter instance IF its SDK is loaded, else nil + one warning
- an unknown Symbol -> nil + one warning
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/phlex/reactive/apm.rb', line 30 def detect(apm) return nil if apm.nil? return apm unless apm.is_a?(Symbol) klass_name = BUILT_INS[apm] unless klass_name known = BUILT_INS.keys.map(&:inspect).join(", ") return warn_and_nil("apm = #{apm.inspect} — unknown APM flavour (known: #{known})") end klass = klass_name.constantize # Memoize the instance PER SYMBOL so repeated detect/attach! calls return # the SAME object — Subscriber.install keys idempotency on adapter # identity (equal?), so a fresh klass.new each time would double-subscribe. return (built_in_instances[apm] ||= klass.new) if klass.available? warn_and_nil("apm = #{apm.inspect} set but #{apm} is not loaded — no-op. " \ "Require the SDK (or remove the setting).") end |
.reset! ⇒ Object
Drop the installed subscriber + adapter AND the memoized built-in instances. Tests only (so a stubbed SDK doesn't leak a stale adapter into the next example).
68 69 70 71 72 |
# File 'lib/phlex/reactive/apm.rb', line 68 def reset! Subscriber.uninstall Phlex::Reactive.resolved_apm_adapter = nil @built_in_instances = nil end |