2013-05-20 56 views
16

我已成立了芹菜使用他們的系統守護進程指令(http://docs.celeryproject.org/en/latest/tutorials/daemonizing.html#daemonizing如何登錄

這裏是我的測試任務

@periodic_task(run_every=timedelta(seconds=10)) 
def debugger(): 
    logger.info("Running debugger") 
    raise Exception('Failed') 

我需要用我的Django應用程序的工作在Django芹菜任務發生的例外知道這個任務(調試器)由於異常而失敗的方法。 Celery的日誌文件打印logger.info(「運行調試器」)日誌,但它不記錄異常。我錯過了什麼,或者我應該用其他方式找到失敗的任務嗎?

+1

什麼芹菜想要什麼?我不能像桌面應用程序一樣崩潰。你可以使用兩種簡單的方法。 1.使用結果後端並將任務標記爲失敗。 2.將所有代碼包裝在芹菜中以嘗試除外。 – Rustem

+3

@Rustem我希望Celery能夠捕捉異常,並將它們寫入日誌文件,而不是顯然吞噬它們... –

回答

1

使用回溯模塊將跟蹤捕獲爲字符串並將其發送到記錄器。

try: 
    ... 
except: 
    import traceback 
    logger.info(traceback.format_exc()) 
+3

fwif,python logger可以在任何級別上包含回溯。你所要做的就是將exc_info = 1添加到呼叫中。例如 logger.info('其他東西的失敗b/c',exc_info = 1) – user2399268

6

你可以看一下Celery User Guide

from celery.utils.log import get_task_logger 

logger = get_task_logger(__name__) 

@app.task 
def div(): 
    try: 
     1/0 
    except ZeroDivisionError: 
     logger.exception("Task error") 

從文檔python logging module

Logger.exception(MSG,*參數)

在此記錄器上記錄級別爲ERROR的消息。參數解釋爲debug()。異常信息被添加到日誌消息中。該方法只能從異常處理程序調用。

+1

等一下,我希望在工作日誌中記錄一些東西,至少對於每個失敗的任務... –

3

問題:

我想芹菜捕捉異常,並寫入到一個日誌文件,而不是吞嚥顯然他們......

目前頂級爲了達到專業解決方案,這裏的答案馬馬虎虎。許多python開發人員會根據具體情況考慮總體錯誤捕獲紅旗。合理的厭惡,這是在註釋中表述清楚:

上,我認爲會有一些記錄在日誌工人,至少是,對於每一個失敗的任務

杭...

Celery確實發現了異常,它只是沒有做OP想要它做的事情(它將它存儲在結果後端)。以下要點是互聯網在這個問題上所能提供的最好的。這有點過時了,但請注意叉子和星星的數量。

https://gist.github.com/darklow/c70a8d1147f05be877c3

要點走的是失敗案例,並做一些自定義它。這是OP問題的一個超集。以下是如何在要點中調整解決方案以記錄異常。

import logging 

logger = logging.getLogger('your.desired.logger') 


class LogErrorsTask(Task): 
    def on_failure(self, exc, task_id, args, kwargs, einfo): 
     logger.exception('Celery task failure!!!1', exc_info=exc) 
     super(LogErrorsTask, self).on_failure(exc, task_id, args, kwargs, einfo) 

您仍需要確保所有的任務,從這個任務類繼承和要點顯示如何,如果你使用的@task裝飾(與base=LogErrorsTask kwarg)來做到這一點。

此解決方案的好處是不會將代碼嵌套在任何其他嘗試除外的情況下。這是抄襲芹菜已經使用的故障代碼路徑。

0

您也可以覆蓋芹菜的應用程序,以避免增加base kwarg每個@app.task裝飾:

import logging 
from celery import Celery, Task 

logger = logging.getLogger(__name__) 

class LoggingTask(Task): 
    def on_failure(self, exc, task_id, args, kwargs, einfo): 
     logger.exception('Task failed: %s' % exc, exc_info=exc) 
     super(LoggingTask, self).on_failure(exc, task_id, args, kwargs, einfo) 

class LoggingCelery(Celery): 
    def task(self, *args, **kwargs): 
     kwargs.setdefault('base', LoggingTask) 
     return super(LoggingCelery, self).task(*args, **kwargs) 

app = LoggingCelery(__name__)