diff --git a/src/instana/instrumentation/aio_pika.py b/src/instana/instrumentation/aio_pika.py index db6b7586..6dbe5778 100644 --- a/src/instana/instrumentation/aio_pika.py +++ b/src/instana/instrumentation/aio_pika.py @@ -15,7 +15,7 @@ from instana.log import logger from instana.propagators.format import Format - from instana.util.traceutils import get_tracer_tuple, tracing_is_off + from instana.util.traceutils import get_tracer_tuple from instana.singletons import get_tracer if TYPE_CHECKING: @@ -41,10 +41,10 @@ async def publish_with_instana( args: Tuple[object], kwargs: Dict[str, Any], ) -> Optional["ConfirmationFrameType"]: - if tracing_is_off(): + tracer, parent_span, _ = get_tracer_tuple() + if not tracer: return await wrapped(*args, **kwargs) - tracer, parent_span, _ = get_tracer_tuple() parent_context = parent_span.get_span_context() if parent_span else None def _bind_args( diff --git a/src/instana/instrumentation/aioamqp.py b/src/instana/instrumentation/aioamqp.py index 01efdc4a..a54efca6 100644 --- a/src/instana/instrumentation/aioamqp.py +++ b/src/instana/instrumentation/aioamqp.py @@ -8,7 +8,7 @@ from opentelemetry.trace.status import StatusCode from instana.log import logger - from instana.util.traceutils import get_tracer_tuple, tracing_is_off + from instana.util.traceutils import get_tracer_tuple @wrapt.patch_function_wrapper("aioamqp.channel", "Channel.basic_publish") async def basic_publish_with_instana( @@ -17,10 +17,10 @@ async def basic_publish_with_instana( argv: Tuple[object, Tuple[object, ...]], kwargs: Dict[str, Any], ) -> object: - if tracing_is_off(): + tracer, parent_span, _ = get_tracer_tuple() + if not tracer: return await wrapped(*argv, **kwargs) - tracer, parent_span, _ = get_tracer_tuple() parent_context = parent_span.get_span_context() if parent_span else None with tracer.start_as_current_span( "aioamqp-publisher", span_context=parent_context @@ -57,11 +57,11 @@ async def basic_consume_with_instana( argv: Tuple[object, Tuple[object, ...]], kwargs: Dict[str, Any], ) -> object: - if tracing_is_off(): + tracer, parent_span, _ = get_tracer_tuple() + if not tracer: return await wrapped(*argv, **kwargs) callback = argv[0] - tracer, parent_span, _ = get_tracer_tuple() parent_context = parent_span.get_span_context() if parent_span else None @wrapt.decorator diff --git a/src/instana/instrumentation/aiohttp/client.py b/src/instana/instrumentation/aiohttp/client.py index 667c2620..f30adf52 100644 --- a/src/instana/instrumentation/aiohttp/client.py +++ b/src/instana/instrumentation/aiohttp/client.py @@ -12,7 +12,7 @@ from instana.propagators.format import Format from instana.singletons import agent from instana.util.secrets import strip_secrets_from_query -from instana.util.traceutils import get_tracer_tuple, tracing_is_off, extract_custom_headers +from instana.util.traceutils import get_tracer_tuple, extract_custom_headers try: import aiohttp @@ -21,17 +21,16 @@ from aiohttp.client import ClientSession from instana.span.span import InstanaSpan - async def stan_request_start( session: "ClientSession", trace_config_ctx: SimpleNamespace, params ) -> Awaitable[None]: try: + tracer, parent_span, _ = get_tracer_tuple() # If we're not tracing, just return - if tracing_is_off(): + if not tracer: trace_config_ctx.span_context = None return - tracer, parent_span, _ = get_tracer_tuple() parent_context = parent_span.get_span_context() if parent_span else None span = tracer.start_span("aiohttp-client", span_context=parent_context) diff --git a/src/instana/instrumentation/asyncio.py b/src/instana/instrumentation/asyncio.py index 070dfe85..3b7ec48c 100644 --- a/src/instana/instrumentation/asyncio.py +++ b/src/instana/instrumentation/asyncio.py @@ -4,7 +4,7 @@ import time from contextlib import contextmanager -from typing import Any, Callable, Dict, Iterator, Tuple +from typing import TYPE_CHECKING, Any, Callable, Dict, Iterator, Tuple import wrapt from opentelemetry.trace import use_span @@ -13,11 +13,14 @@ from instana.configurator import config from instana.log import logger from instana.span.span import InstanaSpan -from instana.util.traceutils import get_tracer_tuple, tracing_is_off +from instana.util.traceutils import get_tracer_tuple try: import asyncio + if TYPE_CHECKING: + from instana.tracer import InstanaTracer + @wrapt.patch_function_wrapper("asyncio", "ensure_future") def ensure_future_with_instana( wrapped: Callable[..., asyncio.ensure_future], @@ -25,13 +28,11 @@ def ensure_future_with_instana( argv: Tuple[object, Tuple[object, ...]], kwargs: Dict[str, Any], ) -> object: - if ( - not config["asyncio_task_context_propagation"]["enabled"] - or tracing_is_off() - ): + tracer, parent_span, _ = get_tracer_tuple() + if not config["asyncio_task_context_propagation"]["enabled"] or not tracer: return wrapped(*argv, **kwargs) - with _start_as_current_async_span() as span: + with _start_as_current_async_span(tracer, parent_span) as span: try: span.set_status(StatusCode.OK) return wrapped(*argv, **kwargs) @@ -47,13 +48,11 @@ def create_task_with_instana( argv: Tuple[object, Tuple[object, ...]], kwargs: Dict[str, Any], ) -> object: - if ( - not config["asyncio_task_context_propagation"]["enabled"] - or tracing_is_off() - ): + tracer, parent_span, _ = get_tracer_tuple() + if not config["asyncio_task_context_propagation"]["enabled"] or not tracer: return wrapped(*argv, **kwargs) - with _start_as_current_async_span() as span: + with _start_as_current_async_span(tracer, parent_span) as span: try: span.set_status(StatusCode.OK) return wrapped(*argv, **kwargs) @@ -61,12 +60,14 @@ def create_task_with_instana( logger.debug(f"asyncio create_task_with_instana error: {exc}") @contextmanager - def _start_as_current_async_span() -> Iterator[InstanaSpan]: + def _start_as_current_async_span( + tracer: "InstanaTracer", + parent_span: "InstanaSpan", + ) -> Iterator[InstanaSpan]: """ Creates and yield a special InstanaSpan to only propagate the Asyncio context. """ - tracer, parent_span, _ = get_tracer_tuple() parent_context = parent_span.get_span_context() if parent_span else None _time = time.time_ns() diff --git a/src/instana/instrumentation/aws/boto3.py b/src/instana/instrumentation/aws/boto3.py index a41c7b87..e29dc2ca 100644 --- a/src/instana/instrumentation/aws/boto3.py +++ b/src/instana/instrumentation/aws/boto3.py @@ -14,6 +14,7 @@ from botocore.client import BaseClient from instana.span.span import InstanaSpan + from instana.tracer import InstanaTracer import json @@ -22,14 +23,16 @@ from instana.log import logger from instana.propagators.format import Format from instana.singletons import get_tracer - from instana.span.span import get_current_span from instana.util.traceutils import ( extract_custom_headers, get_tracer_tuple, - tracing_is_off, ) - def lambda_inject_context(payload: Dict[str, Any], span: "InstanaSpan") -> None: + def lambda_inject_context( + tracer: "InstanaTracer", + payload: Dict[str, Any], + span: "InstanaSpan", + ) -> None: """ When boto3 lambda client 'Invoke' is called, we want to inject the tracing context. boto3/botocore has specific requirements: @@ -54,9 +57,9 @@ def emit_add_auth_with_instana( args: Tuple[object], kwargs: Dict[str, Any], ) -> Callable[..., None]: - current_span = get_current_span() - if not tracing_is_off() and current_span and current_span.is_recording(): - extract_custom_headers(current_span, args[0].headers) + _, parent_span, _ = get_tracer_tuple() + if parent_span: + extract_custom_headers(parent_span, args[0].headers) return wrapped(*args, **kwargs) @wrapt.patch_function_wrapper("botocore.client", "BaseClient._make_api_call") @@ -66,12 +69,11 @@ def make_api_call_with_instana( args: Sequence[Dict[str, Any]], kwargs: Dict[str, Any], ) -> Dict[str, Any]: + tracer, parent_span, _ = get_tracer_tuple() # If we're not tracing, just return - if tracing_is_off(): + if not tracer: return wrapped(*args, **kwargs) - tracer, parent_span, _ = get_tracer_tuple() - parent_context = parent_span.get_span_context() if parent_span else None if instance.meta.service_model.service_name == "dynamodb": @@ -101,7 +103,7 @@ def make_api_call_with_instana( # Inject context when invoking lambdas if "lambda" in instance._endpoint.host and operation == "Invoke": - lambda_inject_context(payload, span) + lambda_inject_context(tracer, payload, span) try: result = wrapped(*args, **kwargs) diff --git a/src/instana/instrumentation/aws/s3.py b/src/instana/instrumentation/aws/s3.py index 78ac17fe..59123ffd 100644 --- a/src/instana/instrumentation/aws/s3.py +++ b/src/instana/instrumentation/aws/s3.py @@ -15,7 +15,6 @@ from instana.singletons import get_tracer from instana.util.traceutils import ( get_tracer_tuple, - tracing_is_off, ) operations = { @@ -48,12 +47,11 @@ def collect_s3_injected_attributes( args: Sequence[object], kwargs: Dict[str, Any], ) -> Callable[..., object]: + tracer, parent_span, _ = get_tracer_tuple() # If we're not tracing, just return - if tracing_is_off(): + if not tracer: return wrapped(*args, **kwargs) - tracer, parent_span, _ = get_tracer_tuple() - parent_context = parent_span.get_span_context() if parent_span else None with tracer.start_as_current_span("s3", span_context=parent_context) as span: diff --git a/src/instana/instrumentation/cassandra.py b/src/instana/instrumentation/cassandra.py index 2ad9d768..8feaca11 100644 --- a/src/instana/instrumentation/cassandra.py +++ b/src/instana/instrumentation/cassandra.py @@ -14,7 +14,7 @@ import wrapt from instana.log import logger - from instana.util.traceutils import get_tracer_tuple, tracing_is_off + from instana.util.traceutils import get_tracer_tuple if TYPE_CHECKING: from cassandra.cluster import ResponseFuture, Session @@ -73,11 +73,11 @@ def request_init_with_instana( fn: "ResponseFuture", ) -> None: tracer, parent_span, _ = get_tracer_tuple() - parent_context = parent_span.get_span_context() if parent_span else None - - if tracing_is_off(): + if not tracer: return + parent_context = parent_span.get_span_context() if parent_span else None + attributes = {} if isinstance(fn.query, cassandra.query.SimpleStatement): attributes["cassandra.query"] = fn.query.query_string diff --git a/src/instana/instrumentation/celery.py b/src/instana/instrumentation/celery.py index 16589175..e709950d 100644 --- a/src/instana/instrumentation/celery.py +++ b/src/instana/instrumentation/celery.py @@ -145,40 +145,42 @@ def before_task_publish( ) -> None: try: tracer, parent_span, _ = get_tracer_tuple() + if not tracer: + return + parent_context = parent_span.get_span_context() if parent_span else None - if tracer: - body = kwargs["body"] - headers = kwargs["headers"] - task_name = kwargs["sender"] - task = registry.tasks.get(task_name) - task_id = _get_task_id(headers, body) - - span = tracer.start_span("celery-client", span_context=parent_context) - span.set_attribute("task", task_name) - span.set_attribute("task_id", task_id) - add_broker_attributes(span, task.app.conf["broker_url"]) - - # Context propagation - context_headers = {} - tracer.inject( - span.context, - Format.HTTP_HEADERS, - context_headers, - disable_w3c_trace_context=True, - ) + body = kwargs["body"] + headers = kwargs["headers"] + task_name = kwargs["sender"] + task = registry.tasks.get(task_name) + task_id = _get_task_id(headers, body) + + span = tracer.start_span("celery-client", span_context=parent_context) + span.set_attribute("task", task_name) + span.set_attribute("task_id", task_id) + add_broker_attributes(span, task.app.conf["broker_url"]) + + # Context propagation + context_headers = {} + tracer.inject( + span.context, + Format.HTTP_HEADERS, + context_headers, + disable_w3c_trace_context=True, + ) + + # Fix for broken header propagation + # https://github.com/celery/celery/issues/4875 + task_headers = kwargs.get("headers") or {} + task_headers.setdefault("headers", {}) + task_headers["headers"].update(context_headers) + kwargs["headers"] = task_headers - # Fix for broken header propagation - # https://github.com/celery/celery/issues/4875 - task_headers = kwargs.get("headers") or {} - task_headers.setdefault("headers", {}) - task_headers["headers"].update(context_headers) - kwargs["headers"] = task_headers - - ctx = trace.set_span_in_context(span) - token = context.attach(ctx) - client_token["token"] = token - client_span.set(span) + ctx = trace.set_span_in_context(span) + token = context.attach(ctx) + client_token["token"] = token + client_span.set(span) except Exception: logger.debug("celery-client before_task_publish: ", exc_info=True) diff --git a/src/instana/instrumentation/couchbase.py b/src/instana/instrumentation/couchbase.py index d9678230..3edd5819 100644 --- a/src/instana/instrumentation/couchbase.py +++ b/src/instana/instrumentation/couchbase.py @@ -25,7 +25,7 @@ import wrapt from instana.span.span import InstanaSpan - from instana.util.traceutils import get_tracer_tuple, tracing_is_off + from instana.util.traceutils import get_tracer_tuple # List of operations to instrument # incr, incr_multi, decr, decr_multi, retrieve_in are wrappers around operations above @@ -94,12 +94,12 @@ def wrapper( kwargs: Dict[str, Any], ) -> object: tracer, parent_span, _ = get_tracer_tuple() - parent_context = parent_span.get_span_context() if parent_span else None - # If we're not tracing, just return - if tracing_is_off(): + if not tracer: return wrapped(*args, **kwargs) + parent_context = parent_span.get_span_context() if parent_span else None + with tracer.start_as_current_span( "couchbase", span_context=parent_context ) as span: @@ -120,12 +120,12 @@ def query_with_instana( kwargs: Dict[str, Any], ) -> object: tracer, parent_span, _ = get_tracer_tuple() - parent_context = parent_span.get_span_context() if parent_span else None - # If we're not tracing, just return - if tracing_is_off(): + if not tracer: return wrapped(*args, **kwargs) + parent_context = parent_span.get_span_context() if parent_span else None + with tracer.start_as_current_span( "couchbase", span_context=parent_context ) as span: diff --git a/src/instana/instrumentation/google/cloud/pubsub.py b/src/instana/instrumentation/google/cloud/pubsub.py index d2275c83..be2af051 100644 --- a/src/instana/instrumentation/google/cloud/pubsub.py +++ b/src/instana/instrumentation/google/cloud/pubsub.py @@ -9,7 +9,7 @@ from instana.log import logger from instana.propagators.format import Format from instana.singletons import get_tracer -from instana.util.traceutils import get_tracer_tuple, tracing_is_off +from instana.util.traceutils import get_tracer_tuple if TYPE_CHECKING: from instana.span.span import InstanaSpan @@ -49,11 +49,11 @@ def publish_with_instana( """References: - PublisherClient.publish(topic_path, messages, metadata) """ + tracer, parent_span, _ = get_tracer_tuple() # return early if we're not tracing - if tracing_is_off(): + if not tracer: return wrapped(*args, **kwargs) - tracer, parent_span, _ = get_tracer_tuple() parent_context = parent_span.get_span_context() if parent_span else None with tracer.start_as_current_span( diff --git a/src/instana/instrumentation/google/cloud/storage.py b/src/instana/instrumentation/google/cloud/storage.py index a1ccb6d9..8e921146 100644 --- a/src/instana/instrumentation/google/cloud/storage.py +++ b/src/instana/instrumentation/google/cloud/storage.py @@ -8,7 +8,7 @@ from typing import Any, Callable, Dict, Tuple, Union from instana.log import logger from instana.instrumentation.google.cloud.collectors import _storage_api -from instana.util.traceutils import get_tracer_tuple, tracing_is_off +from instana.util.traceutils import get_tracer_tuple try: from google.cloud import storage @@ -60,12 +60,13 @@ def execute_with_instana( args: Tuple[object, ...], kwargs: Dict[str, Any], ) -> object: + tracer, parent_span, _ = get_tracer_tuple() + # batch requests are traced with finish_batch_with_instana() # also return early if we're not tracing - if isinstance(instance, storage.Batch) or tracing_is_off(): + if isinstance(instance, storage.Batch) or not tracer: return wrapped(*args, **kwargs) - tracer, parent_span, _ = get_tracer_tuple() parent_context = parent_span.get_span_context() if parent_span else None with tracer.start_as_current_span("gcs", span_context=parent_context) as span: @@ -91,11 +92,11 @@ def download_with_instana( args: Tuple[object, ...], kwargs: Dict[str, Any], ) -> object: + tracer, parent_span, _ = get_tracer_tuple() # return early if we're not tracing - if tracing_is_off(): + if not tracer: return wrapped(*args, **kwargs) - tracer, parent_span, _ = get_tracer_tuple() parent_context = parent_span.get_span_context() if parent_span else None with tracer.start_as_current_span("gcs", span_context=parent_context) as span: @@ -127,11 +128,11 @@ def upload_with_instana( args: Tuple[object, ...], kwargs: Dict[str, Any], ) -> object: + tracer, parent_span, _ = get_tracer_tuple() # return early if we're not tracing - if tracing_is_off(): + if not tracer: return wrapped(*args, **kwargs) - tracer, parent_span, _ = get_tracer_tuple() parent_context = parent_span.get_span_context() if parent_span else None with tracer.start_as_current_span("gcs", span_context=parent_context) as span: @@ -152,11 +153,11 @@ def finish_batch_with_instana( args: Tuple[object, ...], kwargs: Dict[str, Any], ) -> object: + tracer, parent_span, _ = get_tracer_tuple() # return early if we're not tracing - if tracing_is_off(): + if not tracer: return wrapped(*args, **kwargs) - tracer, parent_span, _ = get_tracer_tuple() parent_context = parent_span.get_span_context() if parent_span else None with tracer.start_as_current_span("gcs", span_context=parent_context) as span: diff --git a/src/instana/instrumentation/httpx.py b/src/instana/instrumentation/httpx.py index 3c25b814..854ac376 100644 --- a/src/instana/instrumentation/httpx.py +++ b/src/instana/instrumentation/httpx.py @@ -14,7 +14,6 @@ from instana.util.traceutils import ( extract_custom_headers, get_tracer_tuple, - tracing_is_off, ) if TYPE_CHECKING: @@ -72,11 +71,11 @@ def handle_request_with_instana( args: Tuple[int, str, Tuple[Any, ...]], kwargs: Dict[str, Any], ) -> httpx.Response: + tracer, parent_span, _ = get_tracer_tuple() # If we're not tracing, just return - if tracing_is_off(): + if not tracer: return wrapped(*args, **kwargs) - tracer, parent_span, _ = get_tracer_tuple() parent_context = parent_span.get_span_context() if parent_span else None with tracer.start_as_current_span( @@ -101,11 +100,11 @@ async def handle_async_request_with_instana( args: Tuple[int, str, Tuple[Any, ...]], kwargs: Dict[str, Any], ) -> httpx.Response: + tracer, parent_span, _ = get_tracer_tuple() # If we're not tracing, just return - if tracing_is_off(): + if not tracer: return await wrapped(*args, **kwargs) - tracer, parent_span, _ = get_tracer_tuple() parent_context = parent_span.get_span_context() if parent_span else None with tracer.start_as_current_span( diff --git a/src/instana/instrumentation/kafka/confluent_kafka_python.py b/src/instana/instrumentation/kafka/confluent_kafka_python.py index f2f327f1..e37d0bb6 100644 --- a/src/instana/instrumentation/kafka/confluent_kafka_python.py +++ b/src/instana/instrumentation/kafka/confluent_kafka_python.py @@ -15,7 +15,7 @@ from instana.propagators.format import Format from instana.singletons import get_tracer from instana.span.span import InstanaSpan - from instana.util.traceutils import get_tracer_tuple, tracing_is_off + from instana.util.traceutils import get_tracer_tuple consumer_token = None consumer_span = contextvars.ContextVar("confluent_kafka_consumer_span") @@ -61,10 +61,10 @@ def trace_kafka_produce( args: Tuple[int, str, Tuple[Any, ...]], kwargs: Dict[str, Any], ) -> None: - if tracing_is_off(): + tracer, parent_span, _ = get_tracer_tuple() + if not tracer: return wrapped(*args, **kwargs) - tracer, parent_span, _ = get_tracer_tuple() parent_context = parent_span.get_span_context() if parent_span else None # Get the topic from either args or kwargs diff --git a/src/instana/instrumentation/kafka/kafka_python.py b/src/instana/instrumentation/kafka/kafka_python.py index 307b7d52..25b05e13 100644 --- a/src/instana/instrumentation/kafka/kafka_python.py +++ b/src/instana/instrumentation/kafka/kafka_python.py @@ -15,7 +15,7 @@ from instana.propagators.format import Format from instana.singletons import get_tracer from instana.span.span import InstanaSpan - from instana.util.traceutils import get_tracer_tuple, tracing_is_off + from instana.util.traceutils import get_tracer_tuple if TYPE_CHECKING: from kafka.producer.future import FutureRecordMetadata @@ -30,10 +30,11 @@ def trace_kafka_send( args: Tuple[int, str, Tuple[Any, ...]], kwargs: Dict[str, Any], ) -> "FutureRecordMetadata": - if tracing_is_off(): + tracer, parent_span, _ = get_tracer_tuple() + + if not tracer: return wrapped(*args, **kwargs) - tracer, parent_span, _ = get_tracer_tuple() parent_context = parent_span.get_span_context() if parent_span else None # Get the topic from either args or kwargs diff --git a/src/instana/instrumentation/logging.py b/src/instana/instrumentation/logging.py index fdbaaa58..204de0a6 100644 --- a/src/instana/instrumentation/logging.py +++ b/src/instana/instrumentation/logging.py @@ -12,7 +12,7 @@ from instana.log import logger from instana.singletons import agent from instana.util.runtime import get_runtime_env_info -from instana.util.traceutils import get_tracer_tuple, tracing_is_off +from instana.util.traceutils import get_tracer_tuple @wrapt.patch_function_wrapper("logging", "Logger._log") @@ -34,16 +34,15 @@ def log_with_instana( stacklevel = stacklevel_in + 1 try: + tracer, parent_span, _ = get_tracer_tuple() # Only needed if we're tracing and serious log and logging spans are not disabled if ( - tracing_is_off() + not tracer or argv[0] < logging.WARN or agent.options.is_span_disabled(category="logging") ): return wrapped(*argv, **kwargs, stacklevel=stacklevel) - tracer, parent_span, _ = get_tracer_tuple() - msg = str(argv[1]) args = argv[2] if args and len(args) == 1 and isinstance(args[0], Mapping) and args[0]: diff --git a/src/instana/instrumentation/pep0249.py b/src/instana/instrumentation/pep0249.py index 1108433b..3923ef9e 100644 --- a/src/instana/instrumentation/pep0249.py +++ b/src/instana/instrumentation/pep0249.py @@ -7,10 +7,9 @@ from typing_extensions import Self from opentelemetry.semconv.trace import SpanAttributes -from opentelemetry.trace import SpanKind from instana.log import logger -from instana.util.traceutils import get_tracer_tuple, tracing_is_off +from instana.util.traceutils import get_tracer_tuple from instana.util.sql import sql_sanitizer if TYPE_CHECKING: @@ -70,7 +69,7 @@ def execute( tracer, parent_span, operation_name = get_tracer_tuple() # If not tracing or we're being called from sqlalchemy, just pass through - if tracing_is_off() or (operation_name == "sqlalchemy"): + if not tracer or (operation_name == "sqlalchemy"): return self.__wrapped__.execute(sql, params) parent_context = parent_span.get_span_context() if parent_span else None @@ -95,7 +94,7 @@ def executemany( tracer, parent_span, operation_name = get_tracer_tuple() # If not tracing or we're being called from sqlalchemy, just pass through - if tracing_is_off() or (operation_name == "sqlalchemy"): + if not tracer or (operation_name == "sqlalchemy"): return self.__wrapped__.executemany(sql, seq_of_parameters) parent_context = parent_span.get_span_context() if parent_span else None @@ -120,7 +119,7 @@ def callproc( tracer, parent_span, operation_name = get_tracer_tuple() # If not tracing or we're being called from sqlalchemy, just pass through - if tracing_is_off() or (operation_name == "sqlalchemy"): + if not tracer or (operation_name == "sqlalchemy"): return self.__wrapped__.execute(proc_name, params) parent_context = parent_span.get_span_context() if parent_span else None diff --git a/src/instana/instrumentation/pika.py b/src/instana/instrumentation/pika.py index 5fe0736f..0deb96b8 100644 --- a/src/instana/instrumentation/pika.py +++ b/src/instana/instrumentation/pika.py @@ -22,7 +22,7 @@ from instana.log import logger from instana.propagators.format import Format from instana.singletons import get_tracer - from instana.util.traceutils import get_tracer_tuple, tracing_is_off + from instana.util.traceutils import get_tracer_tuple if TYPE_CHECKING: import pika.adapters.blocking_connection @@ -73,11 +73,12 @@ def _bind_args( ) -> Tuple[object, ...]: return (exchange, routing_key, body, properties, args, kwargs) + tracer, parent_span, _ = get_tracer_tuple() + # If we're not tracing, just return - if tracing_is_off(): + if not tracer: return wrapped(*args, **kwargs) - tracer, parent_span, _ = get_tracer_tuple() parent_context = parent_span.get_span_context() if parent_span else None (exchange, routing_key, body, properties, args, kwargs) = _bind_args( @@ -125,6 +126,11 @@ def basic_get_with_instana( args: Tuple[object, ...], kwargs: Dict[str, Any], ) -> object: + tracer = get_tracer() + + if not tracer: + return wrapped(*args, **kwargs) + def _bind_args(*args: object, **kwargs: object) -> Tuple[object, ...]: args = list(args) queue = kwargs.pop("queue", None) or args.pop(0) @@ -175,6 +181,11 @@ def basic_consume_with_instana( args: Tuple[object, ...], kwargs: Dict[str, Any], ) -> object: + tracer = get_tracer() + + if not tracer: + return wrapped(*args, **kwargs) + def _bind_args( queue: str, on_message_callback: object, @@ -225,6 +236,11 @@ def consume_with_instana( args: Tuple[object, ...], kwargs: Dict[str, Any], ) -> object: + tracer = get_tracer() + + if not tracer: + return wrapped(*args, **kwargs) + def _bind_args( queue: str, *args: object, **kwargs: object ) -> Tuple[object, ...]: diff --git a/src/instana/instrumentation/pymongo.py b/src/instana/instrumentation/pymongo.py index 2c0bc203..23cbf4f7 100644 --- a/src/instana/instrumentation/pymongo.py +++ b/src/instana/instrumentation/pymongo.py @@ -4,7 +4,7 @@ from instana.span.span import InstanaSpan from instana.log import logger -from instana.util.traceutils import get_tracer_tuple, tracing_is_off +from instana.util.traceutils import get_tracer_tuple try: import pymongo @@ -18,7 +18,7 @@ def __init__(self) -> None: def started(self, event: pymongo.monitoring.CommandStartedEvent) -> None: tracer, parent_span, _ = get_tracer_tuple() # return early if we're not tracing - if tracing_is_off(): + if not tracer: return parent_context = parent_span.get_span_context() if parent_span else None diff --git a/src/instana/instrumentation/redis.py b/src/instana/instrumentation/redis.py index 621bca26..b4962581 100644 --- a/src/instana/instrumentation/redis.py +++ b/src/instana/instrumentation/redis.py @@ -2,15 +2,15 @@ # (c) Copyright Instana Inc. 2018 -from typing import Any, Callable, Dict, Tuple -import wrapt - -from instana.log import logger -from instana.span.span import InstanaSpan -from instana.util.traceutils import get_tracer_tuple, tracing_is_off - try: + from typing import Any, Callable, Dict, Tuple + import redis + import wrapt + + from instana.log import logger + from instana.span.span import InstanaSpan + from instana.util.traceutils import get_tracer_tuple EXCLUDED_PARENT_SPANS = ["redis", "celery-client", "celery-worker"] @@ -44,12 +44,13 @@ def execute_command_with_instana( kwargs: Dict[str, Any], ) -> object: tracer, parent_span, operation_name = get_tracer_tuple() - parent_context = parent_span.get_span_context() if parent_span else None # If we're not tracing, just return - if tracing_is_off() or (operation_name in EXCLUDED_PARENT_SPANS): + if not tracer or (operation_name in EXCLUDED_PARENT_SPANS): return wrapped(*args, **kwargs) + parent_context = parent_span.get_span_context() if parent_span else None + with tracer.start_as_current_span("redis", span_context=parent_context) as span: try: collect_attributes(span, instance, args, kwargs) @@ -70,12 +71,13 @@ def execute_with_instana( kwargs: Dict[str, Any], ) -> object: tracer, parent_span, operation_name = get_tracer_tuple() - parent_context = parent_span.get_span_context() if parent_span else None # If we're not tracing, just return - if tracing_is_off() or (operation_name in EXCLUDED_PARENT_SPANS): + if not tracer or (operation_name in EXCLUDED_PARENT_SPANS): return wrapped(*args, **kwargs) + parent_context = parent_span.get_span_context() if parent_span else None + with tracer.start_as_current_span("redis", span_context=parent_context) as span: try: collect_attributes(span, instance, args, kwargs) diff --git a/src/instana/instrumentation/sqlalchemy.py b/src/instana/instrumentation/sqlalchemy.py index 3f44b526..8ccda7ef 100644 --- a/src/instana/instrumentation/sqlalchemy.py +++ b/src/instana/instrumentation/sqlalchemy.py @@ -10,7 +10,7 @@ from instana.log import logger from instana.span.span import InstanaSpan, get_current_span from instana.span_context import SpanContext -from instana.util.traceutils import get_tracer_tuple, tracing_is_off +from instana.util.traceutils import get_tracer_tuple try: from sqlalchemy import __version__ as sqlalchemy_version @@ -24,11 +24,12 @@ def receive_before_cursor_execute( **kw: Dict[str, Any], ) -> None: try: + tracer, parent_span, _ = get_tracer_tuple() + # If we're not tracing, just return - if tracing_is_off(): + if not tracer: return - tracer, parent_span, _ = get_tracer_tuple() parent_context = parent_span.get_span_context() if parent_span else None span = tracer.start_span("sqlalchemy", span_context=parent_context) @@ -54,8 +55,9 @@ def receive_after_cursor_execute( **kw: Dict[str, Any], ) -> None: try: + tracer = get_tracer_tuple() # If we're not tracing, just return - if tracing_is_off(): + if not tracer: return current_span = get_current_span() @@ -96,10 +98,10 @@ def receive_handle_db_error( **kw: Dict[str, Any], ) -> None: try: - if tracing_is_off(): - return + tracer, parent_span, _ = get_tracer_tuple() - current_span = get_current_span() + if not tracer: + return # support older db error event if error_event == "dbapi_error": @@ -110,7 +112,7 @@ def receive_handle_db_error( exception_string = "sqlalchemy_exception" if context: - _set_error_attributes(context, exception_string, current_span) + _set_error_attributes(context, exception_string, parent_span) except Exception: logger.debug( "Instrumenting sqlalchemy @ receive_handle_db_error", diff --git a/src/instana/instrumentation/urllib3.py b/src/instana/instrumentation/urllib3.py index 52d3e9c8..b102714f 100644 --- a/src/instana/instrumentation/urllib3.py +++ b/src/instana/instrumentation/urllib3.py @@ -13,7 +13,6 @@ from instana.util.secrets import strip_secrets_from_query from instana.util.traceutils import ( get_tracer_tuple, - tracing_is_off, extract_custom_headers, ) @@ -107,7 +106,7 @@ def urlopen_with_instana( host = getattr(instance, "host", "") or "" if ( - tracing_is_off() + not tracer or span_name == "boto3" or "com.instana" in request_url_or_path or "com.instana" in host diff --git a/src/instana/util/traceutils.py b/src/instana/util/traceutils.py index 6ea17bff..cb75b301 100644 --- a/src/instana/util/traceutils.py +++ b/src/instana/util/traceutils.py @@ -16,9 +16,9 @@ from instana.log import logger from instana.singletons import agent, get_tracer from instana.span.span import get_current_span +from instana.span.span import InstanaSpan if TYPE_CHECKING: - from instana.span.span import InstanaSpan from instana.tracer import InstanaTracer @@ -62,22 +62,6 @@ def extract_custom_headers( logger.debug("extract_custom_headers: ", exc_info=True) -def get_active_tracer() -> Optional["InstanaTracer"]: - """Get the currently active tracer if one exists.""" - try: - current_span = get_current_span() - if current_span: - # asyncio Spans are used as NonRecording Spans solely for context propagation - if current_span.is_recording() or current_span.name == "asyncio": - return get_tracer() - return None - return None - except Exception: - # Do not try to log this with instana, as there is no active tracer and there will be an infinite loop at least - # for PY2 - return None - - def get_tracer_tuple() -> ( Tuple[ Optional["InstanaTracer"], @@ -86,15 +70,17 @@ def get_tracer_tuple() -> ( ] ): """Get a tuple of (tracer, span, span_name) for the current context.""" - active_tracer = get_active_tracer() - current_span = get_current_span() - if active_tracer: - return (active_tracer, current_span, current_span.name) - elif agent.options.allow_exit_as_root: - return (get_tracer(), None, None) - return (None, None, None) - - -def tracing_is_off() -> bool: - """Check if tracing is currently disabled.""" - return not (bool(get_active_tracer()) or agent.options.allow_exit_as_root) + try: + active_tracer = get_tracer() + current_span = get_current_span() + # asyncio Spans are used as NonRecording Spans solely for context propagation + if current_span and isinstance(current_span, InstanaSpan): + if current_span.is_recording() or current_span.name == "asyncio": + return (active_tracer, current_span, current_span.name) + elif agent.options.allow_exit_as_root: + return (active_tracer, None, None) + return (None, None, None) + except Exception: + # Do not try to log this with instana, as there is no active tracer and there will be an infinite loop at least + # for PY2 + return (None, None, None) diff --git a/tests/clients/test_google-cloud-storage.py b/tests/clients/test_google-cloud-storage.py index 23af7dc7..ea2f3009 100644 --- a/tests/clients/test_google-cloud-storage.py +++ b/tests/clients/test_google-cloud-storage.py @@ -1073,13 +1073,13 @@ def test_execute_with_instana_without_tags(self, mock_requests: Mock) -> None: pass assert isinstance(buckets, page_iterator.HTTPIterator) - def test_execute_with_instana_tracing_is_off(self) -> None: + def test_execute_with_instana_is_tracing_off(self) -> None: client = self._client( credentials=AnonymousCredentials(), project="test-project" ) with self.tracer.start_as_current_span("test"), patch( - "instana.instrumentation.google.cloud.storage.tracing_is_off", - return_value=True, + "instana.instrumentation.google.cloud.storage.get_tracer_tuple", + return_value=(None, None, None), ): response = client.list_buckets() assert isinstance(response.client, storage.Client) @@ -1089,7 +1089,7 @@ def test_execute_with_instana_tracing_is_off(self) -> None: reason='Avoiding "Fatal Python error: Segmentation fault"', ) @patch("requests.Session.request") - def test_download_with_instana_tracing_is_off(self, mock_requests: Mock) -> None: + def test_download_with_instana_is_tracing_off(self, mock_requests: Mock) -> None: mock_requests.return_value = self._mock_response( content=b"CONTENT", status_code=http_client.OK ) @@ -1097,8 +1097,8 @@ def test_download_with_instana_tracing_is_off(self, mock_requests: Mock) -> None credentials=AnonymousCredentials(), project="test-project" ) with self.tracer.start_as_current_span("test"), patch( - "instana.instrumentation.google.cloud.storage.tracing_is_off", - return_value=True, + "instana.instrumentation.google.cloud.storage.get_tracer_tuple", + return_value=(None, None, None), ): response = ( client.bucket("test bucket") @@ -1111,7 +1111,7 @@ def test_download_with_instana_tracing_is_off(self, mock_requests: Mock) -> None assert not response @patch("requests.Session.request") - def test_upload_with_instana_tracing_is_off(self, mock_requests: Mock) -> None: + def test_upload_with_instana_is_tracing_off(self, mock_requests: Mock) -> None: mock_requests.return_value = self._mock_response( json_content={"kind": "storage#object"}, status_code=http_client.OK ) @@ -1121,8 +1121,8 @@ def test_upload_with_instana_tracing_is_off(self, mock_requests: Mock) -> None: ) with self.tracer.start_as_current_span("test"), patch( - "instana.instrumentation.google.cloud.storage.tracing_is_off", - return_value=True, + "instana.instrumentation.google.cloud.storage.get_tracer_tuple", + return_value=(None, None, None), ): response = ( client.bucket("test bucket") @@ -1132,7 +1132,7 @@ def test_upload_with_instana_tracing_is_off(self, mock_requests: Mock) -> None: assert not response @patch("requests.Session.request") - def test_finish_batch_operation_tracing_is_off(self, mock_requests: Mock) -> None: + def test_finish_batch_operation_is_tracing_off(self, mock_requests: Mock) -> None: mock_requests.return_value = self._mock_response( _TWO_PART_BATCH_RESPONSE, status_code=http_client.OK, @@ -1145,8 +1145,8 @@ def test_finish_batch_operation_tracing_is_off(self, mock_requests: Mock) -> Non bucket = client.bucket("test-bucket") with self.tracer.start_as_current_span("test"), patch( - "instana.instrumentation.google.cloud.storage.tracing_is_off", - return_value=True, + "instana.instrumentation.google.cloud.storage.get_tracer_tuple", + return_value=(None, None, None), ): with client.batch() as batch_response: for obj in ["obj1", "obj2"]: diff --git a/tests/clients/test_pika.py b/tests/clients/test_pika.py index 7abb2991..affd9284 100644 --- a/tests/clients/test_pika.py +++ b/tests/clients/test_pika.py @@ -467,8 +467,8 @@ def test_basic_publish_with_headers(self, send_method, _unused) -> None: @mock.patch("pika.channel.Channel._send_method") def test_basic_publish_tracing_off(self, send_method, _unused, mocker) -> None: mocker.patch( - "instana.instrumentation.pika.tracing_is_off", - return_value=True, + "instana.instrumentation.pika.get_tracer_tuple", + return_value=(None, None, None), ) self.obj._set_state(self.obj.OPEN) diff --git a/tests/frameworks/test_aiohttp_client.py b/tests/frameworks/test_aiohttp_client.py index 39659dcb..349772fb 100644 --- a/tests/frameworks/test_aiohttp_client.py +++ b/tests/frameworks/test_aiohttp_client.py @@ -476,8 +476,8 @@ async def test(): def test_client_get_tracing_off(self, mocker) -> None: mocker.patch( - "instana.instrumentation.aiohttp.client.tracing_is_off", - return_value=True, + "instana.instrumentation.aiohttp.client.get_tracer_tuple", + return_value=(None, None, None), ) async def test(): diff --git a/tests/frameworks/test_sanic.py b/tests/frameworks/test_sanic.py index c938937c..5fe57436 100644 --- a/tests/frameworks/test_sanic.py +++ b/tests/frameworks/test_sanic.py @@ -37,7 +37,6 @@ def _resource(self) -> Generator[None, None, None]: """Setup and Teardown""" # setup # Clear all spans before a test run - self.tracer = get_tracer() self.recorder = self.tracer.span_processor self.recorder.clear_spans() diff --git a/tests/util/test_traceutils.py b/tests/util/test_traceutils.py index 462ed1b8..2e666a8a 100644 --- a/tests/util/test_traceutils.py +++ b/tests/util/test_traceutils.py @@ -5,12 +5,9 @@ import pytest from instana.singletons import agent, get_tracer -from instana.tracer import InstanaTracer from instana.util.traceutils import ( extract_custom_headers, - get_active_tracer, get_tracer_tuple, - tracing_is_off, ) @@ -66,21 +63,7 @@ def test_extract_custom_headers(self, span, custom_headers, format) -> None: assert span.attributes["http.header.X-Capture-This-Too"] == "this too" assert span.attributes["http.header.X-Capture-That-Too"] == "that too" - def test_get_activate_tracer(self, mocker) -> None: - assert not get_active_tracer() - - with self.tracer.start_as_current_span("test"): - response = get_active_tracer() - assert isinstance(response, InstanaTracer) - assert response == self.tracer - with mocker.patch( - "instana.span.span.InstanaSpan.is_recording", return_value=False - ): - assert not get_active_tracer() - - def test_get_tracer_tuple( - self, - ) -> None: + def test_get_tracer_tuple(self) -> None: response = get_tracer_tuple() assert response == (None, None, None) @@ -92,15 +75,3 @@ def test_get_tracer_tuple( with self.tracer.start_as_current_span("test") as span: response = get_tracer_tuple() assert response == (self.tracer, span, span.name) - - def test_tracing_is_off(self) -> None: - response = tracing_is_off() - assert response - with self.tracer.start_as_current_span("test"): - response = tracing_is_off() - assert not response - - agent.options.allow_exit_as_root = True - response = tracing_is_off() - assert not response - agent.options.allow_exit_as_root = False