foam-otel 1.9.0 → 1.9.1

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: d27bb6b38712364503503fecd37ea383f9a7e3fb3648da8ef41524c575ef9302
4
- data.tar.gz: 0c9fee962999043120904c8ffe85621e32ae04fcb300280ec8af0b2c77291a0d
3
+ metadata.gz: a2e506ae900650923638df263e5775efa20dd8ab7a63540eefb9d5156c1d008c
4
+ data.tar.gz: 64ea4091c85c9541ec1f08dd5560608e560ec80e8ee6918f95098b976b0ec82e
5
5
  SHA512:
6
- metadata.gz: 8bdcb84ca5d9becc44e9a181512ac19c9c8c24f5035e7da9da09a1ab59a4c09cd96b9cde80a8b5d073001ae6f36d9f4e1b3e1a3e640c4eafa6d30ac34800e47c
7
- data.tar.gz: b09d59343870e8d16ef9e4c0794e7ec78486d5ab9c3eea339d99c4f8b4fa46f58ca5246ca3df70ed8a82c795fd4108c296c3bb19e720640c5acce080f0e90a98
6
+ metadata.gz: 4c776696c10dc442394e5b023db7b47d178ec4b328addd693ba72b60e726c19f923533f0f1645e7b62ec322e63d6fcd0b39b1ca917cd9aa66403295c0b67e266
7
+ data.tar.gz: 615ec0ee4400e6e11baa6a6572fcafdccdeb6764f9bb2e65afcf4ff72a8185e9ba45086cd5e8e039934ea1043fe165d94784983539ac0d3e361a6b28f72a986e
data/README.md CHANGED
@@ -672,6 +672,11 @@ The per-record contract (Sentry `beforeSend` semantics):
672
672
  in place, they are shared structures. Foam re-normalizes the record's
673
673
  `total_recorded_*` bookkeeping after your hooks run, so adding/deleting
674
674
  attributes never corrupts the wire's dropped-count accounting.
675
+ `record.resource` and `record.instrumentation_scope` are **identity, not
676
+ payload**: read them freely, but edits and replacements are discarded —
677
+ the original identity objects always ship (they are process-global and
678
+ the encoder groups by them; a writable resource would also bypass
679
+ redaction, which never masks resource attributes).
675
680
  * **return `nil`** → the record is dropped, silently (that is the filter
676
681
  mechanism, not an error).
677
682
  * **raise, or return a foreign object** → that record is dropped
@@ -62,6 +62,7 @@ module Foam
62
62
  # flood an adversary-shaped record stream controls — rule 15's
63
63
  # "loud but never a flood" posture).
64
64
  def run(hooks, record, signal, faults)
65
+ identity = identity_of(record)
65
66
  current, counters = thaw(record)
66
67
  hooks.each do |hook|
67
68
  result = hook.call(current)
@@ -74,6 +75,7 @@ module Foam
74
75
  current = result
75
76
  end
76
77
  restore_counters!(current, counters)
78
+ restore_identity!(current, identity)
77
79
  current
78
80
  rescue StandardError, SystemStackError => e
79
81
  faults << e.class.name
@@ -110,9 +112,43 @@ module Foam
110
112
  copy.attributes = attributes.nil? ? {} : attributes.transform_values { |v| thaw_value(v) }
111
113
  end
112
114
  copy.body = thaw_body(copy.body) if copy.respond_to?(:body) && copy.respond_to?(:body=)
115
+ # The scope handed to the hook is a COPY: InstrumentationScope is a
116
+ # mutable Struct, and an in-place `scope.name =` on the shared
117
+ # object would corrupt process-global identity (see identity_of).
118
+ if copy.respond_to?(:instrumentation_scope) && copy.respond_to?(:instrumentation_scope=)
119
+ copy.instrumentation_scope = copy.instrumentation_scope&.dup
120
+ end
113
121
  [copy, sdk_drop_counters(record)]
114
122
  end
115
123
 
124
+ # resource / instrumentation_scope are process-global IDENTITY objects
125
+ # shared by every record the tracer/logger emits — and Ruby's
126
+ # InstrumentationScope is a plain MUTABLE Struct. A hook that renames
127
+ # the scope would corrupt the identity of EVERY subsequent span/log
128
+ # from that instrument (proven live in the 2026-07-29 retro-probe),
129
+ # and a wholesale `record.resource =` replacement would ship
130
+ # hook-authored resource attributes RAW — redaction never masks
131
+ # resource, so that path could widen what ships. Both are closed the
132
+ # way the Go port does it: identity always comes from the ORIGINAL
133
+ # record — captured here, force-restored onto the survivor after the
134
+ # pipeline (hook edits to identity are discarded; the encoder's
135
+ # group-by-identity stays intact). Documented in the README:
136
+ # resource/instrumentation_scope are informational, not hook-writable.
137
+ def identity_of(record)
138
+ {
139
+ resource: (record.resource if record.respond_to?(:resource)),
140
+ scope: (record.instrumentation_scope if record.respond_to?(:instrumentation_scope)),
141
+ }
142
+ end
143
+
144
+ def restore_identity!(record, identity)
145
+ record.resource = identity[:resource] if record.respond_to?(:resource=)
146
+ if record.respond_to?(:instrumentation_scope=)
147
+ record.instrumentation_scope = identity[:scope]
148
+ end
149
+ record
150
+ end
151
+
116
152
  def thaw_value(value)
117
153
  case value
118
154
  when String then value.dup
@@ -175,6 +175,17 @@ module Foam
175
175
  # case) install NOTHING. Proven against the real agents in
176
176
  # test-apps/ruby-coexistence (six vendors, both patch mechanisms,
177
177
  # patched-client probe REQUIRED green).
178
- VERSION = "1.9.0"
178
+ # 1.9.1: before_send IDENTITY RESTORE (retro-probe class 14; PATCH —
179
+ # bugfix-only). resource / instrumentation_scope are process-global
180
+ # identity objects, and InstrumentationScope is a MUTABLE Struct: a
181
+ # hook renaming it corrupted the identity of every subsequent
182
+ # span/log from that instrument (proven live), and a wholesale
183
+ # `record.resource =` replacement shipped hook-authored resource
184
+ # attributes RAW (redaction never masks resource — the one
185
+ # can-never-widen gap). Hooks now receive a COPIED scope, and the
186
+ # ORIGINAL resource/scope are force-restored onto every survivor
187
+ # after the pipeline (identity is not hook-writable — the Go port's
188
+ # contract; README updated).
189
+ VERSION = "1.9.1"
179
190
  end
180
191
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foam-otel
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.0
4
+ version: 1.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Foam