diff --git a/src/instana/agent/host.py b/src/instana/agent/host.py index 89daff8ee..5a7bb6ede 100644 --- a/src/instana/agent/host.py +++ b/src/instana/agent/host.py @@ -40,6 +40,9 @@ class HostAgent(BaseAgent): """ AGENT_DISCOVERY_PATH = "com.instana.plugin.python.discovery" AGENT_DATA_PATH = "com.instana.plugin.python.%d" + AGENT_HEADERS = { + "User-Agent": f"instana-python-tracer/{VERSION}", + } def __init__(self): super(HostAgent, self).__init__() @@ -154,7 +157,8 @@ def is_agent_listening(self, host, port): result = False try: url = "http://%s:%s/" % (host, port) - response = self.client.get(url, timeout=5) + headers = self.AGENT_HEADERS + response = self.client.get(url, timeout=5, headers=headers) if 200 <= response.status_code < 300: logger.debug("Instana host agent found on %s:%d", host, port) @@ -174,9 +178,11 @@ def announce(self, discovery): """ try: url = self.__discovery_url() + headers = {"Content-Type": "application/json"} + headers.update(self.AGENT_HEADERS) response = self.client.put(url, data=to_json(discovery), - headers={"Content-Type": "application/json"}, + headers=headers, timeout=0.8) except Exception as exc: logger.debug("announce: connection error (%s)", type(exc)) @@ -224,10 +230,14 @@ def log_message_to_host_agent(self, message): payload["m"] = message url = self.__agent_logger_url() + headers = { + "Content-Type": "application/json", + "X-Log-Level": "INFO", + } + headers.update(self.AGENT_HEADERS) response = self.client.post(url, data=to_json(payload), - headers={"Content-Type": "application/json", - "X-Log-Level": "INFO"}, + headers=headers, timeout=0.8) if 200 <= response.status_code <= 204: @@ -241,7 +251,8 @@ def is_agent_ready(self): """ ready = False try: - response = self.client.head(self.__data_url(), timeout=0.8) + headers = self.AGENT_HEADERS + response = self.client.head(self.__data_url(), timeout=0.8, headers=headers) if response.status_code == 200: ready = True @@ -259,9 +270,11 @@ def report_data_payload(self, payload): span_count = len(payload['spans']) if span_count > 0: logger.debug("Reporting %d spans", span_count) + headers = {"Content-Type": "application/json"} + headers.update(self.AGENT_HEADERS) response = self.client.post(self.__traces_url(), data=to_json(payload['spans']), - headers={"Content-Type": "application/json"}, + headers=headers, timeout=0.8) if response is not None and 200 <= response.status_code <= 204: @@ -271,9 +284,11 @@ def report_data_payload(self, payload): profile_count = len(payload['profiles']) if profile_count > 0: logger.debug("Reporting %d profiles", profile_count) + headers = {"Content-Type": "application/json"} + headers.update(self.AGENT_HEADERS) response = self.client.post(self.__profiles_url(), data=to_json(payload['profiles']), - headers={"Content-Type": "application/json"}, + headers=headers, timeout=0.8) if response is not None and 200 <= response.status_code <= 204: @@ -281,9 +296,11 @@ def report_data_payload(self, payload): # Report metrics metric_bundle = payload["metrics"]["plugins"][0]["data"] + headers = {"Content-Type": "application/json"} + headers.update(self.AGENT_HEADERS) response = self.client.post(self.__data_url(), data=to_json(metric_bundle), - headers={"Content-Type": "application/json"}, + headers=headers, timeout=0.8) if response is not None and 200 <= response.status_code <= 204: @@ -375,9 +392,11 @@ def __task_response(self, message_id, data): logger.debug("Task response is %s: %s", self.__response_url(message_id), payload) + headers = {"Content-Type": "application/json"} + headers.update(self.AGENT_HEADERS) response = self.client.post(self.__response_url(message_id), data=payload, - headers={"Content-Type": "application/json"}, + headers=headers, timeout=0.8) except Exception as exc: logger.debug("__task_response: Instana host agent connection error (%s)", type(exc)) diff --git a/src/instana/instrumentation/urllib3.py b/src/instana/instrumentation/urllib3.py index 12542bc5f..3f6b162d4 100644 --- a/src/instana/instrumentation/urllib3.py +++ b/src/instana/instrumentation/urllib3.py @@ -8,7 +8,7 @@ from ..log import logger from ..singletons import agent -from ..util.traceutils import get_tracer_tuple, tracing_is_off +from ..util.traceutils import get_tracer_tuple, is_internal_request, tracing_is_off from ..util.secrets import strip_secrets_from_query try: @@ -78,7 +78,7 @@ def collect_response(scope, response): def urlopen_with_instana(wrapped, instance, args, kwargs): tracer, parent_span, operation_name = get_tracer_tuple() # If we're not tracing, just return; boto3 has it's own visibility - if (tracing_is_off() or (operation_name == 'boto3')): + if tracing_is_off() or (operation_name == 'boto3') or is_internal_request(kwargs.get("headers", {})): return wrapped(*args, **kwargs) with tracer.start_active_span("urllib3", child_of=parent_span) as scope: diff --git a/src/instana/util/traceutils.py b/src/instana/util/traceutils.py index a5b333044..8e158e918 100644 --- a/src/instana/util/traceutils.py +++ b/src/instana/util/traceutils.py @@ -1,6 +1,7 @@ # (c) Copyright IBM Corp. 2021 # (c) Copyright Instana Inc. 2021 +from typing import Any, Dict from ..singletons import agent, tracer, async_tracer, tornado_tracer from ..log import logger @@ -43,3 +44,17 @@ def get_tracer_tuple(): def tracing_is_off(): return not (bool(get_active_tracer()) or agent.options.allow_exit_as_root) + + +def is_internal_request(headers: Dict[str, Any]) -> bool: + """ + Check for the "instana-python-tracer/{VERSION}" string in the "User-Agent" + header for identify internal requests. + """ + # make all keys from the dict lowercase. + headers = dict(map(lambda kv: (kv[0].lower(), kv[1]), headers.items())) + + if "user-agent" in headers.keys(): + if "instana-python-tracer" in headers["user-agent"]: + return True + return False