bitfab 0.10.4 → 0.10.6
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/client.rb +20 -3
- data/lib/bitfab/http_client.rb +20 -1
- data/lib/bitfab/replay.rb +28 -7
- data/lib/bitfab/span_context.rb +3 -2
- 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: f20353e1bb03affda1786ed5f8566ab1b3a401f0f9635023bae2fd350bcc7de6
|
|
4
|
+
data.tar.gz: 8e10f199e9d81cfdbfa2bc9172327131301dc3959307340bbe6c55e1ef2bc235
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ade88c2b4d5878a3f6e0cee6f70c4a2d63b1a2f0359f425e9da6ab787806c8ef9396ca0e0a71f5ec7c75647e658419f0e9eb099fbbb4ce22a56c38adf26632e8
|
|
7
|
+
data.tar.gz: 9aa7b82e532a84893533b97d67d413cd4012729624d6bde8433bfdecf73c1d929269e6a1d779e50ed7d13e6dcc84a050f22fdf41282f2de4469bd0c5a6a35b30
|
data/lib/bitfab/client.rb
CHANGED
|
@@ -36,9 +36,18 @@ module Bitfab
|
|
|
36
36
|
# @param limit [Integer] maximum number of traces to replay (default: 5)
|
|
37
37
|
# @param trace_ids [Array<String>, nil] optional list of trace IDs to filter
|
|
38
38
|
# @param max_concurrency [Integer, nil] max threads for parallel replay (default: 10)
|
|
39
|
+
# @param code_change_description [String, nil] optional rationale for the
|
|
40
|
+
# code change being tested in this replay (stored on the experiment)
|
|
41
|
+
# @param code_change_files [Array<Hash>, nil] optional list of edited files,
|
|
42
|
+
# each as { path:, before:, after: } (use "" for new/deleted files)
|
|
39
43
|
# @return [Hash] with :items, :test_run_id, :test_run_url
|
|
40
|
-
def replay(receiver, method_name, trace_function_key:, limit: 5, trace_ids: nil, max_concurrency: 10
|
|
41
|
-
|
|
44
|
+
def replay(receiver, method_name, trace_function_key:, limit: 5, trace_ids: nil, max_concurrency: 10,
|
|
45
|
+
code_change_description: nil, code_change_files: nil)
|
|
46
|
+
Replay.run(
|
|
47
|
+
self, receiver, method_name,
|
|
48
|
+
trace_function_key:, limit:, trace_ids:, max_concurrency:,
|
|
49
|
+
code_change_description:, code_change_files:
|
|
50
|
+
)
|
|
42
51
|
end
|
|
43
52
|
|
|
44
53
|
# Execute a block inside a span context, sending trace data on completion.
|
|
@@ -56,10 +65,15 @@ module Bitfab
|
|
|
56
65
|
replay_ctx = ReplayContext.current
|
|
57
66
|
resolved_test_run_id = replay_ctx&.dig(:test_run_id)
|
|
58
67
|
resolved_input_source_span_id = replay_ctx&.dig(:input_source_span_id)
|
|
68
|
+
resolved_input_source_trace_id = replay_ctx&.dig(:input_source_trace_id)
|
|
59
69
|
|
|
60
70
|
# Register trace state for root spans
|
|
61
71
|
if is_root_span && !TraceState.get(trace_id)
|
|
62
|
-
TraceState.create(
|
|
72
|
+
TraceState.create(
|
|
73
|
+
trace_id,
|
|
74
|
+
test_run_id: resolved_test_run_id,
|
|
75
|
+
input_source_trace_id: resolved_input_source_trace_id
|
|
76
|
+
)
|
|
63
77
|
end
|
|
64
78
|
|
|
65
79
|
if is_root_span
|
|
@@ -219,6 +233,9 @@ module Bitfab
|
|
|
219
233
|
if trace_state&.dig(:contexts)
|
|
220
234
|
raw_trace["contexts"] = trace_state[:contexts]
|
|
221
235
|
end
|
|
236
|
+
if trace_state&.dig(:input_source_trace_id)
|
|
237
|
+
raw_trace["input_source_trace_id"] = trace_state[:input_source_trace_id]
|
|
238
|
+
end
|
|
222
239
|
|
|
223
240
|
payload = {
|
|
224
241
|
"type" => "sdk-function",
|
data/lib/bitfab/http_client.rb
CHANGED
|
@@ -98,12 +98,19 @@ module Bitfab
|
|
|
98
98
|
|
|
99
99
|
# Start a replay session by fetching historical traces.
|
|
100
100
|
# Blocking call. Returns hash with testRunId, testRunUrl, and items array.
|
|
101
|
-
|
|
101
|
+
#
|
|
102
|
+
# @param code_change_description [String, nil] optional rationale for the
|
|
103
|
+
# code change being tested in this replay
|
|
104
|
+
# @param code_change_files [Array<Hash>, nil] optional list of edited files,
|
|
105
|
+
# each as { path:, before:, after: } (use "" for new/deleted files)
|
|
106
|
+
def start_replay(trace_function_key, limit, trace_ids: nil, code_change_description: nil, code_change_files: nil)
|
|
102
107
|
payload = {
|
|
103
108
|
"traceFunctionKey" => trace_function_key,
|
|
104
109
|
"limit" => limit
|
|
105
110
|
}
|
|
106
111
|
payload["traceIds"] = trace_ids if trace_ids
|
|
112
|
+
payload["codeChangeDescription"] = code_change_description unless code_change_description.nil?
|
|
113
|
+
payload["codeChangeFiles"] = normalize_code_change_files(code_change_files) unless code_change_files.nil?
|
|
107
114
|
|
|
108
115
|
request("/api/sdk/replay/start", payload, timeout: 30)
|
|
109
116
|
end
|
|
@@ -129,6 +136,18 @@ module Bitfab
|
|
|
129
136
|
|
|
130
137
|
private
|
|
131
138
|
|
|
139
|
+
# Normalize each entry to a hash with stable string keys, accepting either
|
|
140
|
+
# symbol-keyed or string-keyed hashes from callers.
|
|
141
|
+
def normalize_code_change_files(files)
|
|
142
|
+
files.map do |file|
|
|
143
|
+
{
|
|
144
|
+
"path" => file[:path] || file["path"],
|
|
145
|
+
"before" => file[:before] || file["before"],
|
|
146
|
+
"after" => file[:after] || file["after"]
|
|
147
|
+
}
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
132
151
|
def headers
|
|
133
152
|
{
|
|
134
153
|
"Content-Type" => "application/json",
|
data/lib/bitfab/replay.rb
CHANGED
|
@@ -14,11 +14,12 @@ module Bitfab
|
|
|
14
14
|
|
|
15
15
|
# Execute a block with replay context set on the current thread.
|
|
16
16
|
# The context is automatically cleared when the block completes.
|
|
17
|
-
def with_context(test_run_id:, input_source_span_id: nil)
|
|
17
|
+
def with_context(test_run_id:, input_source_span_id: nil, input_source_trace_id: nil)
|
|
18
18
|
previous = Thread.current[REPLAY_CONTEXT_KEY]
|
|
19
19
|
Thread.current[REPLAY_CONTEXT_KEY] = {
|
|
20
20
|
test_run_id:,
|
|
21
|
-
input_source_span_id
|
|
21
|
+
input_source_span_id:,
|
|
22
|
+
input_source_trace_id:
|
|
22
23
|
}
|
|
23
24
|
yield
|
|
24
25
|
ensure
|
|
@@ -42,11 +43,22 @@ module Bitfab
|
|
|
42
43
|
# @param limit [Integer] maximum number of traces to replay (default: 5)
|
|
43
44
|
# @param trace_ids [Array<String>, nil] optional list of trace IDs to filter
|
|
44
45
|
# @param max_concurrency [Integer, nil] max threads for parallel replay (default: 10)
|
|
46
|
+
# @param code_change_description [String, nil] optional rationale for the
|
|
47
|
+
# code change being tested in this replay (stored on the experiment)
|
|
48
|
+
# @param code_change_files [Array<Hash>, nil] optional list of edited files,
|
|
49
|
+
# each as { path:, before:, after: } (empty string for new/deleted files)
|
|
45
50
|
# @return [Hash] with :items, :test_run_id, :test_run_url
|
|
46
|
-
def run(client, receiver, method_name, trace_function_key:, limit: 5, trace_ids: nil, max_concurrency: 10
|
|
51
|
+
def run(client, receiver, method_name, trace_function_key:, limit: 5, trace_ids: nil, max_concurrency: 10,
|
|
52
|
+
code_change_description: nil, code_change_files: nil)
|
|
47
53
|
http_client = client.instance_variable_get(:@http_client)
|
|
48
54
|
|
|
49
|
-
replay_data = http_client.start_replay(
|
|
55
|
+
replay_data = http_client.start_replay(
|
|
56
|
+
trace_function_key,
|
|
57
|
+
limit,
|
|
58
|
+
trace_ids:,
|
|
59
|
+
code_change_description:,
|
|
60
|
+
code_change_files:
|
|
61
|
+
)
|
|
50
62
|
test_run_id = replay_data["testRunId"]
|
|
51
63
|
test_run_url = replay_data["testRunUrl"]
|
|
52
64
|
server_items = replay_data["items"] || []
|
|
@@ -106,7 +118,15 @@ module Bitfab
|
|
|
106
118
|
span = http_client.get_external_span(server_item["externalSpanId"])
|
|
107
119
|
item_data = extract_span_data(span)
|
|
108
120
|
metrics = extract_server_item_metrics(server_item)
|
|
109
|
-
execute_item(
|
|
121
|
+
execute_item(
|
|
122
|
+
item_data,
|
|
123
|
+
receiver,
|
|
124
|
+
method_name,
|
|
125
|
+
test_run_id,
|
|
126
|
+
span["id"],
|
|
127
|
+
metrics,
|
|
128
|
+
input_source_trace_id: span["externalTraceId"]
|
|
129
|
+
)
|
|
110
130
|
end
|
|
111
131
|
|
|
112
132
|
# Extract input/output data from an external span's rawData.
|
|
@@ -144,13 +164,14 @@ module Bitfab
|
|
|
144
164
|
end
|
|
145
165
|
|
|
146
166
|
# Execute a single replay item: deserialize inputs, call method with replay context.
|
|
147
|
-
def execute_item(item, receiver, method_name, test_run_id, input_source_span_id = nil, metrics = {}
|
|
167
|
+
def execute_item(item, receiver, method_name, test_run_id, input_source_span_id = nil, metrics = {},
|
|
168
|
+
input_source_trace_id: nil)
|
|
148
169
|
args, kwargs = Serialize.deserialize_inputs(item)
|
|
149
170
|
|
|
150
171
|
fn_result = nil
|
|
151
172
|
fn_error = nil
|
|
152
173
|
|
|
153
|
-
ReplayContext.with_context(test_run_id:, input_source_span_id:) do
|
|
174
|
+
ReplayContext.with_context(test_run_id:, input_source_span_id:, input_source_trace_id:) do
|
|
154
175
|
fn_result = if kwargs.empty?
|
|
155
176
|
receiver.send(method_name, *args)
|
|
156
177
|
else
|
data/lib/bitfab/span_context.rb
CHANGED
|
@@ -131,12 +131,13 @@ module Bitfab
|
|
|
131
131
|
@states_mutex.synchronize { @states[trace_id] }
|
|
132
132
|
end
|
|
133
133
|
|
|
134
|
-
def create(trace_id, test_run_id: nil)
|
|
134
|
+
def create(trace_id, test_run_id: nil, input_source_trace_id: nil)
|
|
135
135
|
@states_mutex.synchronize do
|
|
136
136
|
@states[trace_id] ||= {
|
|
137
137
|
trace_id:,
|
|
138
138
|
started_at: Time.now.utc.strftime("%Y-%m-%dT%H:%M:%S.%3NZ"),
|
|
139
|
-
test_run_id
|
|
139
|
+
test_run_id:,
|
|
140
|
+
input_source_trace_id:
|
|
140
141
|
}.compact
|
|
141
142
|
end
|
|
142
143
|
end
|
data/lib/bitfab/version.rb
CHANGED