2012-11-13 18 views
56

मैं Django के साथ काम कर रहे सेलेरी लॉगिंग प्राप्त करने का प्रयास कर रहा हूं। मैंने कंसोल पर जाने के लिए settings.py में सेट-अप लॉगिंग किया है (जो ठीक काम करता है क्योंकि मैं Heroku पर होस्ट कर रहा हूं)। प्रत्येक मॉड्यूल के शीर्ष पर, मेरे पास है:Django Celery लॉगिंग सर्वश्रेष्ठ अभ्यास

import logging 
logger = logging.getLogger(__name__) 

और मेरे tasks.py में, मेरे पास है:

from celery.utils.log import get_task_logger 
logger = get_task_logger(__name__) 

कि किसी कार्य से प्रवेश कॉल के लिए ठीक काम करता है और मैं इस तरह उत्पादन मिलता है:

2012-11-13T18:05:38+00:00 app[worker.1]: [2012-11-13 18:05:38,527: INFO/PoolWorker-2] Syc feed is starting 

लेकिन यदि वह कार्य तब किसी अन्य मॉड्यूल में एक विधि को कॉल करता है, उदाहरण के लिए queryset विधि, मुझे डुप्लिकेट लॉग प्रविष्टियां मिलती हैं, उदा।

2012-11-13T18:00:51+00:00 app[worker.1]: [INFO] utils.generic_importers.ftp_processor process(): File xxx.csv already imported. Not downloaded 
2012-11-13T18:00:51+00:00 app[worker.1]: [2012-11-13 18:00:51,736: INFO/PoolWorker-6] File xxx.csv already imported. Not downloaded 

मुझे लगता है कि मैं इस्तेमाल कर सकते हैं

CELERY_HIJACK_ROOT_LOGGER = False 

सिर्फ Django लॉगिंग उपयोग करने के लिए, लेकिन यह काम नहीं किया, जब मैं इसे करने की कोशिश और यहां तक ​​कि अगर मैं यह काम करने के लिए मिलता था, मैं "PoolWorker-6" खो देगा थोड़ा जो मैं चाहता हूँ। (संयोग से, मैं यह नहीं समझ सकता कि सेलेरी से लॉग एंट्री में कार्य नाम को कैसे प्रदर्शित किया जाए, क्योंकि the docs इंगित करता है कि यह होना चाहिए)।

मुझे संदेह है कि मुझे यहां कुछ आसान याद आ रहा है।

+0

संबंधित: [अजवाइन और अजगर के कार्यों के अंदर प्रवेश] (http://stackoverflow.com/questions/6192265) –

+1

मैंने इसे देखा। Get_task_logger() बिट स्पष्ट रूप से add.get_logger() बिट – alan

+1

करने का नया तरीका है, वास्तव में, ऐसा लगता है कि मेरा जवाब सेलेरी 3.0 के लिए पुराना है; चूंकि मैं इस समय सेलेरी का उपयोग नहीं करता क्योंकि मुझे इसके बारे में पता नहीं था। :-) –

उत्तर

66

जब आपका लॉगर "अन्य मॉड्यूल" की शुरुआत में शुरू हुआ, तो यह किसी अन्य लॉगर से लिंक होता है। जो आपके संदेशों को संभालता है। यह रूट लॉगर हो सकता है, या आमतौर पर मैं Django प्रोजेक्ट्स में देखता हूं - '' नाम के साथ लॉगर। इस मामले में मैं के रूप में आप यह मान यह काम करना चाहिए लगता है में

LOGGING = { 
    'version': 1, 
    'disable_existing_loggers': True, 
    'formatters': { 
     'simple': { 
      'format': '%(levelname)s %(message)s', 
      'datefmt': '%y %b %d, %H:%M:%S', 
      }, 
     }, 
    'handlers': { 
     'console': { 
      'level': 'DEBUG', 
      'class': 'logging.StreamHandler', 
      'formatter': 'simple' 
     }, 
     'celery': { 
      'level': 'DEBUG', 
      'class': 'logging.handlers.RotatingFileHandler', 
      'filename': 'celery.log', 
      'formatter': 'simple', 
      'maxBytes': 1024 * 1024 * 100, # 100 mb 
     }, 
    }, 
    'loggers': { 
     'celery': { 
      'handlers': ['celery', 'console'], 
      'level': 'DEBUG', 
     }, 
    } 
} 

from logging.config import dictConfig 
dictConfig(LOGGING) 

:

बेस्ट यहाँ तरह से, आपके प्रवेश config अधिभावी है।

पीएस dictConfig Python2.7 + में जोड़ा गया।

+0

के लिए कस्टम लॉगर प्रारूप मुझे लॉग फ़ाइलों की बजाय कंसोल पर जाने के लिए सेलेरी लॉगिंग की आवश्यकता है। क्या यह इस के साथ काम करेगा? – alan

+0

निश्चित रूप से, स्ट्रीमहैंडलर कंसोल पर लिखेगा। – Rustem

+0

आप लॉगफाइल का अधिकतम एनआर भी सेट कर सकते हैं , अधिकतम बाइट्स को दंड में संपत्ति के बाद जोड़ें: 'बैकअपकाउंट': 10, –

7

यह परेशान है कि सेलेरी रूट लॉगर (जो सबसे अच्छा अभ्यास नहीं है और पूरी तरह से नियंत्रित नहीं किया जा सकता है) में हस्तक्षेप करता है, लेकिन यह आपके ऐप के कस्टम लॉगर्स को किसी भी तरह से अक्षम नहीं करता है, इसलिए अपने हैंडलर नामों का उपयोग करें और परिभाषित करें सेलेरी के साथ इस मुद्दे को ठीक करने की कोशिश करने के बजाय अपने स्वयं के व्यवहार। [मैं वैसे भी अपना आवेदन लॉगिंग अलग रखना चाहता हूं)। आप Django कोड और सेलेरी कार्यों के लिए अलग हैंडलर या समान उपयोग कर सकते हैं, आपको बस उन्हें अपने Django LOGGING कॉन्फ़िगरेशन में परिभाषित करने की आवश्यकता है। मॉड्यूल, फ़ाइल नाम, और प्रक्रिया के लिए फॉर्मेटिंग तर्क जोड़ें, जो आपके व्यक्तित्व में स्वच्छता के लिए नाम है, ताकि आप कहां से उत्पन्न हो सकें।

[यह मानता है कि आपने लॉगिंग सेटिंग मान में 'yourapp' के लिए एक हैंडलर सेट किया है जो एक एपेंडर को इंगित करता है - जैसे लगता है कि आप इसके बारे में जानते हैं]।

views.py

log = logging.getLogger('yourapp') 
def view_fun(): 
    log.info('about to call a task') 
    yourtask.delay() 

tasks.py

log = logging.getLogger('yourapp') 
@task 
def yourtask(): 
    log.info('doing task') 

लॉगिंग कि अजवाइन उत्पन्न करता है के लिए - celeryd झंडे अजवाइन उत्पादन भेजने के लिए --logfile का उपयोग (जैसे, कार्यकर्ता init, कार्य शुरू कर दिया , काम विफल रहा) वांछित अगर एक अलग जगह पर।या, यहां दूसरे उत्तर का उपयोग करें जो आपके चयन की फ़ाइल में 'अजवाइन' लॉगर भेजता है।

नोट: मैं RotatingFileHandlers का उपयोग नहीं करता - वे बहु-प्रक्रिया ऐप्स के लिए समर्थित नहीं हैं। लॉग्रोटेट जैसे किसी अन्य टूल से लॉग रोटेशन सुरक्षित है, वही है जो Django से लॉगिंग के साथ जाता है मानते हैं कि आपके पास कई प्रक्रियाएं हैं, या उसी लॉग फ़ाइलों को सेलेरी श्रमिकों के साथ साझा किया जाता है। यदि आप एक बहु-सर्वर समाधान का उपयोग कर रहे हैं तो शायद आप कहीं भी केंद्रीकृत लॉगिंग करना चाहते हैं।

+0

सेलेरी लॉगिंग संदेशों के साथ कार्य नाम लॉग करना है। क्या यह काम करने का कोई तरीका है? तो एक लॉग संदेश fr ओम एक और मॉड्यूल में लॉग संदेश में "yourtask" शामिल होगा यदि इसे "yourtask" – alan

+0

से लॉग किया गया था log.info ("कार्य आईडी% आर निष्पादित करना, तर्क:% r kwargs:% r"% ( yourtask.request.id , yourtask.request.args, yourtask.request.kwargs)) अपने कार्य फ़ंक्शन के अंदर। –

+1

कारण सेलरी रूट लॉगर में हस्तक्षेप करता है क्योंकि वहां लॉगिंग को कॉन्फ़िगर करने वाले कई तृतीय पक्ष ऐप्स/libs हैं। कई मामलों में इसका परिणाम उपयोगकर्ताओं के लिए कोई आउटपुट नहीं हुआ है। सेलेरी उपयोगकर्ताओं के पास अभी भी लॉगिंग मैन्युअल रूप से कॉन्फ़िगर करने का विकल्प है। – asksol

4

डुप्लीकेट प्रवेश समस्या को हल करने, क्या मेरे लिए काम किया जब मेरे settings.LOGGING dict की घोषणा को गलत पर स्थापित करने प्रचार स्थापित करने के लिए है

LOGGING = { 
    'version': 1, 
    'disable_existing_loggers': False, 
    'handlers': { 
     'console': { 
      'level': 'DEBUG', 
      'class': 'logging.StreamHandler', 
      'formatter': 'verbose' 
     }, 
    }, 
    'formatters': { 
     'verbose': { 
      'format': '%(asctime)s %(levelname)s module=%(module)s, ' 
      'process_id=%(process)d, %(message)s' 
     } 
    }, 
    'loggers': { 
     'my_app1': { 
      'handlers': ['console'], 
      'level': 'DEBUG', 
      'propagate': False #this will do the trick 
     }, 
     'celery': { 
      'handlers': ['console'], 
      'level': 'DEBUG', 
      'propagate': True 
     }, 
    } 
} 

मान लीजिए कि आपके Django परियोजना लेआउट लगता है:
my_project/
- functions.py
- ईमेल.py

और कहें कि आपके कार्यों में से कोई एक ईमेल EMAIL.py में कुछ फ़ंक्शन को कॉल करता है; लॉगिंग ईमेल.py में होगी और फिर लॉगिंग 'पैरेंट' को प्रचारित की जाएगी, जो इस मामले में आपका अजवाइन कार्य होता है। इस प्रकार डबल लॉगिंग। लेकिन किसी विशेष लॉगर के लिए गलत तरीके से प्रचार करने का अर्थ है कि उस लॉगर/ऐप के लिए, उसके लॉग माता-पिता को प्रचारित नहीं होंगे, इसलिए उनकी इच्छा 'डबल' लॉगिंग नहीं होगी। , शायद डिफ़ॉल्ट 'का प्रचार' तक यह सच है

पर सेट है यहाँ कि माता-पिता के बारे में link to the django docs अनुभाग है/बच्चों वालों सामान

+0

यह मेरे लिए +1 काम किया है – Montaro

संबंधित मुद्दे