Monitorización en Python#

Logo Python

Monitorización de aplicaciones en Python

Monitorización en Django#

Monitorizar Loggins#

  1. Configurar el logger en settings.py:

 1# importar sys:
 2import sys
 3
 4# Se habilita la constante logging:
 5# Se habilita la constante logging:
 6LOGGING = {
 7    'version': 1,
 8    'disable_existing_loggers': False, # Evitar que pise otros loggers como DEFAULT_LOGGING
 9    'formatters': { # se define el formato de salida
10        'default': { # se utiliza el formater estandar de logging:
11            'class': 'logging.Formatter',
12            # y se define la estructura del mensaje, en este caso TIEMPO - NIVEL - LOGGER - MENSAJE:
13            'format': '%(asctime)s - %(levelname)s - %(name)s: %(message)s'
14        }
15    },
16    'handlers': {
17        'console': { # se define la salida por consola
18            'class': 'logging.StreamHandler', # la clase que controla los logs
19            'stream': sys.stdout, # el stream que los manejará
20            'formatter': 'default' # formato default
21        },
22        'error_file': { # aquí saldría por archivo
23            'class': 'logging.FileHandler', # se usa el filehandler para guardar archivos
24            'filename': 'error.log', # se define el nombre del archivo
25            'formatter': 'default',
26            # 'level': 'ERROR', Si solo queremos almacenar los mensajes de error
27        }
28    },
29    'loggers': {
30        '': { # vamos a coger todos los loggers:
31            'level': 'INFO', # Nivel del mensaje.
32            'handlers': ['console', 'error_file'] # definir la salida por consola y archivo (o solo una)
33        }
34    }
35}
  1. Ir a la vista o viewset que se quiere monitorizar:

 1# Se importa logging:
 2import logging
 3
 4
 5class SerieView(View):
 6
 7    def get(self, request):
 8        context = {
 9            'series': list(Serie.objects.all())
10        }
11
12        return render(request, 'series/series.html', context)
13
14class SerieViewSet(viewsets.ModelViewSet):
15    queryset = Serie.objects.all()
16    serializer_class = SerieSerializer
17    permission_classes = [IsAuthenticatedOrReadOnly]
18
19    # en el constructor de la clase:
20    def __init__(self, *args, **kwargs):
21        # se carga el logger en un atributo:
22        self.logger = logging.getLogger(__name__)
23        super().__init__(*args, **kwargs)
24
25    def get_serializer_class(self):
26        # Se monitoriza el método que devuelve las series:
27        self.logger.error(self.action)
28
29        serializer = self.serializer_class
30
31        if self.action == 'retrieve':
32            serializer = DetailSerieSerializer
33
34        return serializer
  • En este caso solo se está monitorizando las series, pero lo ideal es monitorizar cada parte.

  • El mensaje que muestra cada acción es: 2022-03-03 08:52:36,241 - ERROR - series.views: list

  • Los logs se almacenan en la ruta raiz del proyecto con el nombre que hemos definido antes: error.log

Atención

Si definimos un LOGGING este reemplaza a DEFAULT_LOGGER, es importante que tanto en LOGGING como en DEFAULT_LOGGING se encuentre el valor 'disable_existing_loggers': False

Avisar de errores automáticamente#

Para realizar esto hay que habilitar la constante DEFAULT_LOGGING en settings.py:

 1# Habilitar el logger que se encarga de las queries a la base de datos:
 2DEFAULT_LOGGING = {
 3    'version': 1,
 4    'disable_existing_loggers': False, # no pisar los otros logger
 5    'filters': { # filtrados:
 6        'require_debug_false': { # comprobar que no vienen de debug:
 7            '()': 'django.utils.log.RequireDebugFalse'
 8        },
 9        'require_debug_true': { # comprobar que vienen de debug:
10            '()': 'django.utils.log.RequireDebugTrue'
11        }
12    },
13    'formatters': {
14        'django.server': {
15            '()': 'django.utils.log.ServerFormatter',
16            'format': '[{server_time}] {message}',
17            'style': '{',
18        }
19    },
20    'handlers': {
21        'console': {
22            'level': 'INFO',
23            'filters': ['require_debug_true'], # si el modo debug esta en True saldrá por consola.
24            'class': 'logging.StreamHandler',
25            'formatter': 'django.server'
26        },
27        'mail_admins': {
28            'level': 'ERROR',
29            'filters': ['require_debug_false'], # si el modo debug esta en False (producción) nos enviará un email.
30            'class': 'django.utils.log.AdminEmailHandler'
31        }
32    },
33    'loggers': {
34        'django': {
35            'handlers': ['console', 'mail_admins'] # saldrá por consola y por email los loggersf
36        }
37    }
38}
39
40# Creamos el listado de administradores que se ocupan de la aplicación:
41ADMINS = [('Guillermo', 'guillermo@gggmail.com')]
42
43# Configuramos un email backend de prueba por si no tenemos servidor de email aún configurado:
44EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

Avisar de errores customizados en LOGGING#

Podemos configurar la salida de errores en producción para que los envíe por email:

 1    import sys
 2
 3    LOGGING = {
 4        'version': 1,
 5        'filters': { # Se van a definir un par de filtros que tienen que ver con el entorno de Desarrollo y producción:
 6            'require_debug_false': { # comprobar si estamos en Desarrollo:
 7                '()': 'django.utils.log.RequireDebugFalse'
 8            },
 9            'require_debug_true': { # comprobar si estamos en Producción:
10                '()': 'django.utils.log.RequireDebugTrue'
11            }
12        },
13        'formatters': {
14            'default': {
15                'class': 'logging.Formatter',
16                'format': '%(asctime)s - %(levelname)s - %(name)s: %(message)s'
17            }
18        },
19        'handlers': {
20            'console': {
21                'class': 'logging.StreamHandler',
22                'stream': sys.stdout,
23                'formatter': 'default'
24            },
25            'error_file': {
26                'class': 'logging.FileHandler',
27                'filename': 'error.log',
28                'formatter': 'default',
29                'level': 'ERROR',
30            }, # Se carga el mail admins:
31            'mail_admins': {
32                'level': 'ERROR',
33                'filters': ['require_debug_false'], # si el modo debug esta en False (producción) nos enviará un email.
34                'class': 'django.utils.log.AdminEmailHandler'
35            }
36        },
37        'loggers': {
38            '': {
39                'level': 'INFO',
40                'handlers': ['console', 'error_file', 'mail_admins'] # se añade el mail_admins para los correos
41            }
42        }
43    }
44
45    # Creamos el listado de administradores que se ocupan de la aplicación:
46    ADMINS = [('Guillermo', 'guillermo@gggmail.com')]
47
48    # Configuramos un email backend de prueba por si no tenemos servidor de email aún configurado:
49    EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'