Module: Wurk::Telemetry

Defined in:
lib/wurk/telemetry.rb,
lib/wurk/telemetry/client_middleware.rb,
lib/wurk/telemetry/server_middleware.rb

Overview

Distributed tracing over the Redis hop: a producer span on enqueue whose W3C trace context rides the job hash, and a linked consumer span when a worker picks the job up.

This file is not loaded by require "wurk". Configuration#telemetry= pulls it in, so an app that never opts in never requires opentelemetry-api either — Wurk does not decide on a host's behalf when a third-party gem gets loaded, and an app with the gem installed but tracing off keeps the exact object graph, payload bytes and hot path it has today.

Opt in from the server config:

Wurk.configure_server do |config|
config.telemetry = true
end

Both halves must hold before anything registers: the gem has to be there (Telemetry.available?) and the host has to have asked (Configuration#telemetry?). Telemetry.enabled? is that gate.

There is no Sidekiq::Telemetry alias: upstream Sidekiq has no such constant, so aliasing would invent a Sidekiq surface rather than mirror one — same call as Wurk::Status (see lib/wurk/compat.rb).

Defined Under Namespace

Classes: ClientMiddleware, ServerMiddleware

Constant Summary collapse

INSTRUMENTATION_NAME =

Instrumentation scope stamped on every span this gem emits.

'wurk'
REQUIRED_API =

The API the client/server middlewares call. A defined ::OpenTelemetry is not proof the gem is there — a host can own that constant itself, and an opentelemetry-api old enough to predate these entry points would answer the constant check too. Asking for the surface at install time turns either case into "tracing stays off" rather than a NoMethodError on the first job of a deploy.

%i[propagation tracer_provider].freeze

Class Method Summary collapse

Class Method Details

.available?Boolean

Not memoized. A host is free to require opentelemetry after this file (an initializer ordering Wurk before its tracing setup), and a false cached at load would disable tracing for the life of the process with nothing to point at.

Returns:

  • (Boolean)

    whether opentelemetry-api is loaded and exposes REQUIRED_API.



63
64
65
66
67
# File 'lib/wurk/telemetry.rb', line 63

def available?
  return false unless defined?(::OpenTelemetry)

  REQUIRED_API.all? { |method| ::OpenTelemetry.respond_to?(method) }
end

.enabled?(config = Wurk.configuration) ⇒ Boolean

The registration gate — the host flag first, deliberately: an app that never opted in must not so much as resolve the OTel constant.

Parameters:

Returns:

  • (Boolean)


74
75
76
# File 'lib/wurk/telemetry.rb', line 74

def enabled?(config = Wurk.configuration)
  config.telemetry? && available?
end

.install!(config = Wurk.configuration) ⇒ Object

Bring the middleware registrations in line with enabled?. Called by Configuration#telemetry=, so the chain follows the flag in both directions: a host that turns tracing back off (a test, a capsule built for a client-only process) must stop stamping payloads, not just stop exporting.

Idempotent — Chain#add and the insert helpers all drop any prior entry for the same class first.

Parameters:



88
89
90
91
92
93
94
95
96
# File 'lib/wurk/telemetry.rb', line 88

def install!(config = Wurk.configuration)
  unless enabled?(config)
    config.client_middleware.remove(ClientMiddleware)
    return config.server_middleware.remove(ServerMiddleware)
  end

  config.client_middleware.add(ClientMiddleware)
  install_server(config.server_middleware)
end

.tracerObject

Memoized against the provider that produced it rather than once for the process: OpenTelemetry::SDK.configure is routinely called after the code that will emit spans is loaded, and OpenTelemetry.tracer_provider= swaps the object — a tracer cached before that would silently export nothing for the life of the process. The check costs one equal? per enqueue and re-resolves whenever the provider actually changes.

The pair is published in a single store so a concurrent reader sees either the old provider with its own tracer or the new one with its own, never a tracer attributed to the wrong provider.



108
109
110
111
112
113
114
# File 'lib/wurk/telemetry.rb', line 108

def tracer
  memo     = @tracer
  provider = ::OpenTelemetry.tracer_provider
  return memo[1] if memo && memo[0].equal?(provider)

  (@tracer = [provider, provider.tracer(INSTRUMENTATION_NAME, Wurk::VERSION)].freeze)[1]
end