Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How best to implement a Logging Adapter? #140

Closed
StephenBrown2 opened this issue Jul 24, 2019 · 4 comments
Closed

How best to implement a Logging Adapter? #140

StephenBrown2 opened this issue Jul 24, 2019 · 4 comments

Comments

@StephenBrown2
Copy link
Contributor

I see that adapters were added, debated, and then removed for simplicities sake, but I'd like to set up a logging adapter like is possible by subclassing requests.adapters.HTTPAdapter like so:

class LoggingHTTPAdapter(requests.adapters.HTTPAdapter):
    """Adapter to log request and response."""

    def send(self, request, *args, **kwargs):
        sensitive_params = conf.SENSITIVE_PARAMS

        # transaction ID to identify the logs.
        trans_id = util.generate_uuid()

        headers = util.filter_sensitive_information(
            request.headers, sensitive_params
        )

        log.info(f"<{trans_id}> Request: {request.method} {request.url}")
        log.info(f"<{trans_id}> Request headers: {headers}")
        log.info(f"<{trans_id}> Request body: {request.body}")

        resp = super().send(request, *args, **kwargs)

        headers = util.filter_sensitive_information(
            resp.headers, sensitive_params
        )

        log.info(f"<{trans_id}> Response: {resp.status_code} {resp.reason}")
        log.info(f"<{trans_id}> Response headers: {headers}")
        log.info(f"<{trans_id}> Response body: {resp.content}")

        # Store the transaction ID in the response object, so that it can be
        # added to the logs from test cases.
        resp.__dict__["transaction_id"] = trans_id

        return resp


def mount_adapter(session):
    # currently we only have TimeoutHTTPAdapter and LoggingHTTPAdapter,
    # when we add more in the future, we can use this function to mount
    # our adapters.
    adapters = [LoggingHTTPAdapter()]
    for adapter in adapters:
        session.mount("http://", adapter)
        session.mount("https://", adapter)

With httpx, would I need to wrap/subclass a Dispatcher or Client class instead?

@tomchristie
Copy link
Member

The Dispatcher interface is a very close equivalent to the Adapter interface.

You could achieve the same usage you’ve given an example of by subclassing the default Dispatch implementation (ConnectionPool), and passing it to the client with dispatch=.

That’d be equivalent to how this example subclasses HTTPAdapter, and uses mount to add it to the client.

@StephenBrown2
Copy link
Contributor Author

Excellent. I'll give that a shot tomorrow. Thanks!

@sethmlarson
Copy link
Contributor

This issue is no longer needed it seems? Reopen if I'm wrong here :)

@StephenBrown2
Copy link
Contributor Author

Yup, the custom Dispatcher worked for me, was going to update on Monday once I had a bit more testing done. Good to close 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants