簡體   English   中英

Django中Python登錄的優雅設置

[英]Elegant setup of Python logging in Django

我還沒有找到一種用Django設置Python日志的方法,我很滿意。 我的要求很簡單:

  • 針對不同事件的不同日志處理程序 - 也就是說,我希望能夠記錄到不同的文件
  • 輕松訪問模塊中的記錄器。 該模塊應該能夠輕松找到它的記錄器。
  • 應該很容易適用於命令行模塊。 系統的某些部分是獨立的命令行或守護程序進程。 使用這些模塊可以輕松使用日志記錄。

我目前的設置是使用logging.conf文件並在我記錄的每個模塊中設置日志記錄。 感覺不對勁。

你有自己喜歡的日志設置嗎? 請詳細說明:如何設置配置(使用logging.conf或在代碼中設置),何時/何時啟動記錄器,以及如何在模塊中訪問它們等。

我知道這已經是一個已經解決的答案,但是根據django> = 1.3,有一個新的日志記錄設置。

從舊到新是不自動的,所以我想我會在這里寫下來。

當然,請查看django doc以獲取更多信息。

這是基本的conf,默認使用django-admin createproject v1.3創建 - 里程可能會隨着最新的django版本而改變:

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

此結構基於標准Python日志記錄dictConfig ,它指示以下塊:

  • formatters - 相應的值將是一個dict,其中每個鍵是一個格式化程序ID,每個值都是一個描述如何配置相應的Formatter實例的字典。
  • filters - 相應的值將是一個dict,其中每個鍵都是一個過濾器ID,每個值都是一個描述如何配置相應Filter實例的dict。
  • handlers - 相應的值將是一個dict,其中每個鍵是一個處理程序ID,每個值都是一個描述如何配置相應的Handler實例的dict。 每個處理程序都有以下鍵:

    • class (強制性)。 這是處理程序類的完全限定名稱。
    • level (可選)。 處理程序的級別。
    • formatter (可選)。 此處理程序的格式化程序的ID。
    • filters (可選)。 此處理程序的過濾器的ID列表。

我通常至少這樣做:

  • 添加.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

我更新了上面的示例conf以明確包含mail_admins的正確過濾器,以便默認情況下,當debug為True時不會發送電子郵件。

你應該添加一個過濾器:

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

否則,如果settings.DEBUG為True,則django.core.handers.base.handle_uncaught_exception不會將錯誤傳遞給'django.request'記錄器。

如果你不在Django 1.5中這樣做,你會得到一個

棄用警告:您沒有在'mail_admins'日志記錄處理程序上定義過濾器:添加隱式debug-false-only過濾器

但事情仍然可以在django 1.4和django 1.5中正常工作。

**結束編輯**

這個conf受到django doc中示例conf的強烈啟發,但添加了日志文件部分。

我經常也做以下事情:

LOG_LEVEL = 'DEBUG' if DEBUG else 'INFO'

...
    'level': LOG_LEVEL
...

然后在我的python代碼中,我總是添加一個NullHandler,以防無法定義任何記錄conf。 這避免了沒有指定Handler的警告。 對於不一定只在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.')

希望這可以幫助!

到目前為止,我發現的最好的方法是初始化settings.py中的日志記錄設置 - 其他地方。 您可以使用配置文件,也可以逐步編程 - 這只取決於您的要求。 關鍵是我通常會將我想要的處理程序添加到根記錄程序,使用級別,有時還使用logging.Filters來獲取我想要的事件到相應的文件,控制台,系統日志等。您當然可以將處理程序添加到任何其他記錄器同樣,但根據我的經驗,通常不需要這樣做。

在每個模塊中,我使用定義記錄器

logger = logging.getLogger(__name__)

並使用它來記錄模塊中的事件(如果我想進一步區分),請使用一個記錄器,它是上面創建的記錄器的子代。

如果我的應用程序可能會在未配置settings.py中的日志記錄的站點中使用,我會在某處定義NullHandler,如下所示:

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

這樣做是為了確保您的模塊在沒有配置settings.py中的日志記錄的站點中很好地運行,並且您沒有得到任何惱人的“無法找到記錄器XYZ的處理程序”消息(這是關於潛在的警告錯誤配置的日志記錄)。

這樣做可以滿足您的要求:

  • 您可以像現在一樣為不同的事件設置不同的日志處理程序。
  • 輕松訪問模塊中的記錄器 - 使用getLogger(__name__)
  • 易於應用於命令行模塊 - 它們還可以導入settings.py

更新:請注意,從版本1.3開始,Django現在包含對日志記錄的支持

我們使用logging.ini文件初始化頂級urls.py中的日志記錄。

logging.ini的位置在settings.py提供,但這就是全部。

然后每個模塊都可以

logger = logging.getLogger(__name__)

為了區分測試,開發和生產實例,我們有不同的logging.ini文件。 在大多數情況下,我們有一個“控制台日志”,僅帶有錯誤的stderr。 我們有一個“應用程序日志”,它使用一個轉到日志目錄的常規滾動日志文件。

我目前正在使用我自己創建的日志系統。 它使用CSV格式進行日志記錄。

Django的csvlog

這個項目仍然沒有完整的文檔,但我正在努力。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM