|
| 1 | +# frozen_string_literal: true |
| 2 | + |
| 3 | +# Copyright OpenTelemetry Authors |
| 4 | +# |
| 5 | +# SPDX-License-Identifier: Apache-2.0 |
| 6 | + |
| 7 | +require 'test_helper' |
| 8 | + |
| 9 | +describe OpenTelemetry::Propagator::XRay::LambdaTextMapPropagator do |
| 10 | + Span = OpenTelemetry::Trace::Span |
| 11 | + SpanContext = OpenTelemetry::Trace::SpanContext |
| 12 | + TraceFlags = OpenTelemetry::Trace::TraceFlags |
| 13 | + |
| 14 | + let(:propagator) { OpenTelemetry::Propagator::XRay::LambdaTextMapPropagator.new } |
| 15 | + |
| 16 | + describe('#extract') do |
| 17 | + it 'returns the original context when no headers or env vars exist' do |
| 18 | + parent_context = OpenTelemetry::Context.empty |
| 19 | + carrier = {} |
| 20 | + |
| 21 | + # Ensure environment variable is not set |
| 22 | + original_env = ENV.fetch(OpenTelemetry::Propagator::XRay::LambdaTextMapPropagator::AWS_TRACE_HEADER_ENV_KEY, nil) |
| 23 | + ENV.delete(OpenTelemetry::Propagator::XRay::LambdaTextMapPropagator::AWS_TRACE_HEADER_ENV_KEY) |
| 24 | + |
| 25 | + context = propagator.extract(carrier, context: parent_context) |
| 26 | + extracted_context = OpenTelemetry::Trace.current_span(context).context |
| 27 | + |
| 28 | + _(extracted_context.valid?).must_equal(false) |
| 29 | + _(context).must_equal(parent_context) |
| 30 | + |
| 31 | + # Restore original env value if it existed |
| 32 | + ENV[OpenTelemetry::Propagator::XRay::LambdaTextMapPropagator::AWS_TRACE_HEADER_ENV_KEY] = original_env if original_env |
| 33 | + end |
| 34 | + |
| 35 | + it 'returns existing context when valid and no env var exists' do |
| 36 | + # Create a valid context |
| 37 | + valid_context = create_context( |
| 38 | + trace_id: '80f198eae56343ba864fe8b2a57d3eff', |
| 39 | + span_id: 'e457b5a2e4d86bd1', |
| 40 | + trace_flags: TraceFlags::SAMPLED |
| 41 | + ) |
| 42 | + |
| 43 | + carrier = {} |
| 44 | + |
| 45 | + # Ensure environment variable is not set |
| 46 | + original_env = ENV.fetch(OpenTelemetry::Propagator::XRay::LambdaTextMapPropagator::AWS_TRACE_HEADER_ENV_KEY, nil) |
| 47 | + ENV.delete(OpenTelemetry::Propagator::XRay::LambdaTextMapPropagator::AWS_TRACE_HEADER_ENV_KEY) |
| 48 | + |
| 49 | + context = propagator.extract(carrier, context: valid_context) |
| 50 | + extracted_context = OpenTelemetry::Trace.current_span(context).context |
| 51 | + |
| 52 | + _(extracted_context.hex_trace_id).must_equal('80f198eae56343ba864fe8b2a57d3eff') |
| 53 | + _(extracted_context.hex_span_id).must_equal('e457b5a2e4d86bd1') |
| 54 | + _(extracted_context.trace_flags).must_equal(TraceFlags::SAMPLED) |
| 55 | + _(context).must_equal(valid_context) |
| 56 | + |
| 57 | + # Restore original env value if it existed |
| 58 | + ENV[OpenTelemetry::Propagator::XRay::LambdaTextMapPropagator::AWS_TRACE_HEADER_ENV_KEY] = original_env if original_env |
| 59 | + end |
| 60 | + |
| 61 | + it 'extracts context from environment variable when no headers exist' do |
| 62 | + parent_context = OpenTelemetry::Context.empty |
| 63 | + carrier = {} |
| 64 | + |
| 65 | + # Set environment variable with trace information |
| 66 | + original_env = ENV.fetch(OpenTelemetry::Propagator::XRay::LambdaTextMapPropagator::AWS_TRACE_HEADER_ENV_KEY, nil) |
| 67 | + ENV[OpenTelemetry::Propagator::XRay::LambdaTextMapPropagator::AWS_TRACE_HEADER_ENV_KEY] = 'Root=1-80f198ea-e56343ba864fe8b2a57d3eff;Parent=e457b5a2e4d86bd1;Sampled=1' |
| 68 | + |
| 69 | + context = propagator.extract(carrier, context: parent_context) |
| 70 | + extracted_context = OpenTelemetry::Trace.current_span(context).context |
| 71 | + |
| 72 | + _(extracted_context.hex_trace_id).must_equal('80f198eae56343ba864fe8b2a57d3eff') |
| 73 | + _(extracted_context.hex_span_id).must_equal('e457b5a2e4d86bd1') |
| 74 | + _(extracted_context.trace_flags).must_equal(TraceFlags::SAMPLED) |
| 75 | + _(extracted_context).must_be(:remote?) |
| 76 | + |
| 77 | + # Restore original env value if it existed |
| 78 | + ENV[OpenTelemetry::Propagator::XRay::LambdaTextMapPropagator::AWS_TRACE_HEADER_ENV_KEY] = original_env if original_env |
| 79 | + end |
| 80 | + |
| 81 | + it 'prioritizes header over environment variable' do |
| 82 | + parent_context = OpenTelemetry::Context.empty |
| 83 | + carrier = { 'X-Amzn-Trace-Id' => 'Root=1-90f198ea-f56343ba964fe8b2a67d3eff;Parent=f457b5a2e4d86bd2;Sampled=1' } |
| 84 | + |
| 85 | + # Set environment variable with different trace information |
| 86 | + original_env = ENV.fetch(OpenTelemetry::Propagator::XRay::LambdaTextMapPropagator::AWS_TRACE_HEADER_ENV_KEY, nil) |
| 87 | + ENV[OpenTelemetry::Propagator::XRay::LambdaTextMapPropagator::AWS_TRACE_HEADER_ENV_KEY] = 'Root=1-80f198ea-e56343ba864fe8b2a57d3eff;Parent=e457b5a2e4d86bd1;Sampled=1' |
| 88 | + |
| 89 | + context = propagator.extract(carrier, context: parent_context) |
| 90 | + extracted_context = OpenTelemetry::Trace.current_span(context).context |
| 91 | + |
| 92 | + # Should use the header, not the environment variable |
| 93 | + _(extracted_context.hex_trace_id).must_equal('90f198eaf56343ba964fe8b2a67d3eff') |
| 94 | + _(extracted_context.hex_span_id).must_equal('f457b5a2e4d86bd2') |
| 95 | + _(extracted_context.trace_flags).must_equal(TraceFlags::SAMPLED) |
| 96 | + _(extracted_context).must_be(:remote?) |
| 97 | + |
| 98 | + # Restore original env value if it existed |
| 99 | + ENV[OpenTelemetry::Propagator::XRay::LambdaTextMapPropagator::AWS_TRACE_HEADER_ENV_KEY] = original_env if original_env |
| 100 | + end |
| 101 | + |
| 102 | + it 'handles malformed environment variable gracefully' do |
| 103 | + parent_context = OpenTelemetry::Context.empty |
| 104 | + carrier = {} |
| 105 | + |
| 106 | + # Set environment variable with malformed trace information |
| 107 | + original_env = ENV.fetch(OpenTelemetry::Propagator::XRay::LambdaTextMapPropagator::AWS_TRACE_HEADER_ENV_KEY, nil) |
| 108 | + ENV[OpenTelemetry::Propagator::XRay::LambdaTextMapPropagator::AWS_TRACE_HEADER_ENV_KEY] = 'NotAValidTraceHeader' |
| 109 | + |
| 110 | + context = propagator.extract(carrier, context: parent_context) |
| 111 | + |
| 112 | + # Should return the original context since the env var is invalid |
| 113 | + _(context).must_equal(parent_context) |
| 114 | + |
| 115 | + # Restore original env value if it existed |
| 116 | + ENV[OpenTelemetry::Propagator::XRay::LambdaTextMapPropagator::AWS_TRACE_HEADER_ENV_KEY] = original_env if original_env |
| 117 | + end |
| 118 | + |
| 119 | + it 'uses existing context when valid, even if headers exist' do |
| 120 | + # Create a valid context |
| 121 | + valid_context = create_context( |
| 122 | + trace_id: '80f198eae56343ba864fe8b2a57d3eff', |
| 123 | + span_id: 'e457b5a2e4d86bd1', |
| 124 | + trace_flags: TraceFlags::SAMPLED |
| 125 | + ) |
| 126 | + |
| 127 | + # Create a carrier with header |
| 128 | + carrier = { 'X-Amzn-Trace-Id' => 'Root=1-90f198ea-f56343ba964fe8b2a67d3eff;Parent=f457b5a2e4d86bd2;Sampled=1' } |
| 129 | + |
| 130 | + context = propagator.extract(carrier, context: valid_context) |
| 131 | + extracted_context = OpenTelemetry::Trace.current_span(context).context |
| 132 | + |
| 133 | + # Should use the existing context, not the header |
| 134 | + _(extracted_context.hex_trace_id).must_equal('80f198eae56343ba864fe8b2a57d3eff') |
| 135 | + _(extracted_context.hex_span_id).must_equal('e457b5a2e4d86bd1') |
| 136 | + _(extracted_context.trace_flags).must_equal(TraceFlags::SAMPLED) |
| 137 | + _(context).must_equal(valid_context) |
| 138 | + end |
| 139 | + end |
| 140 | + |
| 141 | + # Helper method to create a context with specified values |
| 142 | + def create_context(trace_id:, span_id:, trace_flags: TraceFlags::DEFAULT, xray_debug: false) |
| 143 | + span_context = SpanContext.new( |
| 144 | + trace_id: Array(trace_id).pack('H*'), |
| 145 | + span_id: Array(span_id).pack('H*'), |
| 146 | + trace_flags: trace_flags, |
| 147 | + remote: false |
| 148 | + ) |
| 149 | + |
| 150 | + span = Span.new( |
| 151 | + span_context: span_context |
| 152 | + ) |
| 153 | + |
| 154 | + context = OpenTelemetry::Trace.context_with_span(span) |
| 155 | + return context unless xray_debug |
| 156 | + |
| 157 | + OpenTelemetry::Propagator::XRay.send(:context_with_debug, context) |
| 158 | + end |
| 159 | +end |
0 commit comments