Reputation: 4538
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
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
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
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
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
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