bitfab 0.51.5 → 0.51.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 +3 -0
- data/lib/bitfab/http_client.rb +19 -1
- data/lib/bitfab/trace_completion.rb +85 -0
- data/lib/bitfab/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 208aed8da4ed9d2c748135161048c595f30507c946f3bb4086a560c55c1a2044
|
|
4
|
+
data.tar.gz: cfd965992d9304db89d53760c7e8ef8ea237394902aa33f5f0862a7388bf4c00
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b76db7c1e008f877c79d6ab25eaacd2733f3e61564eb2211ac77418d050634503b31a4dd43ecd80bf7ea098fa4fec1975b36ec4c4b3125badbbc0a3ef61dfbba
|
|
7
|
+
data.tar.gz: '07281744cb252b83655686936532d9d58297537c35938c2eea468a5359005ba9c8ae97149e3465f990d005f5a80a2890d04662add468602e4ca9ddaaacd704e4'
|
data/lib/bitfab/client.rb
CHANGED
|
@@ -470,6 +470,7 @@ module Bitfab
|
|
|
470
470
|
span_contexts = nil
|
|
471
471
|
span_prompt = nil
|
|
472
472
|
completed = false
|
|
473
|
+
@http_client.trace_completion.start(trace_id, span_id)
|
|
473
474
|
|
|
474
475
|
complete = lambda do |final_result, final_error|
|
|
475
476
|
# Never crash the host app due to span building/sending. Idempotent:
|
|
@@ -549,6 +550,8 @@ module Bitfab
|
|
|
549
550
|
# Silently ignore: user's result/exception takes priority
|
|
550
551
|
# Catches Exception (not just StandardError) to handle SystemStackError
|
|
551
552
|
# from deeply nested serialization
|
|
553
|
+
ensure
|
|
554
|
+
@http_client.trace_completion.finish(trace_id, span_id)
|
|
552
555
|
end
|
|
553
556
|
end
|
|
554
557
|
|
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
|
data/lib/bitfab/version.rb
CHANGED
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.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Harvest Team
|
|
@@ -159,6 +159,7 @@ 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
|
|
163
164
|
- lib/bitfab/transport.rb
|
|
164
165
|
- lib/bitfab/version.rb
|