From c8725cc1674966808567ae22744f0c4943c251ac Mon Sep 17 00:00:00 2001 From: Francis Bogsanyi Date: Tue, 3 Sep 2019 11:02:12 -0400 Subject: [PATCH] Add TraceFlags class --- api/lib/opentelemetry/trace.rb | 3 +- api/lib/opentelemetry/trace/span_context.rb | 27 +++++++--- api/lib/opentelemetry/trace/trace_flags.rb | 50 +++++++++++++++++++ .../opentelemetry/trace/trace_flags_test.rb | 33 ++++++++++++ 4 files changed, 106 insertions(+), 7 deletions(-) create mode 100644 api/lib/opentelemetry/trace/trace_flags.rb create mode 100644 api/test/opentelemetry/trace/trace_flags_test.rb diff --git a/api/lib/opentelemetry/trace.rb b/api/lib/opentelemetry/trace.rb index 92c9132d31..221585e9a1 100644 --- a/api/lib/opentelemetry/trace.rb +++ b/api/lib/opentelemetry/trace.rb @@ -4,9 +4,10 @@ # # SPDX-License-Identifier: Apache-2.0 +require 'opentelemetry/trace/samplers' require 'opentelemetry/trace/span_context' require 'opentelemetry/trace/span_kind' require 'opentelemetry/trace/span' require 'opentelemetry/trace/status' +require 'opentelemetry/trace/trace_flags' require 'opentelemetry/trace/tracer' -require 'opentelemetry/trace/samplers' diff --git a/api/lib/opentelemetry/trace/span_context.rb b/api/lib/opentelemetry/trace/span_context.rb index b2babaab93..ed5cca5e3e 100644 --- a/api/lib/opentelemetry/trace/span_context.rb +++ b/api/lib/opentelemetry/trace/span_context.rb @@ -6,25 +6,40 @@ module OpenTelemetry module Trace - # A SpanContext contains the state that must propagate to child @see Spans and across process boundaries. - # It contains the identifiers (a @see TraceId and @see SpanId) associated with the @see Span and a set of - # @see TraceOptions. + # A SpanContext contains the state that must propagate to child {Span}s and across process boundaries. + # It contains the identifiers (a trace ID and span ID) associated with the {Span} and a set of + # {TraceFlags}. class SpanContext - attr_reader :trace_id, :span_id, :trace_options + attr_reader :trace_id, :span_id, :trace_flags def initialize( trace_id: generate_trace_id, span_id: generate_span_id, - trace_options: TraceOptions::DEFAULT + trace_flags: TraceFlags::DEFAULT ) @trace_id = trace_id @span_id = span_id - @trace_options = trace_options + @trace_flags = trace_flags end def valid? !(@trace_id.zero? || @span_id.zero?) end + + private + + SPAN_ID_RANGE = (1..(2**64 - 1)).freeze + TRACE_ID_RANGE = (1..(2**128 - 1)).freeze + + private_constant(:SPAN_ID_RANGE, :TRACE_ID_RANGE) + + def generate_trace_id + rand(TRACE_ID_RANGE) + end + + def generate_span_id + rand(SPAN_ID_RANGE) + end end end end diff --git a/api/lib/opentelemetry/trace/trace_flags.rb b/api/lib/opentelemetry/trace/trace_flags.rb new file mode 100644 index 0000000000..5acd690a17 --- /dev/null +++ b/api/lib/opentelemetry/trace/trace_flags.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +# Copyright 2019 OpenTelemetry Authors +# +# SPDX-License-Identifier: Apache-2.0 + +module OpenTelemetry + module Trace + # TraceFlags contain details about the trace. Unlike Tracestate values, + # TraceFlags are present in all traces. Currently, the only TraceFlag is a + # boolean {sampled?} {https://www.w3.org/TR/trace-context/#trace-flags flag}. + class TraceFlags + class << self + private :new # rubocop:disable Style/AccessModifierDeclarations + + # Returns a newly created {TraceFlags} with the specified flags. + # + # @param [Integer] flags 8-bit byte of bit flags + # @raise [ArgumentError] If flags is not an 8-bit byte + # @return [TraceFlags] + def from_byte(flags) + raise ArgumentError, 'flags must be an 8-bit byte' unless (0..255).include?(flags) + + new(flags) + end + end + + # @api private + # The constructor is private and only for use internally by the class. + # Users should use the {fromByte} factory method to obtain a {TraceFlags} + # instance. + # + # @param [Integer] flags 8-bit byte of bit flags + # @return [TraceFlags] + def initialize(flags) + @flags = flags + end + + # Returns whether the caller may have recorded trace data. When false, + # the caller did not record trace data out-of-band. + # + # @return [Boolean] + def sampled? + @flags.anybits?(1) + end + + DEFAULT = from_byte(0) + end + end +end diff --git a/api/test/opentelemetry/trace/trace_flags_test.rb b/api/test/opentelemetry/trace/trace_flags_test.rb new file mode 100644 index 0000000000..469ad7fa93 --- /dev/null +++ b/api/test/opentelemetry/trace/trace_flags_test.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require 'test_helper' + +describe OpenTelemetry::Trace::TraceFlags do + describe '.new' do + it 'is private' do + -> { OpenTelemetry::Trace::TraceFlags.new(0) }\ + .must_raise(NoMethodError) + end + end + describe '.fromByte' do + it 'can be initialized with a byte' do + flags = OpenTelemetry::Trace::TraceFlags.from_byte(0) + flags.sampled?.must_equal(false) + end + + it 'enforces flags is an 8-bit byte' do + -> { OpenTelemetry::Trace::TraceFlags.from_byte(256) }\ + .must_raise(ArgumentError) + end + end + + describe '#sampled?' do + it 'reflects the least-significant bit in the flags' do + sampled = OpenTelemetry::Trace::TraceFlags.from_byte(1) + not_sampled = OpenTelemetry::Trace::TraceFlags.from_byte(0) + + sampled.sampled?.must_equal(true) + not_sampled.sampled?.must_equal(false) + end + end +end