bitfab 0.51.5 → 0.51.7
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 +7 -0
- data/lib/bitfab/http_client.rb +19 -1
- data/lib/bitfab/trace_completion.rb +85 -0
- data/lib/bitfab/traces.rb +20 -0
- data/lib/bitfab/version.rb +1 -1
- data/lib/bitfab.rb +1 -0
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 64f734e03ef657b17437062d8827ba0ab1532cb244f0c2bc7ae46e1f599015a0
|
|
4
|
+
data.tar.gz: bef9e05e622daada74cf66907f6fe6f9cc3ecac4447af7b6590936c4dc85ba39
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 979725c68118f1bd070da152c1d4ec607957dc771d3c39d021c68b2bc5f06d1315c49d33c13eae1ce99a1f16e6e0f7b2486dd3051286d3d8016bb552c3f0d14c
|
|
7
|
+
data.tar.gz: 2a71770f9f72528093ed229bd2505dcc7a515fc5ffa9c682933fb5802e65ffa7cc46de7538f077e896f8ad01ea13820253fe781ed2b92477ad8ab8c9cadabeeb
|
data/lib/bitfab/client.rb
CHANGED
|
@@ -34,6 +34,9 @@ module Bitfab
|
|
|
34
34
|
# Dataset operations for the authenticated organization.
|
|
35
35
|
attr_reader :datasets
|
|
36
36
|
|
|
37
|
+
# Trace lookup operations for the authenticated organization.
|
|
38
|
+
attr_reader :traces
|
|
39
|
+
|
|
37
40
|
def initialize(api_key: nil, service_url: nil, enabled: true, strict: false)
|
|
38
41
|
@api_key_config = api_key
|
|
39
42
|
@service_url = service_url || DEFAULT_SERVICE_URL
|
|
@@ -48,6 +51,7 @@ module Bitfab
|
|
|
48
51
|
# at send time, after any env loading has run.
|
|
49
52
|
@http_client = HttpClient.new(api_key: -> { resolve_api_key }, service_url: @service_url)
|
|
50
53
|
@datasets = Datasets.new(@http_client)
|
|
54
|
+
@traces = Traces.new(@http_client)
|
|
51
55
|
# Mock overrides registered via register_mock_override, applied to every
|
|
52
56
|
# replay on this client (after any per-call mock_override). Instance
|
|
53
57
|
# state, no global; clear_mock_overrides resets it.
|
|
@@ -470,6 +474,7 @@ module Bitfab
|
|
|
470
474
|
span_contexts = nil
|
|
471
475
|
span_prompt = nil
|
|
472
476
|
completed = false
|
|
477
|
+
@http_client.trace_completion.start(trace_id, span_id)
|
|
473
478
|
|
|
474
479
|
complete = lambda do |final_result, final_error|
|
|
475
480
|
# Never crash the host app due to span building/sending. Idempotent:
|
|
@@ -549,6 +554,8 @@ module Bitfab
|
|
|
549
554
|
# Silently ignore: user's result/exception takes priority
|
|
550
555
|
# Catches Exception (not just StandardError) to handle SystemStackError
|
|
551
556
|
# from deeply nested serialization
|
|
557
|
+
ensure
|
|
558
|
+
@http_client.trace_completion.finish(trace_id, span_id)
|
|
552
559
|
end
|
|
553
560
|
end
|
|
554
561
|
|
data/lib/bitfab/http_client.rb
CHANGED
|
@@ -9,6 +9,7 @@ require_relative "compress"
|
|
|
9
9
|
require_relative "constants"
|
|
10
10
|
require_relative "serialize"
|
|
11
11
|
require_relative "transport"
|
|
12
|
+
require_relative "trace_completion"
|
|
12
13
|
require_relative "version"
|
|
13
14
|
require_relative "warn_once"
|
|
14
15
|
|
|
@@ -27,7 +28,7 @@ module Bitfab
|
|
|
27
28
|
REPLAY_DB_BRANCH_REQUEST_TIMEOUT_SECONDS = 300
|
|
28
29
|
private_constant :REPLAY_DB_BRANCH_REQUEST_TIMEOUT_SECONDS
|
|
29
30
|
|
|
30
|
-
attr_reader :service_url
|
|
31
|
+
attr_reader :service_url, :trace_completion
|
|
31
32
|
|
|
32
33
|
def initialize(api_key:, service_url: nil, timeout: 120)
|
|
33
34
|
@api_key = api_key
|
|
@@ -38,6 +39,7 @@ module Bitfab
|
|
|
38
39
|
# the export threads recording acks would hand each a different mutex.
|
|
39
40
|
@delivery_mutex = Mutex.new
|
|
40
41
|
@trace_deliveries = {}
|
|
42
|
+
@trace_completion = TraceCompletion.new
|
|
41
43
|
@delivery_pid = Process.pid
|
|
42
44
|
@carrier_seq_mutex = Mutex.new
|
|
43
45
|
@carrier_seq = 0
|
|
@@ -126,6 +128,8 @@ module Bitfab
|
|
|
126
128
|
|
|
127
129
|
# Queue an external span on this client's trace transport (fire-and-forget).
|
|
128
130
|
def send_external_span(payload)
|
|
131
|
+
ref = carrier_ref(payload)
|
|
132
|
+
@trace_completion.record(ref.trace_id, ref.span_id) if ref&.span_id
|
|
129
133
|
trace_transport&.submit(
|
|
130
134
|
"external_span",
|
|
131
135
|
payload.merge("sdkVersion" => VERSION),
|
|
@@ -287,6 +291,18 @@ module Bitfab
|
|
|
287
291
|
|
|
288
292
|
# Queue an external trace on this client's trace transport (fire-and-forget).
|
|
289
293
|
def send_external_trace(payload)
|
|
294
|
+
ref = carrier_ref(payload)
|
|
295
|
+
if payload["completed"] == true && ref
|
|
296
|
+
@trace_completion.close(ref.trace_id, dropped: payload["dropped"] == true) do |count|
|
|
297
|
+
submit_external_trace(payload.merge("expectedSpanCount" => count))
|
|
298
|
+
end
|
|
299
|
+
else
|
|
300
|
+
@trace_completion.open(ref.trace_id) if ref
|
|
301
|
+
submit_external_trace(payload)
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
def submit_external_trace(payload)
|
|
290
306
|
trace_transport&.submit(
|
|
291
307
|
"external_trace",
|
|
292
308
|
payload.merge("sdkVersion" => VERSION),
|
|
@@ -296,6 +312,8 @@ module Bitfab
|
|
|
296
312
|
(payload["completed"] == true) ? carrier_ref(payload) : nil
|
|
297
313
|
)
|
|
298
314
|
)
|
|
315
|
+
rescue => error
|
|
316
|
+
Bitfab.warn_once("trace-completion-submit", "trace completion could not be queued: #{error.message}")
|
|
299
317
|
end
|
|
300
318
|
|
|
301
319
|
# Read the replay traces the server has fully persisted so far.
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "set" # standard:disable Lint/RedundantRequireStatement -- Required on Ruby 3.4.
|
|
4
|
+
|
|
5
|
+
module Bitfab
|
|
6
|
+
class TraceCompletion
|
|
7
|
+
def initialize
|
|
8
|
+
@pid = Process.pid
|
|
9
|
+
@mutex = Mutex.new
|
|
10
|
+
@traces = {}
|
|
11
|
+
@closed = {}
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def start(trace_id, span_id)
|
|
15
|
+
synchronize do
|
|
16
|
+
next if @closed.key?(trace_id)
|
|
17
|
+
|
|
18
|
+
entry = state(trace_id)
|
|
19
|
+
entry[:span_ids].add(span_id)
|
|
20
|
+
entry[:active].add(span_id)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def open(trace_id)
|
|
25
|
+
synchronize { state(trace_id) unless @closed.key?(trace_id) }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def record(trace_id, span_id)
|
|
29
|
+
synchronize do
|
|
30
|
+
state(trace_id)[:span_ids].add(span_id) unless @closed.key?(trace_id)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def finish(trace_id, span_id)
|
|
35
|
+
ready = synchronize do
|
|
36
|
+
entry = @traces[trace_id]
|
|
37
|
+
next if entry.nil?
|
|
38
|
+
|
|
39
|
+
entry[:active].delete(span_id)
|
|
40
|
+
drain(trace_id, entry)
|
|
41
|
+
end
|
|
42
|
+
ready[0].call(ready[1]) unless ready.nil?
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def close(trace_id, dropped: false, &complete)
|
|
46
|
+
ready = synchronize do
|
|
47
|
+
next [complete, @closed[trace_id]] if @closed.key?(trace_id)
|
|
48
|
+
|
|
49
|
+
entry = @traces[trace_id]
|
|
50
|
+
next if entry.nil?
|
|
51
|
+
|
|
52
|
+
entry[:complete] = complete
|
|
53
|
+
entry[:active].clear if dropped
|
|
54
|
+
drain(trace_id, entry)
|
|
55
|
+
end
|
|
56
|
+
ready[0].call(ready[1]) unless ready.nil?
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
private
|
|
60
|
+
|
|
61
|
+
def synchronize(&block)
|
|
62
|
+
if @pid != Process.pid
|
|
63
|
+
@pid = Process.pid
|
|
64
|
+
@mutex = Mutex.new
|
|
65
|
+
@traces = {}
|
|
66
|
+
@closed = {}
|
|
67
|
+
end
|
|
68
|
+
@mutex.synchronize(&block)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def state(trace_id)
|
|
72
|
+
@traces[trace_id] ||= {span_ids: Set.new, active: Set.new}
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def drain(trace_id, entry)
|
|
76
|
+
return unless entry[:active].empty? && entry[:complete]
|
|
77
|
+
|
|
78
|
+
@traces.delete(trace_id)
|
|
79
|
+
count = entry[:span_ids].size
|
|
80
|
+
@closed[trace_id] = count
|
|
81
|
+
@closed.shift if @closed.size > 1024
|
|
82
|
+
[entry[:complete], count]
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Bitfab
|
|
4
|
+
# Trace lookup operations for the authenticated organization.
|
|
5
|
+
class Traces
|
|
6
|
+
def initialize(http_client)
|
|
7
|
+
@http_client = http_client
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# Search by up to 10 exact, case-insensitive caller metadata pairs. Every
|
|
11
|
+
# pair must match. Pass nextCursor from the result as cursor: for another page.
|
|
12
|
+
def search(caller_metadata:, trace_function_key: nil, cursor: nil, limit: nil)
|
|
13
|
+
payload = {"callerMetadata" => caller_metadata}
|
|
14
|
+
payload["traceFunctionKey"] = trace_function_key unless trace_function_key.nil?
|
|
15
|
+
payload["cursor"] = cursor unless cursor.nil?
|
|
16
|
+
payload["limit"] = limit unless limit.nil?
|
|
17
|
+
@http_client.request("/api/sdk/traces/search", payload)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
data/lib/bitfab/version.rb
CHANGED
data/lib/bitfab.rb
CHANGED
|
@@ -14,6 +14,7 @@ require_relative "bitfab/git_state"
|
|
|
14
14
|
require_relative "bitfab/span_context"
|
|
15
15
|
require_relative "bitfab/http_client"
|
|
16
16
|
require_relative "bitfab/datasets"
|
|
17
|
+
require_relative "bitfab/traces"
|
|
17
18
|
require_relative "bitfab/mock_override"
|
|
18
19
|
require_relative "bitfab/replay"
|
|
19
20
|
require_relative "bitfab/replay_branch"
|
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.51.
|
|
4
|
+
version: 0.51.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Harvest Team
|
|
@@ -159,7 +159,9 @@ files:
|
|
|
159
159
|
- lib/bitfab/span_context.rb
|
|
160
160
|
- lib/bitfab/subtree.rb
|
|
161
161
|
- lib/bitfab/timestamp.rb
|
|
162
|
+
- lib/bitfab/trace_completion.rb
|
|
162
163
|
- lib/bitfab/traceable.rb
|
|
164
|
+
- lib/bitfab/traces.rb
|
|
163
165
|
- lib/bitfab/transport.rb
|
|
164
166
|
- lib/bitfab/version.rb
|
|
165
167
|
- lib/bitfab/warn_once.rb
|