{"id":29374709,"url":"https://github.com/garyd203/xraysink","last_synced_at":"2025-07-09T20:11:30.071Z","repository":{"id":40246504,"uuid":"273994789","full_name":"garyd203/xraysink","owner":"garyd203","description":"Instrument asyncio Python for distributed tracing with AWS X-Ray.","archived":false,"fork":false,"pushed_at":"2024-07-08T11:48:01.000Z","size":468,"stargazers_count":23,"open_issues_count":18,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-06-30T00:34:12.195Z","etag":null,"topics":["asyncio","asyncio-python","aws-xray","distributed-tracing","hacktoberfest","python","python3"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/garyd203.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-06-21T22:44:30.000Z","updated_at":"2025-06-22T14:40:07.000Z","dependencies_parsed_at":"2024-07-08T14:15:26.757Z","dependency_job_id":"998826b7-4ba3-4966-9c5d-3ecc8d556709","html_url":"https://github.com/garyd203/xraysink","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/garyd203/xraysink","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garyd203%2Fxraysink","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garyd203%2Fxraysink/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garyd203%2Fxraysink/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garyd203%2Fxraysink/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/garyd203","download_url":"https://codeload.github.com/garyd203/xraysink/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garyd203%2Fxraysink/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264502621,"owners_count":23618658,"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":["asyncio","asyncio-python","aws-xray","distributed-tracing","hacktoberfest","python","python3"],"created_at":"2025-07-09T20:11:28.953Z","updated_at":"2025-07-09T20:11:30.057Z","avatar_url":"https://github.com/garyd203.png","language":"Python","readme":"# xraysink\n\n\u003cdiv align=\"center\"\u003e\n    \u003ca href=\"https://pypi.org/project/xraysink/\"\u003e\n        \u003cimg src=\"https://img.shields.io/pypi/v/xraysink.svg\" alt=\"Package version\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://pypi.org/project/xraysink/\"\u003e\n        \u003cimg src=\"https://img.shields.io/pypi/pyversions/xraysink.svg\" alt=\"Python versions\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://pypi.org/project/xraysink/\"\u003e\n        \u003cimg src=\"https://img.shields.io/pypi/dm/xraysink.svg\" alt=\"Monthly downloads\"\u003e\n    \u003c/a\u003e\n\u003c/div\u003e\n\u003cdiv align=\"center\"\u003e\n    \u003c!-- Coverage badge stored in our wiki by the python-coverage-comment-action plugin --\u003e\n    \u003ca href=\"https://github.com/garyd203/xraysink/\"\u003e\n        \u003cimg src=\"https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/wiki/garyd203/xraysink/python-coverage-comment-action-badge.json\" alt=\"Coverage\"\u003e\n    \u003c/a\u003e\n\u003c/div\u003e\n\nExtra AWS X-Ray instrumentation to use distributed tracing with asyncio Python\nlibraries that are not (yet) supported by the official\n[aws_xray_sdk](https://github.com/aws/aws-xray-sdk-python) library.\n\n\n## What Problem Does xraysink Solve?\n\n`aws_xray_sdk` is the standard library to collect trace data from your Python\ncode and send the trace data to the\n[AWS X-Ray distributed tracing tool](https://aws.amazon.com/xray/). However,\nif you have asyncio Python code, then there are some gaps and occasional\nbugs in the functionality provided by that library. `xraysink` plugs those gaps.\n\nIt can be a bit confusing using two libraries together, so here's a high-level\nbreakdown of which library will help you do what:\n\n* Add tracing to HTTP requests handled by FastAPI (or another async Python\n  web framework): `xraysink` (via [middleware](#fastapi))\n* Add tracing to background (non-HTTP-request) functions written as async\n  Python functions: `xraysink` (via [xray_task_async](#background-jobstasks)\n  decorator)\n* Everything else: [aws_xray_sdk](https://github.com/aws/aws-xray-sdk-python)\n\n\n## Integrations Supported\n* Generic ASGI-compatible tracing middleware for *any* ASGI-compliant web\n  framework. This has been tested with:\n  - [aiohttp server](https://docs.aiohttp.org/en/stable/)\n  - [FastAPI](https://fastapi.tiangolo.com/)\n* asyncio [Task's](https://docs.python.org/3/library/asyncio-task.html)\n* Background jobs/tasks\n\n\n## Installation\nxraysink is distributed as a standard python package through\n[pypi](https://pypi.org/), so you can install it with your favourite Python\npackage manager. For example:\n\n    pip install xraysink\n\n\n## How to use\n`xraysink` augments the functionality provided by `aws_xray_sdk`. Before\nusing the tools in `xraysink`, you first need to configure `aws_xray_sdk` -\nthis will probably involve calling `xray_recorder.configure()` when your\nprocess starts, and optionally `aws_xray_sdk.core.patch()`.\n\nExtra instrumentation provided by `xraysink` is described below.\n\n### FastAPI\nInstrument incoming requests in your FastAPI web server by adding the\n`xray_middleware` to your app. For example, you could do:\n\n    from starlette.middleware.base import BaseHTTPMiddleware\n    from xraysink.asgi.middleware import xray_middleware\n    \n    # Standard asyncio X-Ray configuration, customise as you choose\n    xray_recorder.configure(context=AsyncContext(), service=\"my-cute-little-service\")\n    \n    # Create a FastAPI app with various middleware\n    app = FastAPI()\n    app.add_middleware(MyTracingDependentMiddleware)  # Any middleware that is added earlier will have the X-Ray tracing context available to it\n    app.add_middleware(BaseHTTPMiddleware, dispatch=xray_middleware)\n\n\n### Asyncio Tasks\nIf you start asyncio [Task's](https://docs.python.org/3/library/asyncio-task.html)\nfrom a standard request handler, then the AWS X-Ray SDK will not correctly\ninstrument any outgoing requests made inside those Tasks.\n\nUse the fixed `AsyncContext` from `xraysink` as a drop-in replacement, like so:\n\n    from aws_xray_sdk.core import xray_recorder\n    from xraysink.context import AsyncContext  # NB: Use the AsyncContext from xraysink\n    \n    # Use the fixed AsyncContext when configuring X-Ray,\n    # and customise other configuration as you choose.\n    xray_recorder.configure(context=AsyncContext(use_task_factory=True))\n\n\n### Background Jobs/Tasks\nIf your process starts background tasks that make network calls (eg. to the\ndatabase or an API in another service), then each execution of one of those\ntasks should be treated as a new X-Ray trace. Indeed, if you don't do so then\nyou will likely get `context_missing` errors.\n\nAn async function that implements a background task can be easily instrumented\nusing the `@xray_task_async()` decorator, like so:\n\n    from aws_xray_sdk.core import xray_recorder\n    from xraysink.tasks import xray_task_async\n\n    # Standard asyncio X-Ray configuration, customise as you choose\n    xray_recorder.configure(context=AsyncContext(), service=\"my-cute-little-service\")\n    \n    # Any call to this function will start a new X-Ray trace\n    @xray_task_async()\n    async def cleanup_stale_tokens():\n        await database.get_table(\"tokens\").delete(age__gt=1)\n    \n    # Start your background task using your scheduling system of choice :)\n    schedule_recurring_task(cleanup_stale_tokens)\n\nIf your background task functions are called from a function that is already\ninstrumented (eg. send an email immediately after handling a request), then \nthe background task will appear as a child segment of that trace. In this case,\nyou must ensure you use the non-buggy `AsyncContext` when configuring the recorder\n(ie. `from xraysink.context import AsyncContext`)\n\n\n### CloudWatch Logs integration\nYou can link your X-Ray traces to your CloudWatch Logs log records, which\nenhances the integration with AWS CloudWatch ServiceLens. Take the following\nsteps:\n\n1.  Put the X-Ray trace ID into every log message. There is no convention for\n    how to do this (it just has to appear verbatim in the log message\n    somewhere), but if you are using structured logging then the convention is\n    to use a field called `traceId`. Here's an example\n    \n        trace_id = xray_recorder.get_trace_entity().trace_id\n        logging.getLogger(\"example\").info(\"Hello World!\", extra={\"traceId\": trace_id})\n\n1.  Explicitly set the name of the CloudWatch Logs log group associated with\n    your process. There is no general way to detect the Log Group from inside\n    the process, hence it requires manual configuration as part of your process\n    initialisation (eg. in the same place where you call\n    `xray_recorder.configure`).\n    \n        set_xray_log_group(\"/example/service-name\")\n\nNote that this feature relies on undocumented functionality, and is\n[not yet](https://github.com/aws/aws-xray-sdk-python/issues/188)\nsupported by the official Python SDK.\n\n\n## Licence\nThis project uses the Apache 2.0 licence, to make it compatible with\n[aws_xray_sdk](https://github.com/aws/aws-xray-sdk-python), the\nprimary library for integrating with AWS X-Ray.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgaryd203%2Fxraysink","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgaryd203%2Fxraysink","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgaryd203%2Fxraysink/lists"}