Je n'arrive pas à comprendre le module logging
de Python. Mes besoins sont très simples: je veux juste tout enregistrer dans syslog. Après avoir lu la documentation, je suis arrivé à ce script de test simple:
import logging
import logging.handlers
my_logger = logging.getLogger('MyLogger')
my_logger.setLevel(logging.DEBUG)
handler = logging.handlers.SysLogHandler()
my_logger.addHandler(handler)
my_logger.debug('this is debug')
my_logger.critical('this is critical')
Mais ce script ne produit aucun enregistrement de journal dans syslog. Qu'est-ce qui ne va pas?
Changer la ligne à ceci:
handler = SysLogHandler(address='/dev/log')
Ça marche pour moi
import logging
import logging.handlers
my_logger = logging.getLogger('MyLogger')
my_logger.setLevel(logging.DEBUG)
handler = logging.handlers.SysLogHandler(address = '/dev/log')
my_logger.addHandler(handler)
my_logger.debug('this is debug')
my_logger.critical('this is critical')
Vous devez toujours utiliser l'hôte local pour la journalisation, que ce soit vers/dev/log ou localhost via la pile TCP. Ceci permet au démon de journalisation système entièrement conforme à RFC pour gérer syslog. Cela évite au démon distant de fonctionner et vous offre les fonctionnalités améliorées des démons syslog tels que rsyslog et syslog-ng, par exemple. La même philosophie s’applique à SMTP. Il suffit de la transmettre au logiciel SMTP local. dans ce cas, utilisez le 'mode programme', pas le démon, mais la même idée. Laissez le logiciel le plus capable s'en charger. Retrying, mise en file d'attente, mise en file d'attente locale, en utilisant TCP au lieu de UDP pour syslog, etc.) Vous pouvez aussi [re] configurer ces démons séparément de votre code, comme il se doit.
Enregistrez votre code pour votre application, laissez les autres logiciels faire leur travail de concert.
J'ai trouvé le module syslog pour faciliter l'obtention du comportement de journalisation de base que vous décrivez:
import syslog
syslog.syslog("This is a test message")
syslog.syslog(syslog.LOG_INFO, "Test message at INFO priority")
Vous pouvez également faire d’autres choses, mais même les deux premières lignes vous donneront ce que vous avez demandé tel que je le comprends.
Assembler des objets ici et ailleurs, voici ce que j'ai trouvé qui fonctionne sur unbuntu 12.04 et centOS6
Créer un fichier dans /etc/rsyslog.d/
qui se termine par .conf et ajoute le texte suivant
local6.* /var/log/my-logfile
Redémarrez rsyslog
, le rechargement ne semble PAS fonctionner pour les nouveaux fichiers journaux. Peut-être qu'il ne recharge que les fichiers de configuration existants?
Sudo restart rsyslog
Ensuite, vous pouvez utiliser ce programme de test pour vous assurer qu'il fonctionne réellement.
import logging, sys
from logging import config
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': '%(levelname)s %(module)s P%(process)d T%(thread)d %(message)s'
},
},
'handlers': {
'stdout': {
'class': 'logging.StreamHandler',
'stream': sys.stdout,
'formatter': 'verbose',
},
'sys-logger6': {
'class': 'logging.handlers.SysLogHandler',
'address': '/dev/log',
'facility': "local6",
'formatter': 'verbose',
},
},
'loggers': {
'my-logger': {
'handlers': ['sys-logger6','stdout'],
'level': logging.DEBUG,
'propagate': True,
},
}
}
config.dictConfig(LOGGING)
logger = logging.getLogger("my-logger")
logger.debug("Debug")
logger.info("Info")
logger.warn("Warn")
logger.error("Error")
logger.critical("Critical")
J'ajoute un petit commentaire supplémentaire au cas où cela pourrait aider quelqu'un parce que je trouvais cet échange utile mais que j'avais besoin de ce petit supplément d'informations pour que tout fonctionne.
Pour vous connecter à une installation spécifique à l'aide de SysLogHandler, vous devez spécifier la valeur de l'installation. Disons par exemple que vous avez défini:
local3.* /var/log/mylog
dans syslog, vous voudrez utiliser:
handler = logging.handlers.SysLogHandler(address = ('localhost',514), facility=19)
et vous devez également que syslog écoute sur UDP pour utiliser localhost au lieu de/dev/log.
Est-ce que votre syslog.conf est configuré pour gérer facility = user?
Vous pouvez définir la facilité utilisée par le = python logger avec l'argument facility, quelque chose comme ceci:
handler = logging.handlers.SysLogHandler(facility=SysLogHandler.LOG_DAEMON)
De https://github.com/luismartingil/per.scripts/tree/master/python_syslog
#!/usr/bin/python
# -*- coding: utf-8 -*-
'''
Implements a new handler for the logging module which uses the pure syslog python module.
@author: Luis Martin Gil
@year: 2013
'''
import logging
import syslog
class SysLogLibHandler(logging.Handler):
"""A logging handler that emits messages to syslog.syslog."""
FACILITY = [syslog.LOG_LOCAL0,
syslog.LOG_LOCAL1,
syslog.LOG_LOCAL2,
syslog.LOG_LOCAL3,
syslog.LOG_LOCAL4,
syslog.LOG_LOCAL5,
syslog.LOG_LOCAL6,
syslog.LOG_LOCAL7]
def __init__(self, n):
""" Pre. (0 <= n <= 7) """
try:
syslog.openlog(logoption=syslog.LOG_PID, facility=self.FACILITY[n])
except Exception , err:
try:
syslog.openlog(syslog.LOG_PID, self.FACILITY[n])
except Exception, err:
try:
syslog.openlog('my_ident', syslog.LOG_PID, self.FACILITY[n])
except:
raise
# We got it
logging.Handler.__init__(self)
def emit(self, record):
syslog.syslog(self.format(record))
if __== '__main__':
""" Lets play with the log class. """
# Some variables we need
_id = 'myproj_v2.0'
logStr = 'debug'
logFacilityLocalN = 1
# Defines a logging level and logging format based on a given string key.
LOG_ATTR = {'debug': (logging.DEBUG,
_id + ' %(levelname)-9s %(name)-15s %(threadName)-14s +%(lineno)-4d %(message)s'),
'info': (logging.INFO,
_id + ' %(levelname)-9s %(message)s'),
'warning': (logging.WARNING,
_id + ' %(levelname)-9s %(message)s'),
'error': (logging.ERROR,
_id + ' %(levelname)-9s %(message)s'),
'critical': (logging.CRITICAL,
_id + ' %(levelname)-9s %(message)s')}
loglevel, logformat = LOG_ATTR[logStr]
# Configuring the logger
logger = logging.getLogger()
logger.setLevel(loglevel)
# Clearing previous logs
logger.handlers = []
# Setting formaters and adding handlers.
formatter = logging.Formatter(logformat)
handlers = []
handlers.append(SysLogLibHandler(logFacilityLocalN))
for h in handlers:
h.setFormatter(formatter)
logger.addHandler(h)
# Yep!
logging.debug('test debug')
logging.info('test info')
logging.warning('test warning')
logging.error('test error')
logging.critical('test critical')
import syslog
syslog.openlog(ident="LOG_IDENTIFIER",logoption=syslog.LOG_PID, facility=syslog.LOG_LOCAL0)
syslog.syslog('Log processing initiated...')
le script ci-dessus se connectera à l'installation LOCAL0 avec notre "LOG_IDENTIFIER" personnalisé ... vous pouvez utiliser LOCAL [0-7] à des fins locales.
Voici la méthode yaml dictConfig recommandée pour les versions 3.2 et ultérieures.
Dans le journal cfg.yml
:
version: 1
disable_existing_loggers: true
formatters:
default:
format: "[%(process)d] %(name)s(%(funcName)s:%(lineno)s) - %(levelname)s: %(message)s"
handlers:
syslog:
class: logging.handlers.SysLogHandler
level: DEBUG
formatter: default
address: /dev/log
facility: local0
rotating_file:
class: logging.handlers.RotatingFileHandler
level: DEBUG
formatter: default
filename: rotating.log
maxBytes: 10485760 # 10MB
backupCount: 20
encoding: utf8
root:
level: DEBUG
handlers: [syslog, rotating_file]
propogate: yes
loggers:
main:
level: DEBUG
handlers: [syslog, rotating_file]
propogate: yes
Chargez la configuration en utilisant:
log_config = yaml.safe_load(open('cfg.yml'))
logging.config.dictConfig(log_config)
Configuré à la fois syslog et un fichier direct. Notez que le /dev/log
est spécifique à l'OS.
Je le répare sur mon cahier. Le service rsyslog n'a pas écouté le service de socket.
Je config cette ligne ci-dessous dans /etc/rsyslog.conf
fichier et résolu le problème:
$SystemLogSocketName /dev/log