def _functionPatch(self, original_func, instance, args, kwargs): lambda_context = args[1] ctx_aws_request_id = lambda_context.aws_request_id ctx_invoked_function_arn = lambda_context.invoked_function_arn orig_handler = os.environ.get("ORIG_HANDLER", os.environ.get("_HANDLER")) xray_trace_id = os.environ.get("_X_AMZN_TRACE_ID", "") lambda_name = os.environ.get("AWS_LAMBDA_FUNCTION_NAME") function_version = os.environ.get("AWS_LAMBDA_FUNCTION_VERSION") propagator = AwsXRayFormat() parent_context = propagator.extract(DictGetter(), {"X-Amzn-Trace-Id": xray_trace_id}) with self._tracer.start_as_current_span( orig_handler, context=parent_context, kind=SpanKind.CONSUMER) as span: # Refer: https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/faas.md#example span.set_attribute("faas.execution", ctx_aws_request_id) span.set_attribute("faas.id", ctx_invoked_function_arn) # TODO: fix in Collector because they belong resource attrubutes span.set_attribute("faas.name", lambda_name) span.set_attribute("faas.version", function_version) result = original_func(*args, **kwargs) # force_flush before function quit in case of Lambda freeze. self._tracer_provider.force_flush() return result
def __init__(self, tracer: OtelTracer): super().__init__(scope_manager=ScopeManagerShim(self)) self._otel_tracer = tracer self._supported_formats = ( Format.TEXT_MAP, Format.HTTP_HEADERS, ) self._carrier_getter = DictGetter()
def server_request(): with tracer.start_as_current_span( "server_request", context=propagators.extract(DictGetter(), request.headers), kind=trace.SpanKind.SERVER, attributes=collect_request_attributes(request.environ)): print(request.args.get("param")) return "served"
def test_extract_single_header(benchmark): benchmark( XRAY_PROPAGATOR.extract, DictGetter(), { TRACE_HEADER_KEY: "bdb5b63237ed38aea578af665aa5aa60-00000000000000000c32d953d73ad225" }, )
def test_extract_single_header(benchmark): benchmark( FORMAT.extract, DictGetter(), { FORMAT.SINGLE_HEADER_KEY: "bdb5b63237ed38aea578af665aa5aa60-c32d953d73ad2251-1-11fd79a30b0896cd285b396ae102dd76" }, )
def link_from_headers(cls, headers, attributes=None): # type: (Dict[str, str], Attributes) -> None """ Given a dictionary, extracts the context and links the context to the current tracer. :param headers: A key value pair dictionary :type headers: dict """ ctx = extract(DictGetter(), headers) span_ctx = get_span_from_context(ctx).get_span_context() current_span = cls.get_current_span() current_span.links.append(Link(span_ctx, attributes))
def _function_patch(self, original_func, _, args, kwargs): lambda_context = args[1] ctx_aws_request_id = lambda_context.aws_request_id orig_handler = os.environ.get("ORIG_HANDLER", os.environ.get("_HANDLER")) xray_trace_id = os.environ.get("_X_AMZN_TRACE_ID", "") propagator = AwsXRayFormat() parent_context = propagator.extract(DictGetter(), {TRACE_HEADER_KEY: xray_trace_id}) with self._tracer.start_as_current_span(orig_handler, context=parent_context, kind=SpanKind.CLIENT) as span: # Refer: https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/faas.md#example span.set_attribute("faas.execution", ctx_aws_request_id) result = original_func(*args, **kwargs) # force_flush before function quit in case of Lambda freeze. self._tracer_provider.force_flush() return result
return ExcludeList(urls) def get_traced_request_attrs(): attrs = configuration.Configuration().TORNADO_TRACED_REQUEST_ATTRS or "" if attrs: attrs = [attr.strip() for attr in attrs.split(",")] else: attrs = [] return attrs _excluded_urls = get_excluded_urls() _traced_attrs = get_traced_request_attrs() carrier_getter = DictGetter() class TornadoInstrumentor(BaseInstrumentor): patched_handlers = [] original_handler_new = None def _instrument(self, **kwargs): """ _instrument patches tornado.web.RequestHandler and tornado.httpclient.AsyncHTTPClient classes to automatically instrument requests both received and sent by Tornado. We don't patch RequestHandler._execute as it causes some issues with contextvars based context. Mainly the context fails to detach from within RequestHandler.on_finish() if it is attached inside RequestHandler._execute. Same issue plagues RequestHandler.initialize. RequestHandler.prepare works perfectly on the other hand as it executes in the same context as on_finish and log_exection which
def extract(context_dict: Dict[Any, Any]) -> "Context": """Given a trace context, extract as a Context.""" return cast(Context, propagators.extract(DictGetter(), context_dict))
def __init__(self, tracer): self._tracer = tracer self._carrier_getter = DictGetter()
class AwsXRayPropagatorTest(unittest.TestCase): carrier_setter = CaseInsensitiveDict.__setitem__ carrier_getter = DictGetter() XRAY_PROPAGATOR = AwsXRayFormat() # Inject Tests def test_inject_into_non_sampled_context(self): carrier = CaseInsensitiveDict() AwsXRayPropagatorTest.XRAY_PROPAGATOR.inject( AwsXRayPropagatorTest.carrier_setter, carrier, build_test_current_context(), ) injected_items = set(carrier.items()) expected_items = set( CaseInsensitiveDict( { TRACE_HEADER_KEY: "Root=1-8a3c60f7-d188f8fa79d48a391a778fa6;Parent=53995c3f42cd8ad8;Sampled=0" } ).items() ) self.assertEqual(injected_items, expected_items) def test_inject_into_sampled_context(self): carrier = CaseInsensitiveDict() AwsXRayPropagatorTest.XRAY_PROPAGATOR.inject( AwsXRayPropagatorTest.carrier_setter, carrier, build_test_current_context( trace_flags=TraceFlags(TraceFlags.SAMPLED) ), ) injected_items = set(carrier.items()) expected_items = set( CaseInsensitiveDict( { TRACE_HEADER_KEY: "Root=1-8a3c60f7-d188f8fa79d48a391a778fa6;Parent=53995c3f42cd8ad8;Sampled=1" } ).items() ) self.assertEqual(injected_items, expected_items) def test_inject_into_context_with_non_default_state(self): carrier = CaseInsensitiveDict() AwsXRayPropagatorTest.XRAY_PROPAGATOR.inject( AwsXRayPropagatorTest.carrier_setter, carrier, build_test_current_context(trace_state=TraceState({"foo": "bar"})), ) # TODO: (NathanielRN) Assert trace state when the propagator supports it injected_items = set(carrier.items()) expected_items = set( CaseInsensitiveDict( { TRACE_HEADER_KEY: "Root=1-8a3c60f7-d188f8fa79d48a391a778fa6;Parent=53995c3f42cd8ad8;Sampled=0" } ).items() ) self.assertEqual(injected_items, expected_items) def test_inject_reported_fields_matches_carrier_fields(self): carrier = CaseInsensitiveDict() AwsXRayPropagatorTest.XRAY_PROPAGATOR.inject( AwsXRayPropagatorTest.carrier_setter, carrier, build_test_current_context(), ) injected_keys = set(carrier.keys()) self.assertEqual( injected_keys, AwsXRayPropagatorTest.XRAY_PROPAGATOR.fields() ) # Extract Tests def test_extract_empty_carrier_from_invalid_context(self): context_with_extracted = AwsXRayPropagatorTest.XRAY_PROPAGATOR.extract( AwsXRayPropagatorTest.carrier_getter, CaseInsensitiveDict() ) self.assertEqual( get_nested_span_context(context_with_extracted), INVALID_SPAN_CONTEXT, ) def test_extract_not_sampled_context(self): context_with_extracted = AwsXRayPropagatorTest.XRAY_PROPAGATOR.extract( AwsXRayPropagatorTest.carrier_getter, CaseInsensitiveDict( { TRACE_HEADER_KEY: "Root=1-8a3c60f7-d188f8fa79d48a391a778fa6;Parent=53995c3f42cd8ad8;Sampled=0" } ), ) self.assertEqual( get_nested_span_context(context_with_extracted), build_test_span_context(), ) def test_extract_sampled_context(self): context_with_extracted = AwsXRayPropagatorTest.XRAY_PROPAGATOR.extract( AwsXRayPropagatorTest.carrier_getter, CaseInsensitiveDict( { TRACE_HEADER_KEY: "Root=1-8a3c60f7-d188f8fa79d48a391a778fa6;Parent=53995c3f42cd8ad8;Sampled=1" } ), ) self.assertEqual( get_nested_span_context(context_with_extracted), build_test_span_context( trace_flags=TraceFlags(TraceFlags.SAMPLED) ), ) def test_extract_different_order(self): context_with_extracted = AwsXRayPropagatorTest.XRAY_PROPAGATOR.extract( AwsXRayPropagatorTest.carrier_getter, CaseInsensitiveDict( { TRACE_HEADER_KEY: "Sampled=0;Parent=53995c3f42cd8ad8;Root=1-8a3c60f7-d188f8fa79d48a391a778fa6" } ), ) self.assertEqual( get_nested_span_context(context_with_extracted), build_test_span_context(), ) def test_extract_with_additional_fields(self): context_with_extracted = AwsXRayPropagatorTest.XRAY_PROPAGATOR.extract( AwsXRayPropagatorTest.carrier_getter, CaseInsensitiveDict( { TRACE_HEADER_KEY: "Root=1-8a3c60f7-d188f8fa79d48a391a778fa6;Parent=53995c3f42cd8ad8;Sampled=0;Foo=Bar" } ), ) self.assertEqual( get_nested_span_context(context_with_extracted), build_test_span_context(), ) def test_extract_with_extra_whitespace(self): context_with_extracted = AwsXRayPropagatorTest.XRAY_PROPAGATOR.extract( AwsXRayPropagatorTest.carrier_getter, CaseInsensitiveDict( { TRACE_HEADER_KEY: " Root = 1-8a3c60f7-d188f8fa79d48a391a778fa6 ; Parent = 53995c3f42cd8ad8 ; Sampled = 0 " } ), ) self.assertEqual( get_nested_span_context(context_with_extracted), build_test_span_context(), ) def test_extract_invalid_xray_trace_header(self): context_with_extracted = AwsXRayPropagatorTest.XRAY_PROPAGATOR.extract( AwsXRayPropagatorTest.carrier_getter, CaseInsensitiveDict({TRACE_HEADER_KEY: ""}), ) self.assertEqual( get_nested_span_context(context_with_extracted), INVALID_SPAN_CONTEXT, ) def test_extract_invalid_trace_id(self): context_with_extracted = AwsXRayPropagatorTest.XRAY_PROPAGATOR.extract( AwsXRayPropagatorTest.carrier_getter, CaseInsensitiveDict( { TRACE_HEADER_KEY: "Root=1-12345678-abcdefghijklmnopqrstuvwx;Parent=53995c3f42cd8ad8;Sampled=0" } ), ) self.assertEqual( get_nested_span_context(context_with_extracted), INVALID_SPAN_CONTEXT, ) def test_extract_invalid_trace_id_size(self): context_with_extracted = AwsXRayPropagatorTest.XRAY_PROPAGATOR.extract( AwsXRayPropagatorTest.carrier_getter, CaseInsensitiveDict( { TRACE_HEADER_KEY: "Root=1-8a3c60f7-d188f8fa79d48a391a778fa600;Parent=53995c3f42cd8ad8;Sampled=0=" } ), ) self.assertEqual( get_nested_span_context(context_with_extracted), INVALID_SPAN_CONTEXT, ) def test_extract_invalid_span_id(self): context_with_extracted = AwsXRayPropagatorTest.XRAY_PROPAGATOR.extract( AwsXRayPropagatorTest.carrier_getter, CaseInsensitiveDict( { TRACE_HEADER_KEY: "Root=1-8a3c60f7-d188f8fa79d48a391a778fa6;Parent=abcdefghijklmnop;Sampled=0" } ), ) self.assertEqual( get_nested_span_context(context_with_extracted), INVALID_SPAN_CONTEXT, ) def test_extract_invalid_span_id_size(self): context_with_extracted = AwsXRayPropagatorTest.XRAY_PROPAGATOR.extract( AwsXRayPropagatorTest.carrier_getter, CaseInsensitiveDict( { TRACE_HEADER_KEY: "Root=1-8a3c60f7-d188f8fa79d48a391a778fa6;Parent=53995c3f42cd8ad800;Sampled=0" } ), ) self.assertEqual( get_nested_span_context(context_with_extracted), INVALID_SPAN_CONTEXT, ) def test_extract_invalid_empty_sampled_flag(self): context_with_extracted = AwsXRayPropagatorTest.XRAY_PROPAGATOR.extract( AwsXRayPropagatorTest.carrier_getter, CaseInsensitiveDict( { TRACE_HEADER_KEY: "Root=1-8a3c60f7-d188f8fa79d48a391a778fa6;Parent=53995c3f42cd8ad8;Sampled=" } ), ) self.assertEqual( get_nested_span_context(context_with_extracted), INVALID_SPAN_CONTEXT, ) def test_extract_invalid_sampled_flag_size(self): context_with_extracted = AwsXRayPropagatorTest.XRAY_PROPAGATOR.extract( AwsXRayPropagatorTest.carrier_getter, CaseInsensitiveDict( { TRACE_HEADER_KEY: "Root=1-8a3c60f7-d188f8fa79d48a391a778fa6;Parent=53995c3f42cd8ad8;Sampled=011" } ), ) self.assertEqual( get_nested_span_context(context_with_extracted), INVALID_SPAN_CONTEXT, ) def test_extract_invalid_non_numeric_sampled_flag(self): context_with_extracted = AwsXRayPropagatorTest.XRAY_PROPAGATOR.extract( AwsXRayPropagatorTest.carrier_getter, CaseInsensitiveDict( { TRACE_HEADER_KEY: "Root=1-8a3c60f7-d188f8fa79d48a391a778fa6;Parent=53995c3f42cd8ad8;Sampled=a" } ), ) self.assertEqual( get_nested_span_context(context_with_extracted), INVALID_SPAN_CONTEXT, )
class AwsXRayPropagatorTest(unittest.TestCase): carrier_setter = CaseInsensitiveDict.__setitem__ carrier_getter = DictGetter() XRAY_PROPAGATOR = AwsXRayFormat() # Inject Tests def test_inject_into_non_sampled_context(self): carrier = CaseInsensitiveDict() AwsXRayPropagatorTest.XRAY_PROPAGATOR.inject( AwsXRayPropagatorTest.carrier_setter, carrier, build_test_current_context(), ) injected_items = set(carrier.items()) expected_items = set( CaseInsensitiveDict({ TRACE_HEADER_KEY: "Root=1-8a3c60f7-d188f8fa79d48a391a778fa6;Parent=53995c3f42cd8ad8;Sampled=0" }).items()) self.assertEqual(injected_items, expected_items) def test_inject_into_sampled_context(self): carrier = CaseInsensitiveDict() AwsXRayPropagatorTest.XRAY_PROPAGATOR.inject( AwsXRayPropagatorTest.carrier_setter, carrier, build_test_current_context( trace_flags=TraceFlags(TraceFlags.SAMPLED)), ) injected_items = set(carrier.items()) expected_items = set( CaseInsensitiveDict({ TRACE_HEADER_KEY: "Root=1-8a3c60f7-d188f8fa79d48a391a778fa6;Parent=53995c3f42cd8ad8;Sampled=1" }).items()) self.assertEqual(injected_items, expected_items) def test_inject_into_context_with_non_default_state(self): carrier = CaseInsensitiveDict() AwsXRayPropagatorTest.XRAY_PROPAGATOR.inject( AwsXRayPropagatorTest.carrier_setter, carrier, build_test_current_context(trace_state=TraceState([("foo", "bar")])), ) # TODO: (NathanielRN) Assert trace state when the propagator supports it injected_items = set(carrier.items()) expected_items = set( CaseInsensitiveDict({ TRACE_HEADER_KEY: "Root=1-8a3c60f7-d188f8fa79d48a391a778fa6;Parent=53995c3f42cd8ad8;Sampled=0" }).items()) self.assertEqual(injected_items, expected_items) def test_inject_reported_fields_matches_carrier_fields(self): carrier = CaseInsensitiveDict() AwsXRayPropagatorTest.XRAY_PROPAGATOR.inject( AwsXRayPropagatorTest.carrier_setter, carrier, build_test_current_context(), ) injected_keys = set(carrier.keys()) self.assertEqual(injected_keys, AwsXRayPropagatorTest.XRAY_PROPAGATOR.fields) # Extract Tests def test_extract_empty_carrier_from_invalid_context(self): context_with_extracted = AwsXRayPropagatorTest.XRAY_PROPAGATOR.extract( AwsXRayPropagatorTest.carrier_getter, CaseInsensitiveDict()) self.assertEqual( get_nested_span_context(context_with_extracted), INVALID_SPAN_CONTEXT, ) def test_extract_not_sampled_context(self): context_with_extracted = AwsXRayPropagatorTest.XRAY_PROPAGATOR.extract( AwsXRayPropagatorTest.carrier_getter, CaseInsensitiveDict({ TRACE_HEADER_KEY: "Root=1-8a3c60f7-d188f8fa79d48a391a778fa6;Parent=53995c3f42cd8ad8;Sampled=0" }), ) self.assertEqual( get_nested_span_context(context_with_extracted), build_test_span_context(), ) def test_extract_sampled_context(self): context_with_extracted = AwsXRayPropagatorTest.XRAY_PROPAGATOR.extract( AwsXRayPropagatorTest.carrier_getter, CaseInsensitiveDict({ TRACE_HEADER_KEY: "Root=1-8a3c60f7-d188f8fa79d48a391a778fa6;Parent=53995c3f42cd8ad8;Sampled=1" }), ) self.assertEqual( get_nested_span_context(context_with_extracted), build_test_span_context( trace_flags=TraceFlags(TraceFlags.SAMPLED)), ) def test_extract_different_order(self): context_with_extracted = AwsXRayPropagatorTest.XRAY_PROPAGATOR.extract( AwsXRayPropagatorTest.carrier_getter, CaseInsensitiveDict({ TRACE_HEADER_KEY: "Sampled=0;Parent=53995c3f42cd8ad8;Root=1-8a3c60f7-d188f8fa79d48a391a778fa6" }), ) self.assertEqual( get_nested_span_context(context_with_extracted), build_test_span_context(), ) def test_extract_with_additional_fields(self): context_with_extracted = AwsXRayPropagatorTest.XRAY_PROPAGATOR.extract( AwsXRayPropagatorTest.carrier_getter, CaseInsensitiveDict({ TRACE_HEADER_KEY: "Root=1-8a3c60f7-d188f8fa79d48a391a778fa6;Parent=53995c3f42cd8ad8;Sampled=0;Foo=Bar" }), ) self.assertEqual( get_nested_span_context(context_with_extracted), build_test_span_context(), ) def test_extract_with_extra_whitespace(self): context_with_extracted = AwsXRayPropagatorTest.XRAY_PROPAGATOR.extract( AwsXRayPropagatorTest.carrier_getter, CaseInsensitiveDict({ TRACE_HEADER_KEY: " Root = 1-8a3c60f7-d188f8fa79d48a391a778fa6 ; Parent = 53995c3f42cd8ad8 ; Sampled = 0 " }), ) self.assertEqual( get_nested_span_context(context_with_extracted), build_test_span_context(), ) def test_extract_invalid_xray_trace_header(self): context_with_extracted = AwsXRayPropagatorTest.XRAY_PROPAGATOR.extract( AwsXRayPropagatorTest.carrier_getter, CaseInsensitiveDict({TRACE_HEADER_KEY: ""}), ) self.assertEqual( get_nested_span_context(context_with_extracted), INVALID_SPAN_CONTEXT, ) def test_extract_invalid_trace_id(self): context_with_extracted = AwsXRayPropagatorTest.XRAY_PROPAGATOR.extract( AwsXRayPropagatorTest.carrier_getter, CaseInsensitiveDict({ TRACE_HEADER_KEY: "Root=1-12345678-abcdefghijklmnopqrstuvwx;Parent=53995c3f42cd8ad8;Sampled=0" }), ) self.assertEqual( get_nested_span_context(context_with_extracted), INVALID_SPAN_CONTEXT, ) def test_extract_invalid_trace_id_size(self): context_with_extracted = AwsXRayPropagatorTest.XRAY_PROPAGATOR.extract( AwsXRayPropagatorTest.carrier_getter, CaseInsensitiveDict({ TRACE_HEADER_KEY: "Root=1-8a3c60f7-d188f8fa79d48a391a778fa600;Parent=53995c3f42cd8ad8;Sampled=0=" }), ) self.assertEqual( get_nested_span_context(context_with_extracted), INVALID_SPAN_CONTEXT, ) def test_extract_invalid_span_id(self): context_with_extracted = AwsXRayPropagatorTest.XRAY_PROPAGATOR.extract( AwsXRayPropagatorTest.carrier_getter, CaseInsensitiveDict({ TRACE_HEADER_KEY: "Root=1-8a3c60f7-d188f8fa79d48a391a778fa6;Parent=abcdefghijklmnop;Sampled=0" }), ) self.assertEqual( get_nested_span_context(context_with_extracted), INVALID_SPAN_CONTEXT, ) def test_extract_invalid_span_id_size(self): context_with_extracted = AwsXRayPropagatorTest.XRAY_PROPAGATOR.extract( AwsXRayPropagatorTest.carrier_getter, CaseInsensitiveDict({ TRACE_HEADER_KEY: "Root=1-8a3c60f7-d188f8fa79d48a391a778fa6;Parent=53995c3f42cd8ad800;Sampled=0" }), ) self.assertEqual( get_nested_span_context(context_with_extracted), INVALID_SPAN_CONTEXT, ) def test_extract_invalid_empty_sampled_flag(self): context_with_extracted = AwsXRayPropagatorTest.XRAY_PROPAGATOR.extract( AwsXRayPropagatorTest.carrier_getter, CaseInsensitiveDict({ TRACE_HEADER_KEY: "Root=1-8a3c60f7-d188f8fa79d48a391a778fa6;Parent=53995c3f42cd8ad8;Sampled=" }), ) self.assertEqual( get_nested_span_context(context_with_extracted), INVALID_SPAN_CONTEXT, ) def test_extract_invalid_sampled_flag_size(self): context_with_extracted = AwsXRayPropagatorTest.XRAY_PROPAGATOR.extract( AwsXRayPropagatorTest.carrier_getter, CaseInsensitiveDict({ TRACE_HEADER_KEY: "Root=1-8a3c60f7-d188f8fa79d48a391a778fa6;Parent=53995c3f42cd8ad8;Sampled=011" }), ) self.assertEqual( get_nested_span_context(context_with_extracted), INVALID_SPAN_CONTEXT, ) def test_extract_invalid_non_numeric_sampled_flag(self): context_with_extracted = AwsXRayPropagatorTest.XRAY_PROPAGATOR.extract( AwsXRayPropagatorTest.carrier_getter, CaseInsensitiveDict({ TRACE_HEADER_KEY: "Root=1-8a3c60f7-d188f8fa79d48a391a778fa6;Parent=53995c3f42cd8ad8;Sampled=a" }), ) self.assertEqual( get_nested_span_context(context_with_extracted), INVALID_SPAN_CONTEXT, ) @patch("opentelemetry.sdk.extension.aws.trace." "propagation.aws_xray_format.trace") def test_fields(self, mock_trace): """Make sure the fields attribute returns the fields used in inject""" mock_trace.configure_mock( **{ "get_current_span.return_value": Mock( **{ "get_span_context.return_value": Mock(**{ "is_valid": True, "trace_id": 1, "span_id": 1 }) }) }) mock_set_in_carrier = Mock() AwsXRayPropagatorTest.XRAY_PROPAGATOR.inject(mock_set_in_carrier, {}) inject_fields = set() for call in mock_set_in_carrier.mock_calls: inject_fields.add(call[1][1]) self.assertEqual(AwsXRayPropagatorTest.XRAY_PROPAGATOR.fields, inject_fields)