Python에서 syslog에 대한 로깅을 구성하는 방법은 무엇입니까?


121

나는 파이썬 logging모듈에 대해 머리를 쓸 수 없습니다 . 내 요구 사항은 매우 간단합니다. 모든 것을 syslog에 기록하고 싶습니다. 문서를 읽은 후 다음과 같은 간단한 테스트 스크립트를 만들었습니다.

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

그러나이 스크립트는 syslog에 로그 레코드를 생성하지 않습니다. 뭐가 문제 야?


3
syslog 메시지를 어디에서 확인하고 있습니까? SysLogHandler ()는 이러한 메시지를 localhost의 포트 514에있는 udp 소켓으로 내 보냅니다.
suzanshakya

당신이 절대적으로 옳습니다. 그리고 문서에서 'localhost-514'를 보았지만 / dev / log가 기본적으로 사용되어야한다고 생각하지 않았습니다 .. Sigh ..
thor

답변:


140

줄을 다음과 같이 변경하십시오.

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

이것은 나를 위해 작동합니다

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
로, 그 주 사이먼이 말한다, '/var/run/syslog'OS X에서 옳은 일
offby1

생명의 대답 +1
chachan

3
syslog에서 이러한 로그를 어떻게 식별 할 수 있습니까? 애플리케이션 이름이나 syslogtag = django와 같은 태그를 지정할 수 있습니까?
Luv33preet 17

그리고 /etc/syslog.d/conf 파일을 config (설정)을 기억하고 다시 시작 시스템 로그 / 위해 rsyslog 서비스
linrongbin

5
@ Luv33preet 나는 작동 logging.Formatter(fmt='myscriptname[%(process)d]: %(levelname)s: %(message)s', ...)과 같은 rsyslog 조건과 같은 포맷터를 사용하여 테스트했습니다 $programname == 'myscriptname'.
Peter

26

/ dev / log 또는 TCP 스택을 통한 localhost에 관계없이 항상 로컬 호스트를 사용하여 로깅 해야합니다 . 이를 통해 RFC를 완전히 준수하고 기능이있는 시스템 로깅 데몬이 syslog를 처리 할 수 ​​있습니다. 이렇게하면 원격 데몬이 작동 할 필요가 없으며 예를 들어 rsyslog 및 syslog-ng와 같은 syslog 데몬의 향상된 기능을 제공합니다. SMTP에도 동일한 철학이 적용됩니다. 로컬 SMTP 소프트웨어에 전달하기 만하면됩니다. 이 경우 데몬이 아닌 '프로그램 모드'를 사용하지만 같은 생각입니다. 더 유능한 소프트웨어가 처리하도록하십시오. 재시도, 큐잉, 로컬 스풀링, syslog 용 UDP 대신 TCP 사용 등이 가능해집니다. 또한 해당 데몬을 코드와 별도로 [재-] 구성 할 수 있습니다.

응용 프로그램에 대한 코딩을 저장하고 다른 소프트웨어가 함께 작업하도록하십시오.


2
당신은 공정한 포인트를 올립니다. 다양한 로깅 데몬에서 사용하는 공통 주소와 포트를 나타낼 수 있습니까? 데몬이 tcp 소켓에 바인딩되었는지 여부를 결정하는 표준 검색 메커니즘이 있습니까?
init_js

전적으로 동의합니다.
daks

20

설명하는 기본 로깅 동작을 쉽게 얻을 수 있도록 syslog 모듈 을 찾았 습니다 .

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

당신이 할 수있는 다른 일들도 있지만, 그것의 처음 두 줄만 내가 이해하는대로 당신이 요청한 것을 얻을 수있을 것입니다.


모든 문에 영향을주지 않고 로거 설정을 변경할 수 있으므로 로깅 모듈을 유지합니다. 또한이 시간에 로그의 다른 유형을 할 경우에 행동을 변경할 수 있습니다
chachan

14

여기와 다른 곳에서 사물을 결합하여 unbuntu 12.04 및 centOS6에서 작동하는 것이 제가 생각해 낸 것입니다.

/etc/rsyslog.d/.conf로 끝나는 파일을 만들고 다음 텍스트를 추가하십시오.

local6.*        /var/log/my-logfile

다시 시작 rsyslog, 다시로드가 새 로그 파일에 대해 작동하지 않는 것 같습니다. 아마도 기존 conf 파일 만 다시로드할까요?

sudo restart rsyslog

그런 다음이 테스트 프로그램을 사용하여 실제로 작동하는지 확인할 수 있습니다.

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에서 rsyslog를 다시 시작하려면sudo service rsyslog restart
radtek

12

나는이 교환이 유용하다는 것을 알았 기 때문에 누군가에게 도움이되는 경우를 대비하여 약간의 추가 의견을 추가했지만 모든 것이 작동하려면 약간의 추가 정보가 필요했습니다.

SysLogHandler를 사용하여 특정 시설에 기록하려면 시설 값을 지정해야합니다. 예를 들어 다음과 같이 정의했습니다.

local3.* /var/log/mylog

syslog에서 다음을 사용하고 싶을 것입니다.

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

또한 / dev / log 대신 localhost를 사용하려면 UDP에서 수신 대기하는 syslog가 있어야합니다.


3
syslog가 UDP에서 수신하도록 '필요'가 없습니다. 귀하의 예제는 address = '/ dev / log'에서도 완벽하게 작동합니다.
토르

5
네, 물론,하지만 주소 = ( 'localhost를', 514), 당신은 로그 서버가있는 날, 당신은 서버의 주소로 localhost를 교체하고 당신은 ;-) 원격 로깅있어
올리버 Henriot

5
Facility = 19는 어디에서 왔습니까? 왜 Facility = "local3"이
아닌가

4
@ Mark0978 19는 RFC3146 (및 이후 RFC5424)에 의해 정의 된 local3의 숫자 표현입니다.
Andrew Sledge

3
나도 이것에 대해 궁금해했고, 시설 코드가 Python의 SysLogHandler
clebio dec

11

syslog.conf가 시설 = 사용자를 처리하도록 설정되어 있습니까?

다음과 같이 시설 인수를 사용하여 파이썬 로거가 사용하는 시설을 설정할 수 있습니다.

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

매개 변수 LOG_DAEMON값으로 제공하는 값 을 지정해야합니다 facility.
tzot

4
그것은 SysLogHandler.LOG_DAEMON.
Craig Trader 2011

7
import syslog
syslog.openlog(ident="LOG_IDENTIFIER",logoption=syslog.LOG_PID, facility=syslog.LOG_LOCAL0)
syslog.syslog('Log processing initiated...')

위의 스크립트는 사용자 정의 "LOG_IDENTIFIER"를 사용하여 LOCAL0 시설에 기록합니다 ... 로컬 용도로 LOCAL [0-7]을 사용할 수 있습니다.


1
귀하의 의견은 원래 요청과 관련이 없습니다
thor

@thor 나는 이것이 관련이 있다는 데 동의합니다. 나는거야 생각 은 syslog 패키지는 순수 파이썬 구현보다 조금 더 효율적이라고? (유연성이 적은 경우)
다니엘 산토스

7

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

이것은 매우 흥미롭지 만 python 2.6.6 (RHEL 6.4)에서는 작동하지 않습니다. Traceback (가장 최근 호출) : File "syslog_bridge.py", 라인 68, <module> handlers.append (SysLogLibHandler (logFacilityLocalN) )) 파일 "syslog_bridge.py", 29 행, init syslog.openlog (syslog.LOG_PID, self.FACILITY [n]) TypeError : ident string [, logoption [, 설비]]
Steve Cohen


3

다음은 3.2 이상에 권장되는 yaml dictConfig 방법입니다.

로그인 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

다음을 사용하여 구성을로드합니다.

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

syslog 및 직접 파일을 모두 구성했습니다. (가) 있습니다 /dev/logOS 고유의 것입니다.


1

내 노트북에서 수정합니다. rsyslog 서비스가 소켓 서비스를 수신하지 않았습니다.

이 줄을 /etc/rsyslog.conf파일에 구성하고 문제를 해결했습니다.

$SystemLogSocketName /dev/log


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.