本文首發於 Gevin的部落格
原文連結:基於MongoDB的python日誌功能
未經 Gevin 授權,禁止轉載
基於MongoDB的python日誌功能
我幾個月前在《Python 日誌功能詳解》中介紹了Python log模組的基本使用方法,但按照那篇文章的內容組織,還有一些東西不好放進去展開,原本打算單獨開一篇文章把剩下的事情再講明白的,結果被各種事情耽誤,一直拖到現在,只能按照現在的思路繼續展開了。本文就講一下Python log 模組與mongodb的結合。
MongoDB是專為可擴充套件性,高效能和高可用性而設計的資料庫,可以應用於各種規模的企業、各個行業以及各類應用程式,其資料模式可以隨著應用程式的發展而靈活地更新。
伺服器的日常運維通常會產生大量的日誌資訊(如錯誤、警告和使用者行為),這些日誌資訊通常是以文字格式儲存於伺服器本機的日誌檔案中。文字格式的日誌雖然具有很好的可讀性,但每次都要開啟伺服器本機檢視,使用和分析日誌比較麻煩,再結合當今微服務架構的潮流,基於本機日誌檔案的日誌儲存方式也會給開發和運維帶來不少的附加的、可避免的工作量,將日誌儲存於資料庫會可以讓使用和分析日誌的更加高效。MongoDB效能高,易於擴充套件,且schama freeness
,將日誌儲存於 MongoDB 非常合適,有不少開發者和企業都把日誌儲存於MongoDB中。
那麼,基於Python開發時,如何用MongoDB儲存日誌?
1. log4mongo-python
log4mongo-python 為Python logging 模組提供了一個 mongodb的handler,它依賴於pymongo driver,可以無縫應用到Python logging 模組,所以只要理解《Python 日誌功能詳解》中介紹的內容,log4mongo-python就能直接上手。因此本文不再贅述Python logging 模組的使用,直接提供一個參考樣例(也可以在GitHub中檢視最新版本):
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
import logging
from log4mongo.handlers import MongoHandler
logger = logging.getLogger('mongo_example')
mon = MongoHandler(host='localhost', database_name='mongo_logs')
mon.setLevel(logging.WARNING)
ch = logging.StreamHandler()
ch.setLevel(logging.ERROR)
logger.addHandler(mon)
logger.addHandler(ch)
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')複製程式碼
上面例子中,使用MongoDB儲存日誌的核心是建立了相應的handler,即下面這一行:
mon = MongoHandler(host='localhost', database_name='mongo_logs')複製程式碼
建立MongoHandler非常簡單,大部分引數都有預設值,如果想配置更多引數,直接看一下MongoHandler
的__init__
函式即可:
def __init__(self, level=logging.NOTSET, host='localhost', port=27017,
database_name='logs', collection='logs',
username=None, password=None, authentication_db='admin',
fail_silently=False, formatter=None, capped=False,
capped_max=1000, capped_size=1000000, reuse=True, **kwargs)複製程式碼
2. 通過Dict物件配置log4mongo-python
基於我個人的開發實踐,中大型專案開發中,通過Dict配置logging模組用的最多,由於log4mongo-python
只是在logging模組上增加了一個新的handler,所以Dict與《Python 日誌功能詳解》中的寫法一致,並根據實際情況賦上MongoHandler
初始化的引數值即可。舉例如下:
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
import logging
import logging.config
from log4mongo.handlers import MongoHandler
config = {
'version': 1,
'formatters': {
'simple': {
'format': '%(asctime)s - %(name)s - %(levelname)s - %(message)s',
},
},
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'level': 'DEBUG',
'formatter': 'simple'
},
'file': {
'class': 'logging.FileHandler',
'filename': 'logging.log',
'level': 'DEBUG',
'formatter': 'simple'
},
'mongo': {
'class': 'log4mongo.handlers.MongoHandler',
'host': 'localhost',
# 'port': 27017,
'database_name': 'mongo_logs2',
# 'collection': 'logs',
'level': 'DEBUG',
},
},
'loggers':{
'root': {
'handlers': ['console'],
'level': 'DEBUG',
# 'propagate': True,
},
'simple': {
'handlers': ['console', 'file'],
'level': 'WARN',
},
'mongo': {
'handlers': ['console', 'mongo'],
'level': 'DEBUG',
}
}
}
logging.config.dictConfig(config)
# print 'logger:'
# logger = logging.getLogger('root')
# logger.debug('debug message')
# logger.info('info message')
# logger.warn('warn message')
# logger.error('error message')
# logger.critical('critical message')
# print 'logger2:'
# logger2 = logging.getLogger('simple')
# logger2.debug('debug message')
# logger2.info('info message')
# logger2.warn('warn message')
# logger2.error('error message')
# logger2.critical('critical message')
print 'logger3:'
logger2 = logging.getLogger('mongo')
logger2.debug('debug message')
logger2.info('info message')
logger2.warn('warn message')
logger2.error('error message')
logger2.critical('critical message')複製程式碼
3. What's More?
基於log4mongo
將日誌資訊寫入MongoDB後,可以通過RoboMongo或MongoChef等MongoDB客戶端檢視日誌資訊,並利用各種MongoDB的資料庫查詢語言,對日誌進行分析處理。
題圖來自Logging Application Behavior to MongoDB 相關內容。