class Sentry::Transaction
def self.extract_sentry_trace(sentry_trace)
-
(Array, nil)
-
Parameters:
-
sentry_trace
(String
) -- the sentry-trace header value from the previous transaction.
def self.extract_sentry_trace(sentry_trace) match = SENTRY_TRACE_REGEXP.match(sentry_trace) return nil if match.nil? trace_id, parent_span_id, sampled_flag = match[1..3] parent_sampled = sampled_flag.nil? ? nil : sampled_flag != "0" [trace_id, parent_span_id, parent_sampled] end
def self.from_sentry_trace(sentry_trace, baggage: nil, hub: Sentry.get_current_hub, **options)
-
(Transaction, nil)
-
Parameters:
-
options
(Hash
) -- the options you want to use to initialize a Transaction instance. -
hub
(Hub
) -- the hub that'll be responsible for sending this transaction when it's finished. -
baggage
(String, nil
) -- the incoming baggage header string. -
sentry_trace
(String
) -- the trace string from the previous transaction.
def self.from_sentry_trace(sentry_trace, baggage: nil, hub: Sentry.get_current_hub, **options) return unless hub.configuration.tracing_enabled? return unless sentry_trace sentry_trace_data = extract_sentry_trace(sentry_trace) return unless sentry_trace_data trace_id, parent_span_id, parent_sampled = sentry_trace_data baggage = if baggage && !baggage.empty? Baggage.from_incoming_header(baggage) else # If there's an incoming sentry-trace but no incoming baggage header, # for instance in traces coming from older SDKs, # baggage will be empty and frozen and won't be populated as head SDK. Baggage.new({}) end baggage.freeze! new( trace_id: trace_id, parent_span_id: parent_span_id, parent_sampled: parent_sampled, hub: hub, baggage: baggage, **options ) end
def deep_dup
-
(Transaction)
-
def deep_dup copy = super copy.init_span_recorder(@span_recorder.max_length) @span_recorder.spans.each do |span| # span_recorder's first span is the current span, which should not be added to the copy's spans next if span == self copy.span_recorder.add(span.dup) end copy end
def finish(hub: nil, end_timestamp: nil)
-
(TransactionEvent)
-
Parameters:
-
hub
(Hub
) -- the hub that'll send this transaction. (Deprecated)
def finish(hub: nil, end_timestamp: nil) if hub log_warn( <<~MSG Specifying a different hub in `Transaction#finish` will be deprecated in version 5.0. Please use `Hub#start_transaction` with the designated hub. MSG ) end hub ||= @hub super(end_timestamp: end_timestamp) if @name.nil? @name = UNLABELD_NAME end @profiler.stop if @sampled event = hub.current_client.event_from_transaction(self) hub.capture_event(event) else hub.current_client.transport.record_lost_event(:sample_rate, 'transaction') end end
def generate_transaction_description
def generate_transaction_description result = op.nil? ? "" : "<#{@op}> " result += "transaction" result += " <#{@name}>" if @name result end
def get_baggage
-
(Baggage)
-
def get_baggage populate_head_baggage if @baggage.nil? || @baggage.mutable @baggage end
def init_span_recorder(limit = 1000)
def init_span_recorder(limit = 1000) @span_recorder = SpanRecorder.new(limit) @span_recorder.add(self) end
def initialize(
def initialize( hub:, name: nil, source: :custom, parent_sampled: nil, baggage: nil, **options ) super(transaction: self, **options) set_name(name, source: source) @parent_sampled = parent_sampled @hub = hub @baggage = baggage @configuration = hub.configuration # to be removed @tracing_enabled = hub.configuration.tracing_enabled? @traces_sampler = hub.configuration.traces_sampler @traces_sample_rate = hub.configuration.traces_sample_rate @logger = hub.configuration.logger @release = hub.configuration.release @environment = hub.configuration.environment @dsn = hub.configuration.dsn @effective_sample_rate = nil @contexts = {} @measurements = {} @profiler = Profiler.new(@configuration) init_span_recorder end
def populate_head_baggage
def populate_head_baggage items = { "trace_id" => trace_id, "sample_rate" => effective_sample_rate&.to_s, "environment" => @environment, "release" => @release, "public_key" => @dsn&.public_key } items["transaction"] = name unless source_low_quality? user = @hub.current_scope&.user items["user_segment"] = user["segment"] if user && user["segment"] items.compact! @baggage = Baggage.new(items, mutable: false) end
def set_context(key, value)
-
(void)
-
Parameters:
-
value
(Object
) -- -
key
(String, Symbol
) --
def set_context(key, value) @contexts[key] = value end
def set_initial_sample_decision(sampling_context:)
-
(void)
-
Parameters:
-
sampling_context
(Hash
) -- a context Hash that'll be passed to `traces_sampler` (if provided).
def set_initial_sample_decision(sampling_context:) unless @tracing_enabled @sampled = false return end unless @sampled.nil? @effective_sample_rate = @sampled ? 1.0 : 0.0 return end sample_rate = if @traces_sampler.is_a?(Proc) @traces_sampler.call(sampling_context) elsif !sampling_context[:parent_sampled].nil? sampling_context[:parent_sampled] else @traces_sample_rate end transaction_description = generate_transaction_description if [true, false].include?(sample_rate) @effective_sample_rate = sample_rate ? 1.0 : 0.0 elsif sample_rate.is_a?(Numeric) && sample_rate >= 0.0 && sample_rate <= 1.0 @effective_sample_rate = sample_rate.to_f else @sampled = false log_warn("#{MESSAGE_PREFIX} Discarding #{transaction_description} because of invalid sample_rate: #{sample_rate}") return end if sample_rate == 0.0 || sample_rate == false @sampled = false log_debug("#{MESSAGE_PREFIX} Discarding #{transaction_description} because traces_sampler returned 0 or false") return end if sample_rate == true @sampled = true else @sampled = Random.rand < sample_rate end if @sampled log_debug("#{MESSAGE_PREFIX} Starting #{transaction_description}") else log_debug( "#{MESSAGE_PREFIX} Discarding #{transaction_description} because it's not included in the random sample (sampling rate = #{sample_rate})" ) end end
def set_measurement(name, value, unit = "")
-
(void)
-
Parameters:
-
unit
(String
) -- unit of the measurement -
value
(Float
) -- value of the measurement -
name
(String
) -- name of the measurement
def set_measurement(name, value, unit = "") @measurements[name] = { value: value, unit: unit } end
def set_name(name, source: :custom)
-
(void)
-
Parameters:
-
source
(Symbol
) -- -
name
(String
) --
def set_name(name, source: :custom) @name = name @source = SOURCES.include?(source) ? source.to_sym : :custom end
def source_low_quality?
def source_low_quality? source == :url end
def start_profiler!
-
(void)
-
def start_profiler! profiler.set_initial_sample_decision(sampled) profiler.start end
def to_hash
-
(Hash)
-
def to_hash hash = super hash.merge!( name: @name, source: @source, sampled: @sampled, parent_sampled: @parent_sampled ) hash end