Django Setup การบันทึกเริ่มต้น


94

ฉันไม่สามารถหาวิธีตั้งค่าตัวบันทึก "ค่าเริ่มต้น" สำหรับการติดตั้ง Django ของฉันได้ ฉันต้องการใช้LOGGINGการตั้งค่าใหม่ของ Django 1.3 ในsettings.py.

ฉันได้ดูตัวอย่างของ Django Logging Docแล้ว แต่สำหรับฉันแล้วดูเหมือนว่าพวกเขาจะมีเพียงตัวจัดการการตั้งค่าซึ่งจะทำการบันทึกสำหรับผู้ตัดไม้โดยเฉพาะ ในกรณีของตัวอย่างพวกเขาตั้งค่าตัวจัดการสำหรับคนตัดไม้ชื่อ 'django', 'django.request' และ 'myproject.custom'

สิ่งที่ฉันต้องการทำคือตั้งค่าเริ่มต้นlogging.handlers.RotatingFileHandlerซึ่งจะจัดการกับคนตัดไม้ทั้งหมดตามค่าเริ่มต้น กล่าวคือถ้าฉันสร้างโมดูลใหม่ที่ใดที่หนึ่งในโปรเจ็กต์ของฉันและมันถูกแสดงด้วยสิ่งที่ต้องการ: my_app_name.my_new_moduleฉันควรจะทำได้และมีการบันทึกทั้งหมดไปที่บันทึกไฟล์แบบหมุน

# 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`!

คำตอบ:


155

คิดออก ...

คุณตั้งค่าตัดไม้ 'จับทั้งหมด' ''โดยอ้างอิงกับสตริงว่าง:

ตัวอย่างเช่นในการติดตั้งต่อไปนี้ผมมีเหตุการณ์ทั้งหมดเข้าสู่ระบบได้รับการบันทึกไว้ในlogs/mylog.logที่มีข้อยกเว้นของเหตุการณ์การบันทึกซึ่งจะถูกบันทึกไว้django.request logs/django_request.logเนื่องจาก'propagate'ถูกตั้งค่าเป็นFalseสำหรับdjango.requestคนตัดไม้ของฉันเหตุการณ์ในบันทึกจะไม่ไปถึงคนตัดไม้ "จับทั้งหมด"

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
คริสเอกสาร Django นี้ไม่สับสน ขอบคุณสำหรับสิ่งนี้.

5
การแก้ไขเล็กน้อย: ความคิดเห็นแสดงถึงการบันทึก sql จะได้รับผลกระทบจาก django.request logger หากต้องการเปลี่ยนเส้นทางการบันทึก sql คุณต้องกำหนดคนตัดไม้สำหรับ "django.db" django.request logger จัดการการตอบสนอง 5xx และ 4xx http
rych

ในสิ่งนี้ช่วยให้ noobs อื่น ๆ เช่นฉัน: คนตัดไม้จะสร้างไฟล์บันทึก แต่คุณต้องสร้างlogs/โฟลเดอร์ก่อน :-) ./manange.py runserverมิฉะนั้นคุณจะได้รับข้อผิดพลาดเมื่อคุณเรียกใช้ @Chris W. ขอบคุณสำหรับตัวอย่างการตั้งค่าการบันทึก มันช่วยฉันได้มาก!
hobbes3

3
@arindamroychowdhury ด้วยการกำหนดค่าข้างต้นหากคุณทำเช่นlogger = logging.getLogger('foo'); logger.warn('bar');นั้นdefaultตัวจัดการจะจับการบันทึกนั้นและบางสิ่งบางอย่าง<time> WARN: foo: barจะจบลงในlogs/mylog.log
Chris W.

9
ขอบคุณดูเหมือนว่านี่หมายถึงคนตัดไม้ราก ไม่พบข้อมูลที่เป็นประโยชน์นี้ในเอกสารของ Django
Eino Mäkitalo

25

ดังที่คุณได้กล่าวไว้ในคำตอบของคุณ Chris ทางเลือกหนึ่งในการกำหนดคนตัดไม้เริ่มต้นคือการใช้สตริงว่างเป็นคีย์

อย่างไรก็ตามฉันคิดว่าวิธีที่ตั้งใจไว้คือการกำหนดคนตัดไม้พิเศษภายใต้rootคีย์ของพจนานุกรมการกำหนดค่าการบันทึก ฉันพบสิ่งนี้ในเอกสาร Python :

root - นี่จะเป็นการกำหนดค่าสำหรับ root logger การประมวลผลการกำหนดค่าจะเป็นไปตามสำหรับคนตัดไม้ยกเว้นว่าการpropagateตั้งค่านั้นจะไม่สามารถใช้ได้

นี่คือการกำหนดค่าจากคำตอบของคุณที่เปลี่ยนไปใช้rootคีย์:

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
        },
    }
}

เพื่อความเป็นธรรมฉันไม่เห็นความแตกต่างในพฤติกรรมระหว่างการกำหนดค่าทั้งสอง ดูเหมือนว่าการกำหนดคนตัดไม้ด้วยคีย์สตริงว่างจะแก้ไข root logger เพราะlogging.getLogger('')จะส่งคืน root logger

เหตุผลเดียวที่ฉันชอบ'root'มากกว่า''คือมันชัดเจนเกี่ยวกับการปรับเปลี่ยน root logger ในกรณีที่คุณอยากรู้อยากเห็นให้'root'แทนที่''ถ้าคุณกำหนดทั้งสองอย่างเพียงเพราะรายการรูทถูกประมวลผลล่าสุด


ใช่ถูกต้องขออภัยในความผิดพลาด! ในขณะที่การใช้ '' แทน 'root' นั้นค่อนข้างมีเหตุผล แต่ฉันก็ยังพบว่ามันไม่สอดคล้องกันเล็กน้อยในการย้ายrootรายการไปยังรูทของ dict ในกระบวนการเปลี่ยนจาก 2.6 fileConfig logic ไปเป็น 2.7 dictConfig one
Antony Hatchkins

2
import logging
logger = logging.getLogger(__name__)

หลังจากเพิ่ม:

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

เราอาจเปลี่ยนรูปแบบเป็น:

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

หรือ

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

0

ฉันทำตัวอย่างสั้น ๆ เพื่อตรวจสอบว่าการกำหนดค่าใดที่ใช้เมื่อทั้งสองrootคีย์และตัว''บันทึกเปล่าถูกอ้างอิงใน 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")

พิมพ์ผลลัพธ์ต่อไปนี้:

[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

ระบุว่าการกำหนดค่าภายใต้rootคีย์มีลำดับความสำคัญสูงสุด หากบล็อกถูกลบผลลัพธ์คือ:

[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

ในกรณีที่ทั้งสองก็สามารถที่จะแก้ปัญหาและกำหนดว่าทั้งสามตัดไม้ ( l1, l2และroot) อ้างอิงเช่นตัดไม้เดียวกันตัดไม้ราก

หวังว่าจะช่วยให้คนอื่น ๆ ที่เหมือนฉันสับสนกับ 2 วิธีในการกำหนดค่า root logger

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.