bitfab 0.17.1 → 0.20.0
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 +4 -2
- data/lib/bitfab/http_client.rb +46 -2
- data/lib/bitfab/replay.rb +5 -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: 9624757032370e1e318121cabcf2bfa984c7bcdcd07c9ecd5dcee449fef57a7c
|
|
4
|
+
data.tar.gz: c3925bbae804c16d21c3f373ec6cde4de340ee645fc6423505fc0b5d5f5e638e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d2c33cd4a3432d79703685f00bb8c8278e2bebbd694b3a695f1dee646680a5af11370f233635f04590eeb0d5cedee850c496b40bee2fc176c34cf22fb721cde8
|
|
7
|
+
data.tar.gz: c64be06a07ca8ea807bca23e0f96acb15e1647945b33c3ea731f10c0b52759870b88637d86b680aee07caac7836e3818946f2fb85f0979d83b3ea89ef8ea1704
|
data/lib/bitfab/client.rb
CHANGED
|
@@ -50,6 +50,8 @@ module Bitfab
|
|
|
50
50
|
# each as { path:, before:, after: } (use "" for new/deleted files)
|
|
51
51
|
# @param experiment_group_id [String, nil] optional UUID grouping multiple
|
|
52
52
|
# replay runs into a single experiment batch
|
|
53
|
+
# @param dataset_id [String, nil] optional UUID of the dataset this replay
|
|
54
|
+
# runs against, stored on the resulting experiment for durable attribution
|
|
53
55
|
# @param mock [String] mock strategy for child spans: "none" (default),
|
|
54
56
|
# "all", or "marked". "all" mocks every child span; "marked" only mocks
|
|
55
57
|
# spans declared with mock_on_replay: true.
|
|
@@ -59,12 +61,12 @@ module Bitfab
|
|
|
59
61
|
# { trace_id:, source_span_id: }, and returns [new_args, new_kwargs].
|
|
60
62
|
# @return [Hash] with :items, :test_run_id, :test_run_url
|
|
61
63
|
def replay(receiver, method_name, trace_function_key:, limit: nil, trace_ids: nil, max_concurrency: 10,
|
|
62
|
-
code_change_description: nil, code_change_files: nil, experiment_group_id: nil, mock: "none",
|
|
64
|
+
code_change_description: nil, code_change_files: nil, experiment_group_id: nil, dataset_id: nil, mock: "none",
|
|
63
65
|
adapt_inputs: nil, environment: nil)
|
|
64
66
|
Replay.run(
|
|
65
67
|
self, receiver, method_name,
|
|
66
68
|
trace_function_key:, limit:, trace_ids:, max_concurrency:,
|
|
67
|
-
code_change_description:, code_change_files:, experiment_group_id:, mock:, adapt_inputs:, environment:
|
|
69
|
+
code_change_description:, code_change_files:, experiment_group_id:, dataset_id:, mock:, adapt_inputs:, environment:
|
|
68
70
|
)
|
|
69
71
|
end
|
|
70
72
|
|
data/lib/bitfab/http_client.rb
CHANGED
|
@@ -5,6 +5,7 @@ require "json"
|
|
|
5
5
|
require "uri"
|
|
6
6
|
|
|
7
7
|
require_relative "constants"
|
|
8
|
+
require_relative "serialize"
|
|
8
9
|
require_relative "version"
|
|
9
10
|
|
|
10
11
|
module Bitfab
|
|
@@ -32,7 +33,7 @@ module Bitfab
|
|
|
32
33
|
http.read_timeout = request_timeout
|
|
33
34
|
|
|
34
35
|
req = Net::HTTP::Post.new(uri.path, headers)
|
|
35
|
-
req.body =
|
|
36
|
+
req.body = safe_generate(payload, endpoint)
|
|
36
37
|
|
|
37
38
|
response = http.request(req)
|
|
38
39
|
|
|
@@ -105,8 +106,10 @@ module Bitfab
|
|
|
105
106
|
# each as { path:, before:, after: } (use "" for new/deleted files)
|
|
106
107
|
# @param experiment_group_id [String, nil] optional UUID grouping multiple
|
|
107
108
|
# replay runs into a single experiment batch
|
|
109
|
+
# @param dataset_id [String, nil] optional UUID of the dataset this replay
|
|
110
|
+
# runs against, stored on the resulting experiment for durable attribution
|
|
108
111
|
def start_replay(trace_function_key, limit, trace_ids: nil, code_change_description: nil,
|
|
109
|
-
code_change_files: nil, experiment_group_id: nil, include_db_branch_lease: false)
|
|
112
|
+
code_change_files: nil, experiment_group_id: nil, include_db_branch_lease: false, dataset_id: nil)
|
|
110
113
|
payload = {
|
|
111
114
|
"traceFunctionKey" => trace_function_key
|
|
112
115
|
}
|
|
@@ -118,6 +121,7 @@ module Bitfab
|
|
|
118
121
|
payload["codeChangeFiles"] = normalize_code_change_files(code_change_files) unless code_change_files.nil?
|
|
119
122
|
payload["experimentGroupId"] = experiment_group_id unless experiment_group_id.nil?
|
|
120
123
|
payload["includeDbBranchLease"] = true if include_db_branch_lease
|
|
124
|
+
payload["datasetId"] = dataset_id unless dataset_id.nil?
|
|
121
125
|
|
|
122
126
|
# When DB branching is on, the server resolves a Neon preview branch per
|
|
123
127
|
# item (snapshot + restore + poll), which can run several seconds each.
|
|
@@ -166,6 +170,46 @@ module Bitfab
|
|
|
166
170
|
|
|
167
171
|
private
|
|
168
172
|
|
|
173
|
+
# JSON-encode a request body without ever raising on a stray value.
|
|
174
|
+
#
|
|
175
|
+
# Upstream serialization (Serialize.serialize_value) should already have
|
|
176
|
+
# flattened user data. This is the boundary backstop: if anything
|
|
177
|
+
# non-serializable still slips through, it is run through serialize_value
|
|
178
|
+
# (which never raises and stubs strays) instead of letting JSON.generate
|
|
179
|
+
# raise and drop the whole span/trace silently. A degraded payload warns
|
|
180
|
+
# loudly so the trace isn't quietly left incomplete or not replayable.
|
|
181
|
+
def safe_generate(payload, endpoint)
|
|
182
|
+
JSON.generate(payload)
|
|
183
|
+
rescue => e
|
|
184
|
+
begin
|
|
185
|
+
warn "Bitfab: request body to #{endpoint} held a non-serializable " \
|
|
186
|
+
"value (#{e.message}); it was stubbed so the span still sends, " \
|
|
187
|
+
"but the trace may be incomplete or not replayable. Capture a " \
|
|
188
|
+
"JSON-safe projection of this input to make it replayable."
|
|
189
|
+
rescue
|
|
190
|
+
# Never crash the host app over a log line.
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
begin
|
|
194
|
+
JSON.generate(sanitize_payload(payload))
|
|
195
|
+
rescue
|
|
196
|
+
# Truly pathological. Still never drop silently: send a marker body.
|
|
197
|
+
JSON.generate({"error" => "payload_serialize_failed"})
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# Serialize each top-level value so a bad or oversize value is stubbed in
|
|
202
|
+
# place while the payload keeps its object shape. Running serialize_value on
|
|
203
|
+
# the whole payload could collapse the entire body to a single stub string
|
|
204
|
+
# (oversize/cyclic), sending a JSON string instead of a span object.
|
|
205
|
+
def sanitize_payload(payload)
|
|
206
|
+
return {"error" => "payload_serialize_failed"} unless payload.is_a?(Hash)
|
|
207
|
+
|
|
208
|
+
payload.each_with_object({}) do |(k, v), acc|
|
|
209
|
+
acc[k.to_s] = Serialize.serialize_value(v)
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
169
213
|
# Normalize each entry to a hash with stable string keys, accepting either
|
|
170
214
|
# symbol-keyed or string-keyed hashes from callers.
|
|
171
215
|
def normalize_code_change_files(files)
|
data/lib/bitfab/replay.rb
CHANGED
|
@@ -88,6 +88,8 @@ module Bitfab
|
|
|
88
88
|
# each as { path:, before:, after: } (empty string for new/deleted files)
|
|
89
89
|
# @param experiment_group_id [String, nil] optional UUID grouping multiple
|
|
90
90
|
# replay runs into a single experiment batch
|
|
91
|
+
# @param dataset_id [String, nil] optional UUID of the dataset this replay
|
|
92
|
+
# runs against, stored on the resulting experiment for durable attribution
|
|
91
93
|
# @param mock [String] mock strategy for child spans: "none" (default),
|
|
92
94
|
# "all", or "marked". "all" mocks every child span; "marked" only mocks
|
|
93
95
|
# spans declared with mock_on_replay: true.
|
|
@@ -99,7 +101,7 @@ module Bitfab
|
|
|
99
101
|
# that item's :error rather than crashing the run.
|
|
100
102
|
# @return [Hash] with :items, :test_run_id, :test_run_url
|
|
101
103
|
def run(client, receiver, method_name, trace_function_key:, limit: nil, trace_ids: nil, max_concurrency: 10,
|
|
102
|
-
code_change_description: nil, code_change_files: nil, experiment_group_id: nil, mock: "none",
|
|
104
|
+
code_change_description: nil, code_change_files: nil, experiment_group_id: nil, dataset_id: nil, mock: "none",
|
|
103
105
|
adapt_inputs: nil, environment: nil)
|
|
104
106
|
unless MOCK_STRATEGIES.include?(mock.to_s)
|
|
105
107
|
raise ArgumentError, "Invalid mock strategy '#{mock}'. Must be one of: #{MOCK_STRATEGIES.join(", ")}"
|
|
@@ -130,7 +132,8 @@ module Bitfab
|
|
|
130
132
|
code_change_description:,
|
|
131
133
|
code_change_files:,
|
|
132
134
|
experiment_group_id:,
|
|
133
|
-
include_db_branch_lease
|
|
135
|
+
include_db_branch_lease:,
|
|
136
|
+
dataset_id:
|
|
134
137
|
)
|
|
135
138
|
test_run_id = replay_data["testRunId"]
|
|
136
139
|
test_run_url = replay_data["testRunUrl"]
|
data/lib/bitfab/version.rb
CHANGED