Module: Bitfab::Traceable
- Defined in:
- lib/bitfab/traceable.rb
Overview
Mixin for declarative span tracing on instance methods.
Defined Under Namespace
Modules: ClassMethods
Class Method Summary collapse
- .included(base) ⇒ Object
-
.trace_function_key_for(receiver, method_name) ⇒ Object
Resolve the trace function key a traced method records spans under, or nil if the method carries no Bitfab span wrapper.
-
.wrap(klass, method_name, trace_function_key:, name: nil, type: "custom", mock_on_replay: false, client: nil) ⇒ Object
Wrap an existing method on an external class with span tracing.
Class Method Details
.included(base) ⇒ Object
25 26 27 |
# File 'lib/bitfab/traceable.rb', line 25 def self.included(base) base.extend(ClassMethods) end |
.trace_function_key_for(receiver, method_name) ⇒ Object
Resolve the trace function key a traced method records spans under, or nil if the method carries no Bitfab span wrapper. Walks the receiver’s ancestor chain for the wrapper module that bitfab_span / Traceable.wrap prepended. Instances resolve via the class. A Class/Module receiver resolves either way: singleton-class ancestors first (class/module methods wrapped on the singleton class), then the class’s own ancestors (methods whose wrapper was prepended onto the class itself), so a class-method replay is guarded regardless of which surface carries the wrapper. Singleton-first keeps the method actually dispatched by ‘receiver.send` (a class method shadows a same-named instance wrapper).
replay() uses this to reject a trace_function_key that contradicts the method’s declared key: a mismatch fetches one function’s historical traces but re-records the replay under the method’s own key, producing an incoherent test run. Mirrors the TypeScript and Python SDKs, which throw on the same key mismatch.
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/bitfab/traceable.rb', line 93 def self.trace_function_key_for(receiver, method_name) name = method_name.to_s ancestors = if receiver.is_a?(Module) receiver.singleton_class.ancestors + receiver.ancestors else receiver.class.ancestors end ancestors.each do |mod| next unless mod.instance_variable_defined?(:@bitfab_span_method) next unless mod.instance_variable_get(:@bitfab_span_method) == name return mod.instance_variable_get(:@bitfab_span_key) end nil end |
.wrap(klass, method_name, trace_function_key:, name: nil, type: "custom", mock_on_replay: false, client: nil) ⇒ Object
Wrap an existing method on an external class with span tracing. Use this to trace third-party library calls without modifying their source.
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/bitfab/traceable.rb', line 50 def self.wrap(klass, method_name, trace_function_key:, name: nil, type: "custom", mock_on_replay: false, client: nil) span_name = name || method_name.to_s method_name_str = method_name.to_s bound_client = client wrapper = Module.new do define_method(method_name) do |*args, **kwargs, &block| target_client = bound_client || Bitfab.client target_client.send(:execute_span, trace_function_key:, span_name:, span_type: type, function_name: method_name_str, args:, kwargs:, mock_on_replay:) do super(*args, **kwargs, &block) end end end wrapper.instance_variable_set(:@bitfab_span_method, method_name_str) wrapper.instance_variable_set(:@bitfab_span_key, trace_function_key) klass.prepend(wrapper) end |