Skip to content

Instantly share code, notes, and snippets.

@jonilsonds9
Last active February 1, 2022 12:59
Show Gist options
  • Select an option

  • Save jonilsonds9/18a6a19907b0d5c1c65db663cc6e5e62 to your computer and use it in GitHub Desktop.

Select an option

Save jonilsonds9/18a6a19907b0d5c1c65db663cc6e5e62 to your computer and use it in GitHub Desktop.
Como configurar logs com flask e gunicorn como campo personalizado no log record
# Observe que nesse exemplo temos um pacote python com o nome "src" que é onde fica todo o código da nossa aplicação
# Primeiro devemos ter o arquivo "wsgi.py" que vai ser o cara que vamos usar para subir o servidor gunicorn,
# ele deve ser simples e apenas chamar nossa função de criação da aplicação:
from src import create_app
app = create_app()
# Digamos que temos um arquivo com o nome "logging_config.py" dentro do pacote "logging_config" que fica dentro também do
# pacote "src" e nele temos toda nossa configuração:
import logging.config
from config import basedir # temos um arquivo na raiz do projeto que disponibiliza o `basedir` da aplicação para utilizarmos
# Esse LOGGING_CONFIG é onde colocamos toda nossa configuração de logs, como deve aparecer o log e formatações necessárias
LOGGING_CONFIG = {
'version': 1,
'disable_existing_loggers': False,
'filters': { # essa parte é importante, aqui definimos os filtros que precisamos
'filter_file_path': { # esse é nosso filtro para adicionar um novo campo dentro de cada record de log
'()': 'src.utils.logging_config.FilterPathName', # Aqui passamos uma instancia da classe FilterPathName que está mais abaixo e lá setamos o novo campo
}
},
'formatters': {
'app': {
'format': '%(asctime)s [%(process)d] [%(levelname)s] [app] - %(file_path)s:%(lineno)d: %(message)s', # aqui formatamos todo o log, mas veja que temos o `%(file_path)s` que é um campo que não tem por default no record log e adicionamos pelo filtro
'datefmt': '[%Y-%m-%d %H:%M:%S]' # aqui formatamos a data disponibilizada pelo `%(asctime)s` da linha anterior
},
'gunicorn': {
'format': '%(asctime)s [%(process)d] [%(levelname)s] [gunicorn]: %(message)s',
'datefmt': '[%Y-%m-%d %H:%M:%S]'
}
},
'handlers': {
'app': {
'class': 'logging.StreamHandler',
'filters': ['filter_file_path'], # aqui indicamos que os logs relacionados a aplicação deve usar o nosso filtro e ele vai adicionar o novo campo
'formatter': 'app'
},
'gunicorn': {
'class': 'logging.StreamHandler',
'formatter': 'gunicorn'
}
},
'loggers': {
'gunicorn.error': {
'level': 'INFO',
'handlers': ['gunicorn'],
'propagate': False,
'qualname': 'gunicorn.error'
}
},
'root': {
'level': 'INFO',
'handlers': ['app'],
'propagate': False,
}
}
# Essa função apenas manipula o campo para setar ou não uma barra no final do caminho pra ficar mais interessante a visualização
def get_basedir():
if basedir.endswith('/'):
return basedir
return basedir + '/'
# Aqui está nossa classe de Filtro que extende de `logging.Filter`, e sobreescrevemos o método `filter`
class FilterPathName(logging.Filter):
# Esse método apenas removendo o caminho completo da aplicação, ou seja a até a pasta do projeto
# exemplo: `/home/user/projects/app/src/routes/routes.py` e deixamos apenas `src/routes/routes.py`
def filter(self, record):
app_base_dir = get_basedir()
if record.pathname.startswith(app_base_dir):
record.file_path = record.pathname[len(app_base_dir):]
else:
record.file_path = app_base_dir
return True
# Esse método chamamos no nosso `create_app()` para configurar esses logs usando as configurações acima juntamente com o filtro
def configure_logging():
logging.config.dictConfig(LOGGING_CONFIG)
# Agora no "__init__.py" que é onde fica a função "create_app()", vamos importar as configrações de logs que precisamos,
# que está no pacote "src.utils.logging_config" e temos uma função que configura os logs
from .utils.logging_config import configure_logging
def create_app(test_config=None):
configure_logging()
app = Flask(__name__)
# <parte do código omitido>
return app
# Pronto, assim temos temos tanto os logs do servidor `gunicorn` quanto os logs da aplicação e penso que facilita quando precisamos
# entender algum problema na aplicação.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment