2011-03-16 10 views
5

Estoy usando el registro de Python en mi aplicación django. Una clase que se conecta a una API de back-end inicializa este registrador con un manejador de archivos si es necesario. La clase se instancia cada vez que se realiza una llamada de API. He tratado de asegurarse de que los controladores adicionales no se agregan cada vez, peroRegistro apropiado de Python con manejadores de archivos

lsof | grep my.log 

muestra una cantidad cada vez mayor de los manipuladores en mi archivo de registro y después de un tiempo mi servidor falla debido a este límite de archivos abiertos.

self.logger = logging.getLogger("FPA") 

     try: 
      if self.logger.handlers[0].__class__.__name__=="FileHandler": 
       pass 
     except Exception, e: 
      print 'new filehandler added'+str(e) 
      ch = logging.FileHandler(FPA_LOG_TARGET) 
      formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s - %(pathname)s @ line %(lineno)d") 
      ch.setFormatter(formatter) 
      self.logger.setLevel(logging.DEBUG) 
      self.logger.addHandler(ch) 

Me doy cuenta de que esta puede no ser la mejor manera de hacerlo, pero hasta ahora no he encontrado el error en mi implementación.

+0

¿Cuál es exactamente su pregunta? –

+0

¿qué es lo que imprime '' imprimir 'nuevo manejador de archivos' + str (e) '' en su declaración de registro? –

+0

Mi pregunta es: ¿qué estoy haciendo mal? – pyeleven

Respuesta

1

No analicé si durante mucho tiempo, pero parece un problema de concurrencia.

Cada proceso/subproceso mantiene su propia lista de identificadores de archivo en los archivos de registro abiertos.

¿Cómo corregirlo? Para el código multiproceso, asegúrese de que haya un diccionario global donde se guarden todos los identificadores. Para el multiproceso, me temo que no tengo una respuesta ... cada proceso mantiene sus propios manejadores de archivos, tal vez mapeándolos en la memoria (los archivos mapeados en memoria podrían ser una opción), pero no estoy seguro de que esta es una buena solución - see this remark.

Pero la pregunta principal es por qué es necesario hacer tal cosa.

En primer lugar, puede utilizar el archivo logging.conf para inicializar todos sus registradores/manipuladores/formateadores y cuando sea necesario (por ejemplo, el loger específico es extenso y desea registrarlo en el archivo separado) agregue otro registrador con un nombre de archivo diferente. Lo cual es bastante razonable si se le agrega un registrador por aplicación de Django, añadiendo en el principal __init__.py de la aplicación:

import logging 
log = logging.getLogger(__name__) 

y luego importar log en el resto del código de la aplicación (vistas, modelos, etc.)

para utilizar logging.conf líneas add siguiente a su settings.py:

import os 
import logging 
DIRNAME = os.path.abspath(os.path.dirname(__file__)) 
logging.config.fileConfig(os.path.join(DIRNAME, 'logging.conf')) 

Sí, es manual, pero que no es necesario cambiar el código, sino simplemente un archivo de configuración.

Otro enfoque (si realmente desea tener un archivo por tipo de registrador) es tener un proceso separado que mantenga los archivos abiertos, acepte conexiones desde la aplicación. La documentación del módulo de registro tiene un nice example of this method.

Por último, pero no menos importante, ya hay algunas buenas soluciones que pueden ser útiles. Una, bastante buena, es usar django-centinela. Este módulo puede registrar todas sus excepciones, 404 (con middleware adicional - incluido) y capturar todo el registro (a través del controlador de registro incluido).

Proporcionado UI le dará la posibilidad de buscar todos los mensajes registrados, filtrarlos por la gravedad y la fuente de registro. Pero esto no se limita a eso: simplemente puede agregar sus propios módulos.

Cuestiones relacionadas