class OpenTelemetry::Instrumentation::ActionView::SpanSubscriber
The SpanSubscriber
is a special ActiveSupport::Notification subscription handler which turns notifications into generic spans, taking care to handle context appropriately.
Constants
- ALWAYS_VALID_PAYLOAD_TYPES
Public Class Methods
new(name:, tracer:)
click to toggle source
# File lib/opentelemetry/instrumentation/action_view/span_subscriber.rb, line 16 def initialize(name:, tracer:) @span_name = name.split('.')[0..1].reverse.join(' ').freeze @tracer = tracer end
Public Instance Methods
finish(_name, _id, payload)
click to toggle source
# File lib/opentelemetry/instrumentation/action_view/span_subscriber.rb, line 30 def finish(_name, _id, payload) # rubocop:disable Metrics/AbcSize span = payload.delete(:__opentelemetry_span) token = payload.delete(:__opentelemetry_ctx_token) return unless span && token payload = transform_payload(payload) attrs = payload.map do |k, v| [k.to_s, sanitized_value(v)] if valid_payload_key?(k) && valid_payload_value?(v) end span.add_attributes(attrs.compact.to_h) if (e = payload[:exception_object]) span.record_exception(e) span.status = OpenTelemetry::Trace::Status.error("Unhandled exception of type: #{e.class}") end span.finish OpenTelemetry::Context.detach(token) end
start(_name, _id, payload)
click to toggle source
# File lib/opentelemetry/instrumentation/action_view/span_subscriber.rb, line 21 def start(_name, _id, payload) span = @tracer.start_span(@span_name, kind: :internal) token = OpenTelemetry::Context.attach( OpenTelemetry::Trace.context_with_span(span) ) [span, token] end
Private Instance Methods
instrumentation_config()
click to toggle source
# File lib/opentelemetry/instrumentation/action_view/span_subscriber.rb, line 52 def instrumentation_config ActionView::Instrumentation.instance.config end
sanitized_value(value)
click to toggle source
We'll accept symbols as values, but stringify them; and we'll stringify symbols within an array.
# File lib/opentelemetry/instrumentation/action_view/span_subscriber.rb, line 77 def sanitized_value(value) if value.is_a?(Array) value.map { |v| v.is_a?(Symbol) ? v.to_s : v } elsif value.is_a?(Symbol) value.to_s else value end end
transform_payload(payload)
click to toggle source
# File lib/opentelemetry/instrumentation/action_view/span_subscriber.rb, line 56 def transform_payload(payload) return payload if instrumentation_config[:notification_payload_transform].nil? instrumentation_config[:notification_payload_transform].call(payload) end
valid_payload_key?(key)
click to toggle source
# File lib/opentelemetry/instrumentation/action_view/span_subscriber.rb, line 62 def valid_payload_key?(key) %i[exception exception_object].none?(key) && instrumentation_config[:disallowed_notification_payload_keys].none?(key) end
valid_payload_value?(value)
click to toggle source
# File lib/opentelemetry/instrumentation/action_view/span_subscriber.rb, line 66 def valid_payload_value?(value) if value.is_a?(Array) return true if value.empty? value.map(&:class).uniq.size == 1 && ALWAYS_VALID_PAYLOAD_TYPES.any? { |t| value.first.is_a?(t) } else ALWAYS_VALID_PAYLOAD_TYPES.any? { |t| value.is_a?(t) } end end