bitfab 0.20.0 → 0.20.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/bitfab/replay.rb +44 -14
- data/lib/bitfab/traceable.rb +36 -0
- data/lib/bitfab/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d2428cc39dcd97d154e36ba9792628478e86a4b4dde5101c79d37ebb1635378f
|
|
4
|
+
data.tar.gz: effa0dba40674696ad3d9155615d9d9e2e40a3fe7f9aed9c8ee97516985e13c6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5f172f0178829a08315ae1caf3de6ff4a22389b2f83dbf449721ca53ca3a466580af00c15bd5279dffc2c9d074aee2afd0e157733f9257987460ef8d101350c9
|
|
7
|
+
data.tar.gz: 9c6af19d4ebac35d13280aeaa89ac6104cbff3020e24813e292e4170c6524016a0df943025f3ced5510345c863e4b86f9f027fe281912e99a6438f863dde9d28
|
data/lib/bitfab/replay.rb
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative "constants"
|
|
4
4
|
require_relative "serialize"
|
|
5
|
+
require_relative "traceable"
|
|
5
6
|
|
|
6
7
|
module Bitfab
|
|
7
8
|
# Replay mock strategies. Mirrors the Python and TypeScript SDKs.
|
|
@@ -117,6 +118,21 @@ module Bitfab
|
|
|
117
118
|
"determines how many traces replay."
|
|
118
119
|
end
|
|
119
120
|
|
|
121
|
+
# Reject a trace_function_key that contradicts the method's declared key.
|
|
122
|
+
# replay() fetches historical traces by trace_function_key but records the
|
|
123
|
+
# replayed spans under the method's own bitfab_span key (via send below),
|
|
124
|
+
# so a mismatch produces an incoherent test run (traces fetched for one
|
|
125
|
+
# function, recorded under another). Only fires when the method's key is
|
|
126
|
+
# introspectable; an untraced method falls through to the persistence
|
|
127
|
+
# check in complete_replay. Mirrors the TypeScript/Python SDKs.
|
|
128
|
+
declared_key = Traceable.trace_function_key_for(receiver, method_name)
|
|
129
|
+
if declared_key && declared_key != trace_function_key
|
|
130
|
+
raise ArgumentError,
|
|
131
|
+
"Method #{method_name} is traced under trace function key '#{declared_key}' but replay was " \
|
|
132
|
+
"called with '#{trace_function_key}'. Pass trace_function_key: '#{declared_key}' to replay it, " \
|
|
133
|
+
"or point at the method traced under '#{trace_function_key}'."
|
|
134
|
+
end
|
|
135
|
+
|
|
120
136
|
http_client = client.instance_variable_get(:@http_client)
|
|
121
137
|
|
|
122
138
|
# limit is meaningless with explicit trace_ids (the ID list determines
|
|
@@ -154,6 +170,10 @@ module Bitfab
|
|
|
154
170
|
# loudly.
|
|
155
171
|
complete_response = http_client.complete_replay(test_run_id)
|
|
156
172
|
trace_id_map = complete_response&.dig("traceIds")
|
|
173
|
+
# Per-replay-trace token usage keyed by server trace id: the REPLAYED
|
|
174
|
+
# run's tokens (span-aggregated server-side), used below to fill each
|
|
175
|
+
# item's :tokens.
|
|
176
|
+
replay_tokens = complete_response&.dig("tokens") || {}
|
|
157
177
|
|
|
158
178
|
if trace_id_map.nil?
|
|
159
179
|
# Older servers don't return the mapping. Preserve the legacy
|
|
@@ -186,6 +206,9 @@ module Bitfab
|
|
|
186
206
|
completed_count += 1
|
|
187
207
|
missing << item[:trace_id] if mapped.nil?
|
|
188
208
|
end
|
|
209
|
+
# Pull this item's replayed-run tokens by its server trace id, before
|
|
210
|
+
# :trace_id is overwritten with that id below.
|
|
211
|
+
item[:tokens] = normalize_tokens(replay_tokens[mapped]) if mapped
|
|
189
212
|
item[:trace_id] = mapped
|
|
190
213
|
end
|
|
191
214
|
if missing.any?
|
|
@@ -370,27 +393,34 @@ module Bitfab
|
|
|
370
393
|
}
|
|
371
394
|
end
|
|
372
395
|
|
|
373
|
-
# Pull durationMs /
|
|
374
|
-
#
|
|
375
|
-
#
|
|
396
|
+
# Pull durationMs / model from the start-replay server item. Nil-safe
|
|
397
|
+
# defaults so older servers without these fields still produce a consistent
|
|
398
|
+
# shape. Tokens are intentionally NOT read from the start item (it carries
|
|
399
|
+
# the ORIGINAL trace's tokens); the replayed run's tokens are filled in by
|
|
400
|
+
# run() from the complete-replay response once spans are aggregated
|
|
401
|
+
# server-side, and stay nil here and on older servers.
|
|
376
402
|
def extract_server_item_metrics(server_item)
|
|
377
|
-
raw_tokens = server_item["tokens"]
|
|
378
|
-
tokens = if raw_tokens.is_a?(Hash)
|
|
379
|
-
{
|
|
380
|
-
input: raw_tokens["input"],
|
|
381
|
-
output: raw_tokens["output"],
|
|
382
|
-
cached: raw_tokens["cached"],
|
|
383
|
-
total: raw_tokens["total"]
|
|
384
|
-
}
|
|
385
|
-
end
|
|
386
|
-
|
|
387
403
|
{
|
|
388
404
|
duration_ms: server_item["durationMs"],
|
|
389
|
-
tokens
|
|
405
|
+
tokens: nil,
|
|
390
406
|
model: server_item["model"]
|
|
391
407
|
}
|
|
392
408
|
end
|
|
393
409
|
|
|
410
|
+
# Normalize a complete-replay tokens hash (string-keyed JSON) into the
|
|
411
|
+
# symbol-keyed shape the replay item exposes. Nil when the server reported
|
|
412
|
+
# no token data for this trace.
|
|
413
|
+
def normalize_tokens(raw_tokens)
|
|
414
|
+
return nil unless raw_tokens.is_a?(Hash)
|
|
415
|
+
|
|
416
|
+
{
|
|
417
|
+
input: raw_tokens["input"],
|
|
418
|
+
output: raw_tokens["output"],
|
|
419
|
+
cached: raw_tokens["cached"],
|
|
420
|
+
total: raw_tokens["total"]
|
|
421
|
+
}
|
|
422
|
+
end
|
|
423
|
+
|
|
394
424
|
# Execute a single replay item: deserialize inputs, call method with replay context.
|
|
395
425
|
def execute_item(item, receiver, method_name, test_run_id, input_source_span_id = nil, metrics = {},
|
|
396
426
|
input_source_trace_id: nil, mock_strategy: "none", mock_tree: nil, adapt_inputs: nil, adapt_ctx: nil,
|
data/lib/bitfab/traceable.rb
CHANGED
|
@@ -69,9 +69,43 @@ module Bitfab
|
|
|
69
69
|
end
|
|
70
70
|
end
|
|
71
71
|
|
|
72
|
+
wrapper.instance_variable_set(:@bitfab_span_method, method_name_str)
|
|
73
|
+
wrapper.instance_variable_set(:@bitfab_span_key, trace_function_key)
|
|
72
74
|
klass.prepend(wrapper)
|
|
73
75
|
end
|
|
74
76
|
|
|
77
|
+
# Resolve the trace function key a traced method records spans under, or
|
|
78
|
+
# nil if the method carries no Bitfab span wrapper. Walks the receiver's
|
|
79
|
+
# ancestor chain for the wrapper module that bitfab_span / Traceable.wrap
|
|
80
|
+
# prepended. Instances resolve via the class. A Class/Module receiver
|
|
81
|
+
# resolves either way: singleton-class ancestors first (class/module
|
|
82
|
+
# methods wrapped on the singleton class), then the class's own ancestors
|
|
83
|
+
# (methods whose wrapper was prepended onto the class itself), so a
|
|
84
|
+
# class-method replay is guarded regardless of which surface carries the
|
|
85
|
+
# wrapper. Singleton-first keeps the method actually dispatched by
|
|
86
|
+
# `receiver.send` (a class method shadows a same-named instance wrapper).
|
|
87
|
+
#
|
|
88
|
+
# replay() uses this to reject a trace_function_key that contradicts the
|
|
89
|
+
# method's declared key: a mismatch fetches one function's historical
|
|
90
|
+
# traces but re-records the replay under the method's own key, producing
|
|
91
|
+
# an incoherent test run. Mirrors the TypeScript and Python SDKs, which
|
|
92
|
+
# throw on the same key mismatch.
|
|
93
|
+
def self.trace_function_key_for(receiver, method_name)
|
|
94
|
+
name = method_name.to_s
|
|
95
|
+
ancestors = if receiver.is_a?(Module)
|
|
96
|
+
receiver.singleton_class.ancestors + receiver.ancestors
|
|
97
|
+
else
|
|
98
|
+
receiver.class.ancestors
|
|
99
|
+
end
|
|
100
|
+
ancestors.each do |mod|
|
|
101
|
+
next unless mod.instance_variable_defined?(:@bitfab_span_method)
|
|
102
|
+
next unless mod.instance_variable_get(:@bitfab_span_method) == name
|
|
103
|
+
|
|
104
|
+
return mod.instance_variable_get(:@bitfab_span_key)
|
|
105
|
+
end
|
|
106
|
+
nil
|
|
107
|
+
end
|
|
108
|
+
|
|
75
109
|
module ClassMethods
|
|
76
110
|
# Set the trace function key for this class.
|
|
77
111
|
# All spans declared in this class will be grouped under this key.
|
|
@@ -152,6 +186,8 @@ module Bitfab
|
|
|
152
186
|
end
|
|
153
187
|
end
|
|
154
188
|
|
|
189
|
+
wrapper.instance_variable_set(:@bitfab_span_method, method_name_str)
|
|
190
|
+
wrapper.instance_variable_set(:@bitfab_span_key, trace_function_key)
|
|
155
191
|
prepend(wrapper)
|
|
156
192
|
end
|
|
157
193
|
end
|
data/lib/bitfab/version.rb
CHANGED