snok / asgi-correlation-id

Request ID propagation for ASGI apps
MIT License
369 stars 29 forks source link

Correlation-id header doesn't propagate to outgoing reqeusts. #46

Closed prashantk1220 closed 1 year ago

prashantk1220 commented 1 year ago

As in a typical micro-service architecture, I want the correlation Id to be automatically propagated to the outbound requests made from one API to other APIs. I'm using the HTTPX AsyncClient for the same. But unless I explicitly add the header to the client object, the other API services do not receive it inherently and they create their own header which ultimately defeats the purpose of having a correlation-id.

sondrelg commented 1 year ago

I don't know of a way to hijack outgoing requests unfortunately. One idea might be to have a get_client function where you add the outgoing header logic. In my own projects we have a get_headers method that handles auth + tracing headers.

If you can think of a more general way of solving this issue, I'm open to suggestions 👍

prashantk1220 commented 1 year ago

@sondrelg But then I assume you would need to pass the context variable each time from the requests, isn't? So how easy would it be do add the correlation ids, in already developed micro-services?

And how about the method defined in the middleware.pymodule here: async def handle_outgoing_request(message: 'Message') ? Can't we do a type check here for all outgoing http requests?

JonasKs commented 1 year ago

The handle_outgoing_request is the API request, through your API framework stack. Whatever some other third party module (such as HTTPX) do, won't be handled by middlewares. Tiangolo gives a good description here.

In short, you can easily get the correlation-ID wherever you want it. I recommend writing helper functions to perform API calls, such as this:

from asgi_correlation_id.context import correlation_id

@dataclass
class MySDK:
    @classmethod
    async def get(cls, url ...):
        async with AsyncClient(
            timeout=30,
            auth=BasicAuth(username=settings.USERNAME, password=settings.PASSWORD),
            headers={'Correlation-ID': correlation_id.get()}
        ) as client:
            ...
JonasKs commented 1 year ago

Alternatively, you can use hooks in httpx, and share a client. See the documentation.

prashantk1220 commented 1 year ago

Thanks @JonasKs, that helps!

sondrelg commented 1 year ago

I'll close this for now @prashantk1220 🙂

prashantk1220 commented 1 year ago

Sure thanks, @sondrelg and @JonasKs. I was also going through the Opentelemetry implementation to check how auto-propagation of the IDs can be implemented.