Django में अजगर लॉगिंग का सुरुचिपूर्ण सेटअप


101

मुझे अभी तक Django के साथ पाइथन लॉगिंग स्थापित करने का एक तरीका खोजना है जिससे मैं खुश हूं। मेरी आवश्यकताएं काफी सरल हैं:

  • विभिन्न घटनाओं के लिए अलग लॉग हैंडलर - यानी, मैं अलग-अलग फ़ाइलों में लॉग इन करने में सक्षम होना चाहता हूं
  • मेरे मॉड्यूल में लकड़हारा तक आसान पहुँच। मॉड्यूल कम प्रयास के साथ अपने लकड़हारे को खोजने में सक्षम होना चाहिए।
  • कमांड-लाइन मॉड्यूल पर आसानी से लागू होना चाहिए। सिस्टम के हिस्से स्टैंड-अलोन कमांड लाइन या डेमॉन प्रक्रियाएं हैं। इन मॉड्यूल के साथ लॉगिंग आसानी से उपयोग करने योग्य होनी चाहिए।

मेरा वर्तमान सेटअप उस logging.confफ़ाइल और सेटअप लॉगिंग का उपयोग करना है जिसे मैं प्रत्येक मॉड्यूल से लॉग इन करता हूं। यह सही नहीं लगता।

क्या आपके पास एक लॉगिंग सेटअप है जो आपको पसंद है? कृपया इसे विस्तार से बताएं: आप कॉन्फ़िगरेशन को कैसे सेटअप करते हैं (क्या आप इसका उपयोग करते हैं logging.confया इसे कोड में सेट करते हैं), आप लॉगर्स को कहाँ से / कब आरंभ करते हैं, और आप अपने मॉड्यूल में इन तक कैसे पहुँच पाते हैं, आदि।


1
आपको निम्नलिखित पेंचकस उपयोगी लग सकते हैं - ericholscher.com/blog/2008/aug/29/… । इसके अलावा, Django में प्रवेश करने के लिए बेहतर समर्थन साइमन विलीसन द्वारा प्रस्तावित किया गया है (देखें simonwillison.net/2009/Sep/28/ponies )।
डोमिनिक रॉजर

@ डॉमिनिक रॉजर - आप पहले से ही Django में साइमन लॉगिंग कर सकते हैं, सिमोन का प्रस्ताव मुख्य रूप से Django इंटर्नल में लॉगिंग की सुविधा के लिए है। पायथन लॉगिंग में शब्दकोश-आधारित कॉन्फ़िगरेशन को जोड़ने के लिए पायथन में काम करना बंद है, जिससे Django को फायदा हो सकता है।
विनय साजिप

जवाबों:


57

अब तक मैंने जो सबसे अच्छा तरीका पाया है, वह है सेटिंग्स को लॉग इन करना। आप या तो एक कॉन्फ़िगरेशन फ़ाइल का उपयोग कर सकते हैं या इसे प्रोग्रामेटिक रूप से चरण-दर-चरण कर सकते हैं - यह सिर्फ आपकी आवश्यकताओं पर निर्भर करता है। मुख्य बात यह है कि मैं आमतौर पर हैंडलर को रूट लॉगर में जोड़ना चाहता हूं, स्तरों का उपयोग करके और कभी-कभी लॉगिंग करता हूं। मैं उन घटनाओं को प्राप्त करने के लिए उपयुक्त करता हूं जिन्हें मैं उचित फाइलों, कंसोल, सिसलॉग आदि के लिए चाहता हूं। आप निश्चित रूप से हैंडलर को किसी अन्य एंगल में जोड़ सकते हैं। भी, लेकिन आमतौर पर मेरे अनुभव में इसकी कोई आवश्यकता नहीं है।

प्रत्येक मॉड्यूल में, मैं एक लकड़हारे को परिभाषित करता हूं

logger = logging.getLogger(__name__)

और मॉड्यूल में लॉगिंग घटनाओं के लिए उस का उपयोग करें (और, अगर मैं आगे अंतर करना चाहता हूं) एक लकड़हारे का उपयोग करें जो ऊपर निर्मित लॉगर का एक बच्चा है।

यदि मेरा ऐप संभावित रूप से किसी ऐसी साइट में उपयोग होने जा रहा है, जो सेटिंग्स में लॉग इन नहीं करता है।

#someutils.py

class NullHandler(logging.Handler):
    def emit(self, record):
        pass

null_handler = NullHandler()

और सुनिश्चित करें कि इसका एक उदाहरण मेरे ऐप में मॉड्यूल में बनाए गए सभी लॉगर्स में जोड़ा जाता है जो लॉगिंग का उपयोग करते हैं। (नोट: NullHandler पहले से ही Python 3.1 के लिए लॉगिंग पैकेज में है, और Python 2.7 में होगा।):

logger = logging.getLogger(__name__)
logger.addHandler(someutils.null_handler)

यह सुनिश्चित करने के लिए किया जाता है कि आपके मॉड्यूल एक ऐसी साइट पर अच्छी तरह से चलें, जो सेटिंग्स में लॉग इन नहीं करता है। गलतफहमी लॉगिंग)।

इस तरह से करना आपकी बताई गई आवश्यकताओं को पूरा करता है:

  • आप विभिन्न घटनाओं के लिए अलग लॉग हैंडलर सेट कर सकते हैं, जैसा कि आप वर्तमान में करते हैं।
  • अपने मॉड्यूल में लॉगर्स के लिए आसान पहुंच - उपयोग getLogger(__name__)
  • आसानी से कमांड लाइन मॉड्यूल के लिए लागू - वे भी आयात करते हैं settings.py

अद्यतन: ध्यान दें कि संस्करण 1.3 के रूप में, Django अब लॉगिंग के लिए समर्थन शामिल करता है


क्या इसके लिए यह आवश्यक नहीं है कि हर मॉड्यूल में एक हैंडलर परिभाषित हो (आप foo.bar को संभालने के लिए foo के लिए हैंडलर का उपयोग नहीं कर सकते हैं)? वार्तालाप देखें जो हमने वर्षों पहले समूहों में किया
andrew cooke

1
@andrew cooke: आप लॉग इन की गई घटनाओं को संभालने के लिए हैंडलर का उपयोग कर सकते हैं । पुन। उस थ्रेड - दोनों fileConfig और dictConfig के पास अब पुराने लॉगर को अक्षम करने से रोकने के लिए विकल्प हैं। इस मुद्दे को देखें: bugs.python.org/issue3136 , जो आपके मुद्दे के बाद कुछ महीनों में आया था Bugs.python.org/issue2697 - वैसे भी, इसे जून 2008 से सुलझा लिया गया है।foofoo.bar
विनय साजिप

यह करना बेहतर नहीं होगा कि लॉगर को पहले से जोड़े गए null_handler से logger = someutils.getLogger(__name__)कहाँ someutils.getLoggerलौटाया logging.getLoggerजाए?
7yl4r

1
@ 7yl4r आपको अपने पैकेज पदानुक्रम के लिए आमतौर पर सिर्फ शीर्ष स्तर के लकड़हारे को जोड़ने वाले प्रत्येक लकड़हारे की आवश्यकता नहीं है NullHandler। तो वह ओवरकिल, IMO होगा।
विनय साजिप

122

मुझे पता है कि यह पहले से ही हल किया हुआ उत्तर है, लेकिन django> = 1.3 के अनुसार एक नई लॉगिंग सेटिंग है।

पुराने से नए में जाना स्वचालित नहीं है, इसलिए मैंने सोचा कि मैं इसे यहाँ लिखूंगा।

और निश्चित रूप से कुछ और के लिए django डॉक्टर चेकआउट करें

यह मूल अंतर है, जो डिफ़ॉल्ट रूप से django-admin createproject v1.3 के साथ बनाया गया है - माइलेज नवीनतम dalango संस्करणों के साथ बदल सकता है:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'mail_admins': {
            'level': 'ERROR',
            'class': 'django.utils.log.AdminEmailHandler',
        }
    },
    'loggers': {
        'django.request': {
            'handlers': ['mail_admins'],
            'level': 'ERROR',
            'propagate': True,
        }
    }
}

यह संरचना मानक अजगर लॉगिंग तानाशाह पर आधारित है , जो निम्न ब्लॉकों को निर्धारित करता है:

  • formatters - संबंधित मूल्य एक तानाशाही होगी जिसमें प्रत्येक कुंजी एक फॉर्मेटर आईडी है और प्रत्येक मूल्य एक तानाशाह है जो वर्णन करता है कि संबंधित टेम्पलेट को कैसे कॉन्फ़िगर किया जाए।
  • filters - संबंधित मूल्य एक तानाशाही होगी जिसमें प्रत्येक कुंजी एक फिल्टर आईडी है और प्रत्येक मान एक वर्णन है कि संबंधित फ़िल्टर आवृत्ति को कैसे कॉन्फ़िगर किया जाए।
  • handlers- संबंधित मूल्य एक तानाशाही होगी जिसमें प्रत्येक कुंजी एक हैंडलर आईडी होती है और प्रत्येक मान एक विवरणात्मक वर्णन होता है कि संबंधित हैंडेड आवृत्ति को कैसे कॉन्फ़िगर किया जाए। प्रत्येक हैंडलर में निम्नलिखित कुंजियाँ होती हैं:

    • class(अनिवार्य)। यह हैंडलर वर्ग का पूरी तरह से योग्य नाम है।
    • level(वैकल्पिक)। हैंडलर का स्तर।
    • formatter(वैकल्पिक)। इस हैंडलर के लिए फ़ॉर्मेटर की आईडी।
    • filters(वैकल्पिक)। इस हैंडलर के लिए फिल्टर की आईडी की एक सूची।

मैं आमतौर पर कम से कम यह करता हूं:

  • एक .log फ़ाइल जोड़ें
  • इस लॉग में लिखने के लिए मेरे ऐप्स कॉन्फ़िगर करें

जो इसमें अनुवाद करता है:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
        },
        'simple': {
            'format': '%(levelname)s %(message)s'
        },
    },
    'filters': {
        'require_debug_false': {
            '()': 'django.utils.log.RequireDebugFalse'
        }
    },
    'handlers': {
        'null': {
            'level':'DEBUG',
            'class':'django.utils.log.NullHandler',
        },
        'console':{
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
            'formatter': 'simple'
        },
        # I always add this handler to facilitate separating loggings
        'log_file':{
            'level': 'DEBUG',
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': os.path.join(VAR_ROOT, 'logs/django.log'),
            'maxBytes': '16777216', # 16megabytes
            'formatter': 'verbose'
        },
        'mail_admins': {
            'level': 'ERROR',
            'filters': ['require_debug_false'],
            'class': 'django.utils.log.AdminEmailHandler',
            'include_html': True,
        }
    },
    'loggers': {
        'django.request': {
            'handlers': ['mail_admins'],
            'level': 'ERROR',
            'propagate': True,
        },
        'apps': { # I keep all my of apps under 'apps' folder, but you can also add them one by one, and this depends on how your virtualenv/paths are set
            'handlers': ['log_file'],
            'level': 'INFO',
            'propagate': True,
        },
    },
    # you can also shortcut 'loggers' and just configure logging for EVERYTHING at once
    'root': {
        'handlers': ['console', 'mail_admins'],
        'level': 'INFO'
    },
}

संपादित करें

अनुरोध देखें अपवाद अब हमेशा लॉग इन होते हैं और टिकट # 16288 :

मैंने उपर्युक्त नमूने के अद्यतन को स्पष्ट रूप से mail_admins के लिए सही फ़िल्टर शामिल किया है ताकि डिफ़ॉल्ट रूप से, जब डिबग सत्य हो तो ईमेल नहीं भेजे जाएं।

आपको एक फ़िल्टर जोड़ना चाहिए:

'filters': {
    'require_debug_false': {
        '()': 'django.utils.log.RequireDebugFalse'
    }
},

और इसे mail_admins हैंडलर पर लागू करें:

    'mail_admins': {
        'level': 'ERROR',
        'filters': ['require_debug_false'],
        'class': 'django.utils.log.AdminEmailHandler',
        'include_html': True,
    }

अन्यथा django.core.handers.base.handle_uncaught_exceptionसेटिंग्स'BJU 'सही है, तो' django.request 'लकड़हारे के लिए त्रुटियों को पारित नहीं करता है।

यदि आप Django 1.5 में ऐसा नहीं करते हैं तो आपको एक मिल जाएगा

DeprecationWarning: आपके पास 'mail_admins' लॉगिंग हैंडलर पर परिभाषित कोई फ़िल्टर नहीं है: निहित डिबग-झूठी-केवल फ़िल्टर जोड़ना

लेकिन चीजें अभी भी सही तरीके से काम करेगी django 1.4 और django 1.5 में।

** अंत संपादित करें **

यह मान django doc में नमूना कॉन्फिडेंस से दृढ़ता से प्रेरित है, लेकिन लॉग फ़ाइल भाग को जोड़ रहा है।

मैं अक्सर निम्नलिखित कार्य भी करता हूं:

LOG_LEVEL = 'DEBUG' if DEBUG else 'INFO'

...
    'level': LOG_LEVEL
...

तब मेरे अजगर कोड में मैं हमेशा एक NullHandler जोड़ देता हूं यदि कोई लॉगिंग कॉन्फिडेंस परिभाषित नहीं होता है। यह निर्दिष्ट नहीं हैंडलर के लिए चेतावनी से बचें। विशेष रूप से उन कामों के लिए उपयोगी जो केवल Django ( रेफ ) में जरूरी नहीं हैं

import logging
# Get an instance of a logger
logger = logging.getLogger(__name__)
class NullHandler(logging.Handler): #exists in python 3.1
    def emit(self, record):
        pass
nullhandler = logger.addHandler(NullHandler())

# here you can also add some local logger should you want: to stdout with streamhandler, or to a local file...

[...]

logger.warning('etc.etc.')

उम्मीद है की यह मदद करेगा!


स्टेफानो, विस्तृत उत्तर के लिए बहुत धन्यवाद, बहुत उपयोगी। इसके साथ यह 1.3 के लिए सार्थक उन्नयन कर सकता है।
परांद

Parand, यह निश्चित रूप से है (IMHO!) Django 1.3 के लिए कदम बढ़ाने के लायक है, हालांकि एक चिकनी संक्रमण की देखभाल के लिए कुछ बिंदु हैं - मुसीबत में आने पर एक नया SO प्रश्न खोलें ;-)
Stefano

वैसे: मैं अभी भी इस तरह की सेटिंग्स और फ़ाइल लॉग का उपयोग करता हूं, लेकिन मैं उत्पादन के लिए संतरी में चला गया !
स्टेफानो

@ अच्छी तरह से मैंने इसे उत्तर में ही समझाने की कोशिश की: यदि कोई लॉगिंग कॉन्फिडेंस परिभाषित नहीं किया गया है। यह निर्दिष्ट नहीं हैंडलर के लिए चेतावनी से बचें। विशेष रूप से उन कामों के लिए उपयोगी है जो केवल Django (रेफ) में नहीं कहा जाता है
स्टीफनो

मैं नहीं देखता कि आप इस परिभाषा का उपयोग कैसे करते हैं: 'null': {'level': 'DEBUG', 'class': 'django.utils.log.NullHandler',}
clime

9

हम urls.pyएक logging.iniफ़ाइल का उपयोग करके शीर्ष-स्तर में लॉगिंग को इनिशियलाइज़ करते हैं।

में का स्थान logging.iniप्रदान किया गया है settings.py, लेकिन यह सब है।

प्रत्येक मॉड्यूल तब करता है

logger = logging.getLogger(__name__)

परीक्षण, विकास और उत्पादन उदाहरणों को अलग करने के लिए, हमारे पास अलग-अलग लॉगिंग.इन फाइलें हैं। अधिकांश भाग के लिए, हमारे पास एक "कंसोल लॉग" है जो केवल एरर के साथ स्टडर पर जाता है। हमारे पास एक "एप्लिकेशन लॉग" है जो एक नियमित रोलिंग लॉग फ़ाइल का उपयोग करता है जो लॉग निर्देशिका में जाता है।


मैंने इसका उपयोग करना समाप्त कर दिया, इसके अलावा urls.py के बजाय settings.py में शुरू करने के अलावा
Parand

आप अपनी लॉगिंग.ini फ़ाइल में settings.py से सेटिंग का उपयोग कैसे करते हैं? उदाहरण के लिए, मुझे BASE_DIR सेटिंग की आवश्यकता है, इसलिए मैं यह बता सकता हूं कि मुझे अपनी लॉग फ़ाइलों को कहां संग्रहीत करना है।
slypete

@slypete: हम logging.ini में सेटिंग्स का उपयोग नहीं करते हैं। चूंकि लॉगिंग काफी हद तक स्वतंत्र है, इसलिए हम किसी भी Django सेटिंग का उपयोग नहीं करते हैं। हां, कुछ दोहराने की संभावना है। नहीं, यह बहुत व्यावहारिक अंतर नहीं करता है।
एस.लॉट

उस स्थिति में, मैं अपने ऐप के हर इंस्टॉलेशन में एक अलग लॉगिंग.इन फाइल करूंगा।
1

@slypete: आपके पास प्रत्येक इंस्टॉलेशन के लिए एक सेटिंग्स है। आपके पास प्रत्येक स्थापना के लिए एक लॉगिंग.इन भी है। इसके अलावा, आप शायद प्रत्येक स्थापना के लिए एक अपाचे conf फ़ाइल है, भी। प्लस एक wsgi इंटरफ़ेस फ़ाइल। मुझे यकीन नहीं है कि आपकी बात क्या है।
S.Lott

6

मैं वर्तमान में एक लॉगिंग सिस्टम का उपयोग कर रहा हूं, जिसे मैंने खुद बनाया है। यह लॉगिंग के लिए CSV प्रारूप का उपयोग करता है।

Django-csvlog

इस परियोजना में अभी भी पूर्ण प्रलेखन नहीं है, लेकिन मैं इस पर काम कर रहा हूं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.