Module: Bitfab::Otel
- Defined in:
- lib/bitfab/otel.rb
Overview
OpenTelemetry delivery for Bitfab spans and trace completions.
Bitfab payloads ride as OTLP span attributes (bitfab.operation +
bitfab.payload), so a batch travels to Bitfab as OTLP/JSON without the
payload itself changing shape.
Defined Under Namespace
Modules: Encoder
Classes: BatchTransport, CarrierMeta, CarrierRef, DeliveryError, DeliveryTrackingExporter, DirectExporter, EncodedSpan, RequestBatch, RequestEnvelope
Constant Summary
collapse
- OPERATION_ATTRIBUTE =
"bitfab.operation"
- PAYLOAD_ATTRIBUTE =
"bitfab.payload"
- CARRIER_REF_IVAR =
:@bitfab_carrier_ref
- MAX_REQUEST_BYTES_ENV =
"BITFAB_OTEL_MAX_REQUEST_BYTES"
- EXPORT_CONCURRENCY_ENV =
"BITFAB_OTEL_EXPORT_CONCURRENCY"
- MAX_EXPORT_REQUEST_BYTES =
3_000_000
- MAX_DECOMPRESSED_REQUEST_BYTES =
8_000_000
- MAX_QUEUE_SIZE =
8_192
- DIRECT_MAX_EXPORT_BATCH_SIZE =
512
- DIRECT_MAX_REQUEST_BATCH_SIZE =
8
- DEFAULT_EXPORT_CONCURRENCY =
32
- MAX_EXPORT_CONCURRENCY =
64
- SCHEDULE_DELAY_MILLIS =
5_000
- EXPORT_TIMEOUT_MILLIS =
30_000
- EXPORT_RETRIES =
3
- RETRY_BASE_DELAY_MILLIS =
100
- RETRY_BACKOFF_CEILING_MILLIS =
Ceiling on the exponential growth of our OWN backoff. It does not bound a
wait the server asked for: OTLP says to honor Retry-After, and calls data
dropped while throttled the outcome to avoid. What bounds an honored wait
is the export budget, since the processor kills a longer export.
5_000
- SPAN_SEPARATOR_BYTES =
The comma that joins adjacent spans in the request's span list.
1
- SUCCESS =
OpenTelemetry::SDK::Trace::Export::SUCCESS
- FAILURE =
OpenTelemetry::SDK::Trace::Export::FAILURE
- SPAN_KINDS =
{
internal: 1,
server: 2,
client: 3,
producer: 4,
consumer: 5
}.freeze
- INVALID_SPAN_ID =
("\0" * 8).b
Class Method Summary
collapse
Class Method Details
.create_transport(direct_sender:, on_delivered: nil) ⇒ Object
133
134
135
136
137
138
139
140
|
# File 'lib/bitfab/otel.rb', line 133
def create_transport(direct_sender:, on_delivered: nil)
BatchTransport.new(
direct_sender:,
on_delivered:,
export_concurrency: export_concurrency_from_env,
max_request_bytes: max_request_bytes_from_env
)
end
|
.ensure_process_state ⇒ Object
Ruby has no after-fork hook a library can register (Python's
os.register_at_fork has no equivalent), so every entry point that
touches module state checks the pid first. Inherited mutexes need no
special handling: CRuby abandons a mutex held by a thread the child did
not inherit, so the child sees it unlocked.
177
178
179
180
181
182
|
# File 'lib/bitfab/otel.rb', line 177
def ensure_process_state
@state_pid ||= Process.pid
return if @state_pid == Process.pid
reset_state_after_fork
end
|
.export_concurrency_from_env ⇒ Object
.flush_transports(timeout = 30.0) ⇒ Object
152
153
154
155
156
157
158
|
# File 'lib/bitfab/otel.rb', line 152
def flush_transports(timeout = 30.0)
ensure_process_state
deadline = monotonic_now + [timeout, 0].max
current_process_transports.reduce(true) do |succeeded, transport|
transport.flush([deadline - monotonic_now, 0].max) && succeeded
end
end
|
.max_request_bytes_from_env ⇒ Object
.monotonic_now ⇒ Object
168
169
170
|
# File 'lib/bitfab/otel.rb', line 168
def monotonic_now
Process.clock_gettime(Process::CLOCK_MONOTONIC)
end
|
.register_transport(transport) ⇒ Object
142
143
144
145
|
# File 'lib/bitfab/otel.rb', line 142
def register_transport(transport)
ensure_process_state
live_transports_mutex.synchronize { live_transports << transport }
end
|
.reset_state_after_fork ⇒ Object
184
185
186
|
# File 'lib/bitfab/otel.rb', line 184
def reset_state_after_fork
@state_pid = Process.pid
end
|
.shutdown_transports(timeout = 30.0) ⇒ Object
160
161
162
163
164
165
166
|
# File 'lib/bitfab/otel.rb', line 160
def shutdown_transports(timeout = 30.0)
ensure_process_state
deadline = monotonic_now + [timeout, 0].max
current_process_transports.reduce(true) do |succeeded, transport|
transport.shutdown([deadline - monotonic_now, 0].max) && succeeded
end
end
|
.unregister_transport(transport) ⇒ Object
147
148
149
150
|
# File 'lib/bitfab/otel.rb', line 147
def unregister_transport(transport)
ensure_process_state
live_transports_mutex.synchronize { live_transports.delete(transport) }
end
|