Python'da syslog için günlük kaydı nasıl yapılandırılır?


121

Python'un loggingmodülüne kafamı sokamıyorum . İhtiyaçlarım çok basit: Sadece her şeyi syslog'a kaydetmek istiyorum. Belgeleri okuduktan sonra şu basit test komut dosyasını buldum:

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

Ancak bu komut dosyası syslog'da herhangi bir günlük kaydı oluşturmaz. Sorun nedir?


3
Sistem günlüğü mesajlarınızı nerede kontrol ediyorsunuz? SysLogHandler (), bu mesajları localhost'taki 514 numaralı bağlantı noktasındaki udp soketine gönderir.
suzanshakya

Kesinlikle haklısın. Ve dokümantasyonda 'localhost-514'ü gördüm, ancak / dev / log'un varsayılan olarak kullanılması gerektiğini düşünmedim .. Ah ..
thor

Yanıtlar:


140

Satırı şu şekilde değiştirin:

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

Bu benim için çalışıyor

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

12
Olarak, unutmayın doc diyor '/var/run/syslog'OS X'te Right Thing olduğunu
offby1

Lifesaver answer +1
chachan

3
bu günlükleri syslog'da nasıl tanımlayabiliriz? herhangi bir uygulama adı VEYA syslogtag = django gibi herhangi bir etiket verebilir miyiz?
Luv33preet

ve /etc/syslog.d/conf dosyasını yapılandırmayı ve syslog / rsyslog hizmetini yeniden başlatmayı unutmayın
linrongbin

5
@ Luv33preet Bunu, işler logging.Formatter(fmt='myscriptname[%(process)d]: %(levelname)s: %(message)s', ...)gibi bir rsyslog koşulu gibi bir formatlayıcıyla (ama olmadan) test ettim $programname == 'myscriptname'.
Peter

26

Sen gerektiğini hep / dev / TCP yığını içinden yapın veya localhost olsun, günlük yerel ana bilgisayar kullanmak. Bu, tamamen RFC uyumlu ve özellikli sistem günlüğü arka plan programının syslog'u işlemesine olanak tanır. Bu, uzak arka plan programının işlevsel olma ihtiyacını ortadan kaldırır ve örneğin rsyslog ve syslog-ng gibi syslog arka plan programının gelişmiş yeteneklerini sağlar. Aynı felsefe SMTP için de geçerlidir. Yerel SMTP yazılımına vermeniz yeterlidir. Bu durumda daemon'u değil 'program modunu' kullanın, ancak bu aynı fikirdir. Daha yetenekli yazılımın bunu halletmesine izin verin. Yeniden deneme, sıraya alma, yerel kuyruklama, syslog için UDP yerine TCP kullanma vb. Mümkün hale gelir. Ayrıca bu arka plan yordamlarını olması gerektiği gibi kodunuzdan ayrı olarak [yeniden] yapılandırabilirsiniz.

Uygulamanız için kodlamanızı kaydedin, bırakın diğer yazılım işini birlikte yapsın.


2
adil bir noktayı yükseltiyorsun. çeşitli günlük arka plan programlarının kullandığı ortak adresleri ve bağlantı noktalarını belirtebilir misiniz? daemon'un bir tcp soketine bağlı olup olmadığını belirlemek için standart bir keşif mekanizması var mı?
init_js

Sana tamamiyle katılıyorum.
daks

20

Tanımladığınız temel günlük kaydı davranışını elde etmeyi oldukça kolaylaştırmak için syslog modülünü buldum :

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

Yapabileceğiniz başka şeyler de var, ama bunun sadece ilk iki satırı bile, anladığım kadarıyla istediğiniz şeyi size verecektir.


Loglama modülünü, tüm ifadeleri etkilemeden kaydedici ayarını değiştirmeye izin verdiği için tutuyorum. Ayrıca, aynı anda farklı türde günlük kaydı yapmak istemeniz durumunda davranışı değiştirmenize de izin verir
chachan

14

Bir şeyleri buradan ve diğer yerlerden bir araya getirerek, bulduğum şey bu unbuntu 12.04 ve centOS6'da çalışıyor

/etc/rsyslog.d/.Conf ile biten bir dosya oluşturun ve aşağıdaki metni ekleyin

local6.*        /var/log/my-logfile

Yeniden başlatın rsyslog, yeniden yükleme yeni günlük dosyaları için işe yaramıyor gibi görünüyor. Belki sadece mevcut conf dosyalarını yeniden yükler?

sudo restart rsyslog

Daha sonra gerçekten çalıştığından emin olmak için bu test programını kullanabilirsiniz.

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

1
CentOS7'de rsyslog'u yeniden başlatmak için,sudo service rsyslog restart
radtek

12

Herkese yardımcı olma ihtimaline karşı biraz fazladan yorum ekledim çünkü bu değişimi yararlı buldum, ancak hepsinin çalışmasını sağlamak için bu biraz fazla bilgiye ihtiyacım vardı.

SysLogHandler'ı kullanarak belirli bir tesiste oturum açmak için tesis değerini belirtmeniz gerekir. Örneğin şunları tanımladığınızı söyleyin:

local3.* /var/log/mylog

syslog'da ise şunu kullanmak isteyeceksiniz:

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

ve ayrıca / dev / log yerine localhost kullanmak için UDP'de syslog dinlemeniz gerekir.


3
UDP'de syslog dinlemeye 'gerek' yoktur. Örneğiniz adres = '/ dev / log' ile de mükemmel şekilde çalışacaktır.
Thor

5
evet, elbette, ancak adres = ('localhost', 514) ile, bir günlük sunucunuzun olduğu gün, localhost'u sunucunun adresiyle değiştirirsiniz ve uzaktan oturum
açarsınız

5
Tesis = 19 nereden geliyor? neden tesis değil = "local3"
boatcoder

4
@ Mark0978 19, yerel3'ün RFC3146 (ve ardından RFC5424) tarafından tanımlandığı şekliyle sayısal temsilidir
Andrew Sledge

3
Bunu da merak ettim ve tesis kodlarının Python'un SysLogHandler
clebio

11

Syslog.conf dosyanız tesis = kullanıcı işlemek için mi ayarlandı?

Python günlükçü tarafından kullanılan özelliği, tesis argümanıyla aşağıdaki gibi ayarlayabilirsiniz:

handler = logging.handlers.SysLogHandler(facility=SysLogHandler.LOG_DAEMON)

Parametre LOG_DAEMONiçin bir değer olarak ne sağladığınızı belirtmeniz gerekir facility.
tzot

4
Olurdu 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...')

yukarıdaki komut dosyası, özel "LOG_IDENTIFIER" ile LOCAL0 tesisine giriş yapacak ... yerel amaç için LOCAL [0-7] kullanabilirsiniz.


1
yorumunuzun orijinal istekle ilgisi yok
thor

@thor Bunun alakalı olduğunu kabul ediyorum. Syslog paketinin saf Python uygulamasından biraz daha verimli olduğunu tahmin edeceğim. (daha az esnekse)
Daniel Santos

7

Gönderen 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')

Bu çok ilginç, ancak python 2.6.6 (RHEL 6.4) üzerinde çalışmıyor: Traceback (en son çağrı): "syslog_bridge.py" dosyası, satır 68, <module> handlers.append (SysLogLibHandler (logFacilityLocalN )) "Syslog_bridge.py" dosyası, satır 29, init syslog.openlog'da (syslog.LOG_PID, self.FACILITY [n]) TypeError: ident string [, logoption [, tesis]]
Steve Cohen


3

İşte 3.2 ve sonrası için önerilen yaml dictConfig yöntemi.

Günlükte 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

Yapılandırmayı şunu kullanarak yükleyin:

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

Hem syslog hem de doğrudan bir dosya yapılandırıldı. /dev/logİşletim sistemine özel olduğunu unutmayın .


1

Defterime düzeltirim. Rsyslog hizmeti soket hizmetini dinlemedi.

Bu satırı aşağıdaki /etc/rsyslog.confdosyada yapılandırdım ve sorunu çözdüm :

$SystemLogSocketName /dev/log


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.