Victor Pudeyev
Victor Pudeyev

Reputation: 4538

Skip Flask logging for one endpoint?

I have a Python Flask application. There is a healthcheck that hits one endpoint (/) a lot, and I'd like to not see it in logs. How do I disable logging for only one GET endpoint, and leave it be for everything else?

Upvotes: 8

Views: 5875

Answers (5)

Bogdan Condurache
Bogdan Condurache

Reputation: 445

The other solutions presented are correct and they work for Werkzeug on a default Flask setup. Same approach works for when using Flask with gevent as well, but decided to post it here in case anyone else stumbled upon it and needs the code straight away:

from gevent.pywsgi import WSGIHandler

class CustomWSGIHandler(WSGIHandler):
    def log_request(self):
        requests_to_ignore = ["/health", "/"]
    if self.path in requests_to_ignore:
        return
    super(CustomWSGIHandler, self).log_request()

Upvotes: 0

Diego Miguel
Diego Miguel

Reputation: 628

This is a sligthly modified implementation based on mpaepper's answer.

It allows to specifiy the log-disabled endpoints using regex. This can be useful when you want to ignore logs for endpoints such as "/v1/recipes/<int:recipe_id>":

def disable_endpoint_logs():
    """Disable logs for requests to specific endpoints."""

    disabled_endpoints = ('/', '/healthz', '/v1/recipes/[0-9]+')

    parent_log_request = serving.WSGIRequestHandler.log_request

    def log_request(self, *args, **kwargs):
        if not any(re.match(f"{de}$", self.path) for de in disabled_endpoints):
            parent_log_request(self, *args, **kwargs)

    serving.WSGIRequestHandler.log_request = log_request

With the code above, the logs for the endpoint "/v1/recipes/23992341" would be ignored, but the ones for "/v1/recipes" would not be ignored.

Just call this function once in your code and you're good to go.

Upvotes: 4

Orkhan M.
Orkhan M.

Reputation: 163

Another option is to monkey patch WSGIRequestHandler suggested by Étienne Bersac

this way:

from werkzeug.serving import WSGIRequestHandler
from werkzeug.urls import uri_to_iri


try:
    import click
except ImportError:
    click = None


def log_request(WSGIRequestHandler, code="-", size="-"):
    try:
        path = uri_to_iri(WSGIRequestHandler.path)

        if path in black_listed_routes:
            return

        msg = "%s %s %s" % (WSGIRequestHandler.command, path, WSGIRequestHandler.request_version)
    except AttributeError:
        # path isn't set if the requestline was bad
        msg = WSGIRequestHandler.requestline

    code = str(code)

    if click:
        color = click.style

        if code[0] == "1":  # 1xx - Informational
            msg = color(msg, bold=True)
        elif code[0] == "2":  # 2xx - Success
            msg = color(msg, fg="white")
        elif code == "304":  # 304 - Resource Not Modified
            msg = color(msg, fg="cyan")
        elif code[0] == "3":  # 3xx - Redirection
            msg = color(msg, fg="green")
        elif code == "404":  # 404 - Resource Not Found
            msg = color(msg, fg="yellow")
        elif code[0] == "4":  # 4xx - Client Error
            msg = color(msg, fg="red", bold=True)
        else:  # 5xx, or any other response
            msg = color(msg, fg="magenta", bold=True)

    WSGIRequestHandler.log("info", '"%s" %s %s', msg, code, size)


def monkey_patch_logger():
    WSGIRequestHandler.log_request = log_request

Upvotes: 0

mpaepper
mpaepper

Reputation: 4022

Étienne Bersac pointed me in the right direction.

This is how I implemented it:

from werkzeug import serving

parent_log_request = serving.WSGIRequestHandler.log_request


def log_request(self, *args, **kwargs):
    if self.path == '/healthcheck':
        return

    parent_log_request(self, *args, **kwargs)


def filter_healthcheck_logs():
    serving.WSGIRequestHandler.log_request = log_request

Upvotes: 9

&#201;tienne Bersac
&#201;tienne Bersac

Reputation: 649

I suggest you implement a dedicated logging filter. Plug that filter on the internal werkzeug logger.

You can also investigate subclassing WSGI request handler log_request method at https://github.com/pallets/werkzeug/blob/71cf9902012338f8ee98338fa7bba50572606637/src/werkzeug/serving.py#L378

Upvotes: 4

Related Questions