debugbundle 1.0.0 → 1.1.2
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/README.md +1 -1
- data/lib/debugbundle/client.rb +72 -54
- data/lib/debugbundle/remote_config.rb +46 -3
- data/lib/debugbundle/version.rb +1 -1
- data/spec/fixtures/event-envelope.schema.json +5 -0
- data/spec/rack_integration_spec.rb +3 -3
- data/spec/rack_middleware_spec.rb +6 -2
- data/spec/sidekiq_integration_spec.rb +1 -1
- data/spec/sidekiq_middleware_spec.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2233153d82d41df1121182d5e7f217f02c4b1a0c7348386505c0406e09db3e86
|
|
4
|
+
data.tar.gz: d1b0169d3968aa5c11a2eda1751bf9612afa63109818359d48e7ab1f94384c49
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 279871a9cf53e67fbbd269eaddc86c6003428993729d81c1b6586aa787780687c29b8a602716cbad9e1f33ca829564a9b936aaad282611c6594e66073d2654d1
|
|
7
|
+
data.tar.gz: 6b3b419131b880e0073322aff591c8dabfb5343374331246504b99fb31e1deeb1e79c17769c8a2ce7ad4288b81c186e0d0cd63eaa1ac631a709d13659f0f3554
|
data/README.md
CHANGED
|
@@ -314,7 +314,7 @@ This repository also ships a clean-install app-driven smoke harness that validat
|
|
|
314
314
|
|
|
315
315
|
```sh
|
|
316
316
|
make smoke
|
|
317
|
-
make smoke-published VERSION=1.
|
|
317
|
+
make smoke-published VERSION=1.1.2
|
|
318
318
|
```
|
|
319
319
|
|
|
320
320
|
`make smoke` builds the gem, installs it into a fresh RubyGems home, drives a Rack request plus a browser relay batch through the public SDK surface, validates event envelope shape, and confirms the mock ingestion endpoint receives the expected service, environment, SDK metadata, and correlation fields.
|
data/lib/debugbundle/client.rb
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require 'digest'
|
|
4
4
|
require 'time'
|
|
5
|
+
require 'uri'
|
|
5
6
|
|
|
6
7
|
require 'debugbundle/runtime'
|
|
7
8
|
|
|
@@ -23,7 +24,6 @@ module DebugBundle
|
|
|
23
24
|
].freeze
|
|
24
25
|
BALANCED_IMMEDIATE_REQUEST_STATUSES = [408, 423, 424, 425, 429].freeze
|
|
25
26
|
INVESTIGATIVE_IMMEDIATE_REQUEST_STATUSES = (BALANCED_IMMEDIATE_REQUEST_STATUSES + [409]).freeze
|
|
26
|
-
BALANCED_ANOMALY_REQUEST_STATUSES = [400, 401, 403, 404, 409, 410, 422].freeze
|
|
27
27
|
LOCAL_ENVIRONMENTS = %w[development local test].freeze
|
|
28
28
|
REQUEST_TRIGGER_DIRECTIVES_KEY = :__debugbundle_request_trigger_directives__
|
|
29
29
|
THREAD_HOOK_MUTEX = Mutex.new
|
|
@@ -41,9 +41,7 @@ module DebugBundle
|
|
|
41
41
|
class << self
|
|
42
42
|
attr_accessor :thread_exception_client
|
|
43
43
|
|
|
44
|
-
def dispatch_thread_exception(error)
|
|
45
|
-
thread_exception_client&.__send__(:capture_thread_exception, error)
|
|
46
|
-
end
|
|
44
|
+
def dispatch_thread_exception(error) = thread_exception_client&.__send__(:capture_thread_exception, error)
|
|
47
45
|
|
|
48
46
|
def install_thread_exception_hook!
|
|
49
47
|
THREAD_HOOK_MUTEX.synchronize do
|
|
@@ -128,23 +126,20 @@ module DebugBundle
|
|
|
128
126
|
}
|
|
129
127
|
|
|
130
128
|
causes = exception_causes(error)
|
|
131
|
-
payload['causes'] = causes unless causes.empty?
|
|
132
129
|
|
|
133
130
|
probe_data = probe_snapshot
|
|
134
131
|
payload['probe_data'] = probe_data unless probe_data.empty?
|
|
135
132
|
|
|
136
133
|
extra_context = merged_context.except('request', 'response', 'correlation')
|
|
137
|
-
|
|
134
|
+
extra_context['causes'] = causes unless causes.empty?
|
|
138
135
|
|
|
139
136
|
suppression_key = [payload['name'], payload['message'], payload['stack']].join(':')
|
|
140
137
|
return unless @suppression.should_capture(suppression_key, now: monotonic_now)
|
|
141
138
|
|
|
142
|
-
enqueue_event(base_event('backend_exception', payload,
|
|
139
|
+
enqueue_event(base_event('backend_exception', payload, extra_context))
|
|
143
140
|
end
|
|
144
141
|
|
|
145
|
-
def capture_error(error, context: nil, handled: true)
|
|
146
|
-
capture_exception(error, context: context, handled: handled)
|
|
147
|
-
end
|
|
142
|
+
def capture_error(error, context: nil, handled: true) = capture_exception(error, context: context, handled: handled)
|
|
148
143
|
|
|
149
144
|
def capture_log(message, level: :warning, context: nil)
|
|
150
145
|
return unless capture_enabled?
|
|
@@ -172,7 +167,7 @@ module DebugBundle
|
|
|
172
167
|
sanitized_request = request_payload(request)
|
|
173
168
|
sanitized_response = response_payload(response)
|
|
174
169
|
response_status = (sanitized_response['status_code'] || 0).to_i
|
|
175
|
-
return unless capture_request_event?(response_status)
|
|
170
|
+
return unless capture_request_event?(response_status, sanitized_request)
|
|
176
171
|
|
|
177
172
|
payload = {
|
|
178
173
|
'method' => sanitized_request['method'],
|
|
@@ -183,8 +178,6 @@ module DebugBundle
|
|
|
183
178
|
'response_status' => response_status,
|
|
184
179
|
'duration_ms' => extract_duration_ms(merged_context, sanitized_response),
|
|
185
180
|
'route_template' => merged_context['route_template'],
|
|
186
|
-
'controller' => merged_context['controller'],
|
|
187
|
-
'action' => merged_context['action'],
|
|
188
181
|
'response_headers' => sanitized_response['headers'],
|
|
189
182
|
'response_body' => sanitized_response['body']
|
|
190
183
|
}
|
|
@@ -371,9 +364,7 @@ module DebugBundle
|
|
|
371
364
|
:healthy
|
|
372
365
|
end
|
|
373
366
|
|
|
374
|
-
def buffered_event_count
|
|
375
|
-
@buffer_mutex.synchronize { @buffer.length }
|
|
376
|
-
end
|
|
367
|
+
def buffered_event_count = @buffer_mutex.synchronize { @buffer.length }
|
|
377
368
|
|
|
378
369
|
private
|
|
379
370
|
|
|
@@ -400,9 +391,7 @@ module DebugBundle
|
|
|
400
391
|
)
|
|
401
392
|
end
|
|
402
393
|
|
|
403
|
-
def capture_enabled?
|
|
404
|
-
config.enabled? && config.configured?
|
|
405
|
-
end
|
|
394
|
+
def capture_enabled? = config.enabled? && config.configured?
|
|
406
395
|
|
|
407
396
|
def merge_context(context)
|
|
408
397
|
merged = @context.merge(stringify_hash(context || {}))
|
|
@@ -420,8 +409,8 @@ module DebugBundle
|
|
|
420
409
|
def request_payload(request)
|
|
421
410
|
source = object_to_hash(request)
|
|
422
411
|
{
|
|
423
|
-
'method' => source['method'],
|
|
424
|
-
'path' => source['path'],
|
|
412
|
+
'method' => source['method'] || 'UNKNOWN',
|
|
413
|
+
'path' => source['path'] || '/',
|
|
425
414
|
'query' => @redactor.redact_value(source['query'] || {}),
|
|
426
415
|
'headers' => sanitized_headers(source['headers'] || {}),
|
|
427
416
|
'body' => @redactor.redact_value(source['body'] || {})
|
|
@@ -437,9 +426,7 @@ module DebugBundle
|
|
|
437
426
|
}
|
|
438
427
|
end
|
|
439
428
|
|
|
440
|
-
def runtime_payload
|
|
441
|
-
Runtime.payload
|
|
442
|
-
end
|
|
429
|
+
def runtime_payload = Runtime.payload
|
|
443
430
|
|
|
444
431
|
def exception_causes(error)
|
|
445
432
|
causes = []
|
|
@@ -502,7 +489,7 @@ module DebugBundle
|
|
|
502
489
|
end
|
|
503
490
|
|
|
504
491
|
def base_event(event_type, payload, context)
|
|
505
|
-
{
|
|
492
|
+
event = {
|
|
506
493
|
'schema_version' => SCHEMA_VERSION,
|
|
507
494
|
'event_id' => SecureRandom.uuid,
|
|
508
495
|
'event_type' => event_type,
|
|
@@ -519,15 +506,14 @@ module DebugBundle
|
|
|
519
506
|
'correlation' => correlation_payload(context),
|
|
520
507
|
'payload' => @redactor.redact_value(payload)
|
|
521
508
|
}
|
|
509
|
+
envelope_context = event_context(context)
|
|
510
|
+
event['context'] = envelope_context unless envelope_context.empty?
|
|
511
|
+
event
|
|
522
512
|
end
|
|
523
513
|
|
|
524
|
-
def service_name
|
|
525
|
-
config.service || DEFAULT_SERVICE_NAME
|
|
526
|
-
end
|
|
514
|
+
def service_name = config.service || DEFAULT_SERVICE_NAME
|
|
527
515
|
|
|
528
|
-
def environment_name
|
|
529
|
-
config.environment || DEFAULT_ENVIRONMENT
|
|
530
|
-
end
|
|
516
|
+
def environment_name = config.environment || DEFAULT_ENVIRONMENT
|
|
531
517
|
|
|
532
518
|
def correlation_payload(context)
|
|
533
519
|
request = object_to_hash(context['request'])
|
|
@@ -540,6 +526,18 @@ module DebugBundle
|
|
|
540
526
|
}
|
|
541
527
|
end
|
|
542
528
|
|
|
529
|
+
def event_context(context)
|
|
530
|
+
object_to_hash(context).except(
|
|
531
|
+
'request',
|
|
532
|
+
'response',
|
|
533
|
+
'correlation',
|
|
534
|
+
'request_id',
|
|
535
|
+
'trace_id',
|
|
536
|
+
'session_id',
|
|
537
|
+
'user_id_hash'
|
|
538
|
+
)
|
|
539
|
+
end
|
|
540
|
+
|
|
543
541
|
def object_to_hash(value)
|
|
544
542
|
case value
|
|
545
543
|
when Hash
|
|
@@ -591,14 +589,20 @@ module DebugBundle
|
|
|
591
589
|
end
|
|
592
590
|
end
|
|
593
591
|
|
|
594
|
-
def capture_request_event?(status_code)
|
|
592
|
+
def capture_request_event?(status_code, request)
|
|
595
593
|
mode = @capture_policy.capture_request_events
|
|
596
|
-
immediate_statuses = immediate_request_statuses
|
|
597
|
-
anomaly_statuses = anomaly_request_statuses
|
|
598
594
|
|
|
599
595
|
return true if mode == 'all'
|
|
600
|
-
return true if
|
|
601
|
-
return true if mode == 'failures_only' &&
|
|
596
|
+
return true if immediate_request_event?(status_code, request)
|
|
597
|
+
return true if mode == 'failures_only' && status_code >= 500
|
|
598
|
+
|
|
599
|
+
false
|
|
600
|
+
end
|
|
601
|
+
|
|
602
|
+
def immediate_request_event?(status_code, request)
|
|
603
|
+
return true if status_code >= 500
|
|
604
|
+
return true if immediate_request_statuses.include?(status_code)
|
|
605
|
+
return true if matching_immediate_client_error_path_rule?(status_code, request)
|
|
602
606
|
|
|
603
607
|
false
|
|
604
608
|
end
|
|
@@ -616,10 +620,34 @@ module DebugBundle
|
|
|
616
620
|
statuses + Array(@capture_policy.immediate_client_error_statuses)
|
|
617
621
|
end
|
|
618
622
|
|
|
619
|
-
def
|
|
620
|
-
return
|
|
623
|
+
def matching_immediate_client_error_path_rule?(status_code, request)
|
|
624
|
+
return false unless (400..499).cover?(status_code)
|
|
625
|
+
|
|
626
|
+
path = normalize_request_path(request['path'] || request['url'])
|
|
627
|
+
method = request['method'].to_s.upcase
|
|
628
|
+
Array(@capture_policy.immediate_client_error_path_rules).any? do |rule|
|
|
629
|
+
next false unless rule.status_code == status_code
|
|
630
|
+
next false if !rule.http_methods.empty? && !rule.http_methods.include?(method)
|
|
631
|
+
|
|
632
|
+
if rule.path_pattern.end_with?('*')
|
|
633
|
+
path.start_with?(rule.path_pattern.delete_suffix('*'))
|
|
634
|
+
else
|
|
635
|
+
path == rule.path_pattern
|
|
636
|
+
end
|
|
637
|
+
end
|
|
638
|
+
end
|
|
639
|
+
|
|
640
|
+
def normalize_request_path(value)
|
|
641
|
+
begin
|
|
642
|
+
uri = URI.parse(value.to_s)
|
|
643
|
+
return uri.path if uri.path && !uri.path.empty?
|
|
644
|
+
rescue URI::InvalidURIError
|
|
645
|
+
# Fall through to the lightweight path-only fallback.
|
|
646
|
+
end
|
|
647
|
+
fallback = value.to_s.split('?', 2).first.to_s.split('#', 2).first
|
|
648
|
+
return fallback if fallback.start_with?('/') && !fallback.empty?
|
|
621
649
|
|
|
622
|
-
|
|
650
|
+
'/'
|
|
623
651
|
end
|
|
624
652
|
|
|
625
653
|
def matching_probe_directives(label)
|
|
@@ -630,9 +658,7 @@ module DebugBundle
|
|
|
630
658
|
end
|
|
631
659
|
end
|
|
632
660
|
|
|
633
|
-
def current_request_trigger_directives
|
|
634
|
-
Array(Thread.current[REQUEST_TRIGGER_DIRECTIVES_KEY])
|
|
635
|
-
end
|
|
661
|
+
def current_request_trigger_directives = Array(Thread.current[REQUEST_TRIGGER_DIRECTIVES_KEY])
|
|
636
662
|
|
|
637
663
|
def matching_request_trigger_directives(label)
|
|
638
664
|
current_request_trigger_directives.select do |directive|
|
|
@@ -671,13 +697,9 @@ module DebugBundle
|
|
|
671
697
|
0
|
|
672
698
|
end
|
|
673
699
|
|
|
674
|
-
def rate_limited?
|
|
675
|
-
@retry_at && @retry_at > now
|
|
676
|
-
end
|
|
700
|
+
def rate_limited? = @retry_at && @retry_at > now
|
|
677
701
|
|
|
678
|
-
def local_environment?
|
|
679
|
-
LOCAL_ENVIRONMENTS.include?(environment_name.to_s)
|
|
680
|
-
end
|
|
702
|
+
def local_environment? = LOCAL_ENVIRONMENTS.include?(environment_name.to_s)
|
|
681
703
|
|
|
682
704
|
def poll_remote_config_if_due!
|
|
683
705
|
return unless @config_fetcher
|
|
@@ -713,12 +735,8 @@ module DebugBundle
|
|
|
713
735
|
nil
|
|
714
736
|
end
|
|
715
737
|
|
|
716
|
-
def now
|
|
717
|
-
@time_provider.call
|
|
718
|
-
end
|
|
738
|
+
def now = @time_provider.call
|
|
719
739
|
|
|
720
|
-
def monotonic_now
|
|
721
|
-
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
722
|
-
end
|
|
740
|
+
def monotonic_now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
723
741
|
end
|
|
724
742
|
end
|
|
@@ -11,9 +11,12 @@ module DebugBundle
|
|
|
11
11
|
:capture_breadcrumbs,
|
|
12
12
|
:capture_probe_events,
|
|
13
13
|
:immediate_client_error_statuses,
|
|
14
|
+
:immediate_client_error_path_rules,
|
|
14
15
|
keyword_init: true
|
|
15
16
|
)
|
|
16
17
|
|
|
18
|
+
ImmediateClientErrorPathRule = Struct.new(:status_code, :path_pattern, :http_methods, keyword_init: true)
|
|
19
|
+
|
|
17
20
|
Directive = Struct.new(:id, :label_pattern, :service, :environment, :expires_at, keyword_init: true) do
|
|
18
21
|
def active?(label:, service:, environment:, now:)
|
|
19
22
|
return false if expires_at <= now
|
|
@@ -69,7 +72,8 @@ module DebugBundle
|
|
|
69
72
|
capture_request_events: 'failures_only',
|
|
70
73
|
capture_breadcrumbs: 'local_only',
|
|
71
74
|
capture_probe_events: 'buffer_only',
|
|
72
|
-
immediate_client_error_statuses: []
|
|
75
|
+
immediate_client_error_statuses: [],
|
|
76
|
+
immediate_client_error_path_rules: []
|
|
73
77
|
)
|
|
74
78
|
end
|
|
75
79
|
|
|
@@ -80,7 +84,8 @@ module DebugBundle
|
|
|
80
84
|
capture_request_events: 'failures_only',
|
|
81
85
|
capture_breadcrumbs: 'exception_only',
|
|
82
86
|
capture_probe_events: 'buffer_only',
|
|
83
|
-
immediate_client_error_statuses: []
|
|
87
|
+
immediate_client_error_statuses: [],
|
|
88
|
+
immediate_client_error_path_rules: []
|
|
84
89
|
)
|
|
85
90
|
end
|
|
86
91
|
|
|
@@ -122,10 +127,48 @@ module DebugBundle
|
|
|
122
127
|
capture_probe_events: payload['capture_probe_events'] || payload[:capture_probe_events] || 'buffer_only',
|
|
123
128
|
immediate_client_error_statuses: Array(
|
|
124
129
|
payload['immediate_client_error_statuses'] || payload[:immediate_client_error_statuses]
|
|
125
|
-
).grep(Integer)
|
|
130
|
+
).grep(Integer),
|
|
131
|
+
immediate_client_error_path_rules: parse_immediate_client_error_path_rules(
|
|
132
|
+
payload['immediate_client_error_path_rules'] || payload[:immediate_client_error_path_rules]
|
|
133
|
+
)
|
|
126
134
|
)
|
|
127
135
|
end
|
|
128
136
|
|
|
137
|
+
def self.parse_immediate_client_error_path_rules(value)
|
|
138
|
+
entries = Array(value)
|
|
139
|
+
return [] if entries.empty? || entries.length > 25
|
|
140
|
+
|
|
141
|
+
entries.filter_map do |entry|
|
|
142
|
+
next unless entry.is_a?(Hash)
|
|
143
|
+
|
|
144
|
+
status_code = entry['status_code'] || entry[:status_code]
|
|
145
|
+
path_pattern = entry['path_pattern'] || entry[:path_pattern]
|
|
146
|
+
raw_methods = Array(entry['methods'] || entry[:methods])
|
|
147
|
+
next unless status_code.is_a?(Integer) && (400..499).cover?(status_code)
|
|
148
|
+
next unless valid_path_pattern?(path_pattern)
|
|
149
|
+
next if raw_methods.length > 7
|
|
150
|
+
|
|
151
|
+
http_methods = raw_methods.map { |method| method.to_s.upcase }.uniq
|
|
152
|
+
next unless http_methods.all? { |method| %w[GET POST PUT PATCH DELETE HEAD OPTIONS].include?(method) }
|
|
153
|
+
|
|
154
|
+
ImmediateClientErrorPathRule.new(
|
|
155
|
+
status_code: status_code,
|
|
156
|
+
path_pattern: path_pattern,
|
|
157
|
+
http_methods: http_methods
|
|
158
|
+
)
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def self.valid_path_pattern?(value)
|
|
163
|
+
return false unless value.is_a?(String)
|
|
164
|
+
return false if value.empty? || value.length > 256
|
|
165
|
+
return false unless value.start_with?('/')
|
|
166
|
+
return false if value.include?('?') || value.include?('#')
|
|
167
|
+
|
|
168
|
+
wildcard_index = value.index('*')
|
|
169
|
+
wildcard_index.nil? || wildcard_index == value.length - 1
|
|
170
|
+
end
|
|
171
|
+
|
|
129
172
|
def self.parse_directive(payload)
|
|
130
173
|
return nil unless payload.is_a?(Hash)
|
|
131
174
|
|
data/lib/debugbundle/version.rb
CHANGED
|
@@ -57,11 +57,16 @@
|
|
|
57
57
|
"event_id": { "type": "string", "format": "uuid" },
|
|
58
58
|
"event_type": { "type": "string", "minLength": 1 },
|
|
59
59
|
"project_token": { "type": "string", "minLength": 1 },
|
|
60
|
+
"project_id": { "type": ["string", "null"], "format": "uuid" },
|
|
60
61
|
"sdk_name": { "type": "string", "minLength": 1 },
|
|
61
62
|
"sdk_version": { "type": "string", "minLength": 1 },
|
|
62
63
|
"service": { "$ref": "#/$defs/service" },
|
|
63
64
|
"occurred_at": { "type": "string", "format": "date-time" },
|
|
64
65
|
"correlation": { "$ref": "#/$defs/correlation" },
|
|
66
|
+
"context": {
|
|
67
|
+
"type": "object",
|
|
68
|
+
"additionalProperties": true
|
|
69
|
+
},
|
|
65
70
|
"payload": {}
|
|
66
71
|
}
|
|
67
72
|
},
|
|
@@ -23,7 +23,7 @@ RSpec.describe 'Rack integration' do
|
|
|
23
23
|
client = DebugBundle::Client.new(project_token: 'dbundle_proj_test', service: 'rack-checkout', transport: transport)
|
|
24
24
|
app = Rack::Builder.new do
|
|
25
25
|
use DebugBundle::Rack::Middleware, client: client
|
|
26
|
-
run ->(_env) { [
|
|
26
|
+
run ->(_env) { [503, { 'Content-Type' => 'text/plain' }, ['ok']] }
|
|
27
27
|
end.to_app
|
|
28
28
|
|
|
29
29
|
response = Rack::MockRequest.new(app).get(
|
|
@@ -35,10 +35,10 @@ RSpec.describe 'Rack integration' do
|
|
|
35
35
|
client.flush
|
|
36
36
|
event = transport_events.fetch(0).fetch(:events).fetch(0)
|
|
37
37
|
|
|
38
|
-
expect(response.status).to eq(
|
|
38
|
+
expect(response.status).to eq(503)
|
|
39
39
|
expect(response.body).to eq('ok')
|
|
40
40
|
expect(event.fetch('event_type')).to eq('request_event')
|
|
41
41
|
expect(event.fetch('correlation')).to include('request_id' => 'req-rack', 'trace_id' => 'trace-rack')
|
|
42
|
-
expect(event.fetch('payload')).to include('path' => '/checkout', 'method' => 'GET', 'response_status' =>
|
|
42
|
+
expect(event.fetch('payload')).to include('path' => '/checkout', 'method' => 'GET', 'response_status' => 503)
|
|
43
43
|
end
|
|
44
44
|
end
|
|
@@ -195,10 +195,14 @@ RSpec.describe DebugBundle::Rack::Middleware do
|
|
|
195
195
|
)
|
|
196
196
|
|
|
197
197
|
client.flush
|
|
198
|
-
|
|
198
|
+
event = transport_events.fetch(0).fetch(:events).fetch(0)
|
|
199
|
+
payload = event.fetch('payload')
|
|
200
|
+
context = event.fetch('context')
|
|
199
201
|
|
|
200
202
|
expect(payload).to include(
|
|
201
|
-
'route_template' => '/patients/:patient_id/checkouts'
|
|
203
|
+
'route_template' => '/patients/:patient_id/checkouts'
|
|
204
|
+
)
|
|
205
|
+
expect(context).to include(
|
|
202
206
|
'controller' => 'checkouts',
|
|
203
207
|
'action' => 'create'
|
|
204
208
|
)
|
|
@@ -50,7 +50,7 @@ if defined?(Sidekiq)
|
|
|
50
50
|
|
|
51
51
|
expect(event.fetch('event_type')).to eq('backend_exception')
|
|
52
52
|
expect(event.fetch('correlation')).to include('trace_id' => 'trace-chain-1')
|
|
53
|
-
expect(event.fetch('
|
|
53
|
+
expect(event.fetch('context').fetch('job')).to include(
|
|
54
54
|
'class' => 'CheckoutWorker',
|
|
55
55
|
'queue' => 'critical',
|
|
56
56
|
'jid' => 'jid-chain-1'
|
|
@@ -40,7 +40,7 @@ RSpec.describe DebugBundle::Sidekiq::ServerMiddleware do
|
|
|
40
40
|
|
|
41
41
|
expect(event.fetch('event_type')).to eq('backend_exception')
|
|
42
42
|
expect(event.fetch('correlation')).to include('trace_id' => 'trace-job-1')
|
|
43
|
-
expect(event.fetch('
|
|
43
|
+
expect(event.fetch('context').fetch('job')).to include(
|
|
44
44
|
'class' => 'CheckoutWorker',
|
|
45
45
|
'queue' => 'critical',
|
|
46
46
|
'jid' => 'jid-1',
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: debugbundle
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- DebugBundle
|
|
8
8
|
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-
|
|
10
|
+
date: 2026-06-19 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: base64
|