bitfab 0.64.10 → 0.64.12

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 695e945332f1eacd1d33b085bd44c83d585b22d53d93b1a51c197b8196956a38
4
- data.tar.gz: 12a2f0eb5193b336faa19cefea2b6d3e947de60925f3014fa5626665360403ce
3
+ metadata.gz: 0230d80db2a1be11423ea398d2e948cad51571ff1e539f4837557c409f6bfe5f
4
+ data.tar.gz: 44fce3d40aa1e12945fed6a2b5b88707f04bf5533abcadd13a361442fd174c1a
5
5
  SHA512:
6
- metadata.gz: 66d420f41c8da030c87b6ca7aa6ec3c8bbb04c18362b51792f34288802486238f8dad71ef50888394024ee2b7c5651f352b90a0055f39d985fbaa4ed42824a75
7
- data.tar.gz: 0fc406caf9c0c37c89690fe711fe90299ff6b4bc7f1d89a47fc20e5b2052258ef2aa269015d0fcbf5b4254aecbfd55d07367d0cc8c57a346f3e202a5693b9da2
6
+ metadata.gz: 8c483c3c65d9d50049901c5d0e9769a85502fdf082ecd7b95dfc0f55904fb9cdd98948d1e9d166678f12e74fac73cb33763d2571bbea647502b1d0a776859ff2
7
+ data.tar.gz: 0ae1075d5dfb6a0efae6841c87d4f0f4cccbebd27f83e0561fe2a4498b2e42aed4f895d3c2be8d444aa4d9013bbc00385e52a957cf783e142da3ebef3574bdfe
data/lib/bitfab/client.rb CHANGED
@@ -393,6 +393,12 @@ module Bitfab
393
393
  @http_client.get_trace_span(trace_id, id:, name:, occurrence:)
394
394
  end
395
395
 
396
+ def get_span(span_id)
397
+ raise ArgumentError, "span_id must be a non-empty string" unless span_id.is_a?(String) && !span_id.strip.empty?
398
+
399
+ @http_client.get_span(span_id)
400
+ end
401
+
396
402
  # Execute a block inside a span context, sending trace data on completion.
397
403
  # Called by Traceable, not intended for direct use.
398
404
  def execute_span(trace_function_key:, span_name:, span_type:, function_name:, args:, kwargs:,
@@ -334,6 +334,11 @@ module Bitfab
334
334
  )["span"]
335
335
  end
336
336
 
337
+ def get_span(span_id)
338
+ encoded_span_id = URI.encode_www_form_component(span_id).gsub("+", "%20")
339
+ get("/api/sdk/spans/#{encoded_span_id}", timeout: 30)["span"]
340
+ end
341
+
337
342
  # Fetch the span tree rooted at an external span. Blocking GET request.
338
343
  # Used by replay when a mock strategy is active so child spans can be
339
344
  # matched against their historical outputs.
data/lib/bitfab/replay.rb CHANGED
@@ -464,7 +464,8 @@ module Bitfab
464
464
  # trace-ID mapping complete_replay builds would otherwise race the
465
465
  # in-flight batches and hand back nil for every item.
466
466
  delivered_trace_ids = preserve_replay_failure(result_items, experiment_id, full_experiment_url) do
467
- wait_for_replay_persistence(http_client, experiment_id, result_items.map { |item| item[:_sdk_trace_id] })
467
+ wait_for_replay_persistence(http_client, experiment_id, result_items.map { |item| item[:_sdk_trace_id] },
468
+ labels: replay_labels(result_items))
468
469
  end
469
470
 
470
471
  # Primary source for item[:trace_id]: the server's assigned traces.id, read
@@ -1243,7 +1244,7 @@ module Bitfab
1243
1244
  # repeat itself. Acks cannot settle a request that timed out client-side
1244
1245
  # after the server committed, so anything short of fully delivered falls
1245
1246
  # through to the server poll, which stays the authority there.
1246
- def wait_for_replay_persistence(http_client, experiment_id, sdk_trace_ids, timeout: nil)
1247
+ def wait_for_replay_persistence(http_client, experiment_id, sdk_trace_ids, timeout: nil, labels: {})
1247
1248
  timeout ||= PERSISTENCE_TIMEOUT_SECONDS
1248
1249
  trace_ids = sdk_trace_ids.compact
1249
1250
 
@@ -1286,15 +1287,29 @@ module Bitfab
1286
1287
  sleep((deadline - Otel.monotonic_now).clamp(0, PERSISTENCE_POLL_SECONDS))
1287
1288
  end
1288
1289
 
1289
- cause = if flushed
1290
- ""
1291
- else
1292
- " Delivery was also not confirmed before the flush deadline, so the " \
1293
- "spans likely never reached the server."
1290
+ missing.each do |trace_id|
1291
+ warn_unconfirmed_replay(unconfirmed_replay_warning(labels.fetch(trace_id, trace_id), timeout, flushed))
1292
+ end
1293
+ read_back_trace_ids
1294
+ end
1295
+
1296
+ def unconfirmed_replay_warning(label, seconds, flushed)
1297
+ "[bitfab] replay #{label} could not confirm all spans reached Bitfab within #{format("%g", seconds)}s. " \
1298
+ "The run continues; Bitfab will show this replay as capture incomplete." \
1299
+ "#{" Some spans likely never left this process." unless flushed}"
1300
+ end
1301
+
1302
+ def warn_unconfirmed_replay(message)
1303
+ Bitfab.count_delivery_problem(message)
1304
+ warn message
1305
+ rescue Exception # rubocop:disable Lint/RescueException
1306
+ nil
1307
+ end
1308
+
1309
+ def replay_labels(items)
1310
+ items.each_with_object({}) do |item, labels|
1311
+ labels[item[:_sdk_trace_id]] = "#{item[:original_trace_id]}##{item[:attempt]}" if item[:_sdk_trace_id]
1294
1312
  end
1295
- raise "Replay traces were not fully persisted before the delivery deadline " \
1296
- "(experiment #{experiment_id}, missing #{missing.length} of " \
1297
- "#{expected_span_counts.length} trace(s)).#{cause}"
1298
1313
  end
1299
1314
 
1300
1315
  # Normalize a complete-replay tokens hash (string-keyed JSON) into the
@@ -51,13 +51,13 @@ module Bitfab
51
51
  mock_overrides: overrides, dry_run: assignment.fetch("dry_run"))
52
52
  unless assignment["dry_run"]
53
53
  begin
54
- mapped = Replay.wait_for_replay_persistence(http, assignment.fetch("experiment_id"), [result[:_sdk_trace_id]], timeout: delivery_timeout)
54
+ mapped = Replay.wait_for_replay_persistence(http, assignment.fetch("experiment_id"), [result[:_sdk_trace_id]],
55
+ timeout: delivery_timeout, labels: Replay.replay_labels([result]))
55
56
  result[:trace_id] = mapped[result[:_sdk_trace_id]] || result[:trace_id]
56
57
  if result[:_sdk_trace_id] && result[:trace_id].nil?
57
58
  status = http.get_replay_status(assignment.fetch("experiment_id"), {result[:_sdk_trace_id] => 1})
58
59
  result[:trace_id] = status.fetch("traceIds", {})[result[:_sdk_trace_id]]
59
60
  end
60
- raise "Child replay trace persistence could not be confirmed" if result[:error].nil? && result[:trace_id].nil?
61
61
  rescue => error
62
62
  result[:replay_error] = error
63
63
  result[:error] = error.message
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bitfab
4
- VERSION = "0.64.10"
4
+ VERSION = "0.64.12"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bitfab
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.64.10
4
+ version: 0.64.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Harvest Team