{"id":18915191,"url":"https://github.com/uber-common/opentracing-python-instrumentation","last_synced_at":"2025-04-12T21:35:42.791Z","repository":{"id":51665640,"uuid":"49710586","full_name":"uber-common/opentracing-python-instrumentation","owner":"uber-common","description":"A collection of Python instrumentation tools for the OpenTracing API","archived":false,"fork":false,"pushed_at":"2023-01-30T08:43:49.000Z","size":251,"stargazers_count":163,"open_issues_count":22,"forks_count":58,"subscribers_count":2079,"default_branch":"master","last_synced_at":"2025-04-04T01:09:44.896Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/uber-common.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.rst","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-01-15T09:49:34.000Z","updated_at":"2025-03-14T17:25:22.000Z","dependencies_parsed_at":"2023-02-16T05:45:21.488Z","dependency_job_id":null,"html_url":"https://github.com/uber-common/opentracing-python-instrumentation","commit_stats":null,"previous_names":[],"tags_count":45,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uber-common%2Fopentracing-python-instrumentation","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uber-common%2Fopentracing-python-instrumentation/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uber-common%2Fopentracing-python-instrumentation/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uber-common%2Fopentracing-python-instrumentation/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/uber-common","download_url":"https://codeload.github.com/uber-common/opentracing-python-instrumentation/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248637199,"owners_count":21137530,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-08T10:14:46.794Z","updated_at":"2025-04-12T21:35:42.766Z","avatar_url":"https://github.com/uber-common.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![PyPI version][pypi-img]][pypi] [![Python versions][pyver-img]][pypi] [![Pypi Downloads][pydl-img]][pypi] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov] \n\n\n# opentracing-python-instrumentation\n\nA collection of instrumentation tools to enable tracing with \n[OpenTracing API](http://opentracing.io).\n\n## Module\n\nMake sure you are running recent enough versions of `pip` and `setuptools`, e.g. before installing your project requirements execute this:\n\n```\npip install --upgrade \"setuptools\u003e=29\" \"pip\u003e=9\"\n```\n\nThe module name is `opentracing_instrumentation`.\n\n## What's inside\n\n### Supported client frameworks\n\nThe following libraries are instrumented for tracing in this module:\n * [boto3](https://github.com/boto/boto3) — AWS SDK for Python\n * [Celery](https://github.com/celery/celery) — Distributed Task Queue\n * `urllib2`\n * `requests`\n * `SQLAlchemy`\n * `MySQLdb`\n * `psycopg2`\n * Tornado HTTP client\n *  `redis`\n\n#### Limitations\n\nFor some operations, `Boto3` uses `ThreadPoolExecutor` under the hood.\nSo, in order to make it thread-safe, the instrumentation is implemented using\n`span_in_stack_context()` which\n[forces you](https://github.com/uber-common/opentracing-python-instrumentation#in-process-context-propagation)\nto use `TornadoScopeManager`.\n\n### Server instrumentation\n\nFor inbound requests a helper function `before_request` is provided for creating middleware for frameworks like Flask and uWSGI.\n\n### Manual instrumentation\n\nFinally, a `@traced_function` decorator is provided for manual instrumentation.\n\n### In-process Context Propagation\n\nAs part of the OpenTracing 2.0 API, in-process `Span` propagation happens through the newly defined\n[ScopeManager](https://opentracing-python.readthedocs.io/en/latest/api.html#scope-managers)\ninterface. However, the existing functionality has been kept to provide backwards compatibility and\nease code migration:\n\n`span_in_context()` implements context propagation using the current `opentracing.tracer.scope_manager`,\nexpected to be a thread-local based `ScopeManager`, such as `opentracing.scope_managers.ThreadLocalScopeManager`.\n\n`span_in_stack_context()` implements context propagation for Tornado applications\nusing the current `opentracing.tracer.scope_manager` too, expected to be an instance of\n `opentracing.scope_managers.tornado.TornadoScopeManager`.\n\n`get_current_span()` returns the currently active `Span`, if any.\n\nDirect access to the `request_context` module as well as usage of `RequestContext` and `RequestContextManager`\nhave been **fully** deprecated, as they do not integrate with the new OpenTracing 2.0 API.\nUsing them along `get_current_span()` is guaranteed to work, but it is **highly** recommended\nto switch to the previously mentioned functions.\n\n## Usage\n\nThis library provides two types of instrumentation, explicit instrumentation\nfor server endpoints, and implicit instrumentation for client call sites.\n\nServer endpoints are instrumented by creating a middleware class that:\n\n 1. initializes the specific tracer implementation\n 2. wraps incoming request handlers into a method that reads the incoming\n    tracing info from the request and creates a new tracing Span\n\nClient call sites are instrumented implicitly by executing a set of \navailable `client_hooks` that monkey-patch some API points in several \ncommon libraries like `SQLAlchemy`, `urllib2`, Tornado Async HTTP Client.\nThe initialization of those hooks is usually also done from the middleware\nclass's `__init__` method.\n\nThere is a client-server example using this library with Flask instrumentation\nfrom opentracing-contrib: https://github.com/opentracing-contrib/python-flask/tree/master/example.\n\nHere's an example of a middleware for [Clay framework](https://github.com/uber/clay):\n\n```python\n\nfrom opentracing_instrumentation import span_in_context\nfrom opentracing_instrumentation.http_server import before_request\nfrom opentracing_instrumentation.http_server import WSGIRequestWrapper\nfrom opentracing_instrumentation.client_hooks import install_all_patches\n\n\nclass TracerMiddleware(object):\n\n    def __init__(self, app, wsgi_app):\n        self.wsgi_app = wsgi_app\n        self.service_name = app.name\n\n        CONFIG.app_name = self.service_name\n        CONFIG.caller_name_headers.append('X-Uber-Source')\n        CONFIG.callee_endpoint_headers.append('X-Uber-Endpoint')\n\n        install_all_patches()\n        self.wsgi_app = create_wsgi_middleware(wsgi_app)\n        self.init_tracer()\n\n    def __call__(self, environ, start_response):\n        return self.wsgi_app(environ, start_response)\n\n    def init_tracer(self):\n        # code specific to your tracer implementation\n        pass\n\n\ndef create_wsgi_middleware(other_wsgi, tracer=None):\n    \"\"\"\n    Create a wrapper middleware for another WSGI response handler.\n    If tracer is not passed in, 'opentracing.tracer' is used.\n    \"\"\"\n\n    def wsgi_tracing_middleware(environ, start_response):\n        # TODO find out if the route can be retrieved from somewhere\n\n        request = WSGIRequestWrapper.from_wsgi_environ(environ)\n        span = before_request(request=request, tracer=tracer)\n\n        # Wrapper around the real start_response object to log\n        # additional information to opentracing Span\n        def start_response_wrapper(status, response_headers, exc_info=None):\n            if exc_info is not None:\n                span.set_tag('error', str(exc_info))\n            span.finish()\n\n            return start_response(status, response_headers)\n\n        with span_in_context(span):\n            return other_wsgi(environ, start_response_wrapper)\n\n    return wsgi_tracing_middleware\n```\n\nAnd here's an example for middleware in Tornado-based app:\n\n```python\n\nimport opentracing\nfrom opentracing.scope_managers.tornado import TornadoScopeManager\nfrom opentracing_instrumentation import span_in_stack_context, http_server\n\n\nopentracing.tracer = MyOpenTracingTracer(scope_manager=TornadoScopeManager())\n\n\nclass TracerMiddleware(object):\n\n    def __init__(self):\n        # perform initialization similar to above, including installing\n        # the client_hooks\n        \n    @gen.coroutine\n    def __call__(self, request, handler, next_mw):\n        request_wrapper = http_server.TornadoRequestWrapper(request=request)\n        span = http_server.before_request(request=request_wrapper)\n\n        @gen.coroutine\n        def next_middleware_with_span():\n            yield next_mw()\n\n        yield run_coroutine_with_span(span=span,\n                                      func=next_middleware_with_span)\n\n        span.finish()\n\n\ndef run_coroutine_with_span(span, func, *args, **kwargs):\n    \"\"\"Wrap the execution of a Tornado coroutine func in a tracing span.\n\n    This makes the span available through the get_current_span() function.\n\n    :param span: The tracing span to expose.\n    :param func: Co-routine to execute in the scope of tracing span.\n    :param args: Positional args to func, if any.\n    :param kwargs: Keyword args to func, if any.\n    \"\"\"\n    with span_in_stack_context(span):\n        return func(*args, **kwargs)\n```\n\n### Customization\n\nFor the `requests` library, in case you want to set custom tags\nto spans depending on content or some metadata of responses,\nyou can set `response_handler_hook`.\nThe hook must be a method with a signature `(response, span)`,\nwhere `response` and `span` are positional arguments,\nso you can use different names for them if needed.\n\n```python\nfrom opentracing_instrumentation.client_hooks.requests import patcher\n\n\ndef hook(response, span):\n    if not response.ok:\n        span.set_tag('error', 'true')\n\n\npatcher.set_response_handler_hook(hook)\n```\n\nIf you have issues with getting the parent span, it is possible to override\ndefault function that retrieves parent span. \n\n```python \nfrom opentracing_instrumentation.client_hooks import install_all_patches,\n     set_current_span_func\n\nset_current_span_func(my_custom_extractor_func)\ninstall_all_patches()\n\n``` \n\n## Development\n\n`PostgreSQL`, `RabbitMQ`, `Redis`, and `DynamoDB` are required for certain tests.\n\n```bash\ndocker-compose up -d\n```\n\nTo prepare a development environment please execute the following commands.\n```bash\nvirtualenv env\nsource env/bin/activate\nmake bootstrap\nmake test\n```\n\nYou can use [tox](https://tox.readthedocs.io) to run tests as well.\n```bash\ntox\n```\n\n[ci-img]: https://travis-ci.org/uber-common/opentracing-python-instrumentation.svg?branch=master\n[ci]: https://travis-ci.org/uber-common/opentracing-python-instrumentation\n[pypi-img]: https://img.shields.io/pypi/v/opentracing_instrumentation.svg\n[pypi]: https://pypi.python.org/pypi/opentracing_instrumentation\n[cov-img]: https://coveralls.io/repos/github/uber-common/opentracing-python-instrumentation/badge.svg\n[cov]: https://coveralls.io/github/uber-common/opentracing-python-instrumentation\n[pyver-img]: https://img.shields.io/pypi/pyversions/opentracing-instrumentation.svg \n[pydl-img]: https://img.shields.io/pypi/dm/opentracing-instrumentation.svg \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuber-common%2Fopentracing-python-instrumentation","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fuber-common%2Fopentracing-python-instrumentation","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuber-common%2Fopentracing-python-instrumentation/lists"}