Module: Bitfab

Defined in:
lib/bitfab.rb,
lib/bitfab/client.rb,
lib/bitfab/replay.rb,
lib/bitfab/version.rb,
lib/bitfab/constants.rb,
lib/bitfab/serialize.rb,
lib/bitfab/traceable.rb,
lib/bitfab/warn_once.rb,
lib/bitfab/db_snapshot.rb,
lib/bitfab/http_client.rb,
lib/bitfab/span_context.rb,
lib/bitfab/replay_environment.rb

Defined Under Namespace

Modules: DbSnapshot, Replay, ReplayContext, Serialize, SpanContext, TraceState, Traceable Classes: BitfabFunction, Client, CurrentSpan, CurrentTrace, HttpClient, NoOpCurrentSpan, NoOpCurrentTrace, ReplayEnvironment

Constant Summary collapse

NO_OP_SPAN =
NoOpCurrentSpan.new.freeze
NO_OP_TRACE =
NoOpCurrentTrace.new.freeze
MOCK_STRATEGIES =

Replay mock strategies. Mirrors the Python and TypeScript SDKs.

  • “none” : every child span runs real code (default)

  • “all” : every child span returns its historical output

  • “marked” : only spans declared with mock_on_replay: true return historical

    output; everything else runs real code
    
%w[none all marked].freeze
VERSION =
"0.21.1"
DEFAULT_SERVICE_URL =
"https://bitfab.ai"
REPLAY_CONTEXT_KEY =
:__bitfab_replay_context

Class Method Summary collapse

Class Method Details

._reset_warn_onceObject

Test-only: clear the dedup set so a warning can fire again.



31
32
33
# File 'lib/bitfab/warn_once.rb', line 31

def _reset_warn_once
  @warn_once_mutex.synchronize { @warn_once_seen.clear }
end

._run_in_background(&block) ⇒ Object

Run a block in a background thread with tracking. Returns the thread for callers that need to join on it.



241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/bitfab/http_client.rb', line 241

def _run_in_background(&block)
  thread = Thread.new do
    block.call
  rescue => e
    Bitfab.warn_once(
      "send-request-failed",
      "failed to send a request to the backend (further occurrences " \
      "suppressed): #{e.message}"
    )
  ensure
    @pending_threads_mutex.synchronize { @pending_threads.delete(Thread.current) }
  end

  @pending_threads_mutex.synchronize { @pending_threads << thread }
  thread
end

.clientObject

Returns the global client, raising if not configured.



65
66
67
# File 'lib/bitfab.rb', line 65

def client
  @client or raise "Bitfab not configured. Call Bitfab.configure(api_key: '...') first."
end

.client_or_nilObject

Returns the global client, or nil if not configured. Used on the traced call path so a method invoked before Bitfab.configure runs untraced rather than crashing the host app with a “not configured” error.



72
73
74
# File 'lib/bitfab.rb', line 72

def client_or_nil
  @client
end

.configure(api_key:, service_url: nil, enabled: true) ⇒ Object

Configure the global Bitfab client.

Examples:

Bitfab.configure(api_key: ENV["BITFAB_API_KEY"])

Parameters:

  • api_key (String)

    API key for authentication

  • service_url (String, nil) (defaults to: nil)

    base URL (default: bitfab.ai)



60
61
62
# File 'lib/bitfab.rb', line 60

def configure(api_key:, service_url: nil, enabled: true)
  @client = Client.new(api_key:, service_url:, enabled:)
end

.current_spanCurrentSpan, NoOpCurrentSpan

Get a handle to the current active span.

Call this from inside a traced method to get a span handle that allows setting metadata at runtime.

Returns:



87
88
89
90
91
92
# File 'lib/bitfab.rb', line 87

def current_span
  entry = SpanContext.current
  return NO_OP_SPAN unless entry

  CurrentSpan.new(entry)
end

.current_traceCurrentTrace, NoOpCurrentTrace

Get a handle to the current active trace.

Call this from inside a traced method to get a trace handle that allows setting trace-level context at runtime.

Returns:



100
101
102
103
104
105
# File 'lib/bitfab.rb', line 100

def current_trace
  entry = SpanContext.current
  return NO_OP_TRACE unless entry

  CurrentTrace.new(entry[:trace_id])
end

.flush_traces(timeout: 30) ⇒ Object

Wait for all pending background threads to complete.



259
260
261
262
# File 'lib/bitfab/http_client.rb', line 259

def flush_traces(timeout: 30)
  threads = @pending_threads_mutex.synchronize { @pending_threads.dup }
  threads.each { |t| t.join(timeout) }
end

.reset!Object

Reset the global client (primarily for testing).



77
78
79
# File 'lib/bitfab.rb', line 77

def reset!
  @client = nil
end

.warn_once(key, message) ⇒ Object



17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/bitfab/warn_once.rb', line 17

def warn_once(key, message)
  @warn_once_mutex.synchronize do
    return if @warn_once_seen.include?(key)

    @warn_once_seen.add(key)
  end
  begin
    warn "Bitfab: #{message}"
  rescue Exception # rubocop:disable Lint/RescueException
    # Logging must never crash the host app (e.g. a closed $stderr).
  end
end