def test_traceparent_from_header(): header = "00-0000651916cd43dd8448eb211c80319c-b7ad6b7169203331-03" legacy_header = "00-1111651916cd43dd8448eb211c80319c-b7ad6b7169203331-03" tp1 = TraceParent.from_headers({"traceparent": header}) tp2 = TraceParent.from_headers({"elastic-apm-traceparent": legacy_header}) tp3 = TraceParent.from_headers({ "traceparent": header, "elastic-apm-traceparent": legacy_header }) assert tp1.to_string() == header assert tp2.to_string() == legacy_header # traceparent has precedence over elastic-apm-traceparent assert tp3.to_string() == header
async def _request_started(self, request: Request): """Captures the begin of the request processing to APM. Args: request (Request) """ # When we consume the body, we replace the streaming mechanism with # a mocked version -- this workaround came from # https://github.com/encode/starlette/issues/495#issuecomment-513138055 # and we call the workaround here to make sure that regardless of # `capture_body` settings, we will have access to the body if we need it. if self.client.config.capture_body != "off": await get_body(request) if not self.client.should_ignore_url(request.url.path): trace_parent = TraceParent.from_headers(dict(request.headers)) self.client.begin_transaction("request", trace_parent=trace_parent) await set_context( lambda: get_data_from_request(request, self.client.config, constants.TRANSACTION), "request") transaction_name = self.get_route_name(request) or request.url.path elasticapm.set_transaction_name("{} {}".format( request.method, transaction_name), override=False)
def _request_started_handler(client, sender, *args, **kwargs): if not _should_start_transaction(client): return # try to find trace id if "environ" in kwargs: trace_parent = TraceParent.from_headers( kwargs["environ"], TRACEPARENT_HEADER_NAME_WSGI, TRACEPARENT_LEGACY_HEADER_NAME_WSGI, TRACESTATE_HEADER_NAME_WSGI, ) elif "scope" in kwargs and "headers" in kwargs["scope"]: trace_parent = TraceParent.from_headers(kwargs["scope"]["headers"]) else: trace_parent = None client.begin_transaction("request", trace_parent=trace_parent)
async def call(self, module, method, wrapped, instance, args, kwargs): # Late import to avoid ImportErrors from elasticapm.contrib.tornado.utils import get_data_from_request, get_data_from_response request = instance.request trace_parent = TraceParent.from_headers(request.headers) client = instance.application.elasticapm_client client.begin_transaction("request", trace_parent=trace_parent) elasticapm.set_context( lambda: get_data_from_request(instance, request, client.config, constants.TRANSACTION), "request") # TODO: Can we somehow incorporate the routing rule itself here? elasticapm.set_transaction_name("{} {}".format( request.method, type(instance).__name__), override=False) ret = await wrapped(*args, **kwargs) elasticapm.set_context( lambda: get_data_from_response(instance, client.config, constants. TRANSACTION), "response") result = "HTTP {}xx".format(instance.get_status() // 100) elasticapm.set_transaction_result(result, override=False) client.end_transaction() return ret
async def call(self, module, method, wrapped, instance, args, kwargs): if not hasattr(instance.application, "elasticapm_client"): # If tornado was instrumented but not as the main framework # (i.e. in Flower), we should skip it. return await wrapped(*args, **kwargs) # Late import to avoid ImportErrors from elasticapm.contrib.tornado.utils import get_data_from_request, get_data_from_response request = instance.request trace_parent = TraceParent.from_headers(request.headers) client = instance.application.elasticapm_client client.begin_transaction("request", trace_parent=trace_parent) elasticapm.set_context( lambda: get_data_from_request(instance, request, client.config, constants.TRANSACTION), "request") # TODO: Can we somehow incorporate the routing rule itself here? elasticapm.set_transaction_name("{} {}".format( request.method, type(instance).__name__), override=False) ret = await wrapped(*args, **kwargs) elasticapm.set_context( lambda: get_data_from_response(instance, client.config, constants. TRANSACTION), "response") status = instance.get_status() result = "HTTP {}xx".format(status // 100) elasticapm.set_transaction_result(result, override=False) elasticapm.set_transaction_outcome(http_status_code=status) client.end_transaction() return ret
def __enter__(self): """ Transaction setup """ trace_parent = TraceParent.from_headers(self.event.get("headers", {})) global COLD_START cold_start = COLD_START COLD_START = False self.source = "other" transaction_type = "request" transaction_name = os.environ.get("AWS_LAMBDA_FUNCTION_NAME", self.name) self.httpmethod = nested_key( self.event, "requestContext", "httpMethod") or nested_key( self.event, "requestContext", "http", "method") if self.httpmethod: # API Gateway self.source = "api" if os.environ.get("AWS_LAMBDA_FUNCTION_NAME"): transaction_name = "{} {}".format( self.httpmethod, os.environ["AWS_LAMBDA_FUNCTION_NAME"]) else: transaction_name = self.name elif "Records" in self.event and len(self.event["Records"]) == 1: record = self.event["Records"][0] if record.get("eventSource") == "aws:s3": # S3 self.source = "s3" transaction_name = "{} {}".format( record["eventName"], record["s3"]["bucket"]["name"]) elif record.get("EventSource") == "aws:sns": # SNS self.source = "sns" transaction_type = "messaging" transaction_name = "RECEIVE {}".format( record["Sns"]["TopicArn"].split(":")[5]) elif record.get("eventSource") == "aws:sqs": # SQS self.source = "sqs" transaction_type = "messaging" transaction_name = "RECEIVE {}".format( record["eventSourceARN"].split(":")[5]) self.transaction = self.client.begin_transaction( transaction_type, trace_parent=trace_parent) elasticapm.set_transaction_name(transaction_name, override=False) if self.source == "api": elasticapm.set_context( lambda: get_data_from_request( self.event, capture_body=self.client.config.capture_body in ("transactions", "all"), capture_headers=self.client.config.capture_headers, ), "request", ) self.set_metadata_and_context(cold_start)
def request_started(self, app): if (not self.app.debug or self.client.config.debug) and not self.client.should_ignore_url(request.path): trace_parent = TraceParent.from_headers(request.headers) self.client.begin_transaction("request", trace_parent=trace_parent) elasticapm.set_context( lambda: get_data_from_request(request, self.client.config, constants.TRANSACTION), "request" ) rule = request.url_rule.rule if request.url_rule is not None else "" rule = build_name_with_http_method_prefix(rule, request) elasticapm.set_transaction_name(rule, override=False)
async def _request_started(self, request: Request): """Captures the begin of the request processing to APM. Args: request (Request) """ trace_parent = TraceParent.from_headers(dict(request.headers)) self.client.begin_transaction("request", trace_parent=trace_parent) await set_context(lambda: get_data_from_request(request, self.client.config, constants.TRANSACTION), "request") elasticapm.set_transaction_name("{} {}".format(request.method, request.url.path), override=False)
def _request_started_handler(client, sender, *args, **kwargs): if not _should_start_transaction(client): return # try to find trace id trace_parent = None if "environ" in kwargs: url = get_current_url(kwargs["environ"], strip_querystring=True, path_only=True) if client.should_ignore_url(url): logger.debug( "Ignoring request due to %s matching transaction_ignore_urls") return trace_parent = TraceParent.from_headers( kwargs["environ"], TRACEPARENT_HEADER_NAME_WSGI, TRACEPARENT_LEGACY_HEADER_NAME_WSGI, TRACESTATE_HEADER_NAME_WSGI, ) elif "scope" in kwargs: scope = kwargs["scope"] fake_environ = { "SCRIPT_NAME": scope.get("root_path", ""), "PATH_INFO": scope["path"], "QUERY_STRING": "" } url = get_current_url(fake_environ, strip_querystring=True, path_only=True) if client.should_ignore_url(url): logger.debug( "Ignoring request due to %s matching transaction_ignore_urls") return if "headers" in scope: trace_parent = TraceParent.from_headers(scope["headers"]) client.begin_transaction("request", trace_parent=trace_parent)
def request_started(self, app): if not self.app.debug or self.client.config.debug: trace_parent = TraceParent.from_headers(request.headers) self.client.begin_transaction("request", trace_parent=trace_parent) elasticapm.set_context( lambda: get_data_from_request( request, capture_body=self.client.config.capture_body in ("transactions", "all"), capture_headers=self.client.config.capture_headers, ), "request", ) rule = request.url_rule.rule if request.url_rule is not None else "" rule = build_name_with_http_method_prefix(rule, request) elasticapm.set_transaction_name(rule, override=False)
async def _instrument_request(request: Request): if not self._client.should_ignore_url(url=request.path): trace_parent = TraceParent.from_headers(headers=request.headers) self._client.begin_transaction("request", trace_parent=trace_parent) await set_context( lambda: get_request_info(config=self._client.config, request=request), "request", ) self._setup_transaction_name(request=request) if self._user_context_callback: name, email, uid = await self._user_context_callback(request) set_user_context(username=name, email=email, user_id=uid) await self._setup_custom_context(request=request) if self._label_info_callback: labels = await self._label_info_callback(request) label(**labels)