def test_get_env(self): # ensure `get_env` returns a default value if environment variables # are not set value = get_env('django', 'distributed_tracing') ok_(value is None) value = get_env('django', 'distributed_tracing', False) ok_(value is False)
def test_get_env(self): # ensure `get_env` returns a default value if environment variables # are not set value = get_env("django", "distributed_tracing") self.assertIsNone(value) value = get_env("django", "distributed_tracing", default=False) self.assertFalse(value)
def get_stats_url(): # type: () -> str return get_env("dogstatsd", "url", default="udp://{}:{}".format( get_hostname(), get_stats_port())) # type: ignore[return-value]
def get_trace_agent_timeout(): # type: () -> float return float( get_env("trace", "agent", "timeout", "seconds", default=DEFAULT_TIMEOUT)) # type: ignore[arg-type]
def test_get_env_found_legacy(self): # ensure `get_env` returns a value if legacy environment variables # are used, raising a Deprecation warning with warnings.catch_warnings(record=True) as w: warnings.simplefilter('always') os.environ['DATADOG_REQUESTS_DISTRIBUTED_TRACING'] = '1' value = get_env('requests', 'distributed_tracing') eq_(value, '1') ok_(len(w) == 1) ok_(issubclass(w[-1].category, DeprecationWarning)) ok_('Use `DD_` prefix instead' in str(w[-1].message))
def test_get_env_found_legacy(self): # ensure `get_env` returns a value if legacy environment variables # are used, raising a Deprecation warning with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") os.environ["DATADOG_REQUESTS_DISTRIBUTED_TRACING"] = "1" value = get_env("requests", "distributed_tracing") self.assertEqual(value, "1") self.assertEqual(len(w), 1) self.assertTrue(issubclass(w[-1].category, DeprecationWarning)) self.assertTrue("Use `DD_` prefix instead" in str(w[-1].message))
def get_stats_url(): # type: () -> str user_supplied_host = get_stats_hostname(None) is not None user_supplied_port = get_stats_port(None) is not None url = get_env("dogstatsd", "url", default=None) if not url: if user_supplied_host or user_supplied_port: url = "udp://{}:{}".format(get_stats_hostname(), get_stats_port()) elif os.path.exists("/var/run/datadog/dsd.socket"): url = "unix://%s" % (DEFAULT_UNIX_DSD_PATH) else: url = "udp://{}:{}".format(get_stats_hostname(), get_stats_port()) return url
def test_get_env_key_priority(self): # ensure `get_env` use `DD_` with highest priority os.environ['DD_REQUESTS_DISTRIBUTED_TRACING'] = 'highest' os.environ['DATADOG_REQUESTS_DISTRIBUTED_TRACING'] = 'lowest' value = get_env('requests', 'distributed_tracing') self.assertEqual(value, 'highest')
def test_get_env_long(self): os.environ['DD_SOME_VERY_LONG_TEST_KEY'] = '1' value = get_env('some', 'very', 'long', 'test', 'key', default='2') assert value == '1'
def test_get_env_found(self): # ensure `get_env` returns a value if the environment variable is set os.environ['DD_REQUESTS_DISTRIBUTED_TRACING'] = '1' value = get_env('requests', 'distributed_tracing') self.assertEqual(value, '1')
from ddtrace import Pin from ddtrace import config from ddtrace.contrib.dbapi import TracedConnection from ddtrace.ext import db from ddtrace.ext import net from ddtrace.utils.formats import asbool from ddtrace.utils.formats import get_env from ddtrace.utils.wrappers import unwrap from ddtrace.vendor import wrapt config._add( "mariadb", dict( trace_fetch_methods=asbool( get_env("mariadb", "trace_fetch_methods", default=False)), _default_service="mariadb", ), ) def patch(): if getattr(mariadb, "_datadog_patch", False): return setattr(mariadb, "_datadog_patch", True) wrapt.wrap_function_wrapper("mariadb", "connect", _connect) def unpatch(): if getattr(mariadb, "_datadog_patch", False): setattr(mariadb, "_datadog_patch", False)
from ddtrace.internal.logger import get_logger from ddtrace.propagation.http import HTTPPropagator from ddtrace.utils.formats import asbool, get_env from ddtrace.utils.wrappers import unwrap, iswrapped from .compat import get_resolver, user_is_authenticated from . import utils, conf wrap = wrapt.wrap_function_wrapper log = get_logger(__name__) config._add( "django", dict( service_name=config._get_service(default="django"), cache_service_name=get_env("django", "cache_service_name") or "django", database_service_name_prefix=get_env("django", "database_service_name_prefix", default=""), distributed_tracing_enabled=True, instrument_middleware=asbool( get_env("django", "instrument_middleware", default=True)), instrument_databases=True, instrument_caches=True, analytics_enabled= None, # None allows the value to be overridden by the global config analytics_sample_rate=None, trace_query_string=None, # Default to global config include_user_name=True, ), )
def test_get_env_found(self): # ensure `get_env` returns a value if the environment variable is set os.environ["DD_REQUESTS_DISTRIBUTED_TRACING"] = "1" value = get_env("requests", "distributed_tracing") self.assertEqual(value, "1")
try: from ddtrace import tracer # Respect DATADOG_* environment variables in global tracer configuration # TODO: these variables are deprecated; use utils method and update our documentation # correct prefix should be DD_* hostname = os.environ.get("DD_AGENT_HOST", os.environ.get("DATADOG_TRACE_AGENT_HOSTNAME")) port = os.environ.get("DATADOG_TRACE_AGENT_PORT") priority_sampling = os.environ.get("DATADOG_PRIORITY_SAMPLING") profiling = asbool(os.environ.get("DD_PROFILING_ENABLED", False)) if profiling: import ddtrace.profiling.auto # noqa: F401 if asbool(get_env("runtime_metrics", "enabled")): RuntimeWorker.enable() opts = {} if asbool(os.environ.get("DATADOG_TRACE_ENABLED", True)): patch = True else: patch = False opts["enabled"] = False if hostname: opts["hostname"] = hostname if port: opts["port"] = int(port) if priority_sampling:
import logging import wrapt from ddtrace import Pin from ddtrace.ext import AppTypes, sql from ddtrace.settings import config from ddtrace.utils.formats import asbool, get_env log = logging.getLogger(__name__) config._add( 'dbapi2', dict(trace_fetch_methods=asbool( get_env('dbapi2', 'trace_fetch_methods', 'false')), )) class TracedCursor(wrapt.ObjectProxy): """ TracedCursor wraps a psql cursor and traces it's queries. """ def __init__(self, cursor, pin): super(TracedCursor, self).__init__(cursor) pin.onto(self) name = pin.app or 'sql' self._self_datadog_name = '{}.query'.format(name) self._self_last_execute_operation = None def _trace_method(self, method, name, resource, extra_tags, *args, **kwargs): """ Internal function to trace the call to the underlying cursor method
from ddtrace.vendor import wrapt from . import conf from . import utils from .. import trace_utils from .compat import get_resolver from .compat import user_is_authenticated log = get_logger(__name__) config._add( "django", dict( _default_service="django", cache_service_name=get_env("django", "cache_service_name") or "django", database_service_name_prefix=get_env("django", "database_service_name_prefix", default=""), database_service_name=get_env("django", "database_service_name", default=""), trace_fetch_methods=asbool(get_env("django", "trace_fetch_methods", default=False)), distributed_tracing_enabled=True, instrument_middleware=asbool(get_env("django", "instrument_middleware", default=True)), instrument_databases=True, instrument_caches=True, analytics_enabled=None, # None allows the value to be overridden by the global config analytics_sample_rate=None, trace_query_string=None, # Default to global config include_user_name=True, use_handler_resource_format=asbool(get_env("django", "use_handler_resource_format", default=False)), use_legacy_resource_format=asbool(get_env("django", "use_legacy_resource_format", default=False)), ), )
def test_get_env_key_priority(self): # ensure `get_env` use `DD_` with highest priority os.environ["DD_REQUESTS_DISTRIBUTED_TRACING"] = "highest" os.environ["DATADOG_REQUESTS_DISTRIBUTED_TRACING"] = "lowest" value = get_env("requests", "distributed_tracing") self.assertEqual(value, "highest")
from ddtrace.internal.logger import get_logger from ddtrace.propagation.http import HTTPPropagator from ddtrace.propagation.utils import from_wsgi_header from ddtrace.utils.formats import asbool, get_env from .. import trace_utils from .compat import get_resolver, user_is_authenticated from . import utils, conf log = get_logger(__name__) config._add( "django", dict( _default_service="django", cache_service_name=get_env("django", "cache_service_name") or "django", database_service_name_prefix=get_env("django", "database_service_name_prefix", default=""), database_service_name=get_env("django", "database_service_name", default=""), distributed_tracing_enabled=True, instrument_middleware=asbool( get_env("django", "instrument_middleware", default=True)), instrument_databases=True, instrument_caches=True, analytics_enabled= None, # None allows the value to be overridden by the global config analytics_sample_rate=None, trace_query_string=None, # Default to global config
""" Bootstrapping code that is run when using the `ddtrace-run` Python entrypoint Add all monkey-patching that needs to run by default here """ import os import imp import sys import logging from ddtrace.utils.formats import asbool, get_env logs_injection = asbool(get_env('logs', 'injection')) DD_LOG_FORMAT = '%(asctime)s %(levelname)s [%(name)s] [%(filename)s:%(lineno)d] {}- %(message)s'.format( '[dd.trace_id=%(dd.trace_id)s dd.span_id=%(dd.span_id)s] ' if logs_injection else '') debug = os.environ.get("DATADOG_TRACE_DEBUG") # Set here a default logging format for basicConfig # DEV: Once basicConfig is called here, future calls to it cannot be used to # change the formatter since it applies the formatter to the root handler only # upon initializing it the first time. # See https://github.com/python/cpython/blob/112e4afd582515fcdcc0cde5012a4866e5cfda12/Lib/logging/__init__.py#L1550 if debug and debug.lower() == "true": logging.basicConfig(level=logging.DEBUG, format=DD_LOG_FORMAT) else: logging.basicConfig(format=DD_LOG_FORMAT) log = logging.getLogger(__name__)
def get_stats_port(default=DEFAULT_STATS_PORT): # type: (Union[T, int]) -> Union[T,int] v = get_env("dogstatsd", "port", default=None) if v is not None: return int(v) return default
def test_get_env_key_priority(self): # ensure `get_env` use `DD_` with highest priority os.environ['DD_REQUESTS_DISTRIBUTED_TRACING'] = 'highest' os.environ['DATADOG_REQUESTS_DISTRIBUTED_TRACING'] = 'lowest' value = get_env('requests', 'distributed_tracing') eq_(value, 'highest')
from ddtrace.propagation.http import HTTPPropagator from ddtrace.utils import get_argument_value from ddtrace.utils.formats import asbool from ddtrace.utils.formats import get_env from ddtrace.utils.wrappers import unwrap as _u from ddtrace.vendor.wrapt import wrap_function_wrapper as _w if typing.TYPE_CHECKING: from ddtrace import Span from ddtrace.vendor.wrapt import BoundFunctionWrapper config._add( "httpx", { "distributed_tracing": asbool(get_env("httpx", "distributed_tracing", default=True)), "split_by_domain": asbool(get_env("httpx", "split_by_domain", default=False)), }, ) def _url_to_str(url): # type: (httpx.URL) -> str """ Helper to convert the httpx.URL parts from bytes to a str """ scheme, host, port, raw_path = url.raw url = scheme + b"://" + host if port is not None: url += b":" + ensure_binary(str(port)) url += raw_path
""" Bootstrapping code that is run when using the `ddtrace-run` Python entrypoint Add all monkey-patching that needs to run by default here """ import os import imp import sys import logging from ddtrace.utils.formats import asbool, get_env from ddtrace.internal.logger import get_logger from ddtrace import constants logs_injection = asbool(get_env("logs", "injection")) DD_LOG_FORMAT = "%(asctime)s %(levelname)s [%(name)s] [%(filename)s:%(lineno)d] {}- %(message)s".format( "[dd.trace_id=%(dd.trace_id)s dd.span_id=%(dd.span_id)s] " if logs_injection else "") if logs_injection: # immediately patch logging if trace id injected from ddtrace import patch patch(logging=True) debug = os.environ.get("DATADOG_TRACE_DEBUG") # Set here a default logging format for basicConfig # DEV: Once basicConfig is called here, future calls to it cannot be used to # change the formatter since it applies the formatter to the root handler only
def test_get_env_long(self): os.environ["DD_SOME_VERY_LONG_TEST_KEY"] = "1" value = get_env("some", "very", "long", "test", "key", default="2") assert value == "1"
""" Bootstrapping code that is run when using the `ddtrace-run` Python entrypoint Add all monkey-patching that needs to run by default here """ import os import imp import sys import logging from ddtrace.utils.formats import asbool, get_env from ddtrace.internal.logger import get_logger from ddtrace import constants logs_injection = asbool(get_env('logs', 'injection')) DD_LOG_FORMAT = '%(asctime)s %(levelname)s [%(name)s] [%(filename)s:%(lineno)d] {}- %(message)s'.format( '[dd.trace_id=%(dd.trace_id)s dd.span_id=%(dd.span_id)s] ' if logs_injection else '' ) if logs_injection: # immediately patch logging if trace id injected from ddtrace import patch patch(logging=True) debug = os.environ.get('DATADOG_TRACE_DEBUG') # Set here a default logging format for basicConfig # DEV: Once basicConfig is called here, future calls to it cannot be used to # change the formatter since it applies the formatter to the root handler only # upon initializing it the first time.
from ddtrace.propagation.http import HTTPPropagator from ddtrace.utils.formats import get_env from ddtrace.utils.wrappers import unwrap, iswrapped from .compat import get_resolver, user_is_authenticated from . import utils, conf wrap = wrapt.wrap_function_wrapper log = get_logger(__name__) config._add( "django", dict( service_name=os.environ.get("DD_SERVICE_NAME") or os.environ.get("DATADOG_SERVICE_NAME") or "django", cache_service_name=get_env("django", "cache_service_name") or "django", database_service_name_prefix=get_env("django", "database_service_name_prefix", default=""), distributed_tracing_enabled=True, instrument_databases=True, instrument_caches=True, analytics_enabled= None, # None allows the value to be overridden by the global config analytics_sample_rate=None, trace_query_string=None, # Default to global config ), ) propagator = HTTPPropagator()
def test_get_env_found(self): # ensure `get_env` returns a value if the environment variable is set os.environ['DD_REQUESTS_DISTRIBUTED_TRACING'] = '1' value = get_env('requests', 'distributed_tracing') eq_(value, '1')
def main(): parser = argparse.ArgumentParser( description=USAGE, prog="ddtrace-run", usage="ddtrace-run <your usual python command>", formatter_class=argparse.RawTextHelpFormatter, ) parser.add_argument("command", nargs=argparse.REMAINDER, type=str, help="Command string to execute.") parser.add_argument("-d", "--debug", help="enable debug mode (disabled by default)", action="store_true") parser.add_argument("-i", "--info", help="print library info useful for debugging", action="store_true") parser.add_argument("-p", "--profiling", help="enable profiling (disabled by default)", action="store_true") parser.add_argument("-v", "--version", action="version", version="%(prog)s " + ddtrace.__version__) args = parser.parse_args() if args.profiling: os.environ["DD_PROFILING_ENABLED"] = "true" debug_mode = args.debug or asbool(get_env("trace", "debug", default=False)) if debug_mode: logging.basicConfig(level=logging.DEBUG) os.environ["DD_TRACE_DEBUG"] = "true" if args.info: # Inline imports for performance. import pprint from ddtrace.internal.debug import collect pprint.pprint(collect(ddtrace.tracer)) sys.exit(0) root_dir = os.path.dirname(ddtrace.__file__) log.debug("ddtrace root: %s", root_dir) bootstrap_dir = os.path.join(root_dir, "bootstrap") log.debug("ddtrace bootstrap: %s", bootstrap_dir) _add_bootstrap_to_pythonpath(bootstrap_dir) log.debug("PYTHONPATH: %s", os.environ["PYTHONPATH"]) log.debug("sys.path: %s", sys.path) if not args.command: parser.print_help() sys.exit(1) # Find the executable path executable = spawn.find_executable(args.command[0]) if not executable: print("ddtrace-run: failed to find executable '%s'.\n" % args.command[0]) parser.print_usage() sys.exit(1) log.debug("program executable: %s", executable) if os.path.basename(executable) == "uwsgi": print(( "ddtrace-run has known compatibility issues with uWSGI where the " "tracer is not started properly in uWSGI workers which can cause " "broken behavior. It is recommended you remove ddtrace-run and " "update your uWSGI configuration following " "https://ddtrace.readthedocs.io/en/stable/advanced_usage.html#uwsgi." )) try: # Raises OSError for permissions errors in Python 2 # PermissionError for Python 3 os.execl(executable, executable, *args.command[1:]) except (OSError, PermissionError): print( "ddtrace-run: executable '%s' does not have executable permissions.\n" % executable) parser.print_usage() sys.exit(1) sys.exit(0)
def get_stats_port(): # type: () -> int return int(get_env("dogstatsd", "port", default=DEFAULT_STATS_PORT)) # type: ignore[arg-type]
if profiling: import ddtrace.profiling.auto # noqa: F401 opts = {} if enabled and enabled.lower() == "false": opts["enabled"] = False patch = False if hostname: opts["hostname"] = hostname if port: opts["port"] = int(port) if priority_sampling: opts["priority_sampling"] = asbool(priority_sampling) opts["collect_metrics"] = asbool(get_env("runtime_metrics", "enabled")) if opts: tracer.configure(**opts) if patch: update_patched_modules() from ddtrace import patch_all patch_all(**EXTRA_PATCHED_MODULES) if "DATADOG_ENV" in os.environ: tracer.set_tags({constants.ENV_KEY: os.environ["DATADOG_ENV"]}) if "DD_TRACE_GLOBAL_TAGS" in os.environ: env_tags = os.getenv("DD_TRACE_GLOBAL_TAGS")
import redis from ddtrace.vendor import wrapt # project from ddtrace import config from ddtrace.utils.formats import get_env from ...constants import ANALYTICS_SAMPLE_RATE_KEY, SPAN_MEASURED_KEY from ...pin import Pin from ...ext import SpanTypes, redis as redisx from ...utils.wrappers import unwrap from ... import utils from .util import format_command_args, _extract_conn_tags config._add( "redis", dict(service=get_env("redis", "service") or redisx.DEFAULT_SERVICE, )) def patch(): """Patch the instrumented methods This duplicated doesn't look nice. The nicer alternative is to use an ObjectProxy on top of Redis and StrictRedis. However, it means that any "import redis.Redis" won't be instrumented. """ if getattr(redis, "_datadog_patch", False): return setattr(redis, "_datadog_patch", True) _w = wrapt.wrap_function_wrapper if redis.VERSION < (3, 0, 0):