# frozen_string_literal: true # Copyright The OpenTelemetry Authors # # SPDX-License-Identifier: Apache-2.0 module OpenTelemetry module SDK module Trace module Samplers # @api private # # Implements consistent sampling based on a probability. class ConsistentProbabilityBased include ConsistentProbabilityTraceState attr_reader :description def initialize(probability) if probability < 2e-62 @p_floor = 63 @p_ceil = @p_ceil_probability = 0 @description = 'ConsistentProbabilityBased{0}' return end @p_floor = (Math.frexp(probability)[1] - 1).abs @p_ceil = @p_floor - 1 floor = Math.ldexp(1.0, -@p_floor) ceil = Math.ldexp(1.0, -@p_ceil) @p_ceil_probability = (probability - floor) / (ceil - floor) @description = format('ConsistentProbabilityBased{%.6f}', probability) end def ==(other) @description == other.description end # @api private # # See {Samplers}. def should_sample?(trace_id:, parent_context:, links:, name:, kind:, attributes:) parent_span_context = OpenTelemetry::Trace.current_span(parent_context).context p = probabilistic_p tracestate = parent_span_context.tracestate parse_ot_vendor_tag(tracestate) do |_, r, rest| if r.nil? || r > 62 OpenTelemetry.logger.debug("ConsistentProbabilitySampler: potentially inconsistent trace detected - r: #{r.inspect}") if parent_span_context.valid? r = generate_r(trace_id) end if p <= r Result.new(decision: Decision::RECORD_AND_SAMPLE, tracestate: update_tracestate(tracestate, p, r, rest)) else Result.new(decision: Decision::DROP, tracestate: update_tracestate(tracestate, nil, r, rest)) end end end private def probabilistic_p if Random.rand < @p_ceil_probability @p_ceil else @p_floor end end end end end end end