├── tests ├── __init__.py ├── cache │ ├── __init__.py │ └── conftest.py ├── benchmarks │ ├── __init__.py │ └── test_span_id.py ├── commands │ ├── __init__.py │ ├── bootstrap │ │ ├── __init__.py │ │ └── sitecustomize.py │ ├── ddtrace_minimal.py │ ├── ddtrace_run_argv.py │ ├── ddtrace_run_enabled.py │ ├── ddtrace_run_app_name.py │ ├── ddtrace_run_env.py │ ├── ddtrace_run_patched_modules.py │ ├── ddtrace_run_priority_sampling.py │ ├── ddtrace_run_hostname.py │ ├── ddtrace_run_debug.py │ ├── ddtrace_run_no_debug.py │ ├── ddtrace_run_service.py │ ├── ddtrace_run_disabled.py │ ├── ddtrace_run_gevent.py │ ├── ddtrace_run_global_tags.py │ ├── ddtrace_run_profiling.py │ ├── ddtrace_run_sitecustomize.py │ ├── ddtrace_run_dogstatsd.py │ └── ddtrace_run_logs_injection.py ├── opentracer │ ├── __init__.py │ ├── core │ │ ├── __init__.py │ │ └── test_utils.py │ └── utils.py ├── profiling │ ├── __init__.py │ ├── collector │ │ ├── __init__.py │ │ ├── conftest.py │ │ └── test_traceback.py │ ├── exporter │ │ ├── __init__.py │ │ └── test_file.py │ ├── _wrong_file │ ├── uwsgi-app.py │ ├── test_traceback.py │ ├── conftest.py │ ├── run.py │ ├── gevent_fork.py │ └── utils.py ├── runtime │ └── __init__.py ├── tracer │ ├── __init__.py │ ├── runtime │ │ ├── __init__.py │ │ ├── test_tag_collectors.py │ │ ├── fork_disable.py │ │ └── fork_enable.py │ ├── test_hostname.py │ └── test_hooks.py ├── vendor │ ├── __init__.py │ └── test_dogstatsd.py ├── contrib │ ├── aiohttp │ │ ├── __init__.py │ │ └── app │ │ │ ├── __init__.py │ │ │ ├── templates │ │ │ ├── __init__.py │ │ │ └── template.jinja2 │ │ │ └── statics │ │ │ └── empty.txt │ ├── aiopg │ │ ├── __init__.py │ │ ├── py35 │ │ │ └── __init__.py │ │ └── py37 │ │ │ └── __init__.py │ ├── asyncio │ │ └── __init__.py │ ├── boto │ │ └── __init__.py │ ├── bottle │ │ └── __init__.py │ ├── celery │ │ ├── __init__.py │ │ ├── autopatch.py │ │ ├── test_autopatch.py │ │ ├── test_patch.py │ │ └── test_app.py │ ├── consul │ │ └── __init__.py │ ├── dbapi │ │ └── __init__.py │ ├── django │ │ ├── __init__.py │ │ ├── django_app │ │ │ ├── __init__.py │ │ │ └── extra_urls.py │ │ ├── django1_app │ │ │ └── __init__.py │ │ ├── templates │ │ │ ├── basic.html │ │ │ ├── custom_dispatch.html │ │ │ ├── users_list.html │ │ │ └── cached_list.html │ │ ├── compat.py │ │ └── asgi.py │ ├── falcon │ │ ├── __init__.py │ │ └── app │ │ │ └── __init__.py │ ├── fastapi │ │ └── __init__.py │ ├── futures │ │ └── __init__.py │ ├── gevent │ │ ├── __init__.py │ │ ├── monkeypatch.py │ │ ├── wrong_program_gevent.py │ │ ├── test_provider.py │ │ ├── utils.py │ │ └── test_monkeypatch.py │ ├── grpc │ │ ├── __init__.py │ │ └── hello.proto │ ├── httplib │ │ └── __init__.py │ ├── jinja2 │ │ ├── __init__.py │ │ └── templates │ │ │ ├── base.html │ │ │ └── template.html │ ├── kombu │ │ └── __init__.py │ ├── logging │ │ └── __init__.py │ ├── mako │ │ ├── __init__.py │ │ └── templates │ │ │ └── template.html │ ├── mariadb │ │ └── __init__.py │ ├── molten │ │ └── __init__.py │ ├── mysql │ │ ├── __init__.py │ │ └── test_backwards_compatibility.py │ ├── mysqldb │ │ └── __init__.py │ ├── psycopg │ │ └── __init__.py │ ├── pylibmc │ │ └── __init__.py │ ├── pylons │ │ ├── __init__.py │ │ ├── app │ │ │ ├── __init__.py │ │ │ ├── lib │ │ │ │ ├── __init__.py │ │ │ │ ├── base.py │ │ │ │ └── helpers.py │ │ │ ├── controllers │ │ │ │ └── __init__.py │ │ │ └── templates │ │ │ │ ├── exception.mako │ │ │ │ └── template.mako │ │ └── test.ini │ ├── pymongo │ │ └── __init__.py │ ├── pymysql │ │ ├── __init__.py │ │ └── test_backwards_compatibility.py │ ├── pyodbc │ │ └── __init__.py │ ├── pytest │ │ └── __init__.py │ ├── redis │ │ └── __init__.py │ ├── sanic │ │ ├── __init__.py │ │ └── conftest.py │ ├── sqlite3 │ │ └── __init__.py │ ├── tornado │ │ ├── __init__.py │ │ └── web │ │ │ ├── __init__.py │ │ │ ├── statics │ │ │ └── empty.txt │ │ │ ├── templates │ │ │ ├── item.html │ │ │ ├── exception.html │ │ │ ├── page.html │ │ │ └── list.html │ │ │ └── uimodules.py │ ├── urllib3 │ │ ├── __init__.py │ │ └── test_urllib3_patch.py │ ├── vertica │ │ └── __init__.py │ ├── wsgi │ │ └── __init__.py │ ├── aiobotocore │ │ └── __init__.py │ ├── botocore │ │ └── __init__.py │ ├── cassandra │ │ └── __init__.py │ ├── cherrypy │ │ ├── __init__.py │ │ └── test.conf │ ├── flask_cache │ │ └── __init__.py │ ├── mongoengine │ │ ├── __init__.py │ │ └── test_backwards.py │ ├── pymemcache │ │ ├── __init__.py │ │ └── autopatch │ │ │ └── __init__.py │ ├── pynamodb │ │ └── __init__.py │ ├── rediscluster │ │ └── __init__.py │ ├── requests │ │ └── __init__.py │ ├── sqlalchemy │ │ └── __init__.py │ ├── algoliasearch │ │ └── __init__.py │ ├── dogpile_cache │ │ └── __init__.py │ ├── elasticsearch │ │ └── __init__.py │ ├── flask_autopatch │ │ ├── __init__.py │ │ └── test_templates │ │ │ ├── err.html │ │ │ └── test.html │ ├── djangorestframework │ │ ├── __init__.py │ │ ├── app │ │ │ ├── __init__.py │ │ │ └── exceptions.py │ │ └── conftest.py │ ├── flask │ │ ├── static │ │ │ └── test.txt │ │ └── test_templates │ │ │ ├── err.html │ │ │ ├── test.html │ │ │ └── render_err.html │ ├── pyramid │ │ ├── app │ │ │ └── __init__.py │ │ └── __init__.py │ ├── __init__.py │ └── uwsgi │ │ └── __init__.py ├── integration │ ├── __init__.py │ └── hello.py ├── test_module │ └── __init__.py ├── test_module2 │ └── __init__.py ├── pep562_test │ └── __init__.py ├── ddtrace_run.py └── snapshots │ ├── tests.integration.test_integration_snapshots.test_single_trace_single_span.snap │ ├── tests.contrib.mariadb.test_mariadb.test_commit_snapshot.snap │ ├── tests.contrib.urllib3.test_urllib3.test_urllib3_connectionpool_snapshot.snap │ ├── tests.contrib.urllib3.test_urllib3.test_urllib3_poolmanager_snapshot.snap │ ├── tests.contrib.cherrypy.test_middleware.test_success.snap │ ├── tests.contrib.redis.test_redis.test_basics.snap │ ├── tests.contrib.mariadb.test_mariadb.test_query_proc_snapshot.snap │ ├── tests.contrib.redis.test_redis.test_service_precedence.snap │ ├── tests.contrib.redis.test_redis.test_user_specified_service.snap │ ├── tests.contrib.mariadb.test_mariadb.test_simple_query_snapshot.snap │ ├── tests.contrib.mariadb.test_mariadb.test_user_specified_dd_service_snapshot.snap │ ├── tests.contrib.mariadb.test_mariadb.test_user_specified_dd_mariadb_service_snapshot.snap │ ├── tests.contrib.redis.test_redis.test_meta_override.snap │ ├── tests.contrib.redis.test.test_analytics_with_rate.snap │ ├── tests.integration.test_integration_snapshots.test_filters.snap │ ├── tests.contrib.redis.test_redis.test_analytics_with_rate.snap │ ├── tests.contrib.redis.test_redis.test_analytics_without_rate.snap │ ├── tests.contrib.mariadb.test_mariadb.test_analytics_with_rate_snapshot.snap │ └── tests.contrib.redis.test_redis.test_pipeline_traced.snap ├── benchmarks ├── __init__.py ├── sample │ ├── requirements.txt │ └── meta.yaml ├── startup │ ├── requirements.txt │ ├── run.py │ └── meta.yaml ├── base │ ├── requirements_scenario.txt │ ├── requirements.txt │ ├── entrypoint │ └── benchmark └── django_simple │ ├── config │ ├── __init__.py │ └── settings │ │ └── __init__.py │ ├── ddtrace_django │ ├── users │ │ ├── __init__.py │ │ ├── migrations │ │ │ └── __init__.py │ │ ├── apps.py │ │ ├── urls.py │ │ ├── forms.py │ │ ├── adapters.py │ │ └── models.py │ ├── utils │ │ ├── __init__.py │ │ ├── storages.py │ │ └── context_processors.py │ ├── static │ │ ├── fonts │ │ │ └── .gitkeep │ │ ├── sass │ │ │ ├── custom_bootstrap_vars.scss │ │ │ └── project.scss │ │ ├── js │ │ │ └── project.js │ │ ├── images │ │ │ └── favicons │ │ │ │ └── favicon.ico │ │ └── css │ │ │ └── project.css │ ├── templates │ │ ├── pages │ │ │ ├── about.html │ │ │ └── home.html │ │ ├── 403.html │ │ ├── 404.html │ │ ├── account │ │ │ ├── base.html │ │ │ ├── account_inactive.html │ │ │ ├── password_reset_from_key_done.html │ │ │ ├── signup_closed.html │ │ │ ├── verification_sent.html │ │ │ ├── password_reset_done.html │ │ │ ├── password_set.html │ │ │ ├── password_change.html │ │ │ └── logout.html │ │ ├── 500.html │ │ └── users │ │ │ └── user_form.html │ ├── __init__.py │ └── contrib │ │ ├── __init__.py │ │ └── sites │ │ ├── __init__.py │ │ └── migrations │ │ ├── __init__.py │ │ ├── 0004_alter_options_ordering_domain.py │ │ └── 0002_alter_domain_unique.py │ ├── run │ ├── summarize_k6.jq │ ├── setup │ ├── wait │ ├── script.js │ ├── entrypoint │ ├── summarize_sirun.jq │ ├── benchmark │ └── meta.yaml ├── ddtrace ├── commands │ └── __init__.py ├── internal │ ├── __init__.py │ ├── _rand.pyi │ ├── _stdint.h │ ├── hostname.py │ ├── README.md │ ├── runtime │ │ └── __init__.py │ └── buff_converter.h ├── bootstrap │ └── __init__.py ├── propagation │ └── __init__.py ├── opentracer │ ├── propagation │ │ ├── text.py │ │ ├── binary.py │ │ ├── __init__.py │ │ └── propagator.py │ ├── __init__.py │ ├── helpers.py │ └── tags.py ├── profiling │ ├── collector │ │ ├── stack.pyi │ │ ├── _threading.pyi │ │ ├── _traceback.pyi │ │ ├── _pymacro.h │ │ ├── _memalloc.pyi │ │ └── _memalloc_heap.h │ ├── bootstrap │ │ ├── __init__.py │ │ └── sitecustomize.py │ ├── _build.pyi │ ├── _build.pyx │ ├── _traceback.py │ ├── auto.py │ ├── __init__.py │ └── exporter │ │ └── __init__.py ├── contrib │ ├── kombu │ │ └── constants.py │ ├── mako │ │ ├── constants.py │ │ └── __init__.py │ ├── requests │ │ ├── constants.py │ │ └── session.py │ ├── jinja2 │ │ └── constants.py │ ├── vertica │ │ └── constants.py │ ├── pylons │ │ ├── constants.py │ │ └── compat.py │ ├── pytest │ │ └── constants.py │ ├── cassandra │ │ └── patch.py │ ├── __init__.py │ ├── tornado │ │ ├── constants.py │ │ └── compat.py │ ├── sqlite3 │ │ └── connection.py │ ├── mysql │ │ └── tracers.py │ ├── pymysql │ │ └── tracers.py │ ├── pylibmc │ │ ├── patch.py │ │ └── addrs.py │ ├── pyramid │ │ └── constants.py │ ├── asyncio │ │ └── compat.py │ ├── util.py │ ├── mongoengine │ │ └── patch.py │ ├── celery │ │ └── constants.py │ ├── redis │ │ └── tracers.py │ ├── futures │ │ └── patch.py │ └── boto │ │ └── __init__.py ├── ext │ ├── system.py │ ├── consul.py │ ├── memcached.py │ ├── mongo.py │ ├── net.py │ ├── db.py │ ├── cassandra.py │ ├── elasticsearch.py │ ├── kombu.py │ ├── redis.py │ ├── __init__.py │ ├── http.py │ └── errors.py ├── settings │ ├── exceptions.py │ └── __init__.py ├── vendor │ ├── wrapt │ │ ├── setup.py │ │ └── __init__.py │ ├── psutil │ │ ├── _psutil_posix.h │ │ └── arch │ │ │ ├── freebsd │ │ │ ├── proc_socks.h │ │ │ └── sys_socks.h │ │ │ ├── windows │ │ │ ├── wmi.h │ │ │ ├── process_handles.h │ │ │ ├── security.h │ │ │ ├── inet_ntop.h │ │ │ └── services.h │ │ │ ├── netbsd │ │ │ └── socks.h │ │ │ ├── aix │ │ │ └── net_connections.h │ │ │ ├── solaris │ │ │ ├── environ.h │ │ │ └── v10 │ │ │ │ └── ifaddrs.h │ │ │ └── osx │ │ │ └── process_info.h │ └── dogstatsd │ │ └── __init__.py ├── utils │ ├── attr.py │ └── config.py ├── http │ └── __init__.py ├── encoding.py ├── util.py └── constants.py ├── .github ├── CODEOWNERS ├── dependabot.yml ├── PULL_REQUEST_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE │ ├── feature.md │ └── bugfix.md └── ISSUE_TEMPLATE.md ├── hooks ├── pre-commit │ ├── 01-run-black │ ├── 02-run-mypy │ ├── 03-run-flake8 │ └── 04-run-codespell └── scripts │ ├── run-mypy.sh │ ├── run-black.sh │ ├── run-flake8.sh │ └── run-codespell.sh ├── releasenotes ├── config.yaml └── notes │ ├── py39-5a422b73ba563189.yaml │ ├── mariadb-8e7bc94a0d1b8f02.yaml │ ├── wsgi-30613a9c30834225.yaml │ ├── django-2ebd5565ee27d4d1.yaml │ ├── feature-fastapi-ccce6171c5e1ccde.yaml │ ├── support-flask-2-659163726a5f66aa.yaml │ ├── aiopg-0160-67bac7e073e4bbf9.yaml │ ├── feature-flask-6744ed2003376d74.yaml │ ├── feature-molten-041abc52f37eed37.yaml │ ├── jinja2-3-ec7df3666745f29b.yaml │ ├── agent-url-path-f48aa4949b954dd5.yaml │ ├── flask-241a6dd8c17e2c12.yaml │ ├── mongo-2f086c64dbbc8be1.yaml │ ├── configure-a39313ef4fed9028.yaml │ ├── ddtags-space-82407d0d3f0426cd.yaml │ ├── encoding-strict-types-b2bbd0844b28168a.yaml │ ├── feature-flask-4bdb2b839fada0fb.yaml │ ├── fix-grpc-client-meta-1145db1fec07255f.yaml │ ├── fix-starlette-unpatch-24829144874afc6d.yaml │ ├── feature-aiohttp-23084fcf8e34ad0a.yaml │ ├── feature-bottle-44cadc4aabaa750d.yaml │ ├── feature-pyramid-aa3d4c3361861753.yaml │ ├── feature-urllib3-integration-ab30709c8a39934c.yaml │ ├── fix-aiobotocore-9eeac808a3bf0f63.yaml │ ├── fix-grpc-method-93038a476c9e95aa.yaml │ ├── fix-sanic-21-2d24b817e010ed84.yaml │ ├── futures-f485da98a50c9d50.yaml │ ├── mysql-python-removal-f0578e89590aaf2f.yaml │ ├── build-deploy-py39-wheels-6524f77277e3c788.yaml │ ├── current-span-reset-a860bbbad3acda5c.yaml │ ├── django-view-mro-check-782374fb9c427305.yaml │ ├── fix-elasticsearch-a3f89a915ccc36c4.yaml │ ├── fix-grpc-target-0a1daf38516be79f.yaml │ ├── fix-trace_id_lock-profiling-585779e8713144f3.yaml │ ├── httplib-3b8917c90d162170.yaml │ ├── aiohttp-remove-1.x-7a899e50dff73357.yaml │ ├── dbapi-ctx-manager-008915d487d9f50d.yaml │ ├── django-404-214280e31b72571c.yaml │ ├── dogpile-cc205f8abf149360.yaml │ ├── fix-django-empty-middleware-056f9c75ad963f1f.yaml │ ├── fix-span-type-web-20122b5c57c50341.yaml │ ├── profiling-fix-uds-ebf0ea0587c8a23c.yaml │ ├── psycopg-before-27-removal-d6e551e47038abde.yaml │ ├── traced-session-1f2134ac99449b91.yaml │ ├── remove-payload-submodule-58fac4aaf3d4f5da.yaml │ ├── runtime-metrics-runtime-error-33e2d4cc17cf4aca.yaml │ ├── wsgi-73cf1d35043e7fef.yaml │ ├── fix-django-correct-legacy-resource-c27c7402b6b0be37.yaml │ ├── grpc-client-measured-span-aa043d35bfe71238.yaml │ ├── profiling-fix-newline-error-8d4d10ed61143e16.yaml │ ├── pymongo-double-patching-topology-dd90eda48daa051c.yaml │ ├── runtimeid-39dfdf1e0c1af45d.yaml │ ├── tornado-none-bug-85faed75c859f5e5.yaml │ ├── cherrypy-first-version-89893f512b2fa083.yaml │ ├── django-request-uri-safe-guards-fdd8bd664374ded1.yaml │ ├── drop-gevent-10-438387fecc241e60.yaml │ ├── fix-django-db-postgres-7aa62a1c3aff647d.yaml │ ├── fix.urllib3.integration-610312498fcdce86.yaml │ ├── flask-codes-f0841d78ec847807.yaml │ ├── gevent-pynamodb-fix-72ac7017e51fd4f9.yaml │ ├── perf-celery-reduced-overheads-6afe03acf1af703f.yaml │ ├── remove-apptypes-76c78d46c1792863.yaml │ ├── utils-remove-merge-dicts-9252805c864677f8.yaml │ ├── django-9ce233836fca5d93.yaml │ ├── feature-injectr-trace-sqs-send-message-035dc3300db0cad0.yaml │ ├── fix-django-str-tags-ad4f0b9e2d0eff12.yaml │ ├── profiling-no-flush-on-fork-c6c2b3c2d27a9a32.yaml │ ├── profiling-task-pprof-3afb83e36a63aeaf.yaml │ ├── fix-botocore-missing-response-meta-e80c1cfb34ec0881.yaml │ ├── flask-fix-query-encoding-ef177f8c9c7a679a.yaml │ ├── profiling-remove-profile-fbf8e32388899b05.yaml │ ├── profiling-remove-uncaught-exception-be09cc1bca6b7af6.yaml │ ├── pyramid-config-7db0cb8f089c9417.yaml │ ├── elasticsearch-0a97722c93d66016.yaml │ ├── fix-django-db-connections-b9b98a7b49f27c5f.yaml │ ├── fix-sanic-resource-name-e9f5b0417f3cda13.yaml │ ├── profiling-fix-deadlock-gevent-1e6192828238def3.yaml │ ├── profiling-threading-tracing-6877348333bbaa80.yaml │ ├── docs-gunicorn-bd0db8c3c25c7deb.yaml │ ├── profiling-tags-api-f4d732d3c31ee2cf.yaml │ ├── perf-improve-header-extraction-30f575d5034b7e20.yaml │ ├── bottle-int-config-6772ca40a3954399.yaml │ ├── falcon-int-config-a85b605cac4a7dbc.yaml │ ├── fix-container-id-cgroup-parsing-28790e02a2ac0adc.yaml │ ├── profiler-uds-108b876bdab8a151.yaml │ ├── pylons-int-config-b500a59f78297b88.yaml │ ├── pytest-d174e595f0c8abd0.yaml │ ├── configure-6973c2ed2105a1c0.yaml │ ├── deprecate-pyddprofile-41de3d099775ee0c.yaml │ ├── fix-grpc-streaming-next-5acf03fec7056a48.yaml │ ├── profiler-url-c61885c7d1fd5ea6.yaml │ ├── profiling-export-tags-fixed-9d383890c8e5c4c1.yaml │ ├── profiling-stack-exception-sample-trace-49228a2ce81b32ca.yaml │ ├── span-22c2917b9580c0e6.yaml │ ├── tornado-int-config-a8900a60201d4d61.yaml │ ├── botocore-distributed-tracing-config-cd37b439d6d77dc6.yaml │ ├── deprecate-compat-c70f99dc038bc947.yaml │ ├── feature-inject-trace-lambda-invoke-818866a5de2015a9.yaml │ ├── fix-dbapi-rowcount-guard-6c6455278f15d262.yaml │ ├── gevent-warning-f91ed0e6cac71a21.yaml │ ├── profiling-remove-tracemalloc-memory-collector-7a98634e0d9672a6.yaml │ ├── pytest-patch-all-05b2c812bf6ce0c2.yaml │ ├── pytest-service-name-8c9d0f37b159a561.yaml │ ├── deprecate-ddtrace-encoding-84ffb8a36694161f.yaml │ ├── fix-sampler_sample_rate_bug-b93ffc6036982ba8.yaml │ ├── fix-span-finish-signature-b0c1073b56c3b559.yaml │ ├── profiling-ignore-profiler-daa056f8384008dc.yaml │ ├── pytest-parameters-7d6acf4ca1419be0.yaml │ ├── feature-pyodbc-52e513ccf4c6a03c.yaml │ ├── pymongo-config-6e4495f0be97e288.yaml │ ├── fix-mako-template-filename-31efcdb8592758c6.yaml │ ├── profiling-fix-ignore-profiler-gevent-stack-collector-3270d81c84080ccb.yaml │ ├── tracer-upload-retry-d60310aa6c91059d.yaml │ ├── fix-runtime-default-interval-e3afb49f45296877.yaml │ ├── pylons-http-3d542b80b3fc4b48.yaml │ ├── startup-logs-4d7acd6fa6b34074.yaml │ ├── depends-on-attrs-19687d5b7a597744.yaml │ ├── depends-on-six-e9b79edbf0d169a2.yaml │ ├── feature-service-mapping-b1c6cf37a5ad6417.yaml │ ├── profiling-timeout-10s-a2468ce1444887b5.yaml │ ├── botocore-no-body-params-a440cd8b7fb9bd68.yaml │ ├── datadog-lambda-extension-6ae77025f24a82cc.yaml │ ├── deprecate-monkey-functions-01f8080ab711ae74.yaml │ ├── profiling-remove-pyddprofile-1a699c195d9d3ab0.yaml │ ├── fix-monkey-patch-on-import-7bbf81bcd2a86f11.yaml │ ├── profiler-stack-greenlet-tracer-6f960c1557fd39c4.yaml │ ├── profiling-heap-profiler-enabling-186ae7679b84d39a.yaml │ ├── span-pprint-json-855d32f50798fd8d.yaml │ ├── django-key-error-be8812133f0ef920.yaml │ ├── fix-fargate-cgroup-parsing-9ba690fc7e2e57f4.yaml │ ├── fix-logging-strformatstyle-9c02e1d024961c0f.yaml │ ├── profiling-default-timeout-agent-43b19237a21fd337.yaml │ ├── botocore-exclude-records--74ac3e5d4d4fdc95.yaml │ ├── ci-providers-git-metadata-6229ff3cf9a347d9.yaml │ ├── profiler-gevent-warns-on-late-patch-3f4f897c8904591c.yaml │ ├── restart-profiler-fork-9bfaec1942112026.yaml │ ├── tracer-200a66ebb04f6cb0.yaml │ ├── fix-grpc-streaming-prefetch-95e816bd0fd85723.yaml │ ├── fix-logger-standard-logging-rate-envvar-155e113deea71e85.yaml │ ├── fork-leak-74288f3ce2a2bc28.yaml │ ├── null-trace-propagation-95ca602d2cc05ea1.yaml │ ├── add-py27-windows-support-a624cbc63b8f90de.yaml │ ├── grpc-future-callback-a3cc27b11df34eef.yaml │ ├── profiling-lower-max-cpu-usage-default-59458d90e0d6d33d.yaml │ ├── es-92a00e4a03a65da6.yaml │ ├── pymemcache-update-c6d830daa541b3c8.yaml │ ├── url-7d1cb4e659ebca31.yaml │ ├── deprecate-ddtrace-http-ce198e779de69237.yaml │ ├── fix-manual-runtime-metrics-0873e17de485f8b0.yaml │ ├── os-runtime-metadata-98845c31e21f6ea2.yaml │ ├── pytest-xfail-c15914f8ae3281c9.yaml │ ├── add-dd-trace-agent-timeout-seconds-env-844b53ff0ccc7c9f.yaml │ ├── context-3467ab87a70c601e.yaml │ ├── profiling-fix-uwsgi-empty-profiles-7dbd5fdd93dea47f.yaml │ ├── metrics-api-5fb1d572d7f7137e.yaml │ ├── profiling-use-tracer-config-83aa0ae0c2c53086.yaml │ ├── url-sanitizer-26c7078e37f395c0.yaml │ ├── add-writer-env-config-7c0916dff4f7f80c.yaml │ ├── remove-deprecated-dbapi-config-b25bc1b236672fed.yaml │ ├── fix-pytest-parameterize-encoding-b8711d2d7dbb282a.yaml │ ├── flask-http-helpers-0167071f46a36e00.yaml │ ├── ddtracerun-gevent-928b4050fd96f142.yaml │ ├── feature-starlette-e5171e4b2b2646c3.yaml │ ├── fix-pytest-parameterized-606fbc3a574c67c6.yaml │ ├── profiling-enable-new-memalloc-profiler-default-fac01a6d596b6404.yaml │ ├── fix-deprecate-tracer-reuse-6d989d4acb538013.yaml │ ├── requests-b06e324e36e03ae5.yaml │ ├── profiling-agentless-feb211ee5e1f454f.yaml │ ├── dbapi2-deprecate-analytics-config-ececae6e9274f852.yaml │ ├── profiling-uwsgi-faaeb38f11bd287b.yaml │ ├── botocore-46f5bf04f64777b4.yaml │ ├── deprecate-dbapi-config-0fc5b1acfc4aded2.yaml │ ├── ddtrace-run-enhancements-eb156e6722164894.yaml │ ├── add-dd_call_basic_config-env-15570281d176f438.yaml │ └── trace-58c201a4a5f38002.yaml ├── docs ├── requirements.txt ├── shared.rst ├── release_notes.rst └── _templates │ └── navigation.html ├── NOTICE ├── scripts ├── build-docs ├── stubgen.sh ├── ddtest ├── cformat.sh └── run-tox-scenario ├── setup.cfg ├── LICENSE ├── .coveragerc ├── .readthedocs.yml ├── .dd-ci └── README.md ├── mypy.ini └── ddtrace_gevent_check.py /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /benchmarks/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/cache/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ddtrace/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ddtrace/internal/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/benchmarks/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/opentracer/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/profiling/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/runtime/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/tracer/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/vendor/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ddtrace/bootstrap/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ddtrace/propagation/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/aiohttp/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/aiopg/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/asyncio/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/boto/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/bottle/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/celery/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/consul/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/dbapi/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/django/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/falcon/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/fastapi/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/futures/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/gevent/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/grpc/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/httplib/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/jinja2/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/kombu/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/logging/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/mako/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/mariadb/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/molten/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/mysql/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/mysqldb/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/psycopg/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/pylibmc/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/pylons/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/pymongo/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/pymysql/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/pyodbc/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/pytest/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/redis/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/sanic/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/sqlite3/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/tornado/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/urllib3/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/vertica/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/wsgi/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/integration/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/opentracer/core/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_module/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_module2/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/tracer/runtime/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /benchmarks/sample/requirements.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /benchmarks/startup/requirements.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ddtrace/opentracer/propagation/text.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ddtrace/profiling/collector/stack.pyi: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/commands/bootstrap/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/aiobotocore/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/aiohttp/app/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/aiopg/py35/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/aiopg/py37/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/botocore/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/cassandra/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/cherrypy/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/flask_cache/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/mongoengine/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/pylons/app/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/pymemcache/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/pynamodb/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/rediscluster/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/requests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/sqlalchemy/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/tornado/web/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/profiling/collector/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/profiling/exporter/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /benchmarks/base/requirements_scenario.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /benchmarks/django_simple/config/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ddtrace/opentracer/propagation/binary.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ddtrace/profiling/bootstrap/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/algoliasearch/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/django/django_app/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/dogpile_cache/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/elasticsearch/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/flask_autopatch/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/pylons/app/lib/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @DataDog/apm-python 2 | -------------------------------------------------------------------------------- /tests/contrib/aiohttp/app/templates/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/django/django1_app/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/djangorestframework/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/pylons/app/controllers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/pymemcache/autopatch/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /benchmarks/django_simple/config/settings/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hooks/pre-commit/01-run-black: -------------------------------------------------------------------------------- 1 | ../scripts/run-black.sh -------------------------------------------------------------------------------- /hooks/pre-commit/02-run-mypy: -------------------------------------------------------------------------------- 1 | ../scripts/run-mypy.sh -------------------------------------------------------------------------------- /tests/contrib/djangorestframework/app/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/contrib/flask/static/test.txt: -------------------------------------------------------------------------------- 1 | Hello Flask 2 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/users/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/utils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hooks/pre-commit/03-run-flake8: -------------------------------------------------------------------------------- 1 | ../scripts/run-flake8.sh -------------------------------------------------------------------------------- /tests/contrib/django/templates/basic.html: -------------------------------------------------------------------------------- 1 | some content 2 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/static/fonts/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hooks/pre-commit/04-run-codespell: -------------------------------------------------------------------------------- 1 | ../scripts/run-codespell.sh -------------------------------------------------------------------------------- /hooks/scripts/run-mypy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | riot -v run -s mypy 3 | -------------------------------------------------------------------------------- /tests/contrib/aiohttp/app/statics/empty.txt: -------------------------------------------------------------------------------- 1 | Static file 2 | -------------------------------------------------------------------------------- /tests/contrib/flask/test_templates/err.html: -------------------------------------------------------------------------------- 1 | 2 | oh {{no 3 | -------------------------------------------------------------------------------- /tests/contrib/mako/templates/template.html: -------------------------------------------------------------------------------- 1 | Hello ${name}! 2 | -------------------------------------------------------------------------------- /tests/contrib/pylons/app/templates/exception.mako: -------------------------------------------------------------------------------- 1 | ${1/0} 2 | -------------------------------------------------------------------------------- /tests/contrib/tornado/web/statics/empty.txt: -------------------------------------------------------------------------------- 1 | Static file 2 | -------------------------------------------------------------------------------- /tests/contrib/tornado/web/templates/item.html: -------------------------------------------------------------------------------- 1 | * {{ item }} 2 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/users/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ddtrace/contrib/kombu/constants.py: -------------------------------------------------------------------------------- 1 | DEFAULT_SERVICE = "kombu" 2 | -------------------------------------------------------------------------------- /tests/commands/bootstrap/sitecustomize.py: -------------------------------------------------------------------------------- 1 | CORRECT_IMPORT = True 2 | -------------------------------------------------------------------------------- /tests/contrib/aiohttp/app/templates/template.jinja2: -------------------------------------------------------------------------------- 1 | {{text}} 2 | -------------------------------------------------------------------------------- /tests/contrib/flask/test_templates/test.html: -------------------------------------------------------------------------------- 1 | hello {{world}} 2 | -------------------------------------------------------------------------------- /tests/contrib/pylons/app/templates/template.mako: -------------------------------------------------------------------------------- 1 | Hello world! 2 | -------------------------------------------------------------------------------- /benchmarks/sample/meta.yaml: -------------------------------------------------------------------------------- 1 | name: sample-scenario 2 | run: "echo 1" 3 | -------------------------------------------------------------------------------- /ddtrace/contrib/mako/constants.py: -------------------------------------------------------------------------------- 1 | DEFAULT_TEMPLATE_NAME = "" 2 | -------------------------------------------------------------------------------- /ddtrace/contrib/requests/constants.py: -------------------------------------------------------------------------------- 1 | DEFAULT_SERVICE = "requests" 2 | -------------------------------------------------------------------------------- /releasenotes/config.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | unreleased_version_title: Unreleased 3 | -------------------------------------------------------------------------------- /tests/contrib/falcon/app/__init__.py: -------------------------------------------------------------------------------- 1 | from .app import get_app # noqa 2 | -------------------------------------------------------------------------------- /tests/contrib/flask_autopatch/test_templates/err.html: -------------------------------------------------------------------------------- 1 | 2 | oh {{no 3 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/static/sass/custom_bootstrap_vars.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ddtrace/contrib/jinja2/constants.py: -------------------------------------------------------------------------------- 1 | DEFAULT_TEMPLATE_NAME = "" 2 | -------------------------------------------------------------------------------- /ddtrace/contrib/vertica/constants.py: -------------------------------------------------------------------------------- 1 | # Service info 2 | APP = "vertica" 3 | -------------------------------------------------------------------------------- /tests/contrib/flask_autopatch/test_templates/test.html: -------------------------------------------------------------------------------- 1 | hello {{world}} 2 | -------------------------------------------------------------------------------- /tests/contrib/pyramid/app/__init__.py: -------------------------------------------------------------------------------- 1 | from .web import create_app # noqa 2 | -------------------------------------------------------------------------------- /tests/profiling/_wrong_file: -------------------------------------------------------------------------------- 1 | this is definitely not good python, right? 2 | -------------------------------------------------------------------------------- /benchmarks/base/requirements.txt: -------------------------------------------------------------------------------- 1 | -r requirements_scenario.txt 2 | 3 | pyperf 4 | -------------------------------------------------------------------------------- /ddtrace/contrib/pylons/constants.py: -------------------------------------------------------------------------------- 1 | CONFIG_MIDDLEWARE = "__datadog_middleware" 2 | -------------------------------------------------------------------------------- /tests/contrib/flask/test_templates/render_err.html: -------------------------------------------------------------------------------- 1 | hello {{object.method()}} 2 | -------------------------------------------------------------------------------- /tests/contrib/jinja2/templates/base.html: -------------------------------------------------------------------------------- 1 | Message: {% block content %}{% endblock %} 2 | -------------------------------------------------------------------------------- /tests/integration/hello.py: -------------------------------------------------------------------------------- 1 | if __name__ == "__main__": 2 | print("Test success") 3 | -------------------------------------------------------------------------------- /ddtrace/ext/system.py: -------------------------------------------------------------------------------- 1 | """ 2 | Standard system tags 3 | """ 4 | 5 | PID = "system.pid" 6 | -------------------------------------------------------------------------------- /tests/contrib/tornado/web/templates/exception.html: -------------------------------------------------------------------------------- 1 | {% module ModuleThatDoesNotExist() %} 2 | -------------------------------------------------------------------------------- /tests/contrib/tornado/web/templates/page.html: -------------------------------------------------------------------------------- 1 | This is a rendered page called "{{ name }}" 2 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/templates/pages/about.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/templates/pages/home.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | -------------------------------------------------------------------------------- /ddtrace/profiling/_build.pyi: -------------------------------------------------------------------------------- 1 | import typing 2 | 3 | compiled_with: typing.Tuple[int, int, int] 4 | -------------------------------------------------------------------------------- /releasenotes/notes/py39-5a422b73ba563189.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | prelude: > 3 | Add support for Python 3.9 4 | -------------------------------------------------------------------------------- /tests/contrib/django/templates/custom_dispatch.html: -------------------------------------------------------------------------------- 1 | custom dispatch {{ dispatch_call_counter }} 2 | -------------------------------------------------------------------------------- /tests/contrib/pylons/app/lib/base.py: -------------------------------------------------------------------------------- 1 | # this file is required when Pylons calls the `legacy` module 2 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | cython 2 | sphinx 3 | opentracing 4 | reno 5 | sphinxcontrib-spelling 6 | PyEnchant -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/static/js/project.js: -------------------------------------------------------------------------------- 1 | /* Project specific Javascript goes here. */ 2 | -------------------------------------------------------------------------------- /ddtrace/ext/consul.py: -------------------------------------------------------------------------------- 1 | APP = "consul" 2 | SERVICE = "consul" 3 | CMD = "consul.command" 4 | KEY = "consul.key" 5 | -------------------------------------------------------------------------------- /ddtrace/ext/memcached.py: -------------------------------------------------------------------------------- 1 | CMD = "memcached.command" 2 | SERVICE = "memcached" 3 | QUERY = "memcached.query" 4 | -------------------------------------------------------------------------------- /ddtrace/internal/_rand.pyi: -------------------------------------------------------------------------------- 1 | def seed() -> None: ... 2 | def rand64bits(check_pid: bool = True) -> int: ... 3 | -------------------------------------------------------------------------------- /releasenotes/notes/mariadb-8e7bc94a0d1b8f02.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Add MariaDB integration. 5 | -------------------------------------------------------------------------------- /benchmarks/startup/run.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | if os.getenv("DDTRACE") == "1": 5 | import ddtrace # noqa 6 | -------------------------------------------------------------------------------- /releasenotes/notes/wsgi-30613a9c30834225.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | wsgi: add tracing middleware. 5 | -------------------------------------------------------------------------------- /tests/contrib/django/templates/users_list.html: -------------------------------------------------------------------------------- 1 | {% for user in object_list %} 2 | {{ user }} 3 | {% endfor %} 4 | -------------------------------------------------------------------------------- /tests/profiling/uwsgi-app.py: -------------------------------------------------------------------------------- 1 | import ddtrace.profiling.auto # noqa 2 | 3 | 4 | def application(): 5 | pass 6 | -------------------------------------------------------------------------------- /releasenotes/notes/django-2ebd5565ee27d4d1.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | django: tag root spans as measured. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/feature-fastapi-ccce6171c5e1ccde.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | fastapi: add integration. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/support-flask-2-659163726a5f66aa.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Add support for Flask 2 5 | -------------------------------------------------------------------------------- /releasenotes/notes/aiopg-0160-67bac7e073e4bbf9.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Added support for ``aipg~=0.16.0``. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/feature-flask-6744ed2003376d74.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | flask: store response headers. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/feature-molten-041abc52f37eed37.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | molten: store request headers. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/jinja2-3-ec7df3666745f29b.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Added support for ``jinja2~=3.0.0``. 5 | -------------------------------------------------------------------------------- /tests/contrib/gevent/monkeypatch.py: -------------------------------------------------------------------------------- 1 | import gevent.monkey 2 | 3 | 4 | gevent.monkey.patch_all() 5 | print("Test success") 6 | -------------------------------------------------------------------------------- /tests/contrib/jinja2/templates/template.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% block content %}Hello {{name}}!{% endblock %} 3 | -------------------------------------------------------------------------------- /tests/contrib/pyramid/__init__.py: -------------------------------------------------------------------------------- 1 | from .test_pyramid_autopatch import _include_me 2 | 3 | 4 | __all__ = ["_include_me"] 5 | -------------------------------------------------------------------------------- /releasenotes/notes/agent-url-path-f48aa4949b954dd5.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | agent: support URL with a base path 5 | -------------------------------------------------------------------------------- /releasenotes/notes/flask-241a6dd8c17e2c12.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | flask: fix memory leak of sampled out traces. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/mongo-2f086c64dbbc8be1.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fix pymongo 3.12.0+ spans not being generated. 5 | -------------------------------------------------------------------------------- /ddtrace/contrib/pytest/constants.py: -------------------------------------------------------------------------------- 1 | FRAMEWORK = "pytest" 2 | KIND = "test" 3 | 4 | HELP_MSG = "Enable tracing of pytest functions." 5 | -------------------------------------------------------------------------------- /ddtrace/opentracer/propagation/__init__.py: -------------------------------------------------------------------------------- 1 | from .http import HTTPPropagator 2 | 3 | 4 | __all__ = [ 5 | "HTTPPropagator", 6 | ] 7 | -------------------------------------------------------------------------------- /releasenotes/notes/configure-a39313ef4fed9028.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Tracer: fix configuring tracer with dogstatsd url. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/ddtags-space-82407d0d3f0426cd.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Add support for space-separated `DD_TAGS`. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/encoding-strict-types-b2bbd0844b28168a.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | core: use loose types when encoding. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/feature-flask-4bdb2b839fada0fb.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Store request headers in Flask integration. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-grpc-client-meta-1145db1fec07255f.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | grpc: handle None values for span tags. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-starlette-unpatch-24829144874afc6d.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | starlette: unpatch calls correctly. 5 | -------------------------------------------------------------------------------- /ddtrace/contrib/cassandra/patch.py: -------------------------------------------------------------------------------- 1 | from .session import patch 2 | from .session import unpatch 3 | 4 | 5 | __all__ = ["patch", "unpatch"] 6 | -------------------------------------------------------------------------------- /releasenotes/notes/feature-aiohttp-23084fcf8e34ad0a.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | aiohttp: store request and response headers. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/feature-bottle-44cadc4aabaa750d.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | bottle: store request and response headers. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/feature-pyramid-aa3d4c3361861753.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | pyramid: store request and response headers. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/feature-urllib3-integration-ab30709c8a39934c.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | urllib3: add urllib3 integration 5 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-aiobotocore-9eeac808a3bf0f63.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | aiobotocore: set span error for 5xx status codes. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-grpc-method-93038a476c9e95aa.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | grpc: handle no package in fully qualified method 5 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-sanic-21-2d24b817e010ed84.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | sanic: update instrumentation to support version 21. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/futures-f485da98a50c9d50.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | The futures integration is now enabled by default. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/mysql-python-removal-f0578e89590aaf2f.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | Support for MySQL-python has been removed. 5 | -------------------------------------------------------------------------------- /tests/contrib/cherrypy/test.conf: -------------------------------------------------------------------------------- 1 | [global] 2 | server.socket_host = "127.0.0.1" 3 | server.socket_port = 8080 4 | server.thread_pool = 10 5 | -------------------------------------------------------------------------------- /tests/contrib/gevent/wrong_program_gevent.py: -------------------------------------------------------------------------------- 1 | from gevent import monkey 2 | 3 | import ddtrace # noqa 4 | 5 | 6 | monkey.patch_all() 7 | -------------------------------------------------------------------------------- /tests/contrib/tornado/web/templates/list.html: -------------------------------------------------------------------------------- 1 | This is a list: 2 | {% for item in items %} 3 | {% module Item(item) %} 4 | {% end %} 5 | -------------------------------------------------------------------------------- /releasenotes/notes/build-deploy-py39-wheels-6524f77277e3c788.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | prelude: > 3 | Build and deploy Python 3.9 wheels for releases 4 | -------------------------------------------------------------------------------- /releasenotes/notes/current-span-reset-a860bbbad3acda5c.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | core: always reset the current_span in the context. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/django-view-mro-check-782374fb9c427305.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | django: check view before instrumenting MRO. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-elasticsearch-a3f89a915ccc36c4.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | elasticsearch: set span error for 5xx status codes. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-grpc-target-0a1daf38516be79f.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | grpc: handle IPv6 addresses and no port in target. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-trace_id_lock-profiling-585779e8713144f3.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fixes span id tagging in lock profiling. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/httplib-3b8917c90d162170.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | httplib: distributed tracing is now enabled by default. 5 | -------------------------------------------------------------------------------- /ddtrace/profiling/collector/_threading.pyi: -------------------------------------------------------------------------------- 1 | def get_thread_name(thread_id: int) -> str: ... 2 | def get_thread_native_id(thread_id: int) -> int: ... 3 | -------------------------------------------------------------------------------- /releasenotes/notes/aiohttp-remove-1.x-7a899e50dff73357.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | Support for aiohttp previous to 2.0 has been removed. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/dbapi-ctx-manager-008915d487d9f50d.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | dbapi: add support for connection context manager usage 5 | -------------------------------------------------------------------------------- /releasenotes/notes/django-404-214280e31b72571c.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | django: Http404 exceptions will no longer be flagged as errors 5 | -------------------------------------------------------------------------------- /releasenotes/notes/dogpile-cc205f8abf149360.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | dogpile.cache: is now automatically instrumented by default. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-django-empty-middleware-056f9c75ad963f1f.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | django: handle erroneous middleware gracefully. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-span-type-web-20122b5c57c50341.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | django, DRF, ASGI: fix span type for web request spans. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/profiling-fix-uds-ebf0ea0587c8a23c.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fix UDS upload for profiling not using the correct path. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/psycopg-before-27-removal-d6e551e47038abde.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | Support for psycopg < 2.7 has been removed. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/traced-session-1f2134ac99449b91.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | requests: fix TracedSession when patches are not applied. 5 | -------------------------------------------------------------------------------- /ddtrace/ext/mongo.py: -------------------------------------------------------------------------------- 1 | SERVICE = "mongodb" 2 | COLLECTION = "mongodb.collection" 3 | DB = "mongodb.db" 4 | ROWS = "mongodb.rows" 5 | QUERY = "mongodb.query" 6 | -------------------------------------------------------------------------------- /releasenotes/notes/remove-payload-submodule-58fac4aaf3d4f5da.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | The ``ddtrace.payload`` submodule has been removed. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/runtime-metrics-runtime-error-33e2d4cc17cf4aca.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | core: fix race condition in TracerTagCollector. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/wsgi-73cf1d35043e7fef.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fix a possible NoneType error in the WSGI middleware start_response method. 5 | -------------------------------------------------------------------------------- /tests/commands/ddtrace_minimal.py: -------------------------------------------------------------------------------- 1 | import ddtrace.bootstrap.sitecustomize as module 2 | 3 | 4 | if __name__ == "__main__": 5 | print(module.loaded) 6 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "daily" 7 | -------------------------------------------------------------------------------- /ddtrace/internal/_stdint.h: -------------------------------------------------------------------------------- 1 | #ifdef _MSC_VER 2 | typedef __int64 int64_t; 3 | typedef unsigned __int64 uint64_t; 4 | #else 5 | #include 6 | #endif 7 | -------------------------------------------------------------------------------- /ddtrace/profiling/_build.pyx: -------------------------------------------------------------------------------- 1 | import typing 2 | 3 | 4 | compiled_with: typing.Tuple[int, int, int] = (PY_MAJOR_VERSION, PY_MINOR_VERSION, PY_MICRO_VERSION) 5 | -------------------------------------------------------------------------------- /ddtrace/profiling/_traceback.py: -------------------------------------------------------------------------------- 1 | import traceback 2 | 3 | 4 | def format_exception(e): 5 | return traceback.format_exception_only(type(e), e)[0].rstrip() 6 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-django-correct-legacy-resource-c27c7402b6b0be37.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | django: add legacy resource format of `{handler}`. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/grpc-client-measured-span-aa043d35bfe71238.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | gRPC client spans are now marked as measured by default. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/profiling-fix-newline-error-8d4d10ed61143e16.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fix a formatting issue on error exporting profiles. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/pymongo-double-patching-topology-dd90eda48daa051c.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fix double patching of ``pymongo`` client topology. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/runtimeid-39dfdf1e0c1af45d.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fix runtime-id and system.pid tags not being set on distributed traces. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/tornado-none-bug-85faed75c859f5e5.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | tornado: handle when the current span is None in log_exception(). 5 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Datadog dd-trace-py 2 | Copyright 2016-Present Datadog, Inc. 3 | 4 | This product includes software developed at Datadog, Inc. (https://www.datadoghq.com/). 5 | -------------------------------------------------------------------------------- /releasenotes/notes/cherrypy-first-version-89893f512b2fa083.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | cherrypy: introduce TraceMiddleware for the CherryPy web framework. -------------------------------------------------------------------------------- /releasenotes/notes/django-request-uri-safe-guards-fdd8bd664374ded1.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | django: add safe guards for building http.url span tag. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/drop-gevent-10-438387fecc241e60.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | Support for gevent 1.0 has been removed and gevent >= 1.1 is required. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-django-db-postgres-7aa62a1c3aff647d.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | django: fix a bug when postgres query is composable sql object. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/fix.urllib3.integration-610312498fcdce86.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fix ``urllib3`` patching not properly activating the integration. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/flask-codes-f0841d78ec847807.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | flask: deprecated configuration option `extra_error_codes` has been removed. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/gevent-pynamodb-fix-72ac7017e51fd4f9.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Patch pynamodb on import to prevent patching conflicts with gevent. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/perf-celery-reduced-overheads-6afe03acf1af703f.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Performance of the Celery integration has been improved. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/remove-apptypes-76c78d46c1792863.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | Removed `ddtrace.ext.AppTypes` and its usages in the tracer library. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/utils-remove-merge-dicts-9252805c864677f8.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | The function ``ddtrace.utils.merge_dicts`` has been removed. 5 | -------------------------------------------------------------------------------- /tests/commands/ddtrace_run_argv.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | 4 | if __name__ == "__main__": 5 | assert sys.argv[1:] == ["foo", "bar"] 6 | print("Test success") 7 | -------------------------------------------------------------------------------- /hooks/scripts/run-black.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | staged_files=$(git diff --staged --name-only HEAD --diff-filter=ACMR | grep -E '\.py$') 3 | riot -v run -s black $staged_files 4 | -------------------------------------------------------------------------------- /hooks/scripts/run-flake8.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | staged_files=$(git diff --staged --name-only HEAD --diff-filter=ACMR | grep -E '\.py$') 3 | riot -v run -s flake8 $staged_files 4 | -------------------------------------------------------------------------------- /releasenotes/notes/django-9ce233836fca5d93.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | The legacy Django configuration method (deprecated in 0.34) has 5 | been removed. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/feature-injectr-trace-sqs-send-message-035dc3300db0cad0.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | botocore: inject tracing data to `MessageAttributes`. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-django-str-tags-ad4f0b9e2d0eff12.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fixed the handling of the Django template name tag causing type errors. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/profiling-no-flush-on-fork-c6c2b3c2d27a9a32.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fixed an issue in profiling exporting profiles twice when forking. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/profiling-task-pprof-3afb83e36a63aeaf.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | The profiler now exports active tasks for CPU and wall time profiles. 5 | -------------------------------------------------------------------------------- /tests/commands/ddtrace_run_enabled.py: -------------------------------------------------------------------------------- 1 | from ddtrace import tracer 2 | 3 | 4 | if __name__ == "__main__": 5 | assert tracer.enabled 6 | print("Test success") 7 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-botocore-missing-response-meta-e80c1cfb34ec0881.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | botocore: Do not assume that ResponseMeta exists in the results. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/flask-fix-query-encoding-ef177f8c9c7a679a.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | flask: fix a bug when the query string would contain non-Unicode characters 5 | -------------------------------------------------------------------------------- /releasenotes/notes/profiling-remove-profile-fbf8e32388899b05.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | The deprecated compatibility module `ddtrace.profile` has been removed. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/profiling-remove-uncaught-exception-be09cc1bca6b7af6.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | deprecations: 3 | - | 4 | The profiler does not catch uncaught exception anymore. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/pyramid-config-7db0cb8f089c9417.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | Added `config.pyramid.distributed_tracing` setting to integration config for pyramid. 5 | -------------------------------------------------------------------------------- /ddtrace/opentracer/__init__.py: -------------------------------------------------------------------------------- 1 | from .helpers import set_global_tracer 2 | from .tracer import Tracer 3 | 4 | 5 | __all__ = [ 6 | "Tracer", 7 | "set_global_tracer", 8 | ] 9 | -------------------------------------------------------------------------------- /releasenotes/notes/elasticsearch-0a97722c93d66016.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | elasticsearch: patch versioned elasticsearch modules (elasticsearch1, ..., elasticsearch7). 5 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-django-db-connections-b9b98a7b49f27c5f.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | django: fix a bug where multiple database backends would not be instrumented. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-sanic-resource-name-e9f5b0417f3cda13.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | sanic: use path parameter names instead of parameter values for the resource. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/profiling-fix-deadlock-gevent-1e6192828238def3.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | The profiler won't deadlock on fork when gevent monkey patch is enabled. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/profiling-threading-tracing-6877348333bbaa80.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | The profiler now captures the traces information with the lock profiling. 5 | -------------------------------------------------------------------------------- /scripts/build-docs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | reno lint 6 | sphinx-build -W -b spelling docs docs/_build/html 7 | sphinx-build -W -b html docs docs/_build/html 8 | -------------------------------------------------------------------------------- /tests/commands/ddtrace_run_app_name.py: -------------------------------------------------------------------------------- 1 | from ddtrace.opentracer import Tracer 2 | 3 | 4 | if __name__ == "__main__": 5 | tracer = Tracer() 6 | print(tracer._service_name) 7 | -------------------------------------------------------------------------------- /tests/commands/ddtrace_run_env.py: -------------------------------------------------------------------------------- 1 | from ddtrace import tracer 2 | 3 | 4 | if __name__ == "__main__": 5 | assert tracer.tags["env"] == "test" 6 | print("Test success") 7 | -------------------------------------------------------------------------------- /hooks/scripts/run-codespell.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | staged_files=$(git diff --staged --name-only HEAD --diff-filter=ACMR | grep -E '\.py$') 3 | riot -v run -s hook-codespell $staged_files 4 | -------------------------------------------------------------------------------- /releasenotes/notes/docs-gunicorn-bd0db8c3c25c7deb.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | Documentation on how to use Gunicorn with the ``gevent`` worker class has 5 | been added. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/profiling-tags-api-f4d732d3c31ee2cf.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | The `Profiler` object can now be passed tags with the `tags` keyword 5 | argument. 6 | -------------------------------------------------------------------------------- /tests/contrib/django/compat.py: -------------------------------------------------------------------------------- 1 | __all__ = ["reverse"] 2 | 3 | try: 4 | from django.core.urlresolvers import reverse 5 | except ImportError: 6 | from django.urls import reverse 7 | -------------------------------------------------------------------------------- /ddtrace/contrib/__init__.py: -------------------------------------------------------------------------------- 1 | from ..utils.importlib import func_name # noqa 2 | from ..utils.importlib import module_name # noqa 3 | from ..utils.importlib import require_modules # noqa 4 | -------------------------------------------------------------------------------- /ddtrace/ext/net.py: -------------------------------------------------------------------------------- 1 | """ 2 | Standard network tags. 3 | """ 4 | 5 | # request targets 6 | TARGET_HOST = "out.host" 7 | TARGET_PORT = "out.port" 8 | 9 | BYTES_OUT = "net.out.bytes" 10 | -------------------------------------------------------------------------------- /releasenotes/notes/perf-improve-header-extraction-30f575d5034b7e20.yaml: -------------------------------------------------------------------------------- 1 | other: 2 | - | 3 | The logic behind the header extraction for distributed tracing has been 4 | improved. 5 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [bdist_wheel] 2 | universal=1 3 | 4 | [codespell] 5 | skip = *.c,.riot,.tox,.mypy_cache,.git,*ddtrace/vendor 6 | ignore-words-list = dne,fo,medias,ment,nin,ot,setttings,statics 7 | -------------------------------------------------------------------------------- /releasenotes/notes/bottle-int-config-6772ca40a3954399.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | Added environment variable `DD_BOTTLE_DISTRIBUTED_TRACING` to enable distributed tracing for bottle. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/falcon-int-config-a85b605cac4a7dbc.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | Added environment variable `DD_FALCON_DISTRIBUTED_TRACING` to enable distributed tracing for falcon. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-container-id-cgroup-parsing-28790e02a2ac0adc.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | CGroup file parsing was fixed to correctly parse container ID with preceding characters. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/profiler-uds-108b876bdab8a151.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | The profiler is now able to upload profiles to the Datadog Agent by using a 5 | Unix Domain Socket. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/pylons-int-config-b500a59f78297b88.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | Added environment variable `DD_PYLONS_DISTRIBUTED_TRACING` to enable distributed tracing for pylons. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/pytest-d174e595f0c8abd0.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | pytest integration. 5 | This enables the `pytest `_ runner to trace test executions. 6 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/__init__.py: -------------------------------------------------------------------------------- 1 | __version__ = "0.1.0" 2 | __version_info__ = tuple([int(num) if num.isdigit() else num for num in __version__.replace("-", ".", 1).split(".")]) 3 | -------------------------------------------------------------------------------- /ddtrace/ext/db.py: -------------------------------------------------------------------------------- 1 | # tags 2 | NAME = "db.name" # the database name (eg: dbname for pgsql) 3 | USER = "db.user" # the user connecting to the db 4 | ROWCOUNT = "db.rowcount" # the rowcount of a query 5 | -------------------------------------------------------------------------------- /releasenotes/notes/configure-6973c2ed2105a1c0.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | The deprecated `dogstatsd_host` and `dogstatsd_port` arguments to 5 | `tracer.configure()` have been removed. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/deprecate-pyddprofile-41de3d099775ee0c.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | deprecations: 3 | - | 4 | The `pyddprofile` wrapper is deprecated. Use `DD_PROFILING_ENABLED=true ddtrace-run` instead. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-grpc-streaming-next-5acf03fec7056a48.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | grpc: fix wrapper for streaming response to support libraries that call an internal method directly. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/profiler-url-c61885c7d1fd5ea6.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | It is now possible to pass a `url` parameter to the `Profiler` to specify 5 | the Datadog agent location. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/profiling-export-tags-fixed-9d383890c8e5c4c1.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | The profiler will only load tags from the DD_TAGS environment variable 5 | once at start. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/profiling-stack-exception-sample-trace-49228a2ce81b32ca.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | The exception profiler now gathers and exports the traces and spans information. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/span-22c2917b9580c0e6.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | ``Span`` now accepts a ``on_finish`` argument used for specifying 5 | functions to call when a span finishes. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/tornado-int-config-a8900a60201d4d61.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | Added environment variable `DD_TORNADO_DISTRIBUTED_TRACING` to enable distributed tracing for tornado. 5 | -------------------------------------------------------------------------------- /tests/commands/ddtrace_run_patched_modules.py: -------------------------------------------------------------------------------- 1 | from ddtrace import monkey 2 | 3 | 4 | if __name__ == "__main__": 5 | assert "redis" in monkey.get_patched_modules() 6 | print("Test success") 7 | -------------------------------------------------------------------------------- /tests/commands/ddtrace_run_priority_sampling.py: -------------------------------------------------------------------------------- 1 | from ddtrace import tracer 2 | 3 | 4 | if __name__ == "__main__": 5 | assert tracer.priority_sampler is not None 6 | print("Test success") 7 | -------------------------------------------------------------------------------- /tests/profiling/test_traceback.py: -------------------------------------------------------------------------------- 1 | from ddtrace.profiling import _traceback 2 | 3 | 4 | def test_traceback(): 5 | assert _traceback.format_exception(Exception("hello")) == "Exception: hello" 6 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/static/images/favicons/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coiled/dd-trace-py/master/benchmarks/django_simple/ddtrace_django/static/images/favicons/favicon.ico -------------------------------------------------------------------------------- /releasenotes/notes/botocore-distributed-tracing-config-cd37b439d6d77dc6.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | botocore: added `distributed_tracing` configuration setting which is enabled by default. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/deprecate-compat-c70f99dc038bc947.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | deprecations: 3 | - | 4 | `ddtrace.compat` has been deprecated and will be removed from the public API in ddtrace version 1.0.0. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/feature-inject-trace-lambda-invoke-818866a5de2015a9.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | botocore: inject distributed tracing data to `ClientContext` to trace lambda invocations. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-dbapi-rowcount-guard-6c6455278f15d262.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | dbapi: avoid type error with potential non-compliance in db libraries when setting tag for row count. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/gevent-warning-f91ed0e6cac71a21.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | A warning has been added to alert when gevent monkey patching is done after 5 | ddtrace has been imported. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/profiling-remove-tracemalloc-memory-collector-7a98634e0d9672a6.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | The tracemalloc memory profiler, which was disabled by default, has been removed. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/pytest-patch-all-05b2c812bf6ce0c2.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | The ddtrace pytest plugin can now call ``ddtrace.patch_all`` via the 5 | ``--ddtrace-patch-all`` option. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/pytest-service-name-8c9d0f37b159a561.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | The pytest integration now uses the name of the repository being tested as the default test service name. 5 | -------------------------------------------------------------------------------- /tests/commands/ddtrace_run_hostname.py: -------------------------------------------------------------------------------- 1 | from ddtrace import tracer 2 | 3 | 4 | if __name__ == "__main__": 5 | assert tracer.writer.agent_url == "http://172.10.0.1:8120" 6 | print("Test success") 7 | -------------------------------------------------------------------------------- /tests/contrib/django/asgi.py: -------------------------------------------------------------------------------- 1 | from django.core.asgi import get_asgi_application 2 | 3 | from ddtrace.contrib.asgi import TraceMiddleware 4 | 5 | 6 | application = TraceMiddleware(get_asgi_application()) 7 | -------------------------------------------------------------------------------- /tests/contrib/django/templates/cached_list.html: -------------------------------------------------------------------------------- 1 | {% load cache %} 2 | 3 | {% cache 60 users_list %} 4 | {% for user in object_list %} 5 | {{ user }} 6 | {% endfor %} 7 | {% endcache %} 8 | -------------------------------------------------------------------------------- /ddtrace/profiling/auto.py: -------------------------------------------------------------------------------- 1 | """Automatically starts a collector when imported.""" 2 | from ddtrace.profiling.bootstrap import sitecustomize # noqa 3 | 4 | 5 | start_profiler = sitecustomize.start_profiler 6 | -------------------------------------------------------------------------------- /releasenotes/notes/deprecate-ddtrace-encoding-84ffb8a36694161f.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | deprecations: 3 | - | 4 | The use of ``ddtrace.encoding`` has been deprecated and will be removed 5 | in version 1.0.0. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-sampler_sample_rate_bug-b93ffc6036982ba8.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | sampler: removed bug causing sample_rate of 0 to be reset to 1, and raise ValueError instead of logging. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-span-finish-signature-b0c1073b56c3b559.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fixed the optional argument of ``Span.finish`` to ``Optional[float]`` 5 | instead of ``Optional[int]``. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/profiling-ignore-profiler-daa056f8384008dc.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | The profiler won't be ignoring its own resource usage anymore and will 5 | report it in the profiles. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/pytest-parameters-7d6acf4ca1419be0.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | The pytest plugin now includes support for automatically tagging spans with parameters in parameterized tests. 5 | -------------------------------------------------------------------------------- /tests/contrib/tornado/web/uimodules.py: -------------------------------------------------------------------------------- 1 | import tornado 2 | 3 | 4 | class Item(tornado.web.UIModule): 5 | def render(self, item): 6 | return self.render_string("templates/item.html", item=item) 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | ## License 2 | 3 | This work is dual-licensed under Apache 2.0 or BSD3. 4 | You may select, at your option, one of the above-listed licenses. 5 | 6 | `SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause` 7 | -------------------------------------------------------------------------------- /ddtrace/settings/exceptions.py: -------------------------------------------------------------------------------- 1 | class ConfigException(Exception): 2 | """Configuration exception when an integration that is not available 3 | is called in the `Config` object. 4 | """ 5 | 6 | pass 7 | -------------------------------------------------------------------------------- /releasenotes/notes/feature-pyodbc-52e513ccf4c6a03c.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | pyodbc integration. 5 | This enables the `pyodbc `_ library to trace queries. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/pymongo-config-6e4495f0be97e288.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Added missing pymongo integration configuration, which allows overriding 5 | the service name for all the emitted spans. 6 | -------------------------------------------------------------------------------- /tests/commands/ddtrace_run_debug.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | from ddtrace import tracer 4 | 5 | 6 | if __name__ == "__main__": 7 | assert tracer.log.isEnabledFor(logging.DEBUG) 8 | print("Test success") 9 | -------------------------------------------------------------------------------- /benchmarks/startup/meta.yaml: -------------------------------------------------------------------------------- 1 | name: startup-scenario 2 | run: "python run.py" 3 | iterations: 5 4 | variants: 5 | none: 6 | env: 7 | DDTRACE: "0" 8 | import: 9 | env: 10 | DDTRACE: "1" 11 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-mako-template-filename-31efcdb8592758c6.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fix a bug when tracing a mako ``DefTemplate`` or any ``Template`` that does 5 | not have a ``filename`` property. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/profiling-fix-ignore-profiler-gevent-stack-collector-3270d81c84080ccb.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fix CPU time and wall time profiling not ignoring the profiler tasks with 5 | gevent. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/tracer-upload-retry-d60310aa6c91059d.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Added retry logic to the tracer to mitigate potential networking issues, 5 | like timeouts or dropped connections. 6 | -------------------------------------------------------------------------------- /tests/commands/ddtrace_run_no_debug.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | from ddtrace import tracer 4 | 5 | 6 | if __name__ == "__main__": 7 | assert not tracer.log.isEnabledFor(logging.DEBUG) 8 | print("Test success") 9 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-runtime-default-interval-e3afb49f45296877.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fixes an issue with enabling the runtime worker introduced in v0.49.0 where no runtime metrics were sent to the agent. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/pylons-http-3d542b80b3fc4b48.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | pylons: now supports all the standard http tagging including query string, 5 | custom error codes, and request/response headers. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/startup-logs-4d7acd6fa6b34074.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | Start-up logs are now disabled by default. To enable start-up logs use 5 | `DD_TRACE_STARTUP_LOGS=true` or `DD_TRACE_DEBUG=true`. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/depends-on-attrs-19687d5b7a597744.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | The `attrs` library has been unvendored and is now required as a normal Python dependency 5 | with a minimum version requirement of 19.2.0. -------------------------------------------------------------------------------- /releasenotes/notes/depends-on-six-e9b79edbf0d169a2.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | The `six` library has been removed from `vendor` and the system-wide version 5 | is being used. It requires version 1.12.0 or later. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/feature-service-mapping-b1c6cf37a5ad6417.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Introduce support for the DD_SERVICE_MAPPING environment variable to allow 5 | remapping service names on emitted spans. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/profiling-timeout-10s-a2468ce1444887b5.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | The default agent timeout for profiling has been restored from 2 to 10 5 | seconds to avoid too many profiles from being dropped. 6 | -------------------------------------------------------------------------------- /ddtrace/contrib/pylons/compat.py: -------------------------------------------------------------------------------- 1 | try: 2 | from pylons.templating import render_mako # noqa 3 | 4 | # Pylons > 0.9.7 5 | legacy_pylons = False 6 | except ImportError: 7 | # Pylons <= 0.9.7 8 | legacy_pylons = True 9 | -------------------------------------------------------------------------------- /releasenotes/notes/botocore-no-body-params-a440cd8b7fb9bd68.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | The botocore integration excludes AWS endpoint call parameters that have a 5 | name ending with ``Body`` from the set of span tags. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/datadog-lambda-extension-6ae77025f24a82cc.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Adds support for the Datadog Lambda Extension. The tracer will send traces 5 | to the extension by default if it is present. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/deprecate-monkey-functions-01f8080ab711ae74.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | deprecations: 3 | - | 4 | ``monkey.patch_module`` is deprecated. 5 | - | 6 | ``monkey.get_patch_module`` is deprecated. 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /releasenotes/notes/profiling-remove-pyddprofile-1a699c195d9d3ab0.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | The deprecated ``pyddprofile`` wrapper has been removed. Use 5 | ``ddtrace-run`` with ``DD_PROFILING_ENABLED=1`` set instead. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-monkey-patch-on-import-7bbf81bcd2a86f11.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fixed a bug that prevented the right integration name to be used when 5 | trying to patch a module on import that is already loaded. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/profiler-stack-greenlet-tracer-6f960c1557fd39c4.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | The profiler now tracks the running gevent Greenlet and store it as part 5 | of the CPU and wall time profiling information. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/profiling-heap-profiler-enabling-186ae7679b84d39a.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | The Python heap profiler can now be enabled by setting the 5 | ``DD_PROFILING_HEAP_ENABLED`` environment variable to ``1``. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/span-pprint-json-855d32f50798fd8d.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | The return value of ``Span.pprint()`` has been changed to a single line in the tracer debug logs rather than the previous custom multiline format. 5 | -------------------------------------------------------------------------------- /tests/commands/ddtrace_run_service.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | if __name__ == "__main__": 5 | assert os.getenv("DATADOG_SERVICE_NAME") == "my_test_service" or os.getenv("DD_SERVICE") == "my_test_service" 6 | print("Test success") 7 | -------------------------------------------------------------------------------- /ddtrace/vendor/wrapt/setup.py: -------------------------------------------------------------------------------- 1 | __all__ = ["get_extensions"] 2 | 3 | from setuptools import Extension 4 | 5 | 6 | def get_extensions(): 7 | return [Extension("ddtrace.vendor.wrapt._wrappers", sources=["ddtrace/vendor/wrapt/_wrappers.c"],)] 8 | -------------------------------------------------------------------------------- /releasenotes/notes/django-key-error-be8812133f0ef920.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Resolves an issue in Django tracing where, 5 | if `query_string` is not present in request.META, a KeyError is raised, causing the request to 500 6 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-fargate-cgroup-parsing-9ba690fc7e2e57f4.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | The tracer now captures the task ID from the cgroups file for Fargate >= 1.4.0 5 | and reports it to the agent as the Datadog-Container-ID tag. -------------------------------------------------------------------------------- /releasenotes/notes/fix-logging-strformatstyle-9c02e1d024961c0f.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fix DD_LOGS_INJECTION incompatibility when using a ``logging.StrFormatStyle`` (``logging.Formatter(fmt, style="{")``) 5 | log formatter. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/profiling-default-timeout-agent-43b19237a21fd337.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | The default connection timeout for the profiling agent has now been reduced 5 | from 10 to 2 seconds to match the tracer behavior. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/botocore-exclude-records--74ac3e5d4d4fdc95.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | The ``Records`` parameter to ``Firehose`` endpoint calls is being excluded from the 5 | tags to avoid generating traces with a large payload. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/ci-providers-git-metadata-6229ff3cf9a347d9.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | The pytest plugin now includes git metadata tags including author name and email as well as commit message 5 | from CI provider environments. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/profiler-gevent-warns-on-late-patch-3f4f897c8904591c.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | The `ddtrace.profiling.auto` module will warn users if gevent monkey 5 | patching is done after the profiler is auto-instrumented. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/restart-profiler-fork-9bfaec1942112026.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | The Profiler instances now restart automatically in child process when the 5 | main program is forked. 6 | This only works for Python ≥ 3.7. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/tracer-200a66ebb04f6cb0.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | The ``Tracer`` class properties DEFAULT_HOSTNAME, DEFAULT_PORT, 5 | DEFAULT_DOGSTATSD_PORT, DEFAULT_DOGSTATSD_URL, DEFAULT_AGENT_URL have been 6 | removed. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-grpc-streaming-prefetch-95e816bd0fd85723.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | grpc: Add done callback in streaming response to avoid unfinished spans if a `StopIteration` is never raised, as is found in the Google Cloud libraries. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-logger-standard-logging-rate-envvar-155e113deea71e85.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Deprecate the DD_LOGGING_RATE_LIMIT variable in favor of the standard 5 | DD_TRACE_LOGGING_RATE for configuring the logging rate limit. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/fork-leak-74288f3ce2a2bc28.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | A possible memory leak that occurs when tracing across a fork has been 5 | fixed. See https://github.com/DataDog/dd-trace-py/pull/2497 for more 6 | information. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/null-trace-propagation-95ca602d2cc05ea1.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | When extracting context information from HTTP headers, a new context is 5 | created when the trace ID is either 0 or not available within the headers. 6 | -------------------------------------------------------------------------------- /docs/shared.rst: -------------------------------------------------------------------------------- 1 | .. _setup documentation: https://docs.datadoghq.com/tracing/setup/python/ 2 | 3 | .. _official documentation: https://docs.datadoghq.com/tracing/visualization/ 4 | 5 | .. _development guide: https://github.com/datadog/dd-trace-py#development 6 | -------------------------------------------------------------------------------- /releasenotes/notes/add-py27-windows-support-a624cbc63b8f90de.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fix broken builds for Python 2.7 on windows where ```` was not available. 5 | This change also ensures we build and publish ``cp27-win`` wheels. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/grpc-future-callback-a3cc27b11df34eef.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fixes issue of unfinished spans when response is not a `grpc.Future` but has the same interface, as is the case with the base future class in `google-api-core`. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/profiling-lower-max-cpu-usage-default-59458d90e0d6d33d.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | The default maximum CPU time used for the stack profiler (CPU time, wall 5 | time and exceptions profiling) has been decreased from 2% to 1%. 6 | -------------------------------------------------------------------------------- /tests/commands/ddtrace_run_disabled.py: -------------------------------------------------------------------------------- 1 | from ddtrace import monkey 2 | from ddtrace import tracer 3 | 4 | 5 | if __name__ == "__main__": 6 | assert not tracer.enabled 7 | assert len(monkey.get_patched_modules()) == 0 8 | print("Test success") 9 | -------------------------------------------------------------------------------- /tests/commands/ddtrace_run_gevent.py: -------------------------------------------------------------------------------- 1 | import socket 2 | 3 | import gevent.socket 4 | 5 | 6 | # https://stackoverflow.com/a/24770674 7 | if __name__ == "__main__": 8 | assert socket.socket is gevent.socket.socket 9 | print("Test success") 10 | -------------------------------------------------------------------------------- /tests/commands/ddtrace_run_global_tags.py: -------------------------------------------------------------------------------- 1 | from ddtrace import tracer 2 | 3 | 4 | if __name__ == "__main__": 5 | assert tracer.tags["a"] == "True" 6 | assert tracer.tags["b"] == "0" 7 | assert tracer.tags["c"] == "C" 8 | print("Test success") 9 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/contrib/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | To understand why this file is here, please read: 3 | 4 | http://cookiecutter-django.readthedocs.io/en/latest/faq.html#why-is-there-a-django-contrib-sites-directory-in-cookiecutter-django 5 | """ 6 | -------------------------------------------------------------------------------- /releasenotes/notes/es-92a00e4a03a65da6.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | elasticsearch: add support for version 7. 5 | upgrade: 6 | - | 7 | elasticsearch: removed `get_traced_transport` method and `ddtrace.contrib.elasticsearch.transport` module. 8 | 9 | -------------------------------------------------------------------------------- /releasenotes/notes/pymemcache-update-c6d830daa541b3c8.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fix issue with missing traces when using ``pymemcache.client.hash.HashClient``. 5 | 6 | other: 7 | - | 8 | Update ``pymemcache`` test suite to test latest versions. 9 | -------------------------------------------------------------------------------- /releasenotes/notes/url-7d1cb4e659ebca31.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | A `ValueError` will now be raised on tracer initialization if the Agent URL specified to the initializer or with 5 | the environment variable `DD_TRACE_AGENT_URL` is malformed. 6 | -------------------------------------------------------------------------------- /tests/commands/ddtrace_run_profiling.py: -------------------------------------------------------------------------------- 1 | from ddtrace.profiling import bootstrap 2 | 3 | 4 | if __name__ == "__main__": 5 | if hasattr(bootstrap, "profiler"): 6 | print(str(bootstrap.profiler.status)) 7 | else: 8 | print("NO PROFILER") 9 | -------------------------------------------------------------------------------- /ddtrace/contrib/tornado/constants.py: -------------------------------------------------------------------------------- 1 | """ 2 | This module defines Tornado settings that are shared between 3 | integration modules. 4 | """ 5 | CONFIG_KEY = "datadog_trace" 6 | REQUEST_SPAN_KEY = "__datadog_request_span" 7 | FUTURE_SPAN_KEY = "__datadog_future_span" 8 | -------------------------------------------------------------------------------- /scripts/stubgen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | for file in ddtrace/profiling/_build.pyx \ 3 | ddtrace/profiling/exporter/pprof.pyx 4 | do 5 | stubgen "$file" 6 | mv out/__main__.pyi $(dirname "$file")/$(basename "$file" .pyx).pyi 7 | done 8 | rmdir out 9 | -------------------------------------------------------------------------------- /tests/contrib/__init__.py: -------------------------------------------------------------------------------- 1 | # Do *NOT* `import ddtrace` in here 2 | # DEV: Some tests rely on import order of modules 3 | # in order to properly function. Importing `ddtrace` 4 | # here would mess with those tests since everyone 5 | # will load this file by default 6 | -------------------------------------------------------------------------------- /tests/contrib/pylons/test.ini: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | debug = false 3 | 4 | [app:main] 5 | use = call:tests.contrib.pylons.app.web:make_app 6 | full_stack = true 7 | cache_dir = %(here)s/.cache 8 | beaker.session.key = helloworld 9 | beaker.session.secret = somesecret 10 | -------------------------------------------------------------------------------- /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | omit = ddtrace/vendor/* 3 | 4 | # Ignore warnings when we run as Python 2.7 and have a Python 3.x file 5 | disable_warnings = couldnt-parse 6 | 7 | [paths] 8 | source = 9 | ./ 10 | /home/circleci/project/ 11 | /root/project/ 12 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/contrib/sites/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | To understand why this file is here, please read: 3 | 4 | http://cookiecutter-django.readthedocs.io/en/latest/faq.html#why-is-there-a-django-contrib-sites-directory-in-cookiecutter-django 5 | """ 6 | -------------------------------------------------------------------------------- /ddtrace/ext/cassandra.py: -------------------------------------------------------------------------------- 1 | # tags 2 | CLUSTER = "cassandra.cluster" 3 | KEYSPACE = "cassandra.keyspace" 4 | CONSISTENCY_LEVEL = "cassandra.consistency_level" 5 | PAGINATED = "cassandra.paginated" 6 | ROW_COUNT = "cassandra.row_count" 7 | PAGE_NUMBER = "cassandra.page_number" 8 | -------------------------------------------------------------------------------- /releasenotes/notes/deprecate-ddtrace-http-ce198e779de69237.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | deprecations: 3 | - | 4 | The `ddtrace.http` module has been deprecated and will be removed in version 1.0.0, 5 | with the `ddtrace.http.headers` module now merged into `ddtrace.trace_utils`. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-manual-runtime-metrics-0873e17de485f8b0.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fixes an issue when trying to manually start the runtime metrics worker:: 5 | 6 | AttributeError: module 'ddtrace.internal.runtime' has no attribute 'runtime_metrics' 7 | -------------------------------------------------------------------------------- /releasenotes/notes/os-runtime-metadata-98845c31e21f6ea2.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | The CI tagging for the pytest plugin now includes OS and Python Runtime metadata including 5 | system architecture, platform, version, and Python runtime name and version. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/pytest-xfail-c15914f8ae3281c9.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | The ddtrace pytest plugin can now label spans from test cases marked xfail with the tag "pytest.result" 5 | and the reason for being marked xfail under the tag "pytest.xfail.reason". -------------------------------------------------------------------------------- /tests/profiling/conftest.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import pytest 4 | 5 | 6 | @pytest.fixture(scope="session", autouse=True) 7 | def disable_coverage_for_subprocess(): 8 | try: 9 | del os.environ["COV_CORE_SOURCE"] 10 | except KeyError: 11 | pass 12 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/contrib/sites/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | To understand why this file is here, please read: 3 | 4 | http://cookiecutter-django.readthedocs.io/en/latest/faq.html#why-is-there-a-django-contrib-sites-directory-in-cookiecutter-django 5 | """ 6 | -------------------------------------------------------------------------------- /ddtrace/contrib/sqlite3/connection.py: -------------------------------------------------------------------------------- 1 | from sqlite3 import Connection 2 | 3 | from ...utils.deprecation import deprecated 4 | 5 | 6 | @deprecated(message="Use patching instead (see the docs).", version="1.0.0") 7 | def connection_factory(*args, **kwargs): 8 | return Connection 9 | -------------------------------------------------------------------------------- /ddtrace/ext/elasticsearch.py: -------------------------------------------------------------------------------- 1 | SERVICE = "elasticsearch" 2 | APP = "elasticsearch" 3 | 4 | # standard tags 5 | URL = "elasticsearch.url" 6 | METHOD = "elasticsearch.method" 7 | TOOK = "elasticsearch.took" 8 | PARAMS = "elasticsearch.params" 9 | BODY = "elasticsearch.body" 10 | -------------------------------------------------------------------------------- /tests/contrib/django/django_app/extra_urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url 2 | from django.http import HttpResponse 3 | 4 | 5 | def include_view(request): 6 | return HttpResponse(status=200) 7 | 8 | 9 | urlpatterns = [ 10 | url("test/", include_view), 11 | ] 12 | -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | sphinx: 4 | builder: html 5 | configuration: docs/conf.py 6 | fail_on_warning: false 7 | 8 | python: 9 | version: 3.8 10 | install: 11 | - requirements: docs/requirements.txt 12 | - method: setuptools 13 | path: . 14 | -------------------------------------------------------------------------------- /tests/vendor/test_dogstatsd.py: -------------------------------------------------------------------------------- 1 | from ddtrace.internal.logger import DDLogger 2 | from ddtrace.vendor.dogstatsd.base import log 3 | 4 | 5 | def test_dogstatsd_logger(): 6 | """Ensure dogstatsd logger is initialized as a rate limited logger""" 7 | assert isinstance(log, DDLogger) 8 | -------------------------------------------------------------------------------- /releasenotes/notes/add-dd-trace-agent-timeout-seconds-env-844b53ff0ccc7c9f.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Add new ``DD_TRACE_AGENT_TIMEOUT_SECONDS`` to override the default 5 | connection timeout used when sending data to the trace agent. 6 | The default is ``2.0`` seconds. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/context-3467ab87a70c601e.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - Context.get() has been removed and the functionality has been rolled into 4 | Context.close_span(). 5 | - Tracer.record() has similarly been removed as it is no longer useful with 6 | Context.get() removed. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/profiling-fix-uwsgi-empty-profiles-7dbd5fdd93dea47f.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | In certain circumstances, the profiles generated in a uWSGI application 5 | could have been empty. This is now fixed and the profiler records correctly 6 | the generated events. 7 | -------------------------------------------------------------------------------- /tests/pep562_test/__init__.py: -------------------------------------------------------------------------------- 1 | from ddtrace.internal.compat import ensure_pep562 2 | 3 | 4 | def __getattr__(name): 5 | if name == "deprecated": 6 | raise RuntimeError("bad module attribute!") 7 | return "good module attribute" 8 | 9 | 10 | ensure_pep562(__name__) 11 | -------------------------------------------------------------------------------- /releasenotes/notes/metrics-api-5fb1d572d7f7137e.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | deprecations: 3 | - | 4 | The ``collect_metrics`` argument of the ``tracer.configure`` method has been 5 | deprecated. Runtime metrics should be enabled only via the 6 | ``DD_RUNTIME_METRICS_ENABLED`` environment variable. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/profiling-use-tracer-config-83aa0ae0c2c53086.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | The profiler now uses the tracer configuration is no configuration is provided. 5 | upgrade: 6 | - | 7 | The profiler now uses the tracer configuration is no configuration is provided. 8 | -------------------------------------------------------------------------------- /releasenotes/notes/url-sanitizer-26c7078e37f395c0.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | Query strings are stripped out from URLs by default when setting URL 5 | metadata on a span. This change affects all integrations that store HTTP 6 | metadata, like aiohttp, falcon, requests, urllib3. 7 | -------------------------------------------------------------------------------- /ddtrace/contrib/mysql/tracers.py: -------------------------------------------------------------------------------- 1 | import mysql.connector 2 | 3 | from ...utils.deprecation import deprecated 4 | 5 | 6 | @deprecated(message="Use patching instead (see the docs).", version="1.0.0") 7 | def get_traced_mysql_connection(*args, **kwargs): 8 | return mysql.connector.MySQLConnection 9 | -------------------------------------------------------------------------------- /ddtrace/contrib/pymysql/tracers.py: -------------------------------------------------------------------------------- 1 | import pymysql.connections 2 | 3 | from ...utils.deprecation import deprecated 4 | 5 | 6 | @deprecated(message="Use patching instead (see the docs).", version="1.0.0") 7 | def get_traced_pymysql_connection(*args, **kwargs): 8 | return pymysql.connections.Connection 9 | -------------------------------------------------------------------------------- /ddtrace/ext/kombu.py: -------------------------------------------------------------------------------- 1 | SERVICE = "kombu" 2 | 3 | # net extension 4 | VHOST = "out.vhost" 5 | 6 | # standard tags 7 | EXCHANGE = "kombu.exchange" 8 | BODY_LEN = "kombu.body_length" 9 | ROUTING_KEY = "kombu.routing_key" 10 | 11 | PUBLISH_NAME = "kombu.publish" 12 | RECEIVE_NAME = "kombu.receive" 13 | -------------------------------------------------------------------------------- /releasenotes/notes/add-writer-env-config-7c0916dff4f7f80c.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Add new environment variables to configure the internal trace writer. 5 | 6 | ``DD_TRACE_WRITER_MAX_BUFFER_SIZE``, ``DD_TRACE_WRITER_INTERVAL_SECONDS``, 7 | ``DD_TRACE_WRITER_MAX_PAYLOAD_SIZE_BYTES`` 8 | -------------------------------------------------------------------------------- /releasenotes/notes/remove-deprecated-dbapi-config-b25bc1b236672fed.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | deprecations: 3 | - | 4 | The deprecated dbapi2 configuration has been removed. The 5 | integration-specific configuration should be used instead. Look at the 6 | v0.48.0 release notes for migration instructions. 7 | -------------------------------------------------------------------------------- /docs/release_notes.rst: -------------------------------------------------------------------------------- 1 | Release Notes 2 | ============= 3 | 4 | .. release-notes:: 5 | 6 | 7 | Prior Releases 8 | -------------- 9 | Release notes prior to v0.44.0 can be found in `CHANGELOG.md 10 | `_ in the root 11 | of the repository. 12 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-pytest-parameterize-encoding-b8711d2d7dbb282a.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fixed JSON encoding errors in the pytest plugin for parameterized tests with dictionary parameters with tuple keys. 5 | The pytest plugin now always JSON encodes the string representations of test parameters. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/flask-http-helpers-0167071f46a36e00.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | deprecations: 3 | - | 4 | flask: Use :ref:`HTTP Custom Error Codes ` instead of ``ddtrace.config.flask['extra_error_codes']``. 5 | features: 6 | - | 7 | flask: store request and response headers when auto-instrumented. 8 | -------------------------------------------------------------------------------- /ddtrace/contrib/pylibmc/patch.py: -------------------------------------------------------------------------------- 1 | import pylibmc 2 | 3 | from .client import TracedClient 4 | 5 | 6 | # Original Client class 7 | _Client = pylibmc.Client 8 | 9 | 10 | def patch(): 11 | setattr(pylibmc, "Client", TracedClient) 12 | 13 | 14 | def unpatch(): 15 | setattr(pylibmc, "Client", _Client) 16 | -------------------------------------------------------------------------------- /ddtrace/internal/hostname.py: -------------------------------------------------------------------------------- 1 | import socket 2 | from typing import Optional 3 | 4 | 5 | _hostname = None # type: Optional[str] 6 | 7 | 8 | def get_hostname(): 9 | # type: () -> str 10 | global _hostname 11 | if not _hostname: 12 | _hostname = socket.gethostname() 13 | return _hostname 14 | -------------------------------------------------------------------------------- /ddtrace/vendor/psutil/_psutil_posix.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | int psutil_pid_exists(long pid); 8 | void psutil_raise_for_pid(long pid, char *msg); 9 | -------------------------------------------------------------------------------- /releasenotes/notes/ddtracerun-gevent-928b4050fd96f142.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Add functionality to call gevent.monkey.patch_all() with ddtrace-run by 5 | setting the environment variable DD_GEVENT_PATCH_ALL=true. This ensures 6 | that gevent patching is done as early as possible in the application. 7 | -------------------------------------------------------------------------------- /ddtrace/vendor/dogstatsd/__init__.py: -------------------------------------------------------------------------------- 1 | # Unless explicitly stated otherwise all files in this repository are licensed under the BSD-3-Clause License. 2 | # This product includes software developed at Datadog (https://www.datadoghq.com/). 3 | # Copyright 2015-Present Datadog, Inc 4 | from .base import DogStatsd, statsd # noqa 5 | -------------------------------------------------------------------------------- /releasenotes/notes/feature-starlette-e5171e4b2b2646c3.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | starlette integration resource aggregation 5 | This aggregates endpoints to the starlette application resource that was accessed. 6 | It occurs by default but it is configurable through config.starlette["aggregate_resources"]. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-pytest-parameterized-606fbc3a574c67c6.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fixed JSON encoding errors in the pytest plugin for parameterized tests with complex Python object parameters. 5 | The pytest plugin now defaults to encoding the string representations of non-JSON serializable test parameters. 6 | -------------------------------------------------------------------------------- /tests/tracer/runtime/test_tag_collectors.py: -------------------------------------------------------------------------------- 1 | from ddtrace.internal.runtime import constants 2 | from ddtrace.internal.runtime import tag_collectors 3 | 4 | 5 | def test_values(): 6 | ptc = tag_collectors.PlatformTagCollector() 7 | values = dict(ptc.collect()) 8 | assert constants.PLATFORM_TAGS == set(values.keys()) 9 | -------------------------------------------------------------------------------- /tests/ddtrace_run.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | 5 | # DEV: We must append to sys path before importing ddtrace_run 6 | sys.path.append(".") 7 | from ddtrace.commands import ddtrace_run # noqa 8 | 9 | 10 | os.environ["PYTHONPATH"] = "{}:{}".format(os.getenv("PYTHONPATH"), os.path.abspath(".")) 11 | ddtrace_run.main() 12 | -------------------------------------------------------------------------------- /ddtrace/ext/redis.py: -------------------------------------------------------------------------------- 1 | # defaults 2 | APP = "redis" 3 | DEFAULT_SERVICE = "redis" 4 | 5 | # net extension 6 | DB = "out.redis_db" 7 | 8 | # standard tags 9 | RAWCMD = "redis.raw_command" 10 | CMD = "redis.command" 11 | ARGS_LEN = "redis.args_length" 12 | PIPELINE_LEN = "redis.pipeline_length" 13 | PIPELINE_AGE = "redis.pipeline_age" 14 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/templates/403.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Forbidden (403){% endblock %} 4 | 5 | {% block content %} 6 |

Forbidden (403)

7 | 8 |

{% if exception %}{{ exception }}{% else %}You're not allowed to access this page.{% endif %}

9 | {% endblock content %} 10 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/templates/404.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Page not found{% endblock %} 4 | 5 | {% block content %} 6 |

Page not found

7 | 8 |

{% if exception %}{{ exception }}{% else %}This is not the page you were looking for.{% endif %}

9 | {% endblock content %} 10 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/static/css/project.css: -------------------------------------------------------------------------------- 1 | /* These styles are generated from project.scss. */ 2 | 3 | .alert-debug { 4 | color: black; 5 | background-color: white; 6 | border-color: #d6e9c6; 7 | } 8 | 9 | .alert-error { 10 | color: #b94a48; 11 | background-color: #f2dede; 12 | border-color: #eed3d7; 13 | } 14 | -------------------------------------------------------------------------------- /ddtrace/vendor/psutil/arch/freebsd/proc_socks.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #include 8 | 9 | PyObject* psutil_proc_connections(PyObject* self, PyObject* args); 10 | -------------------------------------------------------------------------------- /tests/contrib/celery/autopatch.py: -------------------------------------------------------------------------------- 1 | from ddtrace import Pin 2 | 3 | 4 | if __name__ == "__main__": 5 | # have to import celery in order to have the post-import hooks run 6 | import celery 7 | 8 | # now celery.Celery should be patched and should have a pin 9 | assert Pin.get_from(celery.Celery) 10 | print("Test success") 11 | -------------------------------------------------------------------------------- /ddtrace/vendor/psutil/arch/freebsd/sys_socks.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2009, Giampaolo Rodola'. 3 | * All rights reserved. 4 | * Use of this source code is governed by a BSD-style license that can be 5 | * found in the LICENSE file. 6 | */ 7 | 8 | #include 9 | 10 | PyObject* psutil_net_connections(PyObject* self, PyObject* args); 11 | -------------------------------------------------------------------------------- /.dd-ci/README.md: -------------------------------------------------------------------------------- 1 | # CI App Python Tracer Feature Tracking 2 | 3 | ## Description: 4 | 5 | The `ci-app-spec.json` file tracks the CI App features supported by 6 | the tracer, currently for pytest spans. This file is then 7 | used in the [datadog-ci-spec](https://github.com/DataDog/datadog-ci-spec/blob/main/.github/workflows/feature-track.yml) 8 | repository. 9 | -------------------------------------------------------------------------------- /releasenotes/notes/profiling-enable-new-memalloc-profiler-default-fac01a6d596b6404.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | The new memory profiler for Python is now enabled by default. This improves 5 | the profiler memory consumption and performance impact. It can still be 6 | disabled by setting `DD_PROFILING_MEMALLOC=0` as an environment variable. 7 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/templates/account/base.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block title %}{% block head_title %}{% endblock head_title %}{% endblock title %} 3 | 4 | {% block content %} 5 |
6 |
7 | {% block inner %}{% endblock %} 8 |
9 |
10 | {% endblock %} 11 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/utils/storages.py: -------------------------------------------------------------------------------- 1 | from storages.backends.s3boto3 import S3Boto3Storage 2 | 3 | 4 | class StaticRootS3Boto3Storage(S3Boto3Storage): 5 | location = "static" 6 | default_acl = "public-read" 7 | 8 | 9 | class MediaRootS3Boto3Storage(S3Boto3Storage): 10 | location = "media" 11 | file_overwrite = False 12 | -------------------------------------------------------------------------------- /ddtrace/contrib/pyramid/constants.py: -------------------------------------------------------------------------------- 1 | SETTINGS_SERVICE = "datadog_trace_service" 2 | SETTINGS_TRACER = "datadog_tracer" 3 | SETTINGS_TRACE_ENABLED = "datadog_trace_enabled" 4 | SETTINGS_DISTRIBUTED_TRACING = "datadog_distributed_tracing" 5 | SETTINGS_ANALYTICS_ENABLED = "datadog_analytics_enabled" 6 | SETTINGS_ANALYTICS_SAMPLE_RATE = "datadog_analytics_sample_rate" 7 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/templates/account/account_inactive.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | 5 | {% block head_title %}{% trans "Account Inactive" %}{% endblock %} 6 | 7 | {% block inner %} 8 |

{% trans "Account Inactive" %}

9 | 10 |

{% trans "This account is inactive." %}

11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /ddtrace/internal/README.md: -------------------------------------------------------------------------------- 1 | # Internal 2 | This internal module is used to define and document an internal only API for `ddtrace`. 3 | 4 | These modules are not intended to be used outside of `ddtrace`. 5 | 6 | The APIs found within `ddtrace.internal` are subject to breaking changes at any time 7 | and do not follow the semver versioning scheme of the `ddtrace` package. 8 | -------------------------------------------------------------------------------- /ddtrace/vendor/psutil/arch/windows/wmi.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | 8 | 9 | #include 10 | 11 | PyObject* psutil_init_loadavg_counter(); 12 | PyObject* psutil_get_loadavg(); 13 | -------------------------------------------------------------------------------- /docs/_templates/navigation.html: -------------------------------------------------------------------------------- 1 | {{ toctree(maxdepth=2, includehidden=theme_sidebar_includehidden, collapse=theme_sidebar_collapse) }} 2 | {% if theme_extra_nav_links %} 3 |
4 |
    5 | {% for text, uri in theme_extra_nav_links.items() %} 6 |
  • {{ text }}
  • 7 | {% endfor %} 8 |
9 | {% endif %} 10 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-deprecate-tracer-reuse-6d989d4acb538013.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | deprecations: 3 | - | 4 | The reuse of a tracer that has been shut down has been deprecated. A new 5 | tracer should be created for generating new traces. 6 | fixes: 7 | - | 8 | The shutdown task is re-registered when a tracer is reused after it has been 9 | shut down. 10 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/templates/account/password_reset_from_key_done.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | {% block head_title %}{% trans "Change Password" %}{% endblock %} 5 | 6 | {% block inner %} 7 |

{% trans "Change Password" %}

8 |

{% trans 'Your password is now changed.' %}

9 | {% endblock %} 10 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/utils/context_processors.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings 2 | 3 | 4 | def settings_context(_request): 5 | """Settings available by default to the templates context.""" 6 | # Note: we intentionally do NOT expose the entire settings 7 | # to prevent accidental leaking of sensitive information 8 | return {"DEBUG": settings.DEBUG} 9 | -------------------------------------------------------------------------------- /benchmarks/django_simple/run: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -o errexit 4 | set -o pipefail 5 | set -o nounset 6 | 7 | ENABLED=${BENCHMARK_TRACING_ENABLED:-"0"} 8 | CMD="gunicorn config.wsgi --bind 0.0.0.0:5000 --chdir=/app --pid gunicorn.pid" 9 | 10 | # if tracer enabled, use prepend command with ddtrace-run 11 | [[ "$ENABLED" == "1" ]] && CMD="ddtrace-run $CMD" 12 | 13 | $CMD 14 | -------------------------------------------------------------------------------- /ddtrace/contrib/asyncio/compat.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | 4 | if hasattr(asyncio, "current_task"): 5 | 6 | def asyncio_current_task(): 7 | try: 8 | return asyncio.current_task() 9 | except RuntimeError: 10 | return None 11 | 12 | 13 | else: 14 | 15 | def asyncio_current_task(): 16 | return asyncio.Task.current_task() 17 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/templates/account/signup_closed.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | 5 | {% block head_title %}{% trans "Sign Up Closed" %}{% endblock %} 6 | 7 | {% block inner %} 8 |

{% trans "Sign Up Closed" %}

9 | 10 |

{% trans "We are sorry, but the sign up is currently closed." %}

11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /ddtrace/vendor/psutil/arch/windows/process_handles.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | PyObject* psutil_get_open_files(long pid, HANDLE processHandle); 11 | -------------------------------------------------------------------------------- /benchmarks/django_simple/summarize_k6.jq: -------------------------------------------------------------------------------- 1 | include "util"; 2 | [.[] | 3 | select(.type=="Point" and .metric == "http_req_duration" and .data.tags.status >= "200")] | 4 | group_by(.data.tags.sirun_variant) | 5 | map({"variant": .[0].data.tags.sirun_variant, 6 | "count": [.[] | .data.value] | length, 7 | "http_req_duration": [.[] | .data.value] | summary, 8 | }) 9 | -------------------------------------------------------------------------------- /ddtrace/ext/__init__.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | 4 | class SpanTypes(Enum): 5 | CACHE = "cache" 6 | CASSANDRA = "cassandra" 7 | ELASTICSEARCH = "elasticsearch" 8 | GRPC = "grpc" 9 | HTTP = "http" 10 | MONGODB = "mongodb" 11 | REDIS = "redis" 12 | SQL = "sql" 13 | TEMPLATE = "template" 14 | TEST = "test" 15 | WEB = "web" 16 | WORKER = "worker" 17 | -------------------------------------------------------------------------------- /releasenotes/notes/requests-b06e324e36e03ae5.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | requests: add global config support. This enables the requests service name to be 5 | configured with ``ddtrace.config.requests['service']`` or the ``DD_REQUESTS_SERVICE`` 6 | environment variable. 7 | upgrade: 8 | - | 9 | requests: spans will no longer inherit the service name from the parent. 10 | -------------------------------------------------------------------------------- /scripts/ddtest: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | CMD=$* 6 | 7 | if [ -z "$CMD" ] 8 | then 9 | CMD=bash 10 | fi 11 | 12 | # install and upgrade tox and riot in case testrunner image has not been updated 13 | docker-compose run -e CIRCLE_NODE_TOTAL -e CIRCLE_NODE_INDEX -e DD_TRACE_AGENT_URL --rm testrunner bash -c "pip install -q --disable-pip-version-check riot==0.6 tox && $CMD" 14 | -------------------------------------------------------------------------------- /ddtrace/vendor/psutil/arch/netbsd/socks.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2009, Giampaolo Rodola'. 3 | * Copyright (c) 2015, Ryo ONODERA. 4 | * All rights reserved. 5 | * Use of this source code is governed by a BSD-style license that can be 6 | * found in the LICENSE file. 7 | */ 8 | 9 | PyObject *psutil_proc_connections(PyObject *, PyObject *); 10 | PyObject *psutil_net_connections(PyObject *, PyObject *); 11 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/templates/500.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Server Error{% endblock %} 4 | 5 | {% block content %} 6 |

Ooops!!! 500

7 | 8 |

Looks like something went wrong!

9 | 10 |

We track these errors automatically, but if the problem persists feel free to contact us. In the meantime, try refreshing.

11 | {% endblock content %} 12 | -------------------------------------------------------------------------------- /ddtrace/settings/__init__.py: -------------------------------------------------------------------------------- 1 | from .._hooks import Hooks 2 | from .config import Config 3 | from .exceptions import ConfigException 4 | from .http import HttpConfig 5 | from .integration import IntegrationConfig 6 | 7 | 8 | # Default global config 9 | _config = Config() 10 | 11 | __all__ = [ 12 | "Config", 13 | "ConfigException", 14 | "HttpConfig", 15 | "Hooks", 16 | "IntegrationConfig", 17 | ] 18 | -------------------------------------------------------------------------------- /tests/profiling/exporter/test_file.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from ddtrace.profiling.exporter import file 4 | 5 | from .. import utils 6 | from ..exporter import test_pprof 7 | 8 | 9 | def test_export(tmp_path): 10 | filename = str(tmp_path / "pprof") 11 | exp = file.PprofFileExporter(filename) 12 | exp.export(test_pprof.TEST_EVENTS, 0, 1) 13 | utils.check_pprof_file(filename + "." + str(os.getpid()) + ".1") 14 | -------------------------------------------------------------------------------- /tests/profiling/run.py: -------------------------------------------------------------------------------- 1 | import os 2 | import runpy 3 | import sys 4 | 5 | 6 | if "DD_PROFILE_TEST_GEVENT" in os.environ: 7 | from gevent import monkey 8 | 9 | monkey.patch_all() 10 | print("=> gevent monkey patching done") 11 | 12 | # TODO Use gevent.monkey once https://github.com/gevent/gevent/pull/1440 is merged? 13 | module = sys.argv[1] 14 | del sys.argv[0] 15 | runpy.run_module(module, run_name="__main__") 16 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/users/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | from django.utils.translation import gettext_lazy as _ 3 | 4 | 5 | class UsersConfig(AppConfig): 6 | name = "ddtrace_django.users" 7 | verbose_name = _("Users") 8 | 9 | def ready(self): 10 | try: 11 | import ddtrace_django.users.signals # noqa F401 12 | except ImportError: 13 | pass 14 | -------------------------------------------------------------------------------- /ddtrace/profiling/collector/_traceback.pyi: -------------------------------------------------------------------------------- 1 | import types 2 | import typing 3 | 4 | # (filename, line number, function name) 5 | FrameType = typing.Tuple[str, int, str] 6 | 7 | def traceback_to_frames( 8 | traceback: types.TracebackType, max_nframes: int 9 | ) -> typing.Tuple[typing.List[FrameType], int]: ... 10 | def pyframe_to_frames(frame: types.FrameType, max_nframes: int) -> typing.Tuple[typing.List[FrameType], int]: ... 11 | -------------------------------------------------------------------------------- /ddtrace/opentracer/helpers.py: -------------------------------------------------------------------------------- 1 | import opentracing 2 | 3 | import ddtrace 4 | 5 | 6 | """ 7 | Helper routines for Datadog OpenTracing. 8 | """ 9 | 10 | 11 | def set_global_tracer(tracer): 12 | """Sets the global tracers to the given tracer.""" 13 | 14 | # overwrite the opentracer reference 15 | opentracing.tracer = tracer 16 | 17 | # overwrite the Datadog tracer reference 18 | ddtrace.tracer = tracer._dd_tracer 19 | -------------------------------------------------------------------------------- /releasenotes/notes/profiling-agentless-feb211ee5e1f454f.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | Support for deprecated `DD_PROFILING_API_URL` environment variable has been 5 | removed. Use `DD_SITE` instead. 6 | - | 7 | Support for deprecated `DD_PROFILING_API_KEY` environment variable has been 8 | removed. Use `DD_API_KEY` instead. 9 | - | 10 | Profiling support for agentless mode must now be explicitly enabled. 11 | -------------------------------------------------------------------------------- /tests/contrib/celery/test_autopatch.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import subprocess 3 | import unittest 4 | 5 | 6 | class DdtraceRunTest(unittest.TestCase): 7 | """Test that celery is patched successfully if run with ddtrace-run.""" 8 | 9 | def test_autopatch(self): 10 | out = subprocess.check_output(["ddtrace-run", "python", "tests/contrib/celery/autopatch.py"]) 11 | assert out.startswith(b"Test success") 12 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | 4 | 5 | ## Checklist 6 | - [ ] Added to the correct milestone. 7 | - [ ] Tests provided or description of manual testing performed is included in the code or PR. 8 | - [ ] Library documentation is updated. 9 | - [ ] [Corp site](https://github.com/DataDog/documentation/) documentation is updated (link to the PR). 10 | -------------------------------------------------------------------------------- /ddtrace/utils/attr.py: -------------------------------------------------------------------------------- 1 | import os 2 | from typing import Callable 3 | from typing import Type 4 | from typing import TypeVar 5 | from typing import Union 6 | 7 | 8 | T = TypeVar("T") 9 | 10 | 11 | def from_env(name, default, value_type): 12 | # type: (str, T, Union[Callable[[Union[str, T, None]], T], Type[T]]) -> Callable[[], T] 13 | def _(): 14 | return value_type(os.environ.get(name, default)) 15 | 16 | return _ 17 | -------------------------------------------------------------------------------- /mypy.ini: -------------------------------------------------------------------------------- 1 | [mypy] 2 | files = ddtrace 3 | show_error_codes = true 4 | warn_unused_ignores = true 5 | warn_unused_configs = true 6 | no_implicit_optional = true 7 | ignore_missing_imports = true 8 | 9 | [mypy-ddtrace.contrib.*] 10 | ignore_errors = true 11 | 12 | [mypy-ddtrace.vendor.*] 13 | ignore_errors = true 14 | 15 | [mypy-ddtrace.opentracer.*] 16 | ignore_errors = true 17 | 18 | [mypy-ddtrace.bootstrap.*] 19 | ignore_errors = true 20 | -------------------------------------------------------------------------------- /ddtrace/http/__init__.py: -------------------------------------------------------------------------------- 1 | from ddtrace.utils.deprecation import deprecation 2 | 3 | from .headers import store_request_headers 4 | from .headers import store_response_headers 5 | 6 | 7 | __all__ = [ 8 | "store_request_headers", 9 | "store_response_headers", 10 | ] 11 | 12 | deprecation( 13 | name="ddtrace.http", 14 | message="The http module has been merged into ddtrace.contrib.trace_utils", 15 | version="1.0.0", 16 | ) 17 | -------------------------------------------------------------------------------- /benchmarks/django_simple/setup: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -o errexit 4 | set -o pipefail 5 | set -o nounset 6 | 7 | # store k6 metrics in temporary file that can be appended to artifact 8 | JSON_OUTPUT="$(mktemp)" 9 | touch $JSON_OUTPUT 10 | 11 | /app/wait 12 | 13 | k6 run --out json=${JSON_OUTPUT} --quiet script.js 14 | 15 | cat $JSON_OUTPUT >> /artifacts/output/k6.ndjson 16 | 17 | # sigterm to server to end iteration 18 | pkill -f gunicorn.pid 19 | -------------------------------------------------------------------------------- /benchmarks/django_simple/wait: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import urllib.request 3 | 4 | from tenacity import retry 5 | from tenacity import stop_after_attempt 6 | from tenacity import wait_fixed 7 | 8 | 9 | @retry( 10 | wait=wait_fixed(5), 11 | stop=stop_after_attempt(50), 12 | ) 13 | def wait_for_app(url="http://localhost:5000"): 14 | return urllib.request.urlopen(url) 15 | 16 | 17 | if __name__ == "__main__": 18 | wait_for_app() 19 | -------------------------------------------------------------------------------- /ddtrace/contrib/pylibmc/addrs.py: -------------------------------------------------------------------------------- 1 | translate_server_specs = None 2 | 3 | try: 4 | # NOTE: we rely on an undocumented method to parse addresses, 5 | # so be a bit defensive and don't assume it exists. 6 | from pylibmc.client import translate_server_specs 7 | except ImportError: 8 | pass 9 | 10 | 11 | def parse_addresses(addrs): 12 | if not translate_server_specs: 13 | return [] 14 | return translate_server_specs(addrs) 15 | -------------------------------------------------------------------------------- /releasenotes/notes/dbapi2-deprecate-analytics-config-ececae6e9274f852.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | deprecations: 3 | - | 4 | Deprecate the configuration of the analytics through the generic dbapi2 5 | configuration. This should now be configured via integration configurations, 6 | for example:: 7 | 8 | # Before 9 | export DD_TRACE_DBAPI2_ANALYTICS_ENABLED=1 10 | 11 | # After 12 | export DD_TRACE_SQLITE3_ANALYTICS_ENABLED=1 13 | -------------------------------------------------------------------------------- /tests/benchmarks/test_span_id.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | @pytest.mark.benchmark(group="span-id", min_time=0.005) 5 | def test_rand64bits_pid_check(benchmark): 6 | from ddtrace.internal import _rand 7 | 8 | benchmark(_rand.rand64bits) 9 | 10 | 11 | @pytest.mark.benchmark(group="span-id", min_time=0.005) 12 | def test_randbits_stdlib(benchmark): 13 | from ddtrace.internal.compat import getrandbits 14 | 15 | benchmark(getrandbits, 64) 16 | -------------------------------------------------------------------------------- /ddtrace/contrib/tornado/compat.py: -------------------------------------------------------------------------------- 1 | try: 2 | # detect if concurrent.futures is available as a Python 3 | # stdlib or Python 2.7 backport 4 | from ..futures import patch as wrap_futures 5 | from ..futures import unpatch as unwrap_futures 6 | 7 | futures_available = True 8 | except ImportError: 9 | 10 | def wrap_futures(): 11 | pass 12 | 13 | def unwrap_futures(): 14 | pass 15 | 16 | futures_available = False 17 | -------------------------------------------------------------------------------- /ddtrace/vendor/psutil/arch/aix/net_connections.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, Arnon Yaari 3 | * All rights reserved. 4 | * Use of this source code is governed by a BSD-style license that can be 5 | * found in the LICENSE file. 6 | */ 7 | 8 | #ifndef __NET_CONNECTIONS_H__ 9 | #define __NET_CONNECTIONS_H__ 10 | 11 | #include 12 | 13 | PyObject* psutil_net_connections(PyObject *self, PyObject *args); 14 | 15 | #endif /* __NET_CONNECTIONS_H__ */ -------------------------------------------------------------------------------- /ddtrace/vendor/psutil/arch/windows/security.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | * 6 | * Security related functions for Windows platform (Set privileges such as 7 | * SeDebug), as well as security helper functions. 8 | */ 9 | 10 | #include 11 | 12 | int psutil_set_se_debug(); 13 | 14 | -------------------------------------------------------------------------------- /tests/profiling/gevent_fork.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | import gevent.monkey 5 | 6 | 7 | gevent.monkey.patch_all() 8 | 9 | from ddtrace.profiling import profiler # noqa 10 | 11 | 12 | p = profiler.Profiler().start(profile_children=True) 13 | 14 | pid = os.fork() 15 | if pid == 0: 16 | print("Exiting") 17 | else: 18 | print(pid) 19 | pid, status = os.waitpid(pid, 0) 20 | print("Exited") 21 | sys.exit(os.WEXITSTATUS(status)) 22 | -------------------------------------------------------------------------------- /ddtrace/ext/http.py: -------------------------------------------------------------------------------- 1 | """ 2 | Standard http tags. 3 | 4 | For example: 5 | 6 | span.set_tag(URL, '/user/home') 7 | span.set_tag(STATUS_CODE, 404) 8 | """ 9 | # tags 10 | URL = "http.url" 11 | METHOD = "http.method" 12 | STATUS_CODE = "http.status_code" 13 | STATUS_MSG = "http.status_msg" 14 | QUERY_STRING = "http.query.string" 15 | RETRIES_REMAIN = "http.retries_remain" 16 | VERSION = "http.version" 17 | 18 | # template render span type 19 | TEMPLATE = "template" 20 | -------------------------------------------------------------------------------- /ddtrace/opentracer/propagation/propagator.py: -------------------------------------------------------------------------------- 1 | from abc import ABCMeta 2 | from abc import abstractmethod 3 | 4 | 5 | # ref: https://stackoverflow.com/a/38668373 6 | ABC = ABCMeta("ABC", (object,), {"__slots__": ()}) 7 | 8 | 9 | class Propagator(ABC): 10 | @staticmethod 11 | @abstractmethod 12 | def inject(span_context, carrier): 13 | pass 14 | 15 | @staticmethod 16 | @abstractmethod 17 | def extract(carrier): 18 | pass 19 | -------------------------------------------------------------------------------- /tests/opentracer/utils.py: -------------------------------------------------------------------------------- 1 | from ddtrace.opentracer import Tracer 2 | 3 | 4 | def init_tracer(service_name, dd_tracer, scope_manager=None): 5 | """A method that emulates what a user of OpenTracing would call to 6 | initialize a Datadog opentracer. 7 | 8 | It accepts a Datadog tracer that should be the same one used for testing. 9 | """ 10 | ot_tracer = Tracer(service_name, dd_tracer=dd_tracer, scope_manager=scope_manager) 11 | return ot_tracer 12 | -------------------------------------------------------------------------------- /benchmarks/django_simple/script.js: -------------------------------------------------------------------------------- 1 | import http from 'k6/http'; 2 | import { sleep } from 'k6'; 3 | 4 | export let options = { 5 | vus: 1, 6 | iterations: 1000, 7 | tags: { 8 | sirun_name: `${__ENV.SIRUN_NAME}`, 9 | sirun_variant: `${__ENV.SIRUN_VARIANT}`, 10 | sirun_iteration: `${__ENV.SIRUN_ITERATION}` 11 | } 12 | }; 13 | 14 | export default function () { 15 | const res = http.get('http://127.0.0.1:5000/accounts/signup/'); 16 | } 17 | -------------------------------------------------------------------------------- /tests/contrib/mysql/test_backwards_compatibility.py: -------------------------------------------------------------------------------- 1 | from ddtrace.contrib.mysql import get_traced_mysql_connection 2 | from tests.contrib import config 3 | from tests.utils import DummyTracer 4 | 5 | 6 | def test_pre_v4(): 7 | tracer = DummyTracer() 8 | MySQL = get_traced_mysql_connection(tracer, service="my-mysql-server") 9 | conn = MySQL(**config.MYSQL_CONFIG) 10 | cursor = conn.cursor() 11 | cursor.execute("SELECT 1") 12 | assert cursor.fetchone()[0] == 1 13 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/feature.md: -------------------------------------------------------------------------------- 1 | # Feature 2 | 3 | 4 | ## Checklist 5 | - [ ] Added to the correct milestone. 6 | - [ ] Library documentation is updated. 7 | - [ ] [Corp site](https://github.com/DataDog/documentation/) documentation is updated (link to the PR). 8 | 9 | ### Testing 10 | - [ ] Tests are run against all relevant library versions (or confirm that the relevant versions are already being tested in `tox.ini`) 11 | 12 | -------------------------------------------------------------------------------- /tests/profiling/utils.py: -------------------------------------------------------------------------------- 1 | import gzip 2 | 3 | from ddtrace.profiling.exporter import pprof 4 | 5 | 6 | def check_pprof_file( 7 | filename, # type: str 8 | ): 9 | # type: (...) -> None 10 | with gzip.open(filename, "rb") as f: 11 | content = f.read() 12 | p = pprof.pprof_pb2.Profile() 13 | p.ParseFromString(content) 14 | assert len(p.sample_type) == 11 15 | assert p.string_table[p.sample_type[0].type] == "cpu-samples" 16 | assert len(p.sample) >= 1 17 | -------------------------------------------------------------------------------- /tests/contrib/gevent/test_provider.py: -------------------------------------------------------------------------------- 1 | from ddtrace.contrib.gevent import provider 2 | 3 | 4 | def test_call_hooks(tracer): 5 | data = {} 6 | 7 | def record(context): 8 | if "trace" not in data: 9 | data["trace"] = context 10 | 11 | tracer.configure(context_provider=provider.GeventContextProvider()) 12 | tracer.context_provider._on_activate(record) 13 | with tracer.trace("test123") as mytrace: 14 | pass 15 | assert data["trace"] is mytrace 16 | -------------------------------------------------------------------------------- /tests/contrib/pymysql/test_backwards_compatibility.py: -------------------------------------------------------------------------------- 1 | from ddtrace.contrib.pymysql import get_traced_pymysql_connection 2 | from tests.contrib import config 3 | from tests.utils import DummyTracer 4 | 5 | 6 | def test_pre_v4(): 7 | tracer = DummyTracer() 8 | MySQL = get_traced_pymysql_connection(tracer, service="my-mysql-server") 9 | conn = MySQL(**config.MYSQL_CONFIG) 10 | cursor = conn.cursor() 11 | cursor.execute("SELECT 1") 12 | assert cursor.fetchone()[0] == 1 13 | -------------------------------------------------------------------------------- /tests/commands/ddtrace_run_sitecustomize.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | 4 | if __name__ == "__main__": 5 | # detect if `-S` is used 6 | suppress = len(sys.argv) == 2 and sys.argv[1] == "-S" 7 | if suppress: 8 | assert "sitecustomize" not in sys.modules 9 | else: 10 | assert "sitecustomize" in sys.modules 11 | 12 | # ensure the right `sitecustomize` will be imported 13 | import sitecustomize 14 | 15 | assert sitecustomize.CORRECT_IMPORT 16 | print("Test success") 17 | -------------------------------------------------------------------------------- /tests/profiling/collector/conftest.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | import ddtrace 4 | from ddtrace.profiling import Profiler 5 | 6 | 7 | @pytest.fixture 8 | def tracer(monkeypatch): 9 | monkeypatch.setenv("DD_TRACE_STARTUP_LOGS", "0") 10 | return ddtrace.Tracer() 11 | 12 | 13 | @pytest.fixture 14 | def profiler(monkeypatch): 15 | monkeypatch.setenv("DD_PROFILING_API_TIMEOUT", "0.1") 16 | p = Profiler() 17 | p.start() 18 | try: 19 | yield p 20 | finally: 21 | p.stop() 22 | -------------------------------------------------------------------------------- /releasenotes/notes/profiling-uwsgi-faaeb38f11bd287b.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | The profiler now supports most operation mode from uWSGI without much 5 | configuration. It will automatically plug itself in post fork hooks when 6 | multiprocess mode is used. 7 | upgrade: 8 | - | 9 | The profiler now automatically sets up uWSGI compatibility in auto mode 10 | or with `profile_children=True`. Make sure that you don't have custom code 11 | instrumenting the profiler in those cases. 12 | -------------------------------------------------------------------------------- /benchmarks/base/entrypoint: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ex 3 | 4 | python3 -m venv ${VENV_DDTRACE_V1} 5 | source ${VENV_DDTRACE_V1}/bin/activate 6 | pip install ${DDTRACE_INSTALL_V1} 7 | export DDTRACE_V1=$(python -c "import ddtrace; print(ddtrace.__version__)") 8 | deactivate 9 | 10 | python3 -m venv ${VENV_DDTRACE_V2} 11 | source ${VENV_DDTRACE_V2}/bin/activate 12 | pip install ${DDTRACE_INSTALL_V2} 13 | export DDTRACE_V2=$(python -c "import ddtrace; print(ddtrace.__version__)") 14 | deactivate 15 | 16 | exec "$@" 17 | -------------------------------------------------------------------------------- /benchmarks/django_simple/entrypoint: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -o errexit 4 | set -o pipefail 5 | set -o nounset 6 | 7 | # Install ddtrace 8 | if [[ -z "${DDTRACE_GIT_COMMIT_ID}" ]]; then 9 | if [[ -z "${DDTRACE_WHEELS}" ]]; then 10 | pip install ddtrace 11 | else 12 | pip install --no-cache-dir --no-index --find-links=${DDTRACE_WHEELS} ${DDTRACE_WHEELS}/* 13 | fi 14 | else 15 | pip install git+https://github.com/Datadog/dd-trace-py@${DDTRACE_GIT_COMMIT_ID} 16 | fi 17 | 18 | exec "$@" 19 | -------------------------------------------------------------------------------- /ddtrace/profiling/collector/_pymacro.h: -------------------------------------------------------------------------------- 1 | #ifndef _DDTRACE_MEMALLOC_PYMACRO 2 | #define _DDTRACE_MEMALLOC_PYMACRO 3 | 4 | #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 9 5 | #define _PY39_AND_LATER 6 | #endif 7 | 8 | #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 8 9 | #define _PY38_AND_LATER 10 | #endif 11 | 12 | #if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION == 8 13 | #define _PY38 14 | #endif 15 | 16 | #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 7 17 | #define _PY37_AND_LATER 18 | #endif 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /ddtrace_gevent_check.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import warnings 3 | 4 | 5 | def gevent_patch_all(event): 6 | if "ddtrace" in sys.modules: 7 | warnings.warn( 8 | "Loading ddtrace before using gevent monkey patching is not supported " 9 | "and is likely to break the application. " 10 | "Use `DD_GEVENT_PATCH_ALL=true ddtrace-run` to fix this or " 11 | "import `ddtrace` after `gevent.monkey.patch_all()` has been called.", 12 | RuntimeWarning, 13 | ) 14 | -------------------------------------------------------------------------------- /tests/contrib/djangorestframework/app/exceptions.py: -------------------------------------------------------------------------------- 1 | from rest_framework import status 2 | from rest_framework.response import Response 3 | from rest_framework.views import exception_handler 4 | 5 | 6 | def custom_exception_handler(exc, context): 7 | response = exception_handler(exc, context) 8 | 9 | # We overwrite the response status code to 500 10 | if response is not None: 11 | return Response({"detail": str(exc)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) 12 | 13 | return response 14 | -------------------------------------------------------------------------------- /tests/commands/ddtrace_run_dogstatsd.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | from ddtrace import tracer 4 | 5 | 6 | if __name__ == "__main__": 7 | # check both configurations with host:port or unix socket 8 | if tracer.writer.dogstatsd.socket_path is None: 9 | assert tracer.writer.dogstatsd.host == "172.10.0.1" 10 | assert tracer.writer.dogstatsd.port == 8120 11 | else: 12 | assert tracer.writer.dogstatsd.socket_path.endswith("dogstatsd.sock") 13 | print("Test success") 14 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/users/urls.py: -------------------------------------------------------------------------------- 1 | from ddtrace_django.users.views import user_detail_view 2 | from ddtrace_django.users.views import user_redirect_view 3 | from ddtrace_django.users.views import user_update_view 4 | from django.urls import path 5 | 6 | 7 | app_name = "users" 8 | urlpatterns = [ 9 | path("~redirect/", view=user_redirect_view, name="redirect"), 10 | path("~update/", view=user_update_view, name="update"), 11 | path("/", view=user_detail_view, name="detail"), 12 | ] 13 | -------------------------------------------------------------------------------- /releasenotes/notes/botocore-46f5bf04f64777b4.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | botocore: Update trace propagation format for directly invoked Lambda functions. 5 | This breaks compatibility with Lambda functions instrumented with datadog-lambda-python < v41 or datadog-lambda-js < v3.57.0. 6 | Please upgrade datadog-lambda-* in invoked lambda functions, or engage legacy compatibility mode in one of two ways: 7 | - ddtrace.config.botocore.invoke_with_legacy_context = True 8 | - DD_BOTOCORE_INVOKE_WITH_LEGACY_CONTEXT=true -------------------------------------------------------------------------------- /tests/contrib/gevent/utils.py: -------------------------------------------------------------------------------- 1 | from functools import wraps 2 | 3 | import gevent 4 | 5 | 6 | _NOT_ERROR = gevent.hub.Hub.NOT_ERROR 7 | 8 | 9 | def silence_errors(f): 10 | """ 11 | Test decorator for gevent that silences all errors when 12 | a greenlet raises an exception. 13 | """ 14 | 15 | @wraps(f) 16 | def wrapper(*args, **kwargs): 17 | gevent.hub.Hub.NOT_ERROR = (Exception,) 18 | f(*args, **kwargs) 19 | gevent.hub.Hub.NOT_ERROR = _NOT_ERROR 20 | 21 | return wrapper 22 | -------------------------------------------------------------------------------- /ddtrace/contrib/util.py: -------------------------------------------------------------------------------- 1 | # [Backward compatibility]: keep importing modules functions 2 | from ..utils.deprecation import deprecation 3 | from ..utils.importlib import func_name 4 | from ..utils.importlib import module_name 5 | from ..utils.importlib import require_modules 6 | 7 | 8 | deprecation( 9 | name="ddtrace.contrib.util", 10 | message="Use `ddtrace.utils.importlib` module instead", 11 | version="1.0.0", 12 | ) 13 | 14 | __all__ = [ 15 | "require_modules", 16 | "func_name", 17 | "module_name", 18 | ] 19 | -------------------------------------------------------------------------------- /ddtrace/profiling/bootstrap/sitecustomize.py: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | """Bootstrapping code that is run when using `ddtrace.profiling.auto`.""" 3 | from ddtrace.profiling import bootstrap 4 | from ddtrace.profiling import profiler 5 | 6 | 7 | def start_profiler(): 8 | if hasattr(bootstrap, "profiler"): 9 | bootstrap.profiler.stop() 10 | # Export the profiler so we can introspect it if needed 11 | bootstrap.profiler = profiler.Profiler() 12 | bootstrap.profiler.start() 13 | 14 | 15 | start_profiler() 16 | -------------------------------------------------------------------------------- /ddtrace/utils/config.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import typing 4 | 5 | 6 | def get_application_name(): 7 | # type: () -> typing.Optional[str] 8 | """Attempts to find the application name using system arguments.""" 9 | try: 10 | import __main__ 11 | 12 | name = __main__.__file__ 13 | except (ImportError, AttributeError): 14 | try: 15 | name = sys.argv[0] 16 | except (AttributeError, IndexError): 17 | return None 18 | 19 | return os.path.basename(name) 20 | -------------------------------------------------------------------------------- /tests/opentracer/core/test_utils.py: -------------------------------------------------------------------------------- 1 | from opentracing.scope_managers import ThreadLocalScopeManager 2 | 3 | import ddtrace 4 | from ddtrace.opentracer.utils import get_context_provider_for_scope_manager 5 | 6 | 7 | class TestOpentracerUtils(object): 8 | def test_get_context_provider_for_scope_manager_thread(self): 9 | scope_manager = ThreadLocalScopeManager() 10 | ctx_prov = get_context_provider_for_scope_manager(scope_manager) 11 | assert isinstance(ctx_prov, ddtrace.provider.DefaultContextProvider) 12 | -------------------------------------------------------------------------------- /releasenotes/notes/deprecate-dbapi-config-0fc5b1acfc4aded2.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | deprecations: 3 | - | 4 | Deprecate `ddtrace.config.dbapi2` as default for `TracedCursor` and 5 | `TracedConnection` as well as `DD_DBAPI2_TRACE_FETCH_METHODS`. Use 6 | `IntegrationConfig` and `DD__TRACE_FETCH_METHODS` specific to 7 | each dbapi-compliant library. For example:: 8 | 9 | # Before 10 | config.dbapi2.trace_fetch_methods = True 11 | 12 | # After 13 | config.psycopg2.trace_fetch_methods = True 14 | -------------------------------------------------------------------------------- /releasenotes/notes/ddtrace-run-enhancements-eb156e6722164894.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | prelude: > 3 | features: 4 | - | 5 | The ddtrace-run command now supports the following arguments: 6 | -h, --help 7 | -d, --debug enable debug mode (disabled by default) 8 | -i, --info print library info useful for debugging 9 | -p, --profiling enable profiling (disabled by default) 10 | -v, --version show program's version number and exit 11 | 12 | It now also has friendlier error messages when used incorrectly. 13 | -------------------------------------------------------------------------------- /ddtrace/opentracer/tags.py: -------------------------------------------------------------------------------- 1 | from collections import namedtuple 2 | 3 | 4 | TAG_NAMES = [ 5 | "RESOURCE_NAME", 6 | "SAMPLING_PRIORITY", 7 | "SERVICE_NAME", 8 | "SPAN_TYPE", 9 | "TARGET_HOST", 10 | "TARGET_PORT", 11 | ] 12 | 13 | TagNames = namedtuple("TagNames", TAG_NAMES) 14 | 15 | Tags = TagNames( 16 | RESOURCE_NAME="resource.name", 17 | SAMPLING_PRIORITY="sampling.priority", 18 | SERVICE_NAME="service.name", 19 | TARGET_HOST="out.host", 20 | TARGET_PORT="out.port", 21 | SPAN_TYPE="span.type", 22 | ) 23 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/bugfix.md: -------------------------------------------------------------------------------- 1 | # Bug fix 2 | 3 | ## Description 4 | 5 | 6 | ## Fix 7 | 8 | 9 | # Checklist 10 | - [ ] Regression test added; or 11 | - [ ] Description of manual testing performed and explanation is included in the code and/or PR. 12 | - [ ] Added to the correct milestone. 13 | 14 | # Testing 15 | - [ ] Tests are run against all relevant library versions (or confirm that the relevant versions are already being tested in `tox.ini`) 16 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/templates/account/verification_sent.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | 5 | {% block head_title %}{% trans "Verify Your E-mail Address" %}{% endblock %} 6 | 7 | {% block inner %} 8 |

{% trans "Verify Your E-mail Address" %}

9 | 10 |

{% blocktrans %}We have sent an e-mail to you for verification. Follow the link provided to finalize the signup process. Please contact us if you do not receive it within a few minutes.{% endblocktrans %}

11 | 12 | {% endblock %} 13 | -------------------------------------------------------------------------------- /ddtrace/profiling/collector/_memalloc.pyi: -------------------------------------------------------------------------------- 1 | import typing 2 | 3 | # (filename, line number, function name) 4 | FrameType = typing.Tuple[str, int, str] 5 | 6 | StackType = typing.Tuple[FrameType, ...] 7 | 8 | # (stack, nframe, thread_id) 9 | TracebackType = typing.Tuple[StackType, int, int] 10 | 11 | def start(max_nframe: int, max_events: int, heap_sample_size: int) -> None: ... 12 | def stop() -> None: ... 13 | def heap() -> typing.List[typing.Tuple[TracebackType, int]]: ... 14 | def iter_events() -> typing.Iterator[typing.Tuple[TracebackType, int]]: ... 15 | -------------------------------------------------------------------------------- /ddtrace/contrib/mongoengine/patch.py: -------------------------------------------------------------------------------- 1 | import mongoengine 2 | 3 | from ...utils.deprecation import deprecated 4 | from .trace import WrappedConnect 5 | 6 | 7 | # Original connect function 8 | _connect = mongoengine.connect 9 | 10 | 11 | def patch(): 12 | setattr(mongoengine, "connect", WrappedConnect(_connect)) 13 | 14 | 15 | def unpatch(): 16 | setattr(mongoengine, "connect", _connect) 17 | 18 | 19 | @deprecated(message="Use patching instead (see the docs).", version="1.0.0") 20 | def trace_mongoengine(*args, **kwargs): 21 | return _connect 22 | -------------------------------------------------------------------------------- /tests/tracer/test_hostname.py: -------------------------------------------------------------------------------- 1 | import mock 2 | 3 | from ddtrace.internal.hostname import get_hostname 4 | 5 | 6 | @mock.patch("socket.gethostname") 7 | def test_get_hostname(socket_gethostname): 8 | # Test that `get_hostname()` just returns `socket.gethostname` 9 | socket_gethostname.return_value = "test-hostname" 10 | assert get_hostname() == "test-hostname" 11 | 12 | # Change the value returned by `socket.gethostname` to test the cache 13 | socket_gethostname.return_value = "new-hostname" 14 | assert get_hostname() == "test-hostname" 15 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/contrib/sites/migrations/0004_alter_options_ordering_domain.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.7 on 2021-02-04 14:49 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ("sites", "0003_set_site_domain_and_name"), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterModelOptions( 14 | name="site", 15 | options={"ordering": ["domain"], "verbose_name": "site", "verbose_name_plural": "sites"}, 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /releasenotes/notes/add-dd_call_basic_config-env-15570281d176f438.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Add ``DD_CALL_BASIC_CONFIG={true,false}`` environment variable to control whether ``ddtrace`` calls ``logging.basicConfig``. 5 | By default when using ``ddtrace-run`` or running in debug mode ``logging.basicConfig`` is called to ensure there is always a 6 | root handler. This has compatibility issues for some logging configurations. ``DD_CALL_BASIC_CONFIG=false`` can be used to 7 | skip calling ``logging.basicConfig``. The default value is ``true`` to maintain existing behavior. 8 | -------------------------------------------------------------------------------- /ddtrace/encoding.py: -------------------------------------------------------------------------------- 1 | from .internal.encoding import Encoder 2 | from .internal.encoding import JSONEncoder 3 | from .internal.encoding import JSONEncoderV2 4 | from .internal.encoding import MsgpackEncoder 5 | from .utils.deprecation import deprecation 6 | 7 | 8 | __all__ = ( 9 | "Encoder", 10 | "JSONEncoder", 11 | "JSONEncoderV2", 12 | "MsgpackEncoder", 13 | ) 14 | 15 | 16 | deprecation( 17 | name="ddtrace.encoding", 18 | message="The encoding module has been moved to ddtrace.internal and will no longer be part of the public API.", 19 | version="1.0.0", 20 | ) 21 | -------------------------------------------------------------------------------- /benchmarks/django_simple/summarize_sirun.jq: -------------------------------------------------------------------------------- 1 | include "util"; 2 | . | 3 | group_by(.variant) | 4 | map({"variant": .[0].variant, 5 | "count": [.[] | .iterations[]] | length, 6 | "system.time": [.[] | .iterations[] | ."system.time"] | summary, 7 | "user.time": [.[] | .iterations[] | ."user.time"] | summary, 8 | "wall.time": [.[] | .iterations[] | ."wall.time"] | summary, 9 | "cpu.pct.wall.time": [.[] | .iterations[] | ."cpu.pct.wall.time"] | summary, 10 | "max.res.size": [.[] | .iterations[] | ."max.res.size"] | summary 11 | }) 12 | -------------------------------------------------------------------------------- /tests/tracer/test_hooks.py: -------------------------------------------------------------------------------- 1 | from ddtrace import _hooks 2 | 3 | 4 | def test_deregister(): 5 | hooks = _hooks.Hooks() 6 | 7 | x = {} 8 | 9 | @hooks.register("key") 10 | def do_not_call(): 11 | x["x"] = True 12 | 13 | hooks.emit("key") 14 | assert x["x"] 15 | del x["x"] 16 | 17 | hooks.deregister("key", do_not_call) 18 | 19 | hooks.emit("key") 20 | 21 | assert len(x) == 0 22 | 23 | 24 | def test_deregister_unknown(): 25 | hooks = _hooks.Hooks() 26 | 27 | hooks.deregister("key", test_deregister_unknown) 28 | 29 | hooks.emit("key") 30 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/templates/users/user_form.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% load crispy_forms_tags %} 3 | 4 | {% block title %}{{ user.username }}{% endblock %} 5 | 6 | {% block content %} 7 |

{{ user.username }}

8 |
9 | {% csrf_token %} 10 | {{ form|crispy }} 11 |
12 |
13 | 14 |
15 |
16 |
17 | {% endblock %} 18 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/templates/account/password_reset_done.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | {% load account %} 5 | 6 | {% block head_title %}{% trans "Password Reset" %}{% endblock %} 7 | 8 | {% block inner %} 9 |

{% trans "Password Reset" %}

10 | 11 | {% if user.is_authenticated %} 12 | {% include "account/snippets/already_logged_in.html" %} 13 | {% endif %} 14 | 15 |

{% blocktrans %}We have sent you an e-mail. Please contact us if you do not receive it within a few minutes.{% endblocktrans %}

16 | {% endblock %} 17 | -------------------------------------------------------------------------------- /ddtrace/contrib/celery/constants.py: -------------------------------------------------------------------------------- 1 | from ddtrace import config 2 | 3 | 4 | # Celery Context key 5 | CTX_KEY = "__dd_task_span" 6 | 7 | # Span names 8 | PRODUCER_ROOT_SPAN = "celery.apply" 9 | WORKER_ROOT_SPAN = "celery.run" 10 | 11 | # Task operations 12 | TASK_TAG_KEY = "celery.action" 13 | TASK_APPLY = "apply" 14 | TASK_APPLY_ASYNC = "apply_async" 15 | TASK_RUN = "run" 16 | TASK_RETRY_REASON_KEY = "celery.retry.reason" 17 | 18 | # Service info 19 | APP = "celery" 20 | PRODUCER_SERVICE = config._get_service(default="celery-producer") 21 | WORKER_SERVICE = config._get_service(default="celery-worker") 22 | -------------------------------------------------------------------------------- /releasenotes/notes/trace-58c201a4a5f38002.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | Spans are now processed per tracer instance. Formerly spans were stored 5 | per-Context which could be shared between tracer instances. Note that 6 | context management is not affected. Tracers will still share active spans. 7 | 8 | - | 9 | Spans from asynchronous executions (asyncio, gevent, tornado) will now be 10 | processed and flushed together. Formerly the spans were handled per-task. 11 | 12 | - | 13 | ``tracer.write()`` will no longer have filters applied to the spans passed 14 | to it. 15 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/templates/account/password_set.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | {% load crispy_forms_tags %} 5 | 6 | {% block head_title %}{% trans "Set Password" %}{% endblock %} 7 | 8 | {% block inner %} 9 |

{% trans "Set Password" %}

10 | 11 |
12 | {% csrf_token %} 13 | {{ form|crispy }} 14 | 15 |
16 | {% endblock %} 17 | -------------------------------------------------------------------------------- /scripts/cformat.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # For more modern versions: 5 | # clang-format --style="\{BasedOnStyle: Mozilla, IndentWidth: 4, ColumnLimit: 120\}" --dry-run -Werror file.c 6 | # would be enough… 7 | 8 | clean () 9 | { 10 | rm -f "$CFORMAT_TMP" 11 | } 12 | 13 | trap clean EXIT 14 | 15 | git ls-files '*.c' | grep -v '^ddtrace/vendor/' | while read filename 16 | do 17 | CFORMAT_TMP=`mktemp` 18 | clang-format --style="{BasedOnStyle: Mozilla, IndentWidth: 4, ColumnLimit: 120}" "$filename" > "$CFORMAT_TMP" 19 | diff -u "$filename" "$CFORMAT_TMP" 20 | rm -f "$CFORMAT_TMP" 21 | done 22 | -------------------------------------------------------------------------------- /tests/contrib/celery/test_patch.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from ddtrace import Pin 4 | 5 | 6 | class CeleryPatchTest(unittest.TestCase): 7 | def test_patch_after_import(self): 8 | import celery 9 | 10 | from ddtrace import patch 11 | 12 | patch(celery=True) 13 | 14 | app = celery.Celery() 15 | assert Pin.get_from(app) is not None 16 | 17 | def test_patch_before_import(self): 18 | from ddtrace import patch 19 | 20 | patch(celery=True) 21 | import celery 22 | 23 | app = celery.Celery() 24 | assert Pin.get_from(app) is not None 25 | -------------------------------------------------------------------------------- /benchmarks/django_simple/benchmark: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -o errexit 4 | set -o pipefail 5 | set -o nounset 6 | 7 | mkdir -p /artifacts/output/ 8 | 9 | # cleanup any existing output artifacts 10 | rm -f /artifacts/output/*.* 11 | 12 | sirun meta.yaml | tee /artifacts/output/sirun.ndjson 13 | 14 | jq -s -f summarize_sirun.jq /artifacts/output/sirun.ndjson | tee /artifacts/output/summary_sirun.json 15 | jq -s -f summarize_k6.jq /artifacts/output/k6.ndjson | tee /artifacts/output/summary_k6.json 16 | 17 | # keep process alive before exiting 18 | # FIXME: remove once artifacts can be uploaded when run in CI 19 | sleep 30m 20 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/templates/account/password_change.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | {% load crispy_forms_tags %} 5 | 6 | {% block head_title %}{% trans "Change Password" %}{% endblock %} 7 | 8 | {% block inner %} 9 |

{% trans "Change Password" %}

10 | 11 |
12 | {% csrf_token %} 13 | {{ form|crispy }} 14 | 15 |
16 | {% endblock %} 17 | -------------------------------------------------------------------------------- /benchmarks/django_simple/meta.yaml: -------------------------------------------------------------------------------- 1 | name: django-simple 2 | setup: bash -c "nohup /app/setup & echo $! > setup.pid" 3 | run: "./run" 4 | iterations: 5 5 | env: 6 | DD_PROFILING_API_TIMEOUT: '0.1' 7 | DD_PROFILING_UPLOAD_INTERVAL: '10' 8 | variants: 9 | disabled: 10 | env: 11 | BENCHMARK_TRACING_ENABLED: '0' 12 | tracer: 13 | env: 14 | BENCHMARK_TRACING_ENABLED: '1' 15 | profiler: 16 | env: 17 | BENCHMARK_TRACING_ENABLED: '0' 18 | BENCHMARK_PROFILING_ENABLED: '1' 19 | tracer_profiler: 20 | env: 21 | BENCHMARK_TRACING_ENABLED: '1' 22 | DD_PROFILING_ENABLED: 'true' 23 | -------------------------------------------------------------------------------- /ddtrace/contrib/requests/session.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | from ddtrace import Pin 4 | from ddtrace import config 5 | from ddtrace.vendor.wrapt import wrap_function_wrapper as _w 6 | 7 | from .connection import _wrap_send 8 | 9 | 10 | class TracedSession(requests.Session): 11 | """TracedSession is a requests' Session that is already traced. 12 | You can use it if you want a finer grained control for your 13 | HTTP clients. 14 | """ 15 | 16 | pass 17 | 18 | 19 | # always patch our `TracedSession` when imported 20 | _w(TracedSession, "send", _wrap_send) 21 | Pin(_config=config.requests).onto(TracedSession) 22 | -------------------------------------------------------------------------------- /ddtrace/vendor/psutil/arch/solaris/environ.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2009, Giampaolo Rodola', Oleksii Shevchuk. 3 | * All rights reserved. Use of this source code is governed by a BSD-style 4 | * license that can be found in the LICENSE file. 5 | */ 6 | 7 | #ifndef PROCESS_AS_UTILS_H 8 | #define PROCESS_AS_UTILS_H 9 | 10 | char ** 11 | psutil_read_raw_args(psinfo_t info, const char *procfs_path, size_t *count); 12 | 13 | char ** 14 | psutil_read_raw_env(psinfo_t info, const char *procfs_path, ssize_t *count); 15 | 16 | void 17 | psutil_free_cstrings_array(char **array, size_t count); 18 | 19 | #endif // PROCESS_AS_UTILS_H 20 | -------------------------------------------------------------------------------- /ddtrace/internal/runtime/__init__.py: -------------------------------------------------------------------------------- 1 | import uuid 2 | 3 | from .. import forksafe 4 | 5 | 6 | __all__ = [ 7 | "get_runtime_id", 8 | ] 9 | 10 | 11 | def _generate_runtime_id(): 12 | return uuid.uuid4().hex 13 | 14 | 15 | _RUNTIME_ID = _generate_runtime_id() 16 | 17 | 18 | @forksafe.register 19 | def _set_runtime_id(): 20 | global _RUNTIME_ID 21 | _RUNTIME_ID = _generate_runtime_id() 22 | 23 | 24 | def get_runtime_id(): 25 | """Return a unique string identifier for this runtime. 26 | 27 | Do not store this identifier as it can change when, e.g., the process forks. 28 | """ 29 | return _RUNTIME_ID 30 | -------------------------------------------------------------------------------- /tests/profiling/collector/test_traceback.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | from ddtrace.profiling.collector import _traceback 4 | 5 | 6 | def _x(): 7 | raise ValueError("hey!") 8 | 9 | 10 | def test_check_traceback_to_frames(): 11 | try: 12 | _x() 13 | except Exception: 14 | exc_type, exc_value, traceback = sys.exc_info() 15 | frames, nframes = _traceback.traceback_to_frames(traceback, 10) 16 | assert nframes == 2 17 | assert frames == [ 18 | (__file__, 7, "_x"), 19 | ( 20 | __file__, 21 | 15, 22 | "test_check_traceback_to_frames", 23 | ), 24 | ] 25 | -------------------------------------------------------------------------------- /tests/contrib/grpc/hello.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package helloworld; 3 | 4 | service Hello { 5 | // Sends a greeting 6 | rpc SayHello (HelloRequest) returns (HelloReply) {} 7 | rpc SayHelloTwice (HelloRequest) returns (stream HelloReply) {} 8 | rpc SayHelloRepeatedly (stream HelloRequest) returns (stream HelloReply) {} 9 | rpc SayHelloLast (stream HelloRequest) returns (HelloReply) {} 10 | } 11 | 12 | // The request message containing the user's name. 13 | message HelloRequest { 14 | string name = 1; 15 | } 16 | 17 | // The response message containing the greetings 18 | message HelloReply { 19 | string message = 1; 20 | } 21 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/users/forms.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth import forms as admin_forms 2 | from django.contrib.auth import get_user_model 3 | from django.utils.translation import gettext_lazy as _ 4 | 5 | 6 | User = get_user_model() 7 | 8 | 9 | class UserChangeForm(admin_forms.UserChangeForm): 10 | class Meta(admin_forms.UserChangeForm.Meta): 11 | model = User 12 | 13 | 14 | class UserCreationForm(admin_forms.UserCreationForm): 15 | class Meta(admin_forms.UserCreationForm.Meta): 16 | model = User 17 | 18 | error_messages = {"username": {"unique": _("This username has already been taken.")}} 19 | -------------------------------------------------------------------------------- /ddtrace/ext/errors.py: -------------------------------------------------------------------------------- 1 | """ 2 | tags for common error attributes 3 | """ 4 | 5 | import traceback 6 | 7 | 8 | ERROR_MSG = "error.msg" # a string representing the error message 9 | ERROR_TYPE = "error.type" # a string representing the type of the error 10 | ERROR_STACK = "error.stack" # a human readable version of the stack. beta. 11 | 12 | # shorthand for -----^ 13 | MSG = ERROR_MSG 14 | TYPE = ERROR_TYPE 15 | STACK = ERROR_STACK 16 | 17 | 18 | def get_traceback(tb=None, error=None): 19 | t = None 20 | if error: 21 | t = type(error) 22 | lines = traceback.format_exception(t, error, tb, limit=20) 23 | return "\n".join(lines) 24 | -------------------------------------------------------------------------------- /tests/snapshots/tests.integration.test_integration_snapshots.test_single_trace_single_span.snap: -------------------------------------------------------------------------------- 1 | [[{"name" "operation" 2 | "service" "my-svc" 3 | "resource" "operation" 4 | "error" 0 5 | "span_id" 0 6 | "trace_id" 0 7 | "parent_id" nil 8 | "start" 1616457150133710000 9 | "duration" 52000 10 | "meta" {"runtime-id" "ddf562510b004d60bdfaa21911ab1e60" 11 | "k" "v"} 12 | "metrics" {"_dd.agent_psr" 1.0 13 | "_sampling_priority_v1" 1 14 | "system.pid" 39631 15 | "int_metric" 4321 16 | "_dd.tracer_kr" 1.0 17 | "float_metric" 12.34 18 | "num" 1234}}]] 19 | -------------------------------------------------------------------------------- /ddtrace/util.py: -------------------------------------------------------------------------------- 1 | # [Backward compatibility]: keep importing modules functions 2 | from .utils.deprecation import deprecated 3 | from .utils.deprecation import deprecation 4 | from .utils.formats import asbool 5 | from .utils.formats import deep_getattr 6 | from .utils.formats import get_env 7 | from .utils.wrappers import safe_patch 8 | from .utils.wrappers import unwrap 9 | 10 | 11 | deprecation( 12 | name="ddtrace.util", 13 | message="Use `ddtrace.utils` package instead", 14 | version="1.0.0", 15 | ) 16 | 17 | __all__ = [ 18 | "deprecated", 19 | "asbool", 20 | "deep_getattr", 21 | "get_env", 22 | "safe_patch", 23 | "unwrap", 24 | ] 25 | -------------------------------------------------------------------------------- /tests/tracer/runtime/fork_disable.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | from ddtrace.internal.runtime.runtime_metrics import RuntimeWorker 5 | from ddtrace.internal.service import ServiceStatus 6 | 7 | 8 | RuntimeWorker.enable() 9 | assert RuntimeWorker._instance is not None 10 | assert RuntimeWorker._instance.status == ServiceStatus.RUNNING 11 | 12 | RuntimeWorker.disable() 13 | assert RuntimeWorker._instance is None 14 | 15 | 16 | child_pid = os.fork() 17 | if child_pid == 0: 18 | assert RuntimeWorker._instance is None 19 | else: 20 | pid, status = os.waitpid(child_pid, 0) 21 | assert RuntimeWorker._instance is None 22 | sys.exit(os.WEXITSTATUS(status)) 23 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/templates/account/logout.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | 5 | {% block head_title %}{% trans "Sign Out" %}{% endblock %} 6 | 7 | {% block inner %} 8 |

{% trans "Sign Out" %}

9 | 10 |

{% trans 'Are you sure you want to sign out?' %}

11 | 12 |
13 | {% csrf_token %} 14 | {% if redirect_field_value %} 15 | 16 | {% endif %} 17 | 18 |
19 | {% endblock %} 20 | -------------------------------------------------------------------------------- /ddtrace/vendor/psutil/arch/windows/inet_ntop.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2009, Giampaolo Rodola', Jeff Tang. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | // because of WSAAddressToStringA 8 | #define _WINSOCK_DEPRECATED_NO_WARNINGS 9 | #include 10 | 11 | PCSTR WSAAPI 12 | inet_ntop( 13 | __in INT Family, 14 | __in const VOID * pAddr, 15 | __out_ecount(StringBufSize) PSTR pStringBuf, 16 | __in size_t StringBufSize 17 | ); 18 | -------------------------------------------------------------------------------- /tests/snapshots/tests.contrib.mariadb.test_mariadb.test_commit_snapshot.snap: -------------------------------------------------------------------------------- 1 | [[{"name" "mariadb.connection.commit" 2 | "service" "mariadb" 3 | "resource" "mariadb.connection.commit" 4 | "error" 0 5 | "span_id" 0 6 | "trace_id" 0 7 | "parent_id" nil 8 | "start" 1626718453452681000 9 | "duration" 1324000 10 | "meta" {"runtime-id" "0cbfb96da3ee4e86be3cf3b8a4004f86" 11 | "out.host" "127.0.0.1" 12 | "db.user" "test" 13 | "db.name" "test"} 14 | "metrics" {"_dd.agent_psr" 1.0 15 | "_sampling_priority_v1" 1 16 | "system.pid" 1502 17 | "out.port" 3306 18 | "_dd.tracer_kr" 1.0}}]] 19 | -------------------------------------------------------------------------------- /ddtrace/profiling/__init__.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | from ddtrace.profiling import _build 4 | 5 | from .profiler import Profiler # noqa:F401 6 | 7 | 8 | def _not_compatible_abi(): 9 | raise ImportError( 10 | "Python ABI is not compatible, you need to recompile this module.\n" 11 | "Reinstall it with the following command:\n" 12 | " pip install --no-binary ddtrace ddtrace" 13 | ) 14 | 15 | 16 | if (3, 7) < _build.compiled_with <= (3, 7, 3): 17 | if sys.version_info[:3] > (3, 7, 3): 18 | _not_compatible_abi() 19 | elif (3, 7, 3) < _build.compiled_with < (3, 8): 20 | if (3, 7) < sys.version_info[:3] <= (3, 7, 3): 21 | _not_compatible_abi() 22 | -------------------------------------------------------------------------------- /tests/snapshots/tests.contrib.urllib3.test_urllib3.test_urllib3_connectionpool_snapshot.snap: -------------------------------------------------------------------------------- 1 | [[{"name" "urllib3.request" 2 | "service" "urllib3" 3 | "resource" "urllib3.request" 4 | "type" "http" 5 | "error" 0 6 | "span_id" 0 7 | "trace_id" 0 8 | "parent_id" nil 9 | "start" 1619121392243862000 10 | "duration" 9724000 11 | "meta" {"runtime-id" "17c4dec94e02426e936e6a7c445f2a38" 12 | "http.method" "GET" 13 | "http.url" "http://localhost:8001/status/200" 14 | "http.status_code" "200"} 15 | "metrics" {"_dd.agent_psr" 1.0 16 | "_sampling_priority_v1" 1 17 | "system.pid" 39986 18 | "_dd.tracer_kr" 1.0}}]] 19 | -------------------------------------------------------------------------------- /tests/snapshots/tests.contrib.urllib3.test_urllib3.test_urllib3_poolmanager_snapshot.snap: -------------------------------------------------------------------------------- 1 | [[{"name" "urllib3.request" 2 | "service" "urllib3" 3 | "resource" "urllib3.request" 4 | "type" "http" 5 | "error" 0 6 | "span_id" 0 7 | "trace_id" 0 8 | "parent_id" nil 9 | "start" 1619121391909007000 10 | "duration" 10709000 11 | "meta" {"runtime-id" "17c4dec94e02426e936e6a7c445f2a38" 12 | "http.method" "GET" 13 | "http.url" "http://localhost:8001/status/200" 14 | "http.status_code" "200"} 15 | "metrics" {"_dd.agent_psr" 1.0 16 | "_sampling_priority_v1" 1 17 | "system.pid" 39986 18 | "_dd.tracer_kr" 1.0}}]] 19 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/users/adapters.py: -------------------------------------------------------------------------------- 1 | from typing import Any 2 | 3 | from allauth.account.adapter import DefaultAccountAdapter 4 | from allauth.socialaccount.adapter import DefaultSocialAccountAdapter 5 | from django.conf import settings 6 | from django.http import HttpRequest 7 | 8 | 9 | class AccountAdapter(DefaultAccountAdapter): 10 | def is_open_for_signup(self, request: HttpRequest): 11 | return getattr(settings, "ACCOUNT_ALLOW_REGISTRATION", True) 12 | 13 | 14 | class SocialAccountAdapter(DefaultSocialAccountAdapter): 15 | def is_open_for_signup(self, request: HttpRequest, sociallogin: Any): 16 | return getattr(settings, "ACCOUNT_ALLOW_REGISTRATION", True) 17 | -------------------------------------------------------------------------------- /tests/cache/conftest.py: -------------------------------------------------------------------------------- 1 | """ 2 | Ensure that cached functions are invalidated between test runs. 3 | """ 4 | import pytest 5 | 6 | from ddtrace.utils import cache 7 | 8 | 9 | _CACHED_FUNCTIONS = [] 10 | 11 | old_cached = cache.cached 12 | 13 | 14 | def wrapped_cached(maxsize=256): 15 | def wrapped_cached_f(f): 16 | cached_f = old_cached(maxsize)(f) 17 | _CACHED_FUNCTIONS.append(cached_f) 18 | return cached_f 19 | 20 | return wrapped_cached_f 21 | 22 | 23 | cache.cached = wrapped_cached 24 | 25 | 26 | @pytest.hookimpl(hookwrapper=True) 27 | def pytest_runtest_teardown(item, nextitem): 28 | for f in _CACHED_FUNCTIONS: 29 | f.invalidate() 30 | 31 | yield 32 | -------------------------------------------------------------------------------- /ddtrace/vendor/psutil/arch/osx/process_info.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #include 8 | 9 | typedef struct kinfo_proc kinfo_proc; 10 | 11 | int psutil_get_argmax(void); 12 | int psutil_is_zombie(long pid); 13 | int psutil_get_kinfo_proc(long pid, struct kinfo_proc *kp); 14 | int psutil_get_proc_list(kinfo_proc **procList, size_t *procCount); 15 | int psutil_proc_pidinfo( 16 | long pid, int flavor, uint64_t arg, void *pti, int size); 17 | PyObject* psutil_get_cmdline(long pid); 18 | PyObject* psutil_get_environ(long pid); 19 | -------------------------------------------------------------------------------- /tests/contrib/uwsgi/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | import subprocess 3 | import sys 4 | 5 | 6 | def run_uwsgi(cmd): 7 | def _run(*args): 8 | env = os.environ.copy() 9 | if sys.version_info[0] == 2: 10 | # On Python2, it's impossible to import uwsgidecorators without this hack 11 | env["PYTHONPATH"] = os.path.join( 12 | os.environ.get("VIRTUAL_ENV", ""), 13 | "lib", 14 | "python%s.%s" % (sys.version_info[0], sys.version_info[1]), 15 | "site-packages", 16 | ) 17 | 18 | return subprocess.Popen(cmd + list(args), stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=env) 19 | 20 | return _run 21 | -------------------------------------------------------------------------------- /ddtrace/vendor/psutil/arch/solaris/v10/ifaddrs.h: -------------------------------------------------------------------------------- 1 | /* Reference: https://lists.samba.org/archive/samba-technical/2009-February/063079.html */ 2 | 3 | 4 | #ifndef __IFADDRS_H__ 5 | #define __IFADDRS_H__ 6 | 7 | #include 8 | #include 9 | 10 | #undef ifa_dstaddr 11 | #undef ifa_broadaddr 12 | #define ifa_broadaddr ifa_dstaddr 13 | 14 | struct ifaddrs { 15 | struct ifaddrs *ifa_next; 16 | char *ifa_name; 17 | unsigned int ifa_flags; 18 | struct sockaddr *ifa_addr; 19 | struct sockaddr *ifa_netmask; 20 | struct sockaddr *ifa_dstaddr; 21 | }; 22 | 23 | extern int getifaddrs(struct ifaddrs **); 24 | extern void freeifaddrs(struct ifaddrs *); 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/contrib/sites/migrations/0002_alter_domain_unique.py: -------------------------------------------------------------------------------- 1 | import django.contrib.sites.models 2 | from django.db import migrations 3 | from django.db import models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [("sites", "0001_initial")] 9 | 10 | operations = [ 11 | migrations.AlterField( 12 | model_name="site", 13 | name="domain", 14 | field=models.CharField( 15 | max_length=100, 16 | unique=True, 17 | validators=[django.contrib.sites.models._simple_domain_name_validator], 18 | verbose_name="domain name", 19 | ), 20 | ) 21 | ] 22 | -------------------------------------------------------------------------------- /ddtrace/contrib/mako/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | The ``mako`` integration traces templates rendering. 3 | Auto instrumentation is available using the ``patch``. The following is an example:: 4 | 5 | from ddtrace import patch 6 | from mako.template import Template 7 | 8 | patch(mako=True) 9 | 10 | t = Template(filename="index.html") 11 | 12 | """ 13 | from ...utils.importlib import require_modules 14 | 15 | 16 | required_modules = ["mako"] 17 | 18 | with require_modules(required_modules) as missing_modules: 19 | if not missing_modules: 20 | from .patch import patch 21 | from .patch import unpatch 22 | 23 | __all__ = [ 24 | "patch", 25 | "unpatch", 26 | ] 27 | -------------------------------------------------------------------------------- /tests/contrib/sanic/conftest.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | import pytest 4 | 5 | import ddtrace 6 | from ddtrace.contrib.sanic import patch 7 | from ddtrace.contrib.sanic import unpatch 8 | from tests.utils import DummyTracer 9 | 10 | 11 | @pytest.fixture 12 | def tracer(): 13 | original_tracer = ddtrace.tracer 14 | tracer = DummyTracer() 15 | if sys.version_info < (3, 7): 16 | # enable legacy asyncio support 17 | from ddtrace.contrib.asyncio.provider import AsyncioContextProvider 18 | 19 | tracer.configure(context_provider=AsyncioContextProvider()) 20 | setattr(ddtrace, "tracer", tracer) 21 | patch() 22 | yield tracer 23 | setattr(ddtrace, "tracer", original_tracer) 24 | unpatch() 25 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thanks for taking the time for reporting an issue! 2 | 3 | Before reporting an issue on dd-trace-py, please be sure to provide all 4 | necessary information. 5 | 6 | If you're hitting a bug, make sure that you're using the latest version of this 7 | library. 8 | 9 | ### Which version of dd-trace-py are you using? 10 | 11 | ### Which version of pip are you using? 12 | 13 | _ddtrace requires pip>=18 to install one of our pre-built wheels_ 14 | 15 | ### Which version of the libraries are you using? 16 | 17 | You can copy/paste the output of `pip freeze` here. 18 | 19 | ### How can we reproduce your problem? 20 | 21 | ### What is the result that you get? 22 | 23 | ### What is the result that you expected? 24 | -------------------------------------------------------------------------------- /ddtrace/contrib/redis/tracers.py: -------------------------------------------------------------------------------- 1 | from redis import StrictRedis 2 | 3 | from ...utils.deprecation import deprecated 4 | 5 | 6 | DEFAULT_SERVICE = "redis" 7 | 8 | 9 | @deprecated(message="Use patching instead (see the docs).", version="1.0.0") 10 | def get_traced_redis(ddtracer, service=DEFAULT_SERVICE, meta=None): 11 | return _get_traced_redis(ddtracer, StrictRedis, service, meta) 12 | 13 | 14 | @deprecated(message="Use patching instead (see the docs).", version="1.0.0") 15 | def get_traced_redis_from(ddtracer, baseclass, service=DEFAULT_SERVICE, meta=None): 16 | return _get_traced_redis(ddtracer, baseclass, service, meta) 17 | 18 | 19 | def _get_traced_redis(ddtracer, baseclass, service, meta): 20 | return baseclass 21 | -------------------------------------------------------------------------------- /tests/contrib/celery/test_app.py: -------------------------------------------------------------------------------- 1 | import celery 2 | 3 | from ddtrace import Pin 4 | from ddtrace.contrib.celery import unpatch_app 5 | 6 | from .base import CeleryBaseTestCase 7 | 8 | 9 | class CeleryAppTest(CeleryBaseTestCase): 10 | """Ensures the default application is properly instrumented""" 11 | 12 | def test_patch_app(self): 13 | # When celery.App is patched it must include a `Pin` instance 14 | app = celery.Celery() 15 | assert Pin.get_from(app) is not None 16 | 17 | def test_unpatch_app(self): 18 | # When celery.App is unpatched it must not include a `Pin` instance 19 | unpatch_app(celery.Celery) 20 | app = celery.Celery() 21 | assert Pin.get_from(app) is None 22 | -------------------------------------------------------------------------------- /tests/contrib/gevent/test_monkeypatch.py: -------------------------------------------------------------------------------- 1 | import os 2 | import subprocess 3 | 4 | import gevent 5 | import pytest 6 | 7 | 8 | @pytest.mark.skipif( 9 | not (gevent.version_info.major >= 1 and gevent.version_info.minor >= 3), reason="gevent 1.3 or later is required" 10 | ) 11 | def test_gevent_warning(monkeypatch): 12 | subp = subprocess.Popen( 13 | ("python", os.path.join(os.path.dirname(__file__), "wrong_program_gevent.py")), 14 | stdout=subprocess.PIPE, 15 | stderr=subprocess.PIPE, 16 | close_fds=True, 17 | ) 18 | assert subp.wait() == 0 19 | assert subp.stdout.read() == b"" 20 | assert b"RuntimeWarning: Loading ddtrace before using gevent monkey patching" in subp.stderr.read() 21 | -------------------------------------------------------------------------------- /tests/snapshots/tests.contrib.cherrypy.test_middleware.test_success.snap: -------------------------------------------------------------------------------- 1 | [[{"name" "cherrypy.request" 2 | "service" "test.cherrypy.service" 3 | "resource" "GET /" 4 | "type" "web" 5 | "error" 0 6 | "span_id" 0 7 | "trace_id" 0 8 | "parent_id" nil 9 | "start" 1612565277618230000 10 | "duration" 1676000 11 | "meta" {"runtime-id" "9ec4e861797b401289c15e82e1a86a76" 12 | "http.method" "GET" 13 | "http.url" "http://127.0.0.1:54583/" 14 | "http.status_code" "200" 15 | "http.request.headers.host" "127.0.0.1:54583"} 16 | "metrics" {"_dd.agent_psr" 1.0 17 | "_sampling_priority_v1" 1 18 | "_dd.tracer_kr" 1.0 19 | "system.pid" 12166}}]] 20 | -------------------------------------------------------------------------------- /ddtrace/vendor/wrapt/__init__.py: -------------------------------------------------------------------------------- 1 | __version_info__ = ('1', '12', '1') 2 | __version__ = '.'.join(__version_info__) 3 | 4 | from .wrappers import (ObjectProxy, CallableObjectProxy, FunctionWrapper, 5 | BoundFunctionWrapper, WeakFunctionProxy, PartialCallableObjectProxy, 6 | resolve_path, apply_patch, wrap_object, wrap_object_attribute, 7 | function_wrapper, wrap_function_wrapper, patch_function_wrapper, 8 | transient_function_wrapper) 9 | 10 | from .decorators import (adapter_factory, AdapterFactory, decorator, 11 | synchronized) 12 | 13 | from .importer import (register_post_import_hook, when_imported, 14 | notify_module_loaded, discover_post_import_hooks) 15 | 16 | from inspect import getcallargs 17 | -------------------------------------------------------------------------------- /tests/tracer/runtime/fork_enable.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | from ddtrace.internal.runtime.runtime_metrics import RuntimeWorker 5 | from ddtrace.internal.service import ServiceStatus 6 | 7 | 8 | RuntimeWorker.enable() 9 | assert RuntimeWorker._instance is not None 10 | assert RuntimeWorker._instance.status == ServiceStatus.RUNNING 11 | 12 | 13 | child_pid = os.fork() 14 | if child_pid == 0: 15 | assert RuntimeWorker._instance is not None 16 | assert RuntimeWorker._instance.status == ServiceStatus.RUNNING 17 | else: 18 | pid, status = os.waitpid(child_pid, 0) 19 | assert RuntimeWorker._instance is not None 20 | assert RuntimeWorker._instance.status == ServiceStatus.RUNNING 21 | sys.exit(os.WEXITSTATUS(status)) 22 | -------------------------------------------------------------------------------- /benchmarks/base/benchmark: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ex 3 | 4 | if [[ -z "${RUN_ID}" ]]; then 5 | export RUN_ID=$(uuidgen) 6 | fi 7 | 8 | ARTIFACTS=/artifacts/${RUN_ID}/${SCENARIO} 9 | mkdir -p ${ARTIFACTS} 10 | RESULTS_V1=${ARTIFACTS}/${DDTRACE_V1}.json 11 | RESULTS_V2=${ARTIFACTS}/${DDTRACE_V2}.json 12 | 13 | # append venvs with ddtrace to sys.path 14 | 15 | PYTHONPATH=${VENV_DDTRACE_V1}/lib/python3.9/site-packages \ 16 | python scenario.py \ 17 | --copy-env \ 18 | --fast \ 19 | -o ${RESULTS_V1} 20 | 21 | PYTHONPATH=${VENV_DDTRACE_V2}/lib/python3.9/site-packages \ 22 | python scenario.py \ 23 | --copy-env \ 24 | --fast \ 25 | -o ${RESULTS_V2} 26 | 27 | pyperf compare_to --table ${RESULTS_V2} ${RESULTS_V1} 28 | -------------------------------------------------------------------------------- /tests/contrib/djangorestframework/conftest.py: -------------------------------------------------------------------------------- 1 | __all__ = ["pytest_configure", "test_spans", "tracer"] 2 | 3 | import os 4 | 5 | import django 6 | from django.conf import settings 7 | 8 | from ddtrace.contrib.django import patch 9 | 10 | from ..django.conftest import test_spans 11 | from ..django.conftest import tracer 12 | 13 | 14 | # We manually designate which settings we will be using in an environment variable 15 | # This is similar to what occurs in the `manage.py` 16 | os.environ["DJANGO_SETTINGS_MODULE"] = "tests.contrib.djangorestframework.app.settings" 17 | 18 | 19 | # `pytest` automatically calls this function once when tests are run. 20 | def pytest_configure(): 21 | settings.DEBUG = False 22 | patch() 23 | django.setup() 24 | -------------------------------------------------------------------------------- /tests/commands/ddtrace_run_logs_injection.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | 4 | if __name__ == "__main__": 5 | # Ensure if module is patched then default log formatter is set up for logs 6 | if getattr(logging, "_datadog_patch"): 7 | assert ( 8 | "[dd.service=%(dd.service)s dd.env=%(dd.env)s dd.version=%(dd.version)s" 9 | " dd.trace_id=%(dd.trace_id)s dd.span_id=%(dd.span_id)s]" in logging.root.handlers[0].formatter._fmt 10 | ) 11 | else: 12 | assert ( 13 | "[dd.service=%(dd.service)s dd.env=%(dd.env)s dd.version=%(dd.version)s" 14 | " dd.trace_id=%(dd.trace_id)s dd.span_id=%(dd.span_id)s]" not in logging.root.handlers[0].formatter._fmt 15 | ) 16 | print("Test success") 17 | -------------------------------------------------------------------------------- /tests/snapshots/tests.contrib.redis.test_redis.test_basics.snap: -------------------------------------------------------------------------------- 1 | [[{"name" "redis.command" 2 | "service" "redis" 3 | "resource" "GET cheese" 4 | "type" "redis" 5 | "error" 0 6 | "span_id" 0 7 | "trace_id" 0 8 | "parent_id" nil 9 | "start" 1600445816750272000 10 | "duration" 2356000 11 | "meta" {"runtime-id" "16ad458b01464f4aa12005b653b660cc" 12 | "redis.raw_command" "GET cheese" 13 | "out.host" "localhost"} 14 | "metrics" {"_dd.agent_psr" 1.0 15 | "_dd.measured" 1 16 | "_sampling_priority_v1" 1 17 | "_dd.tracer_kr" 1.0 18 | "system.pid" 50399 19 | "out.port" 6379 20 | "out.redis_db" 0 21 | "redis.args_length" 2}}]] 22 | -------------------------------------------------------------------------------- /tests/contrib/urllib3/test_urllib3_patch.py: -------------------------------------------------------------------------------- 1 | from ddtrace.contrib.urllib3 import patch 2 | from tests.contrib.patch import PatchTestCase 3 | 4 | 5 | class TestUrllib3Patch(PatchTestCase.Base): 6 | __integration_name__ = "urllib3" 7 | __module_name__ = "urllib3" 8 | __patch_func__ = patch 9 | __unpatch_func__ = None 10 | 11 | def assert_module_patched(self, urllib3): 12 | self.assert_wrapped(urllib3.connectionpool.HTTPConnectionPool.urlopen) 13 | 14 | def assert_not_module_patched(self, urllib3): 15 | self.assert_not_wrapped(urllib3.connectionpool.HTTPConnectionPool.urlopen) 16 | 17 | def assert_not_module_double_patched(self, urllib3): 18 | self.assert_not_double_wrapped(urllib3.connectionpool.HTTPConnectionPool.urlopen) 19 | -------------------------------------------------------------------------------- /tests/snapshots/tests.contrib.mariadb.test_mariadb.test_query_proc_snapshot.snap: -------------------------------------------------------------------------------- 1 | [[{"name" "mariadb.query" 2 | "service" "mariadb" 3 | "resource" "sp_sum" 4 | "type" "sql" 5 | "error" 0 6 | "span_id" 0 7 | "trace_id" 0 8 | "parent_id" nil 9 | "start" 1626718453505520000 10 | "duration" 1564000 11 | "meta" {"runtime-id" "0cbfb96da3ee4e86be3cf3b8a4004f86" 12 | "out.host" "127.0.0.1" 13 | "db.user" "test" 14 | "db.name" "test"} 15 | "metrics" {"_dd.agent_psr" 1.0 16 | "_dd.measured" 1 17 | "_sampling_priority_v1" 1 18 | "system.pid" 1502 19 | "out.port" 3306 20 | "db.rowcount" 0 21 | "sql.rows" 0 22 | "_dd.tracer_kr" 1.0}}]] 23 | -------------------------------------------------------------------------------- /tests/snapshots/tests.contrib.redis.test_redis.test_service_precedence.snap: -------------------------------------------------------------------------------- 1 | [[{"name" "redis.command" 2 | "service" "env-redis" 3 | "resource" "GET cheese" 4 | "type" "redis" 5 | "error" 0 6 | "span_id" 0 7 | "trace_id" 0 8 | "parent_id" nil 9 | "start" 1596062189185636000 10 | "duration" 2615000 11 | "meta" {"runtime-id" "5b043ff215454b3685a99fa16242038e" 12 | "redis.raw_command" "GET cheese" 13 | "out.host" "localhost"} 14 | "metrics" {"_dd.agent_psr" 1.0 15 | "_dd.measured" 1 16 | "_dd.tracer_kr" 1.0 17 | "_sampling_priority_v1" 1 18 | "system.pid" 76424 19 | "out.port" 6379 20 | "out.redis_db" 0 21 | "redis.args_length" 2}}]] 22 | -------------------------------------------------------------------------------- /tests/snapshots/tests.contrib.redis.test_redis.test_user_specified_service.snap: -------------------------------------------------------------------------------- 1 | [[{"name" "redis.command" 2 | "service" "redis" 3 | "resource" "GET cheese" 4 | "type" "redis" 5 | "error" 0 6 | "span_id" 0 7 | "trace_id" 0 8 | "parent_id" nil 9 | "start" 1596062189619805000 10 | "duration" 2395000 11 | "meta" {"runtime-id" "aa72b38bf1554ce49a747687494a4751" 12 | "redis.raw_command" "GET cheese" 13 | "out.host" "localhost"} 14 | "metrics" {"_dd.agent_psr" 1.0 15 | "_dd.measured" 1 16 | "_dd.tracer_kr" 1.0 17 | "_sampling_priority_v1" 1 18 | "system.pid" 76425 19 | "out.port" 6379 20 | "out.redis_db" 0 21 | "redis.args_length" 2}}]] 22 | -------------------------------------------------------------------------------- /tests/snapshots/tests.contrib.mariadb.test_mariadb.test_simple_query_snapshot.snap: -------------------------------------------------------------------------------- 1 | [[{"name" "mariadb.query" 2 | "service" "mariadb" 3 | "resource" "SELECT 1" 4 | "type" "sql" 5 | "error" 0 6 | "span_id" 0 7 | "trace_id" 0 8 | "parent_id" nil 9 | "start" 1626718453185258000 10 | "duration" 824000 11 | "meta" {"runtime-id" "0cbfb96da3ee4e86be3cf3b8a4004f86" 12 | "out.host" "127.0.0.1" 13 | "db.user" "test" 14 | "db.name" "test"} 15 | "metrics" {"_dd.agent_psr" 1.0 16 | "_dd.measured" 1 17 | "_sampling_priority_v1" 1 18 | "system.pid" 1502 19 | "out.port" 3306 20 | "db.rowcount" 0 21 | "sql.rows" 0 22 | "_dd.tracer_kr" 1.0}}]] 23 | -------------------------------------------------------------------------------- /ddtrace/contrib/futures/patch.py: -------------------------------------------------------------------------------- 1 | from concurrent import futures 2 | 3 | from ddtrace.vendor.wrapt import wrap_function_wrapper as _w 4 | 5 | from ...utils.wrappers import unwrap as _u 6 | from .threading import _wrap_submit 7 | 8 | 9 | def patch(): 10 | """Enables Context Propagation between threads""" 11 | if getattr(futures, "__datadog_patch", False): 12 | return 13 | setattr(futures, "__datadog_patch", True) 14 | 15 | _w("concurrent.futures", "ThreadPoolExecutor.submit", _wrap_submit) 16 | 17 | 18 | def unpatch(): 19 | """Disables Context Propagation between threads""" 20 | if not getattr(futures, "__datadog_patch", False): 21 | return 22 | setattr(futures, "__datadog_patch", False) 23 | 24 | _u(futures.ThreadPoolExecutor, "submit") 25 | -------------------------------------------------------------------------------- /ddtrace/constants.py: -------------------------------------------------------------------------------- 1 | FILTERS_KEY = "FILTERS" 2 | SAMPLE_RATE_METRIC_KEY = "_sample_rate" 3 | SAMPLING_PRIORITY_KEY = "_sampling_priority_v1" 4 | ANALYTICS_SAMPLE_RATE_KEY = "_dd1.sr.eausr" 5 | SAMPLING_AGENT_DECISION = "_dd.agent_psr" 6 | SAMPLING_RULE_DECISION = "_dd.rule_psr" 7 | SAMPLING_LIMIT_DECISION = "_dd.limit_psr" 8 | ORIGIN_KEY = "_dd.origin" 9 | HOSTNAME_KEY = "_dd.hostname" 10 | ENV_KEY = "env" 11 | VERSION_KEY = "version" 12 | SERVICE_KEY = "service.name" 13 | SERVICE_VERSION_KEY = "service.version" 14 | SPAN_KIND = "span.kind" 15 | SPAN_MEASURED_KEY = "_dd.measured" 16 | KEEP_SPANS_RATE_KEY = "_dd.tracer_kr" 17 | 18 | NUMERIC_TAGS = (ANALYTICS_SAMPLE_RATE_KEY,) 19 | 20 | MANUAL_DROP_KEY = "manual.drop" 21 | MANUAL_KEEP_KEY = "manual.keep" 22 | 23 | LOG_SPAN_KEY = "__datadog_log_span" 24 | -------------------------------------------------------------------------------- /tests/snapshots/tests.contrib.mariadb.test_mariadb.test_user_specified_dd_service_snapshot.snap: -------------------------------------------------------------------------------- 1 | [[{"name" "mariadb.query" 2 | "service" "mariadb" 3 | "resource" "SELECT 1" 4 | "type" "sql" 5 | "error" 0 6 | "span_id" 0 7 | "trace_id" 0 8 | "parent_id" nil 9 | "start" 1626718452059170000 10 | "duration" 1491000 11 | "meta" {"runtime-id" "cf25a26f85404c2fa6542978216544cd" 12 | "out.host" "127.0.0.1" 13 | "db.user" "test" 14 | "db.name" "test"} 15 | "metrics" {"_dd.agent_psr" 1.0 16 | "_dd.measured" 1 17 | "_sampling_priority_v1" 1 18 | "system.pid" 1508 19 | "out.port" 3306 20 | "db.rowcount" 0 21 | "sql.rows" 0 22 | "_dd.tracer_kr" 1.0}}]] 23 | -------------------------------------------------------------------------------- /scripts/run-tox-scenario: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | PATTERN="$1" 4 | shift 5 | 6 | # CircleCI has a bug in its workspace code where it can't handle filenames with some chars 7 | CLEANED_PATTERN=`echo $PATTERN | tr '^?()$' '_'` 8 | 9 | # If no match -> grep returns 1 -> script stops 10 | ENVLIST=$(tox -l | grep "$PATTERN") 11 | 12 | if [[ -z "${CIRCLE_NODE_TOTAL}" && -z "${CIRCLE_NODE_INDEX}" ]]; then 13 | exec echo "$ENVLIST" | tr '\n' ',' | xargs -I ARGS tox -e ARGS -- $@ 14 | else 15 | exec echo "$ENVLIST" | sort | python -c "import os, sys; t, i = int(os.getenv('CIRCLE_NODE_TOTAL')), int(os.getenv('CIRCLE_NODE_INDEX')); inp = sys.stdin.readlines(); s = len(inp)//t; print(''.join(inp[i*s:(i+1)*s] if i+1 write it in raw C */ 4 | #if PY_MAJOR_VERSION == 2 5 | static PyObject * 6 | buff_to_buff(char *buff, Py_ssize_t size) 7 | { 8 | return PyBuffer_FromMemory(buff, size); 9 | } 10 | 11 | #elif (PY_MAJOR_VERSION == 3) && (PY_MINOR_VERSION >= 3) 12 | static PyObject * 13 | buff_to_buff(char *buff, Py_ssize_t size) 14 | { 15 | return PyMemoryView_FromMemory(buff, size, PyBUF_READ); 16 | } 17 | #else 18 | static PyObject * 19 | buff_to_buff(char *buff, Py_ssize_t size) 20 | { 21 | Py_buffer pybuf; 22 | if (PyBuffer_FillInfo(&pybuf, NULL, buff, size, 1, PyBUF_FULL_RO) == -1) { 23 | return NULL; 24 | } 25 | 26 | return PyMemoryView_FromBuffer(&pybuf); 27 | } 28 | #endif 29 | -------------------------------------------------------------------------------- /tests/contrib/mongoengine/test_backwards.py: -------------------------------------------------------------------------------- 1 | """ 2 | ensure old interfaces exist and won't break things. 3 | """ 4 | import mongoengine 5 | 6 | from tests.contrib import config 7 | from tests.utils import DummyTracer 8 | 9 | 10 | class Singer(mongoengine.Document): 11 | first_name = mongoengine.StringField(max_length=50) 12 | last_name = mongoengine.StringField(max_length=50) 13 | 14 | 15 | def test_less_than_v04(): 16 | # interface from < v0.4 17 | from ddtrace.contrib.mongoengine import trace_mongoengine 18 | 19 | tracer = DummyTracer() 20 | 21 | connect = trace_mongoengine(tracer, service="my-mongo-db", patch=False) 22 | connect(port=config.MONGO_CONFIG["port"]) 23 | 24 | lc = Singer() 25 | lc.first_name = "leonard" 26 | lc.last_name = "cohen" 27 | lc.save() 28 | -------------------------------------------------------------------------------- /tests/snapshots/tests.contrib.redis.test.test_analytics_with_rate.snap: -------------------------------------------------------------------------------- 1 | [[{"name" "redis.command" 2 | "service" "redis" 3 | "resource" "GET cheese" 4 | "type" "redis" 5 | "error" 0 6 | "span_id" 0 7 | "trace_id" 0 8 | "parent_id" nil 9 | "start" 1593544942071235000 10 | "duration" 3194000 11 | "meta" {"runtime-id" "df8ef78c89a94f469b93dcb64328f7df" 12 | "redis.raw_command" "GET cheese" 13 | "out.host" "localhost"} 14 | "metrics" {"_dd.agent_psr" 1.0 15 | "_dd.measured" 1 16 | "_dd1.sr.eausr" 0.5 17 | "_sampling_priority_v1" 1 18 | "_dd.tracer_kr" 1.0 19 | "system.pid" 68083 20 | "out.port" 6379 21 | "out.redis_db" 0 22 | "redis.args_length" 2}}]] 23 | -------------------------------------------------------------------------------- /tests/snapshots/tests.integration.test_integration_snapshots.test_filters.snap: -------------------------------------------------------------------------------- 1 | [[{"name" "root" 2 | "service" nil 3 | "resource" "root" 4 | "error" 0 5 | "span_id" 0 6 | "trace_id" 0 7 | "parent_id" nil 8 | "start" 1616457150171098000 9 | "duration" 43000 10 | "meta" {"runtime-id" "ddf562510b004d60bdfaa21911ab1e60" 11 | "boop" "beep"} 12 | "metrics" {"_dd.agent_psr" 1.0 13 | "_sampling_priority_v1" 1 14 | "system.pid" 39631 15 | "_dd.tracer_kr" 1.0}} 16 | {"name" "child" 17 | "service" nil 18 | "resource" "child" 19 | "error" 0 20 | "span_id" 1 21 | "trace_id" 0 22 | "parent_id" 0 23 | "start" 1616457150171130000 24 | "duration" 7000 25 | "meta" {"boop" "beep"}}]] 26 | -------------------------------------------------------------------------------- /ddtrace/profiling/exporter/__init__.py: -------------------------------------------------------------------------------- 1 | import attr 2 | 3 | 4 | class ExportError(Exception): 5 | pass 6 | 7 | 8 | @attr.s 9 | class Exporter(object): 10 | """Exporter base class.""" 11 | 12 | def export(self, events, start_time_ns, end_time_ns): 13 | # type: (...) -> None 14 | """Export events. 15 | 16 | :param events: List of events to export. 17 | :param start_time_ns: The start time of recording. 18 | :param end_time_ns: The end time of recording. 19 | """ 20 | raise NotImplementedError 21 | 22 | 23 | @attr.s 24 | class NullExporter(Exporter): 25 | """Exporter that does nothing.""" 26 | 27 | def export(self, events, start_time_ns, end_time_ns): 28 | # type: (...) -> None 29 | """Discard events.""" 30 | pass 31 | -------------------------------------------------------------------------------- /tests/snapshots/tests.contrib.redis.test_redis.test_analytics_with_rate.snap: -------------------------------------------------------------------------------- 1 | [[{"name" "redis.command" 2 | "service" "redis" 3 | "resource" "GET cheese" 4 | "type" "redis" 5 | "error" 0 6 | "span_id" 0 7 | "trace_id" 0 8 | "parent_id" nil 9 | "start" 1596062187949991000 10 | "duration" 3527000 11 | "meta" {"runtime-id" "601815e8709646a9ac897c59376c80b6" 12 | "redis.raw_command" "GET cheese" 13 | "out.host" "localhost"} 14 | "metrics" {"_dd.agent_psr" 1.0 15 | "_dd.measured" 1 16 | "_dd1.sr.eausr" 0.5 17 | "_sampling_priority_v1" 1 18 | "_dd.tracer_kr" 1.0 19 | "system.pid" 76411 20 | "out.port" 6379 21 | "out.redis_db" 0 22 | "redis.args_length" 2}}]] 23 | -------------------------------------------------------------------------------- /tests/snapshots/tests.contrib.redis.test_redis.test_analytics_without_rate.snap: -------------------------------------------------------------------------------- 1 | [[{"name" "redis.command" 2 | "service" "redis" 3 | "resource" "GET cheese" 4 | "type" "redis" 5 | "error" 0 6 | "span_id" 0 7 | "trace_id" 0 8 | "parent_id" nil 9 | "start" 1600443665674164000 10 | "duration" 2844000 11 | "meta" {"runtime-id" "81d7379fb04f420c9b55d9ee93ca4ea4" 12 | "redis.raw_command" "GET cheese" 13 | "out.host" "localhost"} 14 | "metrics" {"_dd.agent_psr" 1.0 15 | "_dd.measured" 1 16 | "_dd1.sr.eausr" 1.0 17 | "_dd.tracer_kr" 1.0 18 | "_sampling_priority_v1" 1 19 | "system.pid" 48090 20 | "out.port" 6379 21 | "out.redis_db" 0 22 | "redis.args_length" 2}}]] 23 | -------------------------------------------------------------------------------- /ddtrace/contrib/boto/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Boto integration will trace all AWS calls made via boto2. 3 | This integration is automatically patched when using ``patch_all()``:: 4 | 5 | import boto.ec2 6 | from ddtrace import patch 7 | 8 | # If not patched yet, you can patch boto specifically 9 | patch(boto=True) 10 | 11 | # This will report spans with the default instrumentation 12 | ec2 = boto.ec2.connect_to_region("us-west-2") 13 | # Example of instrumented query 14 | ec2.get_all_instances() 15 | """ 16 | 17 | from ...utils.importlib import require_modules 18 | 19 | 20 | required_modules = ["boto.connection"] 21 | 22 | with require_modules(required_modules) as missing_modules: 23 | if not missing_modules: 24 | from .patch import patch 25 | 26 | __all__ = ["patch"] 27 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/users/models.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth.models import AbstractUser 2 | from django.db.models import CharField 3 | from django.urls import reverse 4 | from django.utils.translation import gettext_lazy as _ 5 | 6 | 7 | class User(AbstractUser): 8 | """Default user for ddtrace-django.""" 9 | 10 | #: First and last name do not cover name patterns around the globe 11 | name = CharField(_("Name of User"), blank=True, max_length=255) 12 | first_name = None # type: ignore 13 | last_name = None # type: ignore 14 | 15 | def get_absolute_url(self): 16 | """Get url for user's detail view. 17 | 18 | Returns: 19 | str: URL for user detail. 20 | 21 | """ 22 | return reverse("users:detail", kwargs={"username": self.username}) 23 | -------------------------------------------------------------------------------- /ddtrace/profiling/collector/_memalloc_heap.h: -------------------------------------------------------------------------------- 1 | #ifndef _DDTRACE_MEMALLOC_HEAP_H 2 | #define _DDTRACE_MEMALLOC_HEAP_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include "_utils.h" 11 | 12 | /* The maximum heap sample size is the maximum value we can store in a heap_tracker_t.allocated_memory */ 13 | #define MAX_HEAP_SAMPLE_SIZE UINT32_MAX 14 | 15 | void 16 | memalloc_heap_tracker_init(uint32_t sample_size); 17 | void 18 | memalloc_heap_tracker_deinit(void); 19 | 20 | PyObject* 21 | memalloc_heap(); 22 | 23 | bool 24 | memalloc_heap_track(uint16_t max_nframe, void* ptr, size_t size); 25 | void 26 | memalloc_heap_untrack(void* ptr); 27 | 28 | #define MEMALLOC_HEAP_PTR_ARRAY_MAX UINT64_MAX 29 | DO_ARRAY(void *, ptr, uint64_t, DO_NOTHING) 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /tests/contrib/pylons/app/lib/helpers.py: -------------------------------------------------------------------------------- 1 | from webhelpers import * # noqa 2 | 3 | 4 | class ExceptionWithCodeMethod(Exception): 5 | """Use case where the status code is defined by 6 | the `code()` method. 7 | """ 8 | 9 | def __init__(self, message): 10 | super(ExceptionWithCodeMethod, self).__init__(message) 11 | 12 | def code(self): 13 | pass 14 | 15 | 16 | class AppGlobals(object): 17 | """Object used to store application globals.""" 18 | 19 | pass 20 | 21 | 22 | def get_render_fn(): 23 | """Re-import the function every time so that double-patching 24 | is correctly tested. 25 | """ 26 | try: 27 | from pylons.templating import render_mako as render 28 | except ImportError: 29 | from pylons.templating import render 30 | 31 | return render 32 | -------------------------------------------------------------------------------- /tests/snapshots/tests.contrib.mariadb.test_mariadb.test_analytics_with_rate_snapshot.snap: -------------------------------------------------------------------------------- 1 | [[{"name" "mariadb.query" 2 | "service" "mariadb" 3 | "resource" "SELECT 1" 4 | "type" "sql" 5 | "error" 0 6 | "span_id" 0 7 | "trace_id" 0 8 | "parent_id" nil 9 | "start" 1626718453548365000 10 | "duration" 980000 11 | "meta" {"runtime-id" "0cbfb96da3ee4e86be3cf3b8a4004f86" 12 | "out.host" "127.0.0.1" 13 | "db.user" "test" 14 | "db.name" "test"} 15 | "metrics" {"_dd.agent_psr" 1.0 16 | "_dd.measured" 1 17 | "_dd1.sr.eausr" 0.5 18 | "_sampling_priority_v1" 1 19 | "system.pid" 1502 20 | "_dd.tracer_kr" 1.0 21 | "sql.rows" 0 22 | "db.rowcount" 0 23 | "out.port" 3306}}]] 24 | -------------------------------------------------------------------------------- /tests/snapshots/tests.contrib.redis.test_redis.test_pipeline_traced.snap: -------------------------------------------------------------------------------- 1 | [[{"name" "redis.command" 2 | "service" "redis" 3 | "resource" "SET blah 32\nRPUSH foo éé\nHGETALL xxx" 4 | "type" "redis" 5 | "error" 0 6 | "span_id" 0 7 | "trace_id" 0 8 | "parent_id" nil 9 | "start" 1596062188760912000 10 | "duration" 2946000 11 | "meta" {"runtime-id" "601815e8709646a9ac897c59376c80b6" 12 | "redis.raw_command" "SET blah 32\nRPUSH foo éé\nHGETALL xxx" 13 | "out.host" "localhost"} 14 | "metrics" {"_dd.agent_psr" 1.0 15 | "_dd.measured" 1 16 | "_dd.tracer_kr" 1.0 17 | "_sampling_priority_v1" 1 18 | "system.pid" 76411 19 | "out.port" 6379 20 | "out.redis_db" 0 21 | "redis.pipeline_length" 3}}]] 22 | -------------------------------------------------------------------------------- /benchmarks/django_simple/ddtrace_django/static/sass/project.scss: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | // project specific CSS goes here 6 | 7 | //////////////////////////////// 8 | //Variables// 9 | //////////////////////////////// 10 | 11 | // Alert colors 12 | 13 | $white: #fff; 14 | $mint-green: #d6e9c6; 15 | $black: #000; 16 | $pink: #f2dede; 17 | $dark-pink: #eed3d7; 18 | $red: #b94a48; 19 | 20 | //////////////////////////////// 21 | //Alerts// 22 | //////////////////////////////// 23 | 24 | // bootstrap alert CSS, translated to the django-standard levels of 25 | // debug, info, success, warning, error 26 | 27 | .alert-debug { 28 | background-color: $white; 29 | border-color: $mint-green; 30 | color: $black; 31 | } 32 | 33 | .alert-error { 34 | background-color: $pink; 35 | border-color: $dark-pink; 36 | color: $red; 37 | } 38 | -------------------------------------------------------------------------------- /ddtrace/vendor/psutil/arch/windows/services.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | SC_HANDLE psutil_get_service_handle( 11 | char service_name, DWORD scm_access, DWORD access); 12 | PyObject *psutil_winservice_enumerate(PyObject *self, PyObject *args); 13 | PyObject *psutil_winservice_query_config(PyObject *self, PyObject *args); 14 | PyObject *psutil_winservice_query_status(PyObject *self, PyObject *args); 15 | PyObject *psutil_winservice_query_descr(PyObject *self, PyObject *args); 16 | PyObject *psutil_winservice_start(PyObject *self, PyObject *args); 17 | PyObject *psutil_winservice_stop(PyObject *self, PyObject *args); 18 | --------------------------------------------------------------------------------