logbrew-sdk 0.1.9 → 0.1.11

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: 95bb6223a8ef074b3c8dd0973fe99e36734849c1b47a19f1c1ed88655888d71b
4
- data.tar.gz: 4ac8224ffe4e2fae6f4262b80a3119f2574982a6c0f384c529c77c74163340fc
3
+ metadata.gz: e4d8cebbc9fcb274134dda84b6de6b086a4dc6cdc119b80f02c3458624ca1587
4
+ data.tar.gz: c35a55684af97f05ef24f3626412f471c12af7cef0bcc7468430393dfbfccfdd
5
5
  SHA512:
6
- metadata.gz: f90b3564b39c4546b8a34b424b1f59e8ca5de6afaba35529e511a688712e770c92c04deb547fd7e370bfa1590688be7ce3b11ca5f04ccd7d11ecb022f37ff401
7
- data.tar.gz: 3d47121b9f61ed19bbeda0e9389f3daa5137c34b88256ea9b5d3f7e47dd28b4d4c36fc7f94bf0c9e2172be0b65f72235e5e96e2923c113811e0b758158498f18
6
+ metadata.gz: e9f385c563b7de3bd38294d83e5aa9b3e72c57efb21cf6b22c59de8c5c0328d3a117dbbbee2bf42a91a36d98d97ece63afb2997661968a902f525c932351e5de
7
+ data.tar.gz: ae840cec0095218353192f4af76c00b4ec80707e4bc208c03ba6ae654e2c98158c2af8c198d68e1d279a84df944382e654312a599d7311cd8ad4a6eb519e8d8a
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  <img src="https://raw.githubusercontent.com/LogBrewCo/sdk/main/assets/brand/logbrew-logo-transparent-512.png" alt="LogBrew logo" width="96" height="96">
5
5
  </p>
6
6
 
7
- Public Ruby SDK for building, validating, previewing, and flushing LogBrew event batches, with automatic Rails request, database, cache, view, error, and ActiveJob capture; standard-library `Net::HTTP` delivery; opt-in standard-library `Logger` support; and manual Rack helpers.
7
+ Public Ruby SDK for building, validating, previewing, and flushing LogBrew event batches, with automatic Rails request, database, cache, view, error, ActiveJob, and outbound `Net::HTTP` capture; standard-library delivery; opt-in standard-library `Logger` support; and manual Rack helpers.
8
8
 
9
9
  The core package has no runtime gem dependencies. Its automatic integration
10
10
  activates only inside an application that has already loaded Rails.
@@ -23,7 +23,7 @@ needed:
23
23
 
24
24
  ```ruby
25
25
  # Gemfile
26
- gem "logbrew-sdk", "~> 0.1.9"
26
+ gem "logbrew-sdk", "~> 0.1.11"
27
27
  ```
28
28
 
29
29
  ```bash
@@ -65,6 +65,11 @@ arguments, serialized payloads, exception messages, or raw backtraces by
65
65
  default. When ActiveJob uses LogBrew's Sidekiq middleware, the inner carrier
66
66
  suppresses duplicate Sidekiq spans and issues.
67
67
 
68
+ Outbound `Net::HTTP` calls made inside an active Rails request or job trace also
69
+ need no initializer. They propagate one W3C child and record only method,
70
+ normalized host, status, duration, adapter source, sampled state, and exception
71
+ type. Calls outside an active trace remain exact pass-throughs.
72
+
68
73
  The explicit Rails capture settings are:
69
74
 
70
75
  | Environment variable | Default | Purpose |
@@ -427,7 +432,9 @@ end
427
432
 
428
433
  ## Outbound HTTP Tracing
429
434
 
430
- Wrap an app-owned `Net::HTTP` connection explicitly when outbound work should become a child of the active LogBrew trace:
435
+ The enabled Rails integration captures `Net::HTTP` automatically while a
436
+ LogBrew trace is active. Outside Rails, wrap an app-owned connection explicitly
437
+ when outbound work should become a child of the active trace:
431
438
 
432
439
  ```ruby
433
440
  uri = URI("https://service.example/health")
@@ -452,7 +459,15 @@ connection = Faraday.new("https://service.example") do |builder|
452
459
  end
453
460
  ```
454
461
 
455
- Both adapters are literal pass-throughs when `LogBrew::Trace.current` is absent. With an active parent, they propagate one W3C `traceparent`, return the caller-visible header and trace scope to their prior values, and capture one completion span per actual execution. Duplicate wrappers, nested LogBrew HTTP middleware, and SDK delivery are suppressed without process-wide hooks. Net::HTTP start blocks, response streaming, Faraday middleware ordering, responses, and exceptions retain their normal behavior; telemetry capture failures are advisory.
462
+ Both explicit adapters are literal pass-throughs when `LogBrew::Trace.current`
463
+ is absent. With an active parent, explicit adapters and automatic Rails
464
+ `Net::HTTP` capture propagate one W3C `traceparent`, return caller-visible
465
+ header and trace state, and capture one completion span per actual execution.
466
+ Duplicate wrappers, nested LogBrew HTTP middleware, and SDK delivery are
467
+ suppressed. Outside an enabled Rails process, the SDK does not patch
468
+ `Net::HTTP`. Start blocks, response streaming, Faraday middleware ordering,
469
+ responses, and exceptions retain normal behavior; capture failures are
470
+ advisory.
456
471
 
457
472
  Outbound HTTP spans allow only method, normalized host, status code, duration, adapter source, sampled state, and exception type. They never record scheme, port, path, query, fragment, full URL, request or response headers, bodies or sizes, exception messages or stacks, authentication material, cookies, baggage, tracestate, resolved addresses, or arbitrary request options.
458
473
 
@@ -19,6 +19,7 @@ module LogBrew
19
19
  @method = HttpClientTracing.normalize_method(method)
20
20
  @host = HttpClientTracing.normalize_host(host)
21
21
  @on_capture_error = on_capture_error
22
+ @timestamp = Time.now.utc.iso8601(6)
22
23
  @started_at = HttpClientTracing.monotonic_time
23
24
  @mutex = Mutex.new
24
25
  @finished = false
@@ -60,7 +61,7 @@ module LogBrew
60
61
 
61
62
  @client.span(
62
63
  "ruby_http_span_#{@context.span_id}",
63
- Time.now.utc.iso8601,
64
+ @timestamp,
64
65
  {
65
66
  name: "http.client:#{@method}",
66
67
  traceId: @context.trace_id,
@@ -86,35 +87,12 @@ module LogBrew
86
87
  end
87
88
 
88
89
  def request(request, body = nil, &block)
89
- prepared = HttpClientTracing.prepare(
90
+ HttpClientTracing.capture_net_http(
91
+ @http,
92
+ request,
90
93
  client: @client,
91
- source: "net_http",
92
94
  on_capture_error: @on_capture_error
93
- ) do
94
- [request.method, address, HttpClientTracing::NetHttpHeaderSnapshot.new(request)]
95
- end
96
- return @http.request(request, body, &block) unless prepared
97
-
98
- operation, header = prepared
99
- begin
100
- header.inject(operation.traceparent)
101
- rescue StandardError => error
102
- operation.capture_error(error)
103
- HttpClientTracing.reset_header(header, operation)
104
- return @http.request(request, body, &block)
105
- end
106
-
107
- response = nil
108
- begin
109
- response = operation.around { @http.request(request, body, &block) }
110
- rescue StandardError => error
111
- operation.finish(error: error)
112
- raise
113
- ensure
114
- HttpClientTracing.reset_header(header, operation)
115
- end
116
- operation.finish(status_code: HttpClientTracing.read_status(response, :code, operation))
117
- response
95
+ ) { @http.request(request, body, &block) }
118
96
  end
119
97
 
120
98
  def start(*arguments)
@@ -187,6 +165,34 @@ module LogBrew
187
165
  NetHttpTracingClient.new(http, client: client, on_capture_error: on_capture_error)
188
166
  end
189
167
 
168
+ def capture_net_http(http, request, client:, on_capture_error: nil)
169
+ prepared = prepare(client: client, source: "net_http", on_capture_error: on_capture_error) do
170
+ [request.method, http.address, NetHttpHeaderSnapshot.new(request)]
171
+ end
172
+ return yield unless prepared
173
+
174
+ operation, header = prepared
175
+ begin
176
+ header.inject(operation.traceparent)
177
+ rescue StandardError => error
178
+ operation.capture_error(error)
179
+ reset_header(header, operation)
180
+ return yield
181
+ end
182
+
183
+ response = nil
184
+ begin
185
+ response = operation.around { yield }
186
+ rescue StandardError => error
187
+ operation.finish(error: error)
188
+ raise
189
+ ensure
190
+ reset_header(header, operation)
191
+ end
192
+ operation.finish(status_code: read_status(response, :code, operation))
193
+ response
194
+ end
195
+
190
196
  def prepare(client:, source:, on_capture_error: nil)
191
197
  parent = Trace.current
192
198
  return nil unless parent
data/lib/logbrew/rails.rb CHANGED
@@ -77,6 +77,7 @@ module LogBrew
77
77
  runtime = LogBrew::Rails.install(application: application)
78
78
  if runtime.configuration.enabled?
79
79
  LogBrew::Rails.const_get(:RequestOperations).install(::ActiveSupport::Notifications)
80
+ LogBrew::Rails.const_get(:OutboundHttp).install
80
81
  end
81
82
  ::ActiveSupport.on_load(:active_job) do
82
83
  prepend LogBrew::Rails::ActiveJobExtension unless ancestors.include?(LogBrew::Rails::ActiveJobExtension)
@@ -398,6 +398,30 @@ module LogBrew
398
398
  end
399
399
  end
400
400
 
401
+ # Adds bounded child spans to Net::HTTP calls made inside an active Rails trace.
402
+ module OutboundHttp
403
+ module Request
404
+ def request(request, body = nil, &block)
405
+ runtime = LogBrew::Rails.runtime
406
+ client = LogBrew::Trace.current && runtime&.client
407
+ return super unless client
408
+
409
+ LogBrew::HttpClientTracing.capture_net_http(
410
+ self,
411
+ request,
412
+ client: client,
413
+ on_capture_error: ->(error) { runtime.report_error("outbound_http_capture", error) }
414
+ ) { super(request, body, &block) }
415
+ end
416
+ end
417
+
418
+ module_function
419
+
420
+ def install
421
+ Net::HTTP.prepend(Request) unless Net::HTTP.ancestors.include?(Request)
422
+ end
423
+ end
424
+
401
425
  # One privacy-bounded producer or worker operation for ActiveJob.
402
426
  class ActiveJobOperation
403
427
  attr_reader :context
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module LogBrew
4
- VERSION = "0.1.9"
4
+ VERSION = "0.1.11"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logbrew-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.9
4
+ version: 0.1.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - LogBrew