logbrew-sdk 0.1.12 → 0.1.14

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: a0af4b97ef8e2b7c4e89c4c7541e1a512d85f4d8aa6e3d87639551145f99875c
4
- data.tar.gz: eaa3d1ff11b605c3547964918cfb37714e8ea737c72748f02d08ce2b27fed221
3
+ metadata.gz: ba29c0ee35c6f7287dbdeadcc2f215b32270218de626d2338de40d8082be04a4
4
+ data.tar.gz: efade8df92a9d851cf9fce4f482ff632a50bcc79038157b048cdb792e6a4fb30
5
5
  SHA512:
6
- metadata.gz: fc95d14c11974aa1c83adefa37beb10864029e9d6c5e518c9dccd99ad1901974aa6fa3885a186ad05a00ae23e12642e61f578bec7f1a78d7629dcbf0e4d022dc
7
- data.tar.gz: 2154ac935379e496a6d8888058ee22964ad7cda7449ed0af86120f5099656a52f7be54042117f650e66259c848e435df8150f70f3f38ff07e856e6f1cafd3fbc
6
+ metadata.gz: a2e498a092d5cbaa2f09b7b9be07112e7656e33df61f73614c09cd4cd1d8d7830d3dd24b6daf1169c834847415acc19898cc0c994ca6bb6a47c972a612e13395
7
+ data.tar.gz: 62b25847c01ab391d7122aca956e8b591961cb2a2020b2af837d75d65c2ae508955c088663b0d78d70e0597d99f97efd0e786bc428227a3180c975567ae64a44
data/README.md CHANGED
@@ -23,7 +23,7 @@ needed:
23
23
 
24
24
  ```ruby
25
25
  # Gemfile
26
- gem "logbrew-sdk", "~> 0.1.12"
26
+ gem "logbrew-sdk", "~> 0.1.14"
27
27
  ```
28
28
 
29
29
  ```bash
@@ -57,13 +57,14 @@ paths. Exception messages and raw backtrace text are separate opt-ins.
57
57
 
58
58
  ActiveJob needs no extra initializer. Each enqueue and execution emits a
59
59
  producer or worker span, including bounded adapter identity, retry count, and
60
- queue wait. A versioned W3C carrier keeps retries and supported queue adapters
61
- on one trace. A retryable failure remains span evidence; only an unexpected
62
- terminal `StandardError` creates an unhandled `rails.active_job` issue with
63
- sanitized structured frames. The adapter does not capture job IDs, queue names,
64
- arguments, serialized payloads, exception messages, or raw backtraces by
65
- default. When ActiveJob uses LogBrew's Sidekiq middleware, the inner carrier
66
- suppresses duplicate Sidekiq spans and issues.
60
+ queue wait. Enqueue spans use `queue.publish`; worker spans use `queue.process`.
61
+ A versioned W3C carrier keeps retries and supported queue adapters on one trace.
62
+ A retryable failure remains span evidence; only an unexpected terminal
63
+ `StandardError` creates an unhandled `rails.active_job` issue with sanitized
64
+ structured frames. The adapter does not capture job IDs, queue names, arguments,
65
+ serialized payloads, exception messages, or raw backtraces by default. When
66
+ ActiveJob uses LogBrew's Sidekiq middleware, the inner carrier suppresses
67
+ duplicate Sidekiq spans and issues.
67
68
 
68
69
  Outbound `Net::HTTP` calls made inside an active Rails request or job trace also
69
70
  need no initializer. They propagate one W3C child and record only method,
@@ -745,7 +746,14 @@ Registration is app-owned, idempotent, and reversible with `unregister_client` a
745
746
 
746
747
  The client middleware adds one bounded `logbrew` carrier containing only a version, W3C `traceparent`, and enqueue time. Valid retries keep that carrier without creating another enqueue span. The server middleware continues a valid carrier or starts a fresh trace when it is absent or malformed, returns the caller trace state after every result, and records bounded queue-wait and execution timing. Set `max_retries` to the same default retry limit used by your Sidekiq configuration; per-job integer or disabled retry settings are honored. Retryable failures keep only error spans, while the terminal escaped failure adds one deduplicated fixed-title issue and preserves the original exception.
747
748
 
748
- Sidekiq spans contain only fixed source, sampled state, bounded retry count, bounded queue-wait duration, execution duration, status, and real cancellation. The integration does not capture job arguments, payload fields, job identifiers, worker names, queue values, connection data, exception messages or stacks, baggage, or tracestate. Capture failures are advisory and never replace job execution or retry behavior. Create fresh clients and instrumentation after `fork`; inherited instances fail closed without changing jobs.
749
+ Sidekiq producer spans use `queue.publish`, and worker spans use `queue.process`.
750
+ They contain only fixed source, sampled state, bounded retry count, bounded
751
+ queue-wait duration, execution duration, status, and real cancellation. The
752
+ integration does not capture job arguments, payload fields, job identifiers,
753
+ worker names, queue values, connection data, exception messages or stacks,
754
+ baggage, or tracestate. Capture failures are advisory and never replace job
755
+ execution or retry behavior. Create fresh clients and instrumentation after
756
+ `fork`; inherited instances fail closed without changing jobs.
749
757
 
750
758
  ## Persistent Worker Delivery
751
759
 
@@ -6,7 +6,11 @@ module LogBrew
6
6
  UNSAFE_METADATA = /authorization|body|broker|cache.?key|command|connection|cookie|dsn|header|host|
7
7
  \bjid\z|job.?id|key|message|param|pass#{'word'}|payload|query|sec#{'ret'}|sql|statement|
8
8
  to#{'ken'}|url|username|value/ix
9
- private_constant :UNSAFE_METADATA
9
+ QUEUE_SEMANTICS = {
10
+ "enqueue" => "queue.publish", "publish" => "queue.publish", "send" => "queue.publish",
11
+ "receive" => "queue.receive", "perform" => "queue.process", "process" => "queue.process", "consume" => "queue.process"
12
+ }.freeze
13
+ private_constant :UNSAFE_METADATA, :QUEUE_SEMANTICS
10
14
 
11
15
  module_function
12
16
 
@@ -28,20 +32,13 @@ module LogBrew
28
32
  Validation.require_non_empty("#{kind} operation name", name)
29
33
  started_at = monotonic_time
30
34
  context = child_context
31
- error = nil
32
- result = nil
33
-
34
- Trace.with_context(context) do
35
- begin
36
- result = yield context
37
- rescue StandardError => captured
38
- error = captured
39
- end
35
+ begin
36
+ result = Trace.with_context(context) { yield context }
37
+ rescue StandardError => error
38
+ capture_span(client, kind, name, context, started_at, options, error)
39
+ raise
40
40
  end
41
-
42
- capture_span(client, kind, name, context, started_at, options, error)
43
- raise error if error
44
-
41
+ capture_span(client, kind, name, context, started_at, options, nil)
45
42
  result
46
43
  end
47
44
 
@@ -88,6 +85,7 @@ module LogBrew
88
85
  metadata["source"] = read_option(options, :source) || "#{kind}.operation"
89
86
  add_option(metadata, "#{kind}.system", read_option(options, :system))
90
87
  add_option(metadata, "#{kind}.operation", read_option(options, :operation))
88
+ add_option(metadata, "operation", QUEUE_SEMANTICS[read_option(options, :operation)]) if kind == "queue"
91
89
  add_option(metadata, "#{kind}.target", read_option(options, :target))
92
90
  metadata["exceptionType"] = error.class.name if error
93
91
  end
@@ -431,11 +431,11 @@ module LogBrew
431
431
  private_constant :LoggerTap
432
432
 
433
433
  module BroadcastOrigin
434
- def dispatch(...)
434
+ def dispatch(*args, &block)
435
435
  previous = Thread.current[ORIGIN_KEY]
436
436
  origin = ApplicationLogCapture.application_caller?(instance_variable_get(ROOT_IVAR))
437
437
  Thread.current[ORIGIN_KEY] = origin
438
- super
438
+ super(*args, &block)
439
439
  ensure
440
440
  Thread.current[ORIGIN_KEY] = previous
441
441
  end
@@ -28,15 +28,12 @@ module LogBrew
28
28
 
29
29
  def around(terminal_failure: false)
30
30
  Trace.with_context(@context) do
31
- begin
32
- result = yield
33
- rescue Exception => error # rubocop:disable Lint/RescueException
34
- finish(error: error, terminal_failure: terminal_failure)
35
- raise
36
- else
37
- finish
38
- result
39
- end
31
+ result = yield
32
+ finish
33
+ result
34
+ rescue Exception => error # rubocop:disable Lint/RescueException
35
+ finish(error: error, terminal_failure: terminal_failure)
36
+ raise
40
37
  end
41
38
  end
42
39
 
@@ -50,7 +47,7 @@ module LogBrew
50
47
  end
51
48
 
52
49
  @instrumentation.send(:capture_span, self, error)
53
- @instrumentation.send(:capture_terminal_issue, self) if error && terminal_failure && !cancellation?(error)
50
+ @instrumentation.send(:capture_terminal_issue, self, error) if error && terminal_failure && !cancellation?(error)
54
51
  rescue StandardError => capture_error
55
52
  @instrumentation.send(:report_capture_error, capture_error)
56
53
  end
@@ -64,6 +61,7 @@ module LogBrew
64
61
  def span_attributes(error)
65
62
  metadata = {
66
63
  "source" => @source,
64
+ "operation" => @source == "sidekiq.client" ? "queue.publish" : "queue.process",
67
65
  "sampled" => @context.sampled
68
66
  }
69
67
  metadata["retryCount"] = @retry_count unless @retry_count.nil?
@@ -81,20 +79,22 @@ module LogBrew
81
79
  }
82
80
  end
83
81
 
84
- def issue_attributes
85
- {
86
- "title" => "Sidekiq job failed",
87
- "level" => "error",
88
- "metadata" => {
89
- "source" => @source,
90
- "sampled" => @context.sampled,
91
- "retryCount" => @retry_count + 1
92
- }
82
+ def issue_attributes(error)
83
+ exception_type = IssueDiagnostics.safe_exception_type(error)
84
+ frame = IssueDiagnostics.stack_frames_from_exception(error).first
85
+ metadata = {
86
+ "source" => @source,
87
+ "sampled" => @context.sampled,
88
+ "retryCount" => @retry_count + 1,
89
+ "errorName" => exception_type
93
90
  }
94
- end
95
-
96
- def retry_count
97
- @retry_count
91
+ unless frame.nil?
92
+ metadata["errorFrameFile"] = frame.fetch("filename")
93
+ metadata["errorFrameLine"] = frame.fetch("line")
94
+ end
95
+ IssueDiagnostics.from_exception(
96
+ error, title: exception_type, mechanism_type: "sidekiq.job", handled: false, metadata: metadata
97
+ )
98
98
  end
99
99
 
100
100
  def failure_key
@@ -383,7 +383,7 @@ module LogBrew
383
383
  )
384
384
  end
385
385
 
386
- def capture_terminal_issue(operation)
386
+ def capture_terminal_issue(operation, error)
387
387
  key = operation.failure_key
388
388
  reserved = @failure_mutex.synchronize do
389
389
  next false if @reported_failures.key?(key)
@@ -398,7 +398,7 @@ module LogBrew
398
398
  @client.issue(
399
399
  "ruby_sidekiq_issue_#{operation.context.span_id}",
400
400
  Time.now.utc.iso8601,
401
- operation.issue_attributes
401
+ operation.issue_attributes(error)
402
402
  )
403
403
  rescue StandardError
404
404
  @failure_mutex.synchronize { @reported_failures.delete(key) }
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module LogBrew
4
- VERSION = "0.1.12"
4
+ VERSION = "0.1.14"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logbrew-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.12
4
+ version: 0.1.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - LogBrew
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-08-17 00:00:00.000000000 Z
11
+ date: 2026-09-03 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Public LogBrew Ruby SDK with typed issue diagnostics, automatic Rails
14
14
  request/error capture, and standard-library delivery.