Last active
February 1, 2022 12:59
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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