Il logger Python nativo utilizzato dalla nostra app flask sembra interrompere la scrittura nel log dopo che si è verificata un'eccezione. L'ultima voce registrata prima di ogni interruzione è un messaggio che descrive l'eccezione. In genere il messaggio successivo è uno scritto dal codice in after_request, ma nei casi in cui il logger si arresta, il messaggio after_request non viene mai scritto.Il logger Python interrompe la registrazione dopo l'eccezione non rilevata
Qualche idea di cosa potrebbe causare questo?
Nota: Inizialmente avevo postato questa domanda su Serverfault (https://serverfault.com/questions/655683/python-logger-stops-logging) pensando che si trattasse di un problema di infrastruttura. Ma ora che abbiamo ridotto il problema fino a quando si è verificato dopo un'eccezione, questo problema potrebbe essere più adatto a StackOverflow.
Aggiornamento [2015/12/22]:
Logger esemplificazione:
logging.addLevelName(Config.LOG_AUDIT_LEVEL_NUM, Config.LOG_AUDIT_LEVEL_NAME)
logger = logging.getLogger(Config.LOGGER_NAME)
logger.setLevel(Config.LOG_LEVEL)
handler = SysLogHandler(address='/dev/log', facility=SysLogHandler.LOG_LOCAL3)
handler.setLevel(Config.LOG_LEVEL)
formatter = log_formatter()
handler.setFormatter(formatter)
logger.addHandler(handler)
log_formatter:
class log_formatter(logging.Formatter):
def __init__(self,
fmt=None,
datefmt=None,
json_cls=None,
json_default=_default_json_default):
"""
:param fmt: Config as a JSON string, allowed fields;
extra: provide extra fields always present in logs
source_host: override source host name
:param datefmt: Date format to use (required by logging.Formatter
interface but not used)
:param json_cls: JSON encoder to forward to json.dumps
:param json_default: Default JSON representation for unknown types,
by default coerce everything to a string
"""
if fmt is not None:
self._fmt = json.loads(fmt)
else:
self._fmt = {}
self.json_default = json_default
self.json_cls = json_cls
if 'extra' not in self._fmt:
self.defaults = {}
else:
self.defaults = self._fmt['extra']
try:
self.source_host = socket.gethostname()
except:
self.source_host = ""
def format(self, record):
"""
Format a log record to JSON, if the message is a dict
assume an empty message and use the dict as additional
fields.
"""
fields = record.__dict__.copy()
aux_fields = [
'relativeCreated', 'process', 'args', 'module', 'funcName', 'name',
'thread', 'created', 'threadName', 'msecs', 'filename', 'levelno',
'processName', 'pathname', 'lineno', 'levelname'
]
for k in aux_fields:
del fields[k]
if isinstance(record.msg, dict):
fields.update(record.msg)
fields.pop('msg')
msg = ""
else:
msg = record.getMessage()
if 'msg' in fields:
fields.pop('msg')
if 'exc_info' in fields:
if fields['exc_info']:
formatted = tb.format_exception(*fields['exc_info'])
fields['exception'] = formatted
fields.pop('exc_info')
if 'exc_text' in fields and not fields['exc_text']:
fields.pop('exc_text')
logr = self.defaults.copy()
logr = {
'timestamp': datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%fZ'),
'host': self.source_host,
}
logr.update(self._build_fields(logr, fields))
if msg:
logr['message'] = msg
something = json.dumps(logr, default=self.json_default, cls=self.json_cls)
return something
def _build_fields(self, defaults, fields):
return dict(defaults.get('fields', {}).items() + fields.items())
Aggiornamento [2015/01/03]:
Answering domande postate:
L'applicazione funziona ancora dopo l'eccezione?
Sì, l'applicazione continua a funzionare.
Quale tipo di eccezione viene generato e quale è la causa?
Eccezione interna/personalizzata. Il logger si è fermato a causa di diversi tipi di eccezioni.
Stai utilizzando thread nell'applicazione?
Sì, l'app è infilata da gunicorn.
Come viene utilizzata la libreria di registrazione?
Stiamo utilizzando di default FileHandler, SysLogHandler ed una formattazione personalizzata (uscite JSON)
lo fa collegarvi un file? Usa la rotazione del registro?
Sì, registra in un file, ma senza rotazione.
http://stackoverflow.com/help/how-to-ask - frammenti di codice e quello che si è tentato sarebbe utile – dnozay
@dnozay: frammenti di codice aggiunto. – Jason
Hai mai risolto questo problema? Ho avuto un problema simile quando un'eccezione viene lanciata all'interno del formattatore di log (ricorsione infinita da json.dumps che tenta di serializzare un oggetto) e mi chiedevo se avessi trovato una soluzione. – notpeter