2015-02-23 125 views
3

我們正在使用uWSGI來爲我們的Django應用程序提供服務。我們還利用uWSGI的mules和假脫機系統定期運行作業,並在請求/響應週期之外異步執行一些任務。uWSGI異步函數不知道Django的日誌記錄設置

的uWSGI的一部分處理HTTP請求使用Django logging configuration就好了。但是,使用uWSGI的cronmulefunc功能時,通常不會配置記錄器 - 您將調用log.error(),異常就會消失。我們發現了一個奇怪的解決方法,我將在下面解釋。

這是我們的日誌記錄設置,在settings.py。 StreamHandler默認路由到stderr,所以我們應該看到DEBUG級別和更高級別的任何日誌路由到stderr。

 
LOGGING = { 
    'version': 1, 
    'disable_existing_loggers': True, 
    'formatters': { 
     'verbose': { 
      'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s' 
     }, 
    }, 
    'handlers': { 
     'console': { 
      'level': 'DEBUG', 
      'class': 'logging.StreamHandler', 
      'formatter': 'verbose' 
     } 
    }, 
    'loggers': { 
     '': { 
      'handlers': ['console'], 
      'level': 'NOTSET', 
     } 
    } 
} 

這裏有什麼行不通的例子:

 
from uwsgidecorators import mulefunc 

log = logging.getLogger(__name__) 

@timer(10, target="mule") 
def test_mule_logging(signum): 
    log.error("You'll never see this message") 

然而,有一個很奇怪的解決方法。如果你導入Django的設置,並且訪問它上面的一個鍵,那麼這個記錄器會神奇地工作。例如:

 
from django.conf import settings 
getattr(settings, "doesntmatter", None) 

from uwsgidecorators import timer 
import logging 

log = logging.getLogger(__name__) 

@timer(10, target="mule") 
def test_mule_logging(signum): 
    log.error("I WILL see this log!") 

雖然這看起來像一個可怕的解決方法。

回答

0

我認爲你描述的行爲是有意義的。

在常規的工人,uwsgi加載一個WSGI應用程序,使Django的負載設置,並作爲該部分配置全局的Python日誌系統。由django應用程序運行幷包含日誌記錄語句的庫代碼最終由日誌記錄配置處理(而不必知道django是否存在或配置了日誌記錄系統)。

在騾子,uwsgi只運行你給它的代碼,而不是正式工定義的WSGI模塊/腳本,所以沒有什麼是配置日誌系統。騾子仍然是相同的環境(UID,GID,CHDIR,virtualenv中,PYTHONPATH,ENV瓦爾像DJANGO_SETTINGS_MODULE)內運行,因此調用django.setup()(或django.configure_settings)將導入您的設置,並配置全球記錄系統(全球到Python的過程,是騾工),修理您的日誌記錄呼叫。

最後一塊拼圖:django.conf.settings模塊是一個特殊的懶惰對象,因此它可以在django完成自我配置之前通過各種模塊導入,並推遲真正加載設置,直到嘗試訪問模塊屬性爲止。在現代Django版本中可以更加明確地獲得這種行爲,其中django.setup()