Skip to content

Instantly share code, notes, and snippets.

@wshayes
Created July 1, 2019 13:33
Show Gist options
  • Save wshayes/067fe781af341d4783e113f037c3959d to your computer and use it in GitHub Desktop.
Save wshayes/067fe781af341d4783e113f037c3959d to your computer and use it in GitHub Desktop.
[Logging tip] #fastapi #python
version: 1
disable_existing_loggers: False
formatters:
simple:
format: "%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(message)s"
handlers:
console:
class: logging.StreamHandler
level: DEBUG
formatter: simple
filters:
- healthcheck_filter
stream: ext://sys.stdout
info_file_handler:
class: logging.handlers.RotatingFileHandler
level: INFO
formatter: simple
filename: applog/info.log
maxBytes: 10485760 # 10MB
backupCount: 20
encoding: utf8
error_file_handler:
class: logging.handlers.RotatingFileHandler
level: ERROR
formatter: simple
filename: applog/errors.log
maxBytes: 10485760 # 10MB
backupCount: 20
encoding: utf8
loggers:
uvicorn:
level: INFO
handlers: [console]
propagate: no
gunicorn:
level: INFO
handlers: [console]
propagate: no
filters:
healthcheck_filter:
"()": applog.utils.NoHealthCheckFilter
root:
level: INFO
handlers: [console]

From: https://gitlab.com/euri10/euri10_fastapi_base

euri10 @euri10 Jun 27 09:31 well I just did it, quite simple in fact L) will add it to my logging facility you can see it here : euri10/euri10_fastapi_base@814404f in summary I added this to my docker-compose

healthcheck:
  	test: ["CMD", "wget", "http://localhost:8000/healthcheck"]
  	interval: 1s

which effectively spams the logger every second

@app.get("/healthcheck")
async def healthcheck():
	return {"status": "alive"}

now it depends how logging is performed on your app in my case everything is configured through a logging.yaml that is read at app initialization and then setup with

logging.config.dictConfig(logging_config)

euri10 @euri10 Jun 27 09:38 so depending on how you configuire it, the only thing to know is you add a filter to the handler that spits the log you want to avoid,

it's here : https://gitlab.com/euri10/euri10_fastapi_base/blob/814404fc44636c8ebd04af91e33cb325f72db294/python3.7-alpine3.8/app/applog/logging.yml#L12

then you declare a custom filter , it's here : https://gitlab.com/euri10/euri10_fastapi_base/blob/814404fc44636c8ebd04af91e33cb325f72db294/python3.7-alpine3.8/app/applog/logging.yml#L41

then you write that custom filter class subclassing logging.Filter, its here https://gitlab.com/euri10/euri10_fastapi_base/blob/814404fc44636c8ebd04af91e33cb325f72db294/python3.7-alpine3.8/app/applog/utils.py#L32 pretty simple in fact

import logging.config
import os
import yaml
def read_logging_config(default_path="logging.yml", env_key="LOG_CFG"):
path = default_path
value = os.getenv(env_key, None)
if value:
path = value
if os.path.exists(path):
with open(path, "rt") as f:
logging_config = yaml.safe_load(f.read())
return logging_config
else:
return None
def setup_logging(logging_config, default_level=logging.INFO):
if logging_config:
logging.config.dictConfig(logging_config)
else:
logging.basicConfig(level=default_level)
class NoHealthCheckFilter(logging.Filter):
def __init__(self, param=None):
self.param = param
def filter(self, record):
return record.getMessage().find('/healthcheck') == -1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment