11# frozen_string_literal: true
22
3+ require "set"
34require "sentry/breadcrumb_buffer"
45require "sentry/propagation_context"
56require "sentry/attachment"
@@ -24,7 +25,8 @@ class Scope
2425 :span ,
2526 :session ,
2627 :attachments ,
27- :propagation_context
28+ :propagation_context ,
29+ :attributes
2830 ]
2931
3032 attr_reader ( *ATTRIBUTES )
@@ -84,7 +86,15 @@ def apply_to_event(event, hint = nil)
8486 # @param telemetry [MetricEvent, LogEvent] the telemetry event to apply scope context to
8587 # @return [MetricEvent, LogEvent] the telemetry event with scope context applied
8688 def apply_to_telemetry ( telemetry )
87- # TODO-neel when new scope set_attribute api is added: add them here
89+ # Compare as strings since String and Symbol keys serialize to the same wire key.
90+ existing_keys = telemetry . attributes . keys . map ( &:to_s ) . to_set
91+
92+ attributes . each do |key , value |
93+ next if existing_keys . include? ( key )
94+
95+ telemetry . attributes [ key ] = value
96+ end
97+
8898 trace_context = get_trace_context
8999 telemetry . trace_id = trace_context [ :trace_id ]
90100 telemetry . span_id = trace_context [ :span_id ]
@@ -136,6 +146,7 @@ def dup
136146 copy . propagation_context = propagation_context . deep_dup
137147 copy . attachments = attachments . dup
138148 copy . event_processors = event_processors . dup
149+ copy . attributes = attributes . deep_dup
139150 copy
140151 end
141152
@@ -154,6 +165,7 @@ def update_from_scope(scope)
154165 self . span = scope . span
155166 self . propagation_context = scope . propagation_context
156167 self . attachments = scope . attachments
168+ self . attributes = scope . attributes
157169 end
158170
159171 # Updates the scope's data from the given options.
@@ -256,6 +268,32 @@ def set_context(key, value)
256268 set_contexts ( key => value )
257269 end
258270
271+ # Updates the scope's attributes by merging with the old value.
272+ # @param attributes_hash [Hash]
273+ # @return [Hash]
274+ def set_attributes ( attributes_hash )
275+ check_argument_type! ( attributes_hash , Hash )
276+ attributes_hash . each { |key , value | @attributes [ key . to_s ] = value }
277+ @attributes
278+ end
279+
280+ # Sets a single attribute on the scope.
281+ # @param key [String, Symbol]
282+ # @param value [Object]
283+ # @param unit [String, Symbol, nil] an optional measurement unit for the value
284+ # @return [Hash]
285+ def set_attribute ( key , value , unit : nil )
286+ value = { value : value , unit : unit } unless unit . nil?
287+ set_attributes ( key => value )
288+ end
289+
290+ # Removes a single attribute from the scope. No-op if the attribute is not set.
291+ # @param key [String, Symbol]
292+ # @return [void]
293+ def remove_attribute ( key )
294+ @attributes . delete ( key . to_s )
295+ end
296+
259297 # Sets the scope's level attribute.
260298 # @param level [String, Symbol]
261299 # @return [void]
@@ -361,6 +399,7 @@ def set_default_value
361399 @span = nil
362400 @session = nil
363401 @attachments = [ ]
402+ @attributes = { }
364403 generate_propagation_context
365404 set_new_breadcrumb_buffer
366405 end
0 commit comments