Manejo de log en Flask

Publicado por Andrea Navarro en

En este artículo veremos cómo utilizar el módulo de Python logging para el manejo de log en Flask. También exploraremos como registrar los eventos más importantes de la aplicación para realizar debugging.

Módulo Logging

El módulo logging de Python contiene un sistema de log flexible que puede utilizarse para cualquier aplicación o librería. Al usar este módulo estándar junto en nuestra aplicación los logs generados por otros módulos y librerías estarán incluidos con aquellos creados para la aplicación que se está desarrollando.

Este módulo cuenta con los siguientes tipos de componentes:

  • Loggers: Son los encargados de crear los registros de log. Al hacer la llamada se determina que tipo de log se está creando.
  • Handlers o manejadores: Manejan los registros de log dependiendo del destino (archivo, ubicaciones HTTP GET/POST , email via SMTP, sockets, colas, etc)
  • Filtros: Determinan que registros aparecerán en la salida
  • Formatters: Especifican el formato, orden y contenido de los registros de log en la salida

Existen por convención diferentes niveles de gravedad de los logs y estos pueden definirse utilizando las funciones de logging.

DEBUGInformación detallada de interés cuando se diagnostican problemas
INFOConfirmación de que las cosas están funcionando de la manera esperada
WARNINGIndicación que algo ha pasado inesperadamente o que habrá un problema en el futuro cercano pero el sistema sigue funcionando de la manera esperada
ERRORDebido a un problema serio el sistema no ha sido capaz de realizar alguna función
CRITICALUn error serio. El sistema no ha sido capaz de continuar funcionando.

Logging para log en Flask

Para registrar los logs en Flask es necesario importar el módulo logging de Python antes de la inicialización de la aplicación Flask. En el siguiente ejemplo se muestra como registrar diferentes niveles de log utilizando app.logger. En cada caso se llama el método correspondiente al nivel de log requerido y se le pasa por argumento el mensaje asociado. Es importante destacar que el mensaje puede contener variables para hacer los registros tan específicos como sea necesario.

from flask import Flask
import logging

app = Flask(__name__)

@app.route('/')
def main():
  app.logger.debug("Este es un log DEBUG")
  app.logger.info("Este es un log INFO")
  app.logger.warning("Este es un log WARNING")
  app.logger.error("Este es un log ERROR")
  app.logger.critical("Este es un log CRITICAL")
  return "Test logger"

if __name__ == '__main__':
    app.run(debug = True)

Si se ejecuta la aplicación Flask en modo debug por terminal y se accede a la ruta que genera estos logs puede observarse como los diferentes niveles de registros son mostrados en terminal.

Escribir log en archivo

Para obtener un registro permanente de los logs es necesario configurar el módulo para que escriba dichos logs en un archivo. Para hacerlo se utiliza el método basicConfig y se le especifica el nombre del archivo en el argumento filename. Este archivo almacenara de forma acumulativa todos los registros de log que se generen durante el funcionamiento de la aplicación.

from flask import Flask
import logging

logging.basicConfig(filename='archivo.log')
app = Flask(__name__)

@app.route('/')
def main():
  app.logger.debug("Este es un log DEBUG")
  app.logger.info("Este es un log INFO")
  app.logger.warning("Este es un log WARNING")
  app.logger.error("Este es un log ERROR")
  app.logger.critical("Este es un log CRITICAL")
  return "Test logger"

if __name__ == '__main__':
    app.run(debug = True)

Este archivo contendrá un contenido similar al visto anteriormente por consola.

DEBUG:app:Este es un log DEBUG
INFO:app:Este es un log INFO
WARNING:app:Este es un log WARNING
ERROR:app:Este es un log ERROR
CRITICAL:app:Este es un log CRITICAL

Formato de log

Para que el registro de log sea de utilidad para el diagnóstico de problemas y bugs es necesario que contenga más información que el mensaje y el nivel de log. Para esto se utiliza la configuración de formato.

La opción format contiene las siguientes configuraciones:

%(asctime)sTimestamp
%(levelname)sEl nivel de log
%(name)sEl nombre del logger
%(threadname)sEl nombre del thread
%(message)sEl mensaje de log

En el siguiente ejemplo se configura para que los registros de log contengan el timestamp y el nivel de log separado por dos puntos del mensaje de log.

from flask import Flask
import logging

logging.basicConfig(filename='record.log', format='%(asctime)s %(levelname)s : %(message)s')
app = Flask(__name__)

@app.route('/')
def main():
  app.logger.debug("Este es un log DEBUG")
  app.logger.info("Este es un log INFO")
  app.logger.warning("Este es un log WARNING")
  app.logger.error("Este es un log ERROR")
  app.logger.critical("Este es un log CRITICAL")
  return "Test logger"

if __name__ == '__main__':
    app.run(debug = True)

La salida guardada en el archivo será similar a la siguiente:

2023-02-15 14:59:47,802 DEBUG : Este es un log DEBUG
2023-02-15 14:59:47,803 INFO : Este es un log INFO
2023-02-15 14:59:47,803 WARNING : Este es un log WARNING
2023-02-15 14:59:47,803 ERROR : Este es un log ERROR
2023-02-15 14:59:47,803 CRITICAL : Este es un log CRITICAL

Configuración de nivel

Dependiendo del estado de desarrollo de un sistema es posible que solo sea necesario grabar aquellos registros de log que sobrepasen cierto nivel. Para lograrlo se utiliza el método setLevel en el logger de la aplicación.

from flask import Flask
import logging

logging.basicConfig(filename='record.log', format='%(asctime)s %(levelname)s : %(message)s')

app = Flask(__name__)
app.logger.setLevel(logging.WARNING)

@app.route('/')
def main():
  app.logger.debug("Este es un log DEBUG")
  app.logger.info("Este es un log INFO")
  app.logger.warning("Este es un log WARNING")
  app.logger.error("Este es un log ERROR")
  app.logger.critical("Este es un log CRITICAL")
  return "Test logger"

if __name__ == '__main__':
    app.run(debug = True)

Ya que el nivel está configurado a WARNING cualquier registro de log que se realice cuyo nivel esté por debajo del mismo no será pasado a la salida.

2023-02-15 15:29:37,976 WARNING : Este es un log WARNING
2023-02-15 15:29:37,976 ERROR : Este es un log ERROR
2023-02-15 15:29:37,976 CRITICAL : Este es un log CRITICAL

En este artículo hemos visto como utilizar el módulo logging de python para manejar los registros de log en nuestra aplicación Flask y como configurarlo para nuestras necesidades. Espero que les sirva!


¿Preguntas? ¿Comentarios?

Si tenés dudas, o querés dejarnos tus comentarios y consultas, sumate al grupo de Telegram de la comunidad JuncoTIC!
¡Te esperamos!


Andrea Navarro

- Ingeniera en Informática - Docente universitaria - Investigadora