diff --git a/opentelemetry-api/src/opentelemetry/trace/propagation/tracecontexthttptextformat.py b/opentelemetry-api/src/opentelemetry/trace/propagation/tracecontexthttptextformat.py index 28db4e45575..07d3ee05abc 100644 --- a/opentelemetry-api/src/opentelemetry/trace/propagation/tracecontexthttptextformat.py +++ b/opentelemetry-api/src/opentelemetry/trace/propagation/tracecontexthttptextformat.py @@ -33,7 +33,7 @@ _KEY_WITHOUT_VENDOR_FORMAT = r"[a-z][_0-9a-z\-\*\/]{0,255}" _KEY_WITH_VENDOR_FORMAT = ( - r"[a-z][_0-9a-z\-\*\/]{0,240}@[a-z][_0-9a-z\-\*\/]{0,13}" + r"[a-z0-9][_0-9a-z\-\*\/]{0,240}@[a-z][_0-9a-z\-\*\/]{0,13}" ) _KEY_FORMAT = _KEY_WITHOUT_VENDOR_FORMAT + "|" + _KEY_WITH_VENDOR_FORMAT diff --git a/opentelemetry-api/tests/trace/propagation/test_tracecontexthttptextformat.py b/opentelemetry-api/tests/trace/propagation/test_tracecontexthttptextformat.py index 6ee4a957d29..a13d9630aec 100644 --- a/opentelemetry-api/tests/trace/propagation/test_tracecontexthttptextformat.py +++ b/opentelemetry-api/tests/trace/propagation/test_tracecontexthttptextformat.py @@ -222,3 +222,32 @@ def test_tracestate_header_with_trailing_comma(self): ) ) self.assertEqual(span.get_context().trace_state["foo"], "1") + + def test_tracestate_keys(self): + """Test for valid key patterns in the tracestate + """ + tracestate_value = ",".join( + [ + "1a-2f@foo=bar1", + "1a-_*/2b@foo=bar2", + "foo=bar3", + "foo-_*/bar=bar4", + ] + ) + span = get_span_from_context( + FORMAT.extract( + get_as_list, + { + "traceparent": [ + "00-12345678901234567890123456789012-1234567890123456-00" + ], + "tracestate": [tracestate_value], + }, + ) + ) + self.assertEqual(span.get_context().trace_state["1a-2f@foo"], "bar1") + self.assertEqual( + span.get_context().trace_state["1a-_*/2b@foo"], "bar2" + ) + self.assertEqual(span.get_context().trace_state["foo"], "bar3") + self.assertEqual(span.get_context().trace_state["foo-_*/bar"], "bar4")