def test_propagation(self): traceparent_value = "00-{trace_id}-{span_id}-00".format( trace_id=format(self.TRACE_ID, "032x"), span_id=format(self.SPAN_ID, "016x"), ) tracestate_value = "foo=1,bar=2,baz=3" headers = { "baggage": ["key1=val1,key2=val2"], "traceparent": [traceparent_value], "tracestate": [tracestate_value], } ctx = extract(carrier_getter, headers) baggage_entries = baggage.get_all(context=ctx) expected = {"key1": "val1", "key2": "val2"} self.assertEqual(baggage_entries, expected) span_context = get_current_span(context=ctx).get_span_context() self.assertEqual(span_context.trace_id, self.TRACE_ID) self.assertEqual(span_context.span_id, self.SPAN_ID) span = trace.NonRecordingSpan(span_context) ctx = baggage.set_baggage("key3", "val3") ctx = baggage.set_baggage("key4", "val4", context=ctx) ctx = set_span_in_context(span, context=ctx) output = {} inject(dict.__setitem__, output, context=ctx) self.assertEqual(traceparent_value, output["traceparent"]) self.assertIn("key3=val3", output["baggage"]) self.assertIn("key4=val4", output["baggage"]) self.assertIn("foo=1", output["tracestate"]) self.assertIn("bar=2", output["tracestate"]) self.assertIn("baz=3", output["tracestate"])
def test_remove_baggage_entry(self): self.assertEqual({}, baggage.get_all()) ctx = baggage.set_baggage("test", "value") ctx = baggage.set_baggage("test2", "value2", context=ctx) ctx = baggage.remove_baggage("test", context=ctx) self.assertEqual(baggage.get_baggage("test", context=ctx), None) self.assertEqual(baggage.get_baggage("test2", context=ctx), "value2")
def test_set_baggage(self): self.assertEqual({}, baggage.get_all()) ctx = baggage.set_baggage("test", "value") self.assertEqual(baggage.get_baggage("test", context=ctx), "value") ctx = baggage.set_baggage("test", "value2", context=ctx) self.assertEqual(baggage.get_baggage("test", context=ctx), "value2")
def test_set_multiple_baggage_entries(self): ctx = baggage.set_baggage("test", "value") ctx = baggage.set_baggage("test2", "value2", context=ctx) self.assertEqual(baggage.get_baggage("test", context=ctx), "value") self.assertEqual(baggage.get_baggage("test2", context=ctx), "value2") self.assertEqual( baggage.get_all(context=ctx), {"test": "value", "test2": "value2"}, )
def test_inject_set_baggage(self): """Test that baggage is set""" carrier = {} self.ot_trace_propagator.inject( carrier, set_baggage( "key", "value", context=set_span_in_context( _Span( "child", SpanContext( trace_id=int("80f198ee56343ba864fe8b2a57d3eff7", 16), span_id=int("e457b5a2e4d86bd1", 16), is_remote=True, trace_flags=TraceFlags.SAMPLED, ), )), ), ) self.assertEqual(carrier["".join([OT_BAGGAGE_PREFIX, "key"])], "value")
def get_context_new_carrier(old_carrier, carrier_baggage=None): ctx = FORMAT.extract(carrier_getter, old_carrier) if carrier_baggage: for key, value in carrier_baggage.items(): ctx = baggage.set_baggage(key, value, ctx) parent_span_context = trace_api.get_current_span(ctx).get_span_context() parent = trace._Span("parent", parent_span_context) child = trace._Span( "child", trace_api.SpanContext( parent_span_context.trace_id, id_generator.RandomIdGenerator().generate_span_id(), is_remote=False, trace_flags=parent_span_context.trace_flags, trace_state=parent_span_context.trace_state, ), parent=parent.get_span_context(), ) new_carrier = {} ctx = trace_api.set_span_in_context(child, ctx) FORMAT.inject(dict.__setitem__, new_carrier, context=ctx) return ctx, new_carrier
def test_modifying_baggage(self): ctx = baggage.set_baggage("test", "value") self.assertEqual(baggage.get_baggage("test", context=ctx), "value") baggage_entries = baggage.get_all(context=ctx) with self.assertRaises(TypeError): baggage_entries["test"] = "mess-this-up" self.assertEqual(baggage.get_baggage("test", context=ctx), "value")
def test_inject_invalid_baggage_values(self): """Test that invalid baggage values are not set""" carrier = {} self.ot_trace_propagator.inject( carrier, set_baggage( "key", "α", context=set_span_in_context( _Span( "child", SpanContext( trace_id=int("80f198ee56343ba864fe8b2a57d3eff7", 16), span_id=int("e457b5a2e4d86bd1", 16), is_remote=True, trace_flags=TraceFlags.SAMPLED, ), )), ), ) self.assertNotIn("".join([OT_BAGGAGE_PREFIX, "key"]), carrier.keys())
def _inject(self, values): """Test helper""" ctx = get_current() for k, v in values.items(): ctx = baggage.set_baggage(k, v, context=ctx) output = {} self.propagator.inject(dict.__setitem__, output, context=ctx) return output.get("otcorrelations")
def _inject(self, values): """Test helper""" ctx = get_current() for k, v in values.items(): ctx = baggage.set_baggage(k, v, context=ctx) output = {} self.propagator.inject(output, context=ctx) return output.get("baggage")
def extract( self, carrier: CarrierT, context: Optional[Context] = None, getter: Getter = default_getter, ) -> Context: if context is None: context = Context() traceid = _extract_identifier( getter.get(carrier, OT_TRACE_ID_HEADER), _valid_extract_traceid, INVALID_TRACE_ID, ) spanid = _extract_identifier( getter.get(carrier, OT_SPAN_ID_HEADER), _valid_extract_spanid, INVALID_SPAN_ID, ) sampled = _extract_first_element( getter.get(carrier, OT_SAMPLED_HEADER) ) if sampled == "true": traceflags = TraceFlags.SAMPLED else: traceflags = TraceFlags.DEFAULT if traceid != INVALID_TRACE_ID and spanid != INVALID_SPAN_ID: context = set_span_in_context( NonRecordingSpan( SpanContext( trace_id=traceid, span_id=spanid, is_remote=True, trace_flags=TraceFlags(traceflags), ) ), context, ) baggage = get_all(context) or {} for key in getter.keys(carrier): if not key.startswith(OT_BAGGAGE_PREFIX): continue baggage[ key[len(OT_BAGGAGE_PREFIX) :] ] = _extract_first_element(getter.get(carrier, key)) for key, value in baggage.items(): context = set_baggage(key, value, context) return context
def set_baggage_item(self, key: str, value: str): """Stores a Baggage item in the span as a key/value pair. Args: key: A tag key. value: A tag value. """ # pylint: disable=protected-access self._context._baggage = set_baggage(key, value, context=self._context._baggage)
def _extract_baggage(self, getter, carrier, context): baggage_keys = [ key for key in getter.keys(carrier) if key.startswith(self.BAGGAGE_PREFIX) ] for key in baggage_keys: value = _extract_first_element(getter.get(carrier, key)) context = baggage.set_baggage( key.replace(self.BAGGAGE_PREFIX, ""), urllib.parse.unquote(value).strip(), context=context, ) return context
def extract( self, getter: Getter[TextMapPropagatorT], carrier: TextMapPropagatorT, context: Optional[Context] = None, ) -> Context: traceid = _extract_first_element( getter.get(carrier, OT_TRACE_ID_HEADER)) spanid = _extract_first_element(getter.get(carrier, OT_SPAN_ID_HEADER)) sampled = _extract_first_element(getter.get(carrier, OT_SAMPLED_HEADER)) if sampled == "true": traceflags = TraceFlags.SAMPLED else: traceflags = TraceFlags.DEFAULT if (traceid != INVALID_TRACE_ID and _valid_extract_traceid.fullmatch(traceid) is not None and spanid != INVALID_SPAN_ID and _valid_extract_spanid.fullmatch(spanid) is not None): context = set_span_in_context( DefaultSpan( SpanContext( trace_id=int(traceid, 16), span_id=int(spanid, 16), is_remote=True, trace_flags=traceflags, )), context, ) baggage = get_all(context) or {} for key in getter.keys(carrier): if not key.startswith(OT_BAGGAGE_PREFIX): continue baggage[key[len(OT_BAGGAGE_PREFIX):]] = _extract_first_element( getter.get(carrier, key)) for key, value in baggage.items(): context = set_baggage(key, value, context) return context
def test_propagation_baggage(self): configure_opentelemetry( service_name="service_name", service_version="service_version", access_token="a" * 104, propagators="baggage", ) with trace.get_tracer(__name__).start_as_current_span("test"): ctx = baggage.set_baggage("abc", "def") prop = get_global_textmap() carrier = {} prop.inject(dict.__setitem__, carrier, context=ctx) self.assertIsNone(carrier.get("x-b3-traceid")) self.assertEqual(carrier.get("baggage"), "abc=def")
def test_propagation_tracecontext(self): configure_opentelemetry( service_name="service_name", service_version="service_version", access_token="a" * 104, propagators="tracecontext", ) with trace.get_tracer(__name__).start_as_current_span("test") as span: ctx = baggage.set_baggage("abc", "def") prop = get_global_textmap() carrier = {} prop.inject(dict.__setitem__, carrier, context=ctx) self.assertIn( "00-{}".format(format(span.get_span_context().trace_id, "032x")), carrier.get("traceparent"), )
def send_requests(): RequestsInstrumentor().instrument() configure_opentelemetry( service_name="client_service_name", service_version="client_version", # optional ) tracer = get_tracer(__name__) def request(url): with tracer.start_as_current_span("request to {}".format(url)) as span: try: get(url) except Exception as error: span.set_attribute("error", "true") span.record_exception(error) attempts = 10 for attempt in range(attempts): debug("Sending requests %s/%s", attempt + 1, attempts) with tracer.start_as_current_span("foo"): debug("Current span: %s", get_current_span()) with tracer.start_as_current_span("add-attribute") as span: span.set_attribute("attr1", "valu1") debug("Current span: %s", get_current_span()) debug( "Baggage: %s", get_baggage("example", set_baggage("example", "value")), ) with tracer.start_as_current_span("bar"): debug("Hello, server!") request("http://localhost:8000/hello") request("http://doesnotexist:8000") sleep(1) request("http://localhost:8000/shutdown")
def extract( self, getter: textmap.Getter[textmap.TextMapPropagatorT], carrier: textmap.TextMapPropagatorT, context: typing.Optional[Context] = None, ) -> Context: """Extract Baggage from the carrier. See `opentelemetry.propagators.textmap.TextMapPropagator.extract` """ if context is None: context = get_current() header = _extract_first_element( getter.get(carrier, self._BAGGAGE_HEADER_NAME) ) if not header or len(header) > self.MAX_HEADER_LENGTH: return context baggage_entries = header.split(",") total_baggage_entries = self.MAX_PAIRS for entry in baggage_entries: if total_baggage_entries <= 0: return context total_baggage_entries -= 1 if len(entry) > self.MAX_PAIR_LENGTH: continue try: name, value = entry.split("=", 1) except Exception: # pylint: disable=broad-except continue context = baggage.set_baggage( urllib.parse.unquote(name).strip(), urllib.parse.unquote(value).strip(), context=context, ) return context
# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from opentelemetry import baggage, trace tracer = trace.get_tracer(__name__) global_ctx = baggage.set_baggage("context", "global") with tracer.start_as_current_span(name="root span") as root_span: parent_ctx = baggage.set_baggage("context", "parent") with tracer.start_as_current_span(name="child span", context=parent_ctx) as child_span: child_ctx = baggage.set_baggage("context", "child") print(baggage.get_baggage("context", global_ctx)) print(baggage.get_baggage("context", parent_ctx)) print(baggage.get_baggage("context", child_ctx))
def test_baggages_current_context(self): token = context.attach(baggage.set_baggage("test", "value")) self.assertEqual(baggage.get_baggage("test"), "value") context.detach(token) self.assertEqual(baggage.get_baggage("test"), None)
def extract( self, carrier: textmap.CarrierT, context: Optional[Context] = None, getter: textmap.Getter = textmap.default_getter, ) -> Context: """Extract Baggage from the carrier. See `opentelemetry.propagators.textmap.TextMapPropagator.extract` """ if context is None: context = get_current() header = _extract_first_element( getter.get(carrier, self._BAGGAGE_HEADER_NAME) ) if not header: return context if len(header) > self._MAX_HEADER_LENGTH: _logger.warning( "Baggage header `%s` exceeded the maximum number of bytes per baggage-string", header, ) return context baggage_entries = split(_DELIMITER_PATTERN, header) total_baggage_entries = self._MAX_PAIRS if len(baggage_entries) > self._MAX_PAIRS: _logger.warning( "Baggage header `%s` exceeded the maximum number of list-members", header, ) for entry in baggage_entries: if len(entry) > self._MAX_PAIR_LENGTH: _logger.warning( "Baggage entry `%s` exceeded the maximum number of bytes per list-member", entry, ) continue if not entry: # empty string continue try: name, value = entry.split("=", 1) except Exception: # pylint: disable=broad-except _logger.warning( "Baggage list-member `%s` doesn't match the format", entry ) continue name = unquote_plus(name).strip().lower() value = unquote_plus(value).strip() if not _is_valid_pair(name, value): _logger.warning("Invalid baggage entry: `%s`", entry) continue context = set_baggage( name, value, context=context, ) total_baggage_entries -= 1 if total_baggage_entries == 0: break return context
# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from opentelemetry import baggage, trace from opentelemetry.sdk.trace import TracerProvider trace.set_tracer_provider(TracerProvider()) tracer = trace.get_tracer(__name__) with tracer.start_span(name="root span") as root_span: ctx = baggage.set_baggage("foo", "bar") print(f"Global context baggage: {baggage.get_all()}") print(f"Span context baggage: {baggage.get_all(context=ctx)}")
async def async_span(span): with tracer.use_span(span): ctx = baggage.set_baggage("foo", "bar") return ctx