Wie konfiguriere ich die Protokollierung in Syslog in Python?

121

Ich kann mich nicht mit Pythons loggingModul beschäftigen. Meine Anforderungen sind sehr einfach: Ich möchte einfach alles in Syslog protokollieren. Nachdem ich die Dokumentation gelesen hatte, kam ich auf dieses einfache Testskript:

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')

Dieses Skript erzeugt jedoch keine Protokolldatensätze in Syslog. Was ist los mit dir?

thor
quelle
3
Wo überprüfen Sie Ihre Syslog-Nachrichten? SysLogHandler () sendet diese Nachrichten an den udp-Socket in Port 514 in localhost.
Suzanshakya
Du hast absolut recht. Und ich habe gesehen, dass 'localhost-514' in der Dokumentation, aber nicht gedacht, dass / dev / log standardmäßig verwendet werden sollte .. Seufz ..
Thor

Antworten:

140

Ändern Sie die Zeile in diese:

handler = SysLogHandler(address='/dev/log')

Das funktioniert bei mir

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')
Dr. Jimbob
quelle
12
Beachten Sie, dass, wie das Dokument sagt, '/var/run/syslog'das Richtige unter OS X ist.
offby1
Lebensretter Antwort +1
Chachan
3
Wie können wir diese Protokolle in Syslog identifizieren? Wie können wir einen Anwendungsnamen oder ein Tag wie syslogtag = django angeben?
Luv33preet
und denken Sie daran, die Datei /etc/syslog.d/conf zu konfigurieren und den Dienst syslog / rsyslog
linrongbin
5
@ Luv33preet Ich habe das mit (aber nicht ohne) einem Formatierer wie logging.Formatter(fmt='myscriptname[%(process)d]: %(levelname)s: %(message)s', ...), einem rsyslog-Zustand wie $programname == 'myscriptname'funktioniert getestet .
Peter
26

Sie sollten immer den lokalen Host für die Protokollierung verwenden, egal ob in / dev / log oder localhost über den TCP-Stack. Dadurch kann der vollständig RFC-kompatible und funktionsfähige Systemprotokollierungsdämon Syslog verarbeiten. Dadurch muss der Remote-Daemon nicht mehr funktionsfähig sein, und die erweiterten Funktionen von Syslog-Daemons wie z. B. rsyslog und syslog-ng werden bereitgestellt. Die gleiche Philosophie gilt für SMTP. Geben Sie es einfach an die lokale SMTP-Software weiter. Verwenden Sie in diesem Fall den Programmiermodus, nicht den Dämon, aber es ist dieselbe Idee. Lassen Sie die leistungsfähigere Software damit umgehen. Wiederholen, Anstehen, lokales Spoolen, Verwenden von TCP anstelle von UDP für Syslog usw. werden möglich. Sie können diese Daemons auch separat von Ihrem Code [neu] konfigurieren, wie es sein sollte.

Speichern Sie Ihre Codierung für Ihre Anwendung und lassen Sie andere Software ihre Arbeit gemeinsam erledigen.

egrep
quelle
2
Sie sprechen einen fairen Punkt an. Können Sie gemeinsame Adressen und Ports angeben, die von verschiedenen Protokollierungsdämonen verwendet werden? Gibt es einen Standarderkennungsmechanismus, um festzustellen, ob der Dämon an einen TCP-Socket gebunden ist oder nicht?
init_js
Ich stimme dir vollkommen zu.
Daks
20

Ich habe das Syslog-Modul gefunden , um das von Ihnen beschriebene grundlegende Protokollierungsverhalten ganz einfach zu ermitteln:

import syslog
syslog.syslog("This is a test message")
syslog.syslog(syslog.LOG_INFO, "Test message at INFO priority")

Es gibt noch andere Dinge, die Sie tun könnten, aber schon in den ersten beiden Zeilen erhalten Sie das, wonach Sie gefragt haben, so wie ich es verstehe.

lindes-hw
quelle
Ich behalte das Protokollierungsmodul bei, da es das Ändern der Protokollierungseinstellung ermöglicht, ohne alle Anweisungen zu beeinflussen. Ermöglicht auch das Ändern des Verhaltens für den Fall, dass Sie zu der Zeit verschiedene Arten der Protokollierung haben möchten
Chachan
14

Wenn ich die Dinge von hier und anderen Orten aus zusammensetze, habe ich mir das ausgedacht, das für unbuntu 12.04 und centOS6 funktioniert

Erstellen Sie eine Datei /etc/rsyslog.d/, die auf .conf endet, und fügen Sie den folgenden Text hinzu

local6.*        /var/log/my-logfile

Neustart rsyslog, Neuladen schien für die neuen Protokolldateien NICHT zu funktionieren. Vielleicht werden nur vorhandene conf-Dateien neu geladen?

sudo restart rsyslog

Dann können Sie dieses Testprogramm verwenden, um sicherzustellen, dass es tatsächlich funktioniert.

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")
Bootscodierer
quelle
1
Um rsyslog auf centOS7 neu zu starten,sudo service rsyslog restart
radtek
12

Ich füge einen kleinen zusätzlichen Kommentar hinzu, nur für den Fall, dass es jemandem hilft, weil ich diesen Austausch nützlich fand, aber diese kleinen zusätzlichen Informationen brauchte, um alles zum Laufen zu bringen.

Um sich mit SysLogHandler bei einer bestimmten Einrichtung anzumelden, müssen Sie den Wert der Einrichtung angeben. Sagen Sie zum Beispiel, dass Sie definiert haben:

local3.* /var/log/mylog

In Syslog möchten Sie Folgendes verwenden:

handler = logging.handlers.SysLogHandler(address = ('localhost',514), facility=19)

Außerdem muss Syslog UDP abhören, um localhost anstelle von / dev / log verwenden zu können.

Oliver Henriot
quelle
3
Es ist nicht erforderlich, dass Syslog UDP abhört. Ihr Beispiel funktioniert auch perfekt mit address = '/ dev / log'.
Thor
5
Ja, sicher, aber mit address = ('localhost', 514), an dem Tag, an dem Sie einen Protokollserver haben, ersetzen Sie localhost durch die Adresse des Servers und Sie haben Remote-Protokollierung ;-)
Oliver Henriot
5
Woher kommt die Einrichtung = 19? Warum ist es nicht Facility = "local3"
Bootscodierer
4
@ Mark0978 19 ist die numerische Darstellung von local3 gemäß RFC3146 (und anschließend RFC5424)
Andrew Sledge,
3
Ich habe mich auch darüber gewundert und festgestellt
clebio
11

Ist Ihre syslog.conf für die Behandlung von Facility = User eingerichtet?

Sie können die vom Python-Logger verwendete Einrichtung mit dem Einrichtungsargument wie folgt festlegen:

handler = logging.handlers.SysLogHandler(facility=SysLogHandler.LOG_DAEMON)
bstpierre
quelle
Sie müssen angeben, welchen LOG_DAEMONWert Sie als Wert für den facilityParameter angeben .
Zot
4
Das wäre SysLogHandler.LOG_DAEMON.
Craig Trader
7
import syslog
syslog.openlog(ident="LOG_IDENTIFIER",logoption=syslog.LOG_PID, facility=syslog.LOG_LOCAL0)
syslog.syslog('Log processing initiated...')

Das obige Skript wird mit unserem benutzerdefinierten "LOG_IDENTIFIER" in der LOCAL0-Einrichtung protokolliert. Sie können LOCAL [0-7] für lokale Zwecke verwenden.

San
quelle
1
Ihr Kommentar hat nichts mit der ursprünglichen Anfrage zu tun
Thor
@thor Ich würde zustimmen, dass dies relevant ist. Ich werde denke , dass das syslog - Paket etwas effizienter als die reine Python - Implementierung ist? (wenn weniger flexibel)
Daniel Santos
7

Von 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 __name__ == '__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')
luismartingil
quelle
Dies ist sehr interessant, funktioniert jedoch nicht mit Python 2.6.6 (RHEL 6.4): Traceback (letzter Aufruf zuletzt): Datei "syslog_bridge.py", Zeile 68, in <module> handlers.append (SysLogLibHandler (logFacilityLocalN) )) Datei "syslog_bridge.py", Zeile 29, in init syslog.openlog (syslog.LOG_PID, self.FACILITY [n]) TypeError: ident string [, logoption [, Facility]]
Steve Cohen
Bearbeitet basierend auf: github.com/luismartingil/scripts/commit/…
luismartingil
3

Hier ist die für 3.2 und höher empfohlene yaml dictConfig-Methode.

Im Protokoll 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

Laden Sie die Konfiguration mit:

log_config = yaml.safe_load(open('cfg.yml'))
logging.config.dictConfig(log_config)

Konfigurierte sowohl Syslog als auch eine direkte Datei. Beachten Sie, dass das /dev/logBetriebssystem spezifisch ist.

Bruce Edge
quelle
1

Ich repariere es auf meinem Notizbuch. Der rsyslog-Dienst hat den Socket-Dienst nicht abgehört.

Ich habe diese Zeile unten in der /etc/rsyslog.confDatei konfiguriert und das Problem gelöst:

$SystemLogSocketName /dev/log

Anderson Madureira
quelle
-1

Sie können auch einen Dateihandler oder einen rotierenden Dateihandler hinzufügen, um Ihre Protokolle an eine lokale Datei zu senden: http://docs.python.org/2/library/logging.handlers.html

Benutzer2701173 neu laden
quelle
3
Nicht sehr nützlich, wenn Sie mehr als einen Prozess ausführen möchten.
Bangalore