Ghi nhật ký mặc định thiết lập Django


94

Tôi dường như không thể tìm ra cách thiết lập trình ghi nhật ký "mặc định" cho cài đặt Django của mình. Tôi muốn sử dụng LOGGINGcài đặt mới của Django 1.3 trong settings.py.

Tôi đã xem ví dụ của Tài liệu ghi nhật ký Django , nhưng với tôi thì có vẻ như chúng chỉ thiết lập các trình xử lý sẽ thực hiện ghi nhật ký cho các trình ghi nhật ký cụ thể. Trong trường hợp ví dụ của họ, họ thiết lập trình xử lý cho các trình ghi nhật ký có tên 'django', 'django.request' và 'myproject.custom'.

Tất cả những gì tôi muốn làm là thiết lập một mặc định logging.handlers.RotatingFileHandlersẽ xử lý tất cả các trình ghi nhật ký theo mặc định. tức là, nếu tôi tạo một mô-đun mới ở đâu đó trong dự án của mình và nó được biểu thị bằng một cái gì đó như : my_app_name.my_new_module, Tôi sẽ có thể thực hiện điều này và có tất cả việc ghi nhật ký tệp luân phiên.

# In file './my_app_name/my_new_module.py'
import logging
logger = logging.getLogger('my_app_name.my_new_module')
logger.debug('Hello logs!') # <-- This should get logged to my RotatingFileHandler that I setup in `settings.py`!

Câu trả lời:


153

Tìm ra...

Bạn đặt 'bắt tất cả' logger bằng cách tham khảo nó với chuỗi rỗng: ''.

Ví dụ: trong thiết lập sau, tôi có tất cả các sự kiện nhật ký được lưu vào logs/mylog.log, ngoại trừ các django.requestsự kiện nhật ký sẽ được lưu vào logs/django_request.log. Vì 'propagate'được đặt thành Falsecho django.requesttrình ghi nhật ký của tôi , sự kiện nhật ký sẽ không bao giờ đến trình ghi nhật ký 'bắt tất cả'.

LOGGING = {
    'version': 1,
    'disable_existing_loggers': True,
    'formatters': {
        'standard': {
            'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
        },
    },
    'handlers': {
        'default': {
            'level':'DEBUG',
            'class':'logging.handlers.RotatingFileHandler',
            'filename': 'logs/mylog.log',
            'maxBytes': 1024*1024*5, # 5 MB
            'backupCount': 5,
            'formatter':'standard',
        },  
        'request_handler': {
            'level':'DEBUG',
            'class':'logging.handlers.RotatingFileHandler',
            'filename': 'logs/django_request.log',
            'maxBytes': 1024*1024*5, # 5 MB
            'backupCount': 5,
            'formatter':'standard',
        },
    },
    'loggers': {
        '': {
            'handlers': ['default'],
            'level': 'DEBUG',
            'propagate': True
        },
        'django.request': {
            'handlers': ['request_handler'],
            'level': 'DEBUG',
            'propagate': False
        },
    }
}

2
Chris, tài liệu Django về điều này không gây nhầm lẫn. Cảm ơn vì điều đó.

5
Sửa lỗi nhỏ: nhận xét ngụ ý rằng việc ghi nhật ký sql sẽ bị ảnh hưởng bởi trình ghi nhật ký django.request. Để chuyển hướng ghi nhật ký sql, bạn phải xác định trình ghi nhật ký cho 'django.db'. Trình ghi nhật ký django.request xử lý các phản hồi http 5xx & 4xx.
rych

Điều này giúp những người khác như tôi: Trình ghi nhật ký sẽ tạo các tệp nhật ký, nhưng bạn phải tạo logs/thư mục trước :-). Nếu không, bạn sẽ gặp lỗi khi chạy ./manange.py runserver. @Chris W. Cảm ơn về cài đặt ghi nhật ký mẫu của bạn. Nó đã giúp tôi rất nhiều!
hobbes

3
@arindamroychowdhury Với cấu hình trên nếu bạn làm logger = logging.getLogger('foo'); logger.warn('bar');thì defaultxử lý sẽ bắt mà khai thác gỗ và một cái gì đó như <time> WARN: foo: barsẽ kết thúc tronglogs/mylog.log
Chris W.

8
Cảm ơn, có vẻ như đây '' có nghĩa là trình ghi gốc. Phần thông tin hữu ích này không được tìm thấy trong tài liệu Django.
Eino Mäkitalo

25

Như bạn đã nói trong câu trả lời của mình , Chris, một tùy chọn để xác định trình ghi mặc định là sử dụng chuỗi trống làm khóa của nó.

Tuy nhiên, tôi nghĩ rằng cách dự định là xác định một trình ghi nhật ký đặc biệt dưới rootkhóa của từ điển cấu hình ghi nhật ký. Tôi tìm thấy điều này trong tài liệu Python :

root - đây sẽ là cấu hình cho root log. Việc xử lý cấu hình sẽ giống như đối với bất kỳ trình ghi nhật ký nào, ngoại trừ việc propagatecài đặt sẽ không áp dụng được.

Đây là cấu hình từ câu trả lời của bạn đã được thay đổi để sử dụng rootkhóa:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': True,
    'formatters': {
        'standard': {
            'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
        },
    },
    'handlers': {
        'default': {
            'level':'DEBUG',
            'class':'logging.handlers.RotatingFileHandler',
            'filename': 'logs/mylog.log',
            'maxBytes': 1024*1024*5, # 5 MB
            'backupCount': 5,
            'formatter':'standard',
        },  
        'request_handler': {
            'level':'DEBUG',
            'class':'logging.handlers.RotatingFileHandler',
            'filename': 'logs/django_request.log',
            'maxBytes': 1024*1024*5, # 5 MB
            'backupCount': 5,
            'formatter':'standard',
        },
    },
    'root': {
        'handlers': ['default'],
        'level': 'DEBUG'
    },
    'loggers': {
        'django.request': {
            'handlers': ['request_handler'],
            'level': 'DEBUG',
            'propagate': False
        },
    }
}

Công bằng mà nói, tôi không thể thấy bất kỳ sự khác biệt nào về hành vi giữa hai cấu hình. Có vẻ như việc xác định trình ghi nhật ký bằng khóa chuỗi trống sẽ sửa đổi trình ghi gốc, vì logging.getLogger('')sẽ trả về trình ghi gốc.

Lý do duy nhất tôi thích 'root'hơn ''là nó rõ ràng về việc sửa đổi trình ghi gốc. Trong trường hợp bạn tò mò, hãy 'root'ghi đè ''nếu bạn xác định cả hai, chỉ vì mục gốc được xử lý sau cùng.


Đúng, đúng vậy, xin lỗi vì đã sửa sai! Mặc dù việc sử dụng '' thay vì 'root' hơi hợp lý, tôi vẫn thấy nó hơi mâu thuẫn trong việc di chuyển rootmục nhập vào gốc của dict trong quá trình chuyển đổi suôn sẻ từ logic 2,6 fileConfig sang 2,7 dictConfig một.
Antony Hatchkins

2
import logging
logger = logging.getLogger(__name__)

sau khi thêm:

logging.basicConfig(
    level = logging.DEBUG,
    format = '%(name)s %(levelname)s %(message)s',
)

chúng tôi có thể thay đổi định dạng thành:

format = '"%(levelname)s:%(name)s:%(message)s"  ',

hoặc là

format = '%(name)s %(asctime)s %(levelname)s %(message)s',

0

Tôi đã thực hiện một mẫu nhanh để kiểm tra cấu hình nào được sử dụng khi cả rootkhóa và trình ''ghi trống đều được tham chiếu trong config dict.

import logging.config

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'fmt1': {
            'format': '[FMT1] %(asctime)-15s %(message)s',
        },
        'fmt2': {
            'format': '[FMT2] %(asctime)-15s %(message)s',
        }
    },
    'handlers': {
        'console1': {
            'level': 'INFO',
            'class': 'logging.StreamHandler',
            'formatter': 'fmt1',
        },
        'console2': {
            'level': 'INFO',
            'class': 'logging.StreamHandler',
            'formatter': 'fmt2',
        },
    },
    # First config for root logger: console1 -> fmt1
    'root': {
        'handlers': ['console1'],
        'level': 'DEBUG',
        'propagate': True,
    },
    'loggers': {
        # Second config for root logger: console2 -> fmt2
        '': {
            'handlers': ['console2'],
            'level': 'DEBUG',
            'propagate': True,
        },
    },
}

logging.config.dictConfig(LOGGING)

l1 = logging.getLogger()
l2 = logging.getLogger('')
root = logging.root

l1.info("l1")
l2.info("l2")
root.info("root logger")

In kết quả sau:

[FMT1] 2018-12-18 17:24:47,691 l1
[FMT1] 2018-12-18 17:24:47,691 l2
[FMT1] 2018-12-18 17:24:47,691 root logger

cho biết rằng cấu hình theo rootkhóa có mức ưu tiên cao nhất. Nếu khối bị loại bỏ, kết quả là:

[FMT2] 2018-12-18 17:25:43,757 l1
[FMT2] 2018-12-18 17:25:43,757 l2
[FMT2] 2018-12-18 17:25:43,757 root logger

Trong cả hai trường hợp, tôi đã có thể gỡ lỗi và xác định rằng cả ba logger ( l1, l2root) tham chiếu các ví dụ logger cùng, các logger gốc.

Hy vọng điều đó sẽ giúp những người khác, như tôi, đã bối rối bởi 2 cách khác nhau để cấu hình root logger.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.