2010-10-19 56 views
94

Tôi không thể lấy đầu của mình xung quanh mô-đun logging của Python. Nhu cầu của tôi rất đơn giản: Tôi chỉ muốn đăng nhập mọi thứ vào syslog. Sau khi đọc tài liệu, tôi đã đưa ra kịch bản thử nghiệm đơn giản này:Cách định cấu hình ghi nhật ký vào nhật ký hệ thống trong Python?

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

Nhưng tập lệnh này không tạo ra bất kỳ nhật ký nhật ký nào trong nhật ký hệ thống. Chuyện gì vậy?

+3

Bạn đang kiểm tra thông báo nhật ký hệ thống của mình ở đâu? SysLogHandler() phát ra các thông điệp đó đến udp socket trong cổng 514 trong localhost. – suzanshakya

+0

Bạn hoàn toàn đúng. Và tôi đã thấy rằng 'localhost-514' trong tài liệu nhưng không nghĩ rằng/dev/log nên được sử dụng theo mặc định .. Sigh .. – thor

Trả lời

109

Thay đổi dòng này:

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

này làm việc cho tôi

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

Lưu ý rằng, như [doc] (http://docs.python.org/2/library/logging.handlers.html#logging.handlers.SysLogHandler) nói, ''/ var/run/syslog'' là Điều Đúng trên OS X. – offby1

+0

Câu trả lời của Lifesaver +1 – chachan

+2

cách chúng tôi có thể xác định các nhật ký này trong syslog? như chúng ta có thể cung cấp cho bất kỳ tên ứng dụng HOẶC bất kỳ thẻ nào như syslogtag = django không? – Luv33preet

9

Syslog.conf của bạn có được thiết lập để xử lý cơ sở = người dùng không?

Bạn có thể thiết lập các cơ sở sử dụng bởi các logger python với lập luận cơ sở, một cái gì đó như thế này:

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

Bạn cần phải xác định 'LOG_DAEMON' mà bạn cung cấp làm giá trị cho tham số 'cơ sở'. – tzot

+1

Đó sẽ là 'SysLogHandler.LOG_DAEMON'. –

11

Tôi thêm một chút nhận xét bổ sung chỉ trong trường hợp nó giúp mọi người vì tôi đã tìm thấy tệp excha này Nge hữu ích nhưng cần thêm chút thông tin này để làm cho nó hoạt động.

Để đăng nhập vào một cơ sở cụ thể bằng SysLogHandler, bạn cần xác định giá trị cơ sở. Nói ví dụ mà bạn đã xác định:

local3.* /var/log/mylog

trong syslog, sau đó bạn sẽ muốn sử dụng:

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

và bạn cũng cần phải có nghe syslog trên UDP sử dụng localhost thay vì/dev/log.

+1

không có 'cần' để có syslog lắng nghe trên UDP. Ví dụ của bạn hoàn toàn sẽ làm việc với address = '/ dev/log'. – thor

+4

vâng, chắc chắn, nhưng với địa chỉ = ('localhost', 514), ngày bạn có máy chủ đăng nhập, bạn thay thế localhost bằng địa chỉ của máy chủ và bạn đã đăng nhập từ xa ;-) –

+3

Cơ sở = 19 đến từ? Tại sao không phải là nó cơ sở = "local3" – boatcoder

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

kịch bản trên sẽ đăng nhập vào cơ sở local0 với tùy chỉnh "LOG_IDENTIFIER" của chúng tôi ... bạn có thể sử dụng LOCAL [0-7] cho mục đích địa phương.

+1

nhận xét của bạn không liên quan gì đến yêu cầu ban đầu – thor

+2

@thor như thế nào? phản hồi ở đây là khá hợp lệ ... – Cmag

16

Bạn nên luôn luôn sử dụng máy chủ cục bộ để ghi nhật ký, cho dù là/dev/log hoặc localhost thông qua ngăn xếp TCP. Điều này cho phép hoàn toàn RFC tuân thủ và tính năng hệ thống đăng nhập daemon để xử lý syslog. Điều này giúp loại bỏ sự cần thiết của daemon từ xa để có chức năng và cung cấp khả năng nâng cao của syslog daemon chẳng hạn như rsyslog và syslog-ng chẳng hạn. Cùng một triết lý đi cho SMTP. Chỉ cần đưa nó vào phần mềm SMTP cục bộ. Trong trường hợp này sử dụng 'chế độ chương trình' không phải là daemon, nhưng đó là ý tưởng tương tự. Hãy để phần mềm có khả năng xử lý nó nhiều hơn. Thử lại, xếp hàng, spooling cục bộ, sử dụng TCP thay vì UDP cho syslog và vv trở thành có thể. Bạn cũng có thể [cấu hình lại] các trình tiện ích này riêng biệt với mã của bạn.

Lưu mã hóa cho ứng dụng của bạn, hãy để phần mềm khác thực hiện công việc trong buổi hòa nhạc.

+0

bạn tăng điểm công bằng. bạn có thể chỉ ra các địa chỉ và cổng chung được sử dụng bởi các trình tiện ích ghi nhật ký khác nhau không? có cơ chế khám phá tiêu chuẩn nào để xác định xem daemon có bị ràng buộc vào một socket tcp không? –

7

Từ 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') 
+0

Điều này rất thú vị, nhưng nó không hoạt động trên python 2.6.6 (RHEL 6.4): Traceback (cuộc gọi gần đây nhất): Tệp "syslog_bridge.py", dòng 68, trong handlers.append (SysLogLibHandler (logFacilityLocalN)) Tệp "syslog_bridge.py", dòng 29, trong __init__ syslog.openlog (syslog.LOG_PID, self.FACILITY [n]) LoạiError: ident string [, logoption [, facility]] –

+0

Đã chỉnh sửa dựa trên: https://github.com/luismartingil/scripts/commit/46c947233ca58530bd55336cdc810e9e51c84c90 – luismartingil

12

được bức thứ với nhau từ đây và những nơi khác, đây là những gì tôi đã đưa ra hoạt động trên unbuntu 12.04 và centOS6

Tạo một tập tin trong /etc/rsyslog.d/ kết thúc bằng.conf và thêm văn bản sau đây

local6.*  /var/log/my-logfile 

Khởi động lại rsyslog, tải lại dường như không hoạt động đối với các tệp nhật ký mới. Có lẽ nó chỉ tải lại các tệp conf hiện có?

sudo restart rsyslog 

Sau đó, bạn có thể sử dụng chương trình thử nghiệm này để đảm bảo chương trình thực sự hoạt động.

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

Để khởi động lại rsyslog trên centOS7, 'sudo service rsyslog restart' – radtek

-1

Bạn cũng có thể thêm một handler tập tin hoặc xoay xử lý tập tin để gửi các bản ghi của bạn vào một tập tin địa phương: http://docs.python.org/2/library/logging.handlers.html

+2

Không phải rất hữu ích nếu bạn muốn chạy nhiều quá trình. – dalore

7

tôi thấy the syslog module để làm cho nó khá dễ dàng để có được những hành vi khai thác gỗ cơ bản bạn mô tả:

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

Có những thứ khác bạn có thể làm, nhưng thậm chí chỉ hai dòng đầu tiên sẽ giúp bạn có được những gì bạn đã yêu cầu khi tôi hiểu.

+0

Tôi giữ mô-đun ghi nhật ký vì nó cho phép thay đổi cài đặt nhật ký mà không ảnh hưởng đến tất cả các câu lệnh. Cũng cho phép thay đổi hành vi trong trường hợp bạn muốn có các kiểu ghi nhật ký khác nhau vào thời điểm đó – chachan

1

Đây là cách damChỉ đề yaml được khuyến nghị cho 3.2 & sau đó.

Trong log 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 

tải cấu hình sử dụng:

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

Configured cả syslog & một tập tin trực tiếp. Lưu ý rằng /dev/log là hệ điều hành cụ thể.

Các vấn đề liên quan