Django'da zarif Python günlüğü kurulumu


101

Django ile mutlu olduğum Python günlüğü kurmanın bir yolunu henüz bulamadım. Gereksinimlerim oldukça basit:

  • Farklı etkinlikler için farklı günlük işleyicileri - yani farklı dosyalara giriş yapabilmek istiyorum
  • Modüllerimdeki kaydedicilere kolay erişim. Modül, kaydedicisini çok az çabayla bulabilmelidir.
  • Komut satırı modüllerine kolayca uygulanabilir olmalıdır. Sistemin parçaları, bağımsız komut satırı veya arka plan programı süreçleridir. Loglama bu modüller ile kolaylıkla kullanılabilmelidir.

Mevcut kurulumum, logging.confoturum açtığım her modülde bir dosya ve kurulum günlüğü kullanmaktır . Doğru hissettirmiyor.

Beğendiğiniz bir günlük kaydı kurulumunuz var mı? Lütfen detaylandırın: Yapılandırmayı nasıl kurarsınız ( logging.confkodda kullanır veya kurar mısınız), kaydedicileri nerede / ne zaman başlatırsınız ve modüllerinizde bunlara nasıl erişirsiniz vb.


1
Aşağıdaki ekran video kaydını yararlı bulabilirsiniz - ericholscher.com/blog/2008/aug/29/… . Ayrıca, Django'da oturum açmak için daha iyi destek Simon Willison tarafından önerilmiştir (bkz. Simonwillison.net/2009/Sep/28/ponies ).
Dominic Rodger

@Dominic Rodger - Simon'ın ağırlıklı olarak Django dahili dosyalarında günlük kaydını kolaylaştırma önerisi olan Django'da uygulamaların esnek günlük kaydını zaten yapabilirsiniz. Python'da, Django'nun yararlanabileceği Python günlüğüne sözlük tabanlı konfigürasyon eklemek için çalışmalar var.
Vinay Sajip

Yanıtlar:


58

Şimdiye kadar bulduğum en iyi yol, başka hiçbir yerde settings.py'de günlük kaydı kurulumunu başlatmaktır. Ya bir yapılandırma dosyası kullanabilir ya da bunu programlı olarak adım adım yapabilirsiniz - bu sadece gereksinimlerinize bağlıdır. Önemli olan, genellikle istediğim işleyicileri seviyeleri kullanarak ve bazen de günlük kaydı yaparak root logger'a eklememdir.İstediğim olayları uygun dosyalara, konsola, sistem günlüklerine vb. Almak için filtreler. ama benim deneyimime göre buna genel olarak bir ihtiyaç yok.

Her modülde, bir logger tanımlıyorum.

logger = logging.getLogger(__name__)

ve bunu modüldeki olayları günlüğe kaydetmek için kullanın (ve daha fazla ayırt etmek istersem) yukarıda oluşturulan günlükçünün çocuğu olan bir günlükleyici kullanın.

Uygulamam, settings.py'de oturum açmayı yapılandırmayan bir sitede potansiyel olarak kullanılacaksa, aşağıdaki gibi bir yerde bir NullHandler tanımlıyorum:

#someutils.py

class NullHandler(logging.Handler):
    def emit(self, record):
        pass

null_handler = NullHandler()

ve günlük kaydı kullanan uygulamalarımdaki modüllerde oluşturulan tüm kaydedicilere bir örneğinin eklendiğinden emin olun. (Not: NullHandler zaten Python 3.1 için günlük kaydı paketinde ve Python 2.7'de olacak.) Yani:

logger = logging.getLogger(__name__)
logger.addHandler(someutils.null_handler)

Bu, modüllerinizin settings.py'de oturum açmayı yapılandırmayan bir sitede güzel bir şekilde oynamasını ve can sıkıcı "XYZ kaydedici XYZ için hiçbir işleyici bulunamadı" mesajları (potansiyel olarak uyarılar olan yanlış yapılandırılmış günlük kaydı).

Bu şekilde yapmak, belirtilen gereksinimlerinizi karşılar:

  • Şu anda yaptığınız gibi, farklı olaylar için farklı günlük işleyicileri ayarlayabilirsiniz.
  • Modüllerinizdeki kaydedicilere kolay erişim - kullanın getLogger(__name__).
  • Komut satırı modüllerine kolayca uygulanabilir - ayrıca içe aktarılırlar settings.py.

Güncelleme: 1.3 sürümünden itibaren Django'nun artık günlük kaydı desteği içerdiğini unutmayın .


Bu, her modülün yapılandırmada tanımlanmış bir işleyiciye sahip olmasını gerektirmez mi (foo.bar'ı işlemek için foo için bir işleyici kullanamazsınız)? Yıllar önce groups.google.com/group/comp.lang.python/browse_thread/thread/… adresinde
andrew cooke

1
@ Andrew cooke: Sen edebilirsiniz için bir işleyici kullanmak foosap olayları günlüğe kadar foo.bar. Yeniden. bu iş parçacığı - hem fileConfig hem de dictConfig artık eski günlükçülerin devre dışı bırakılmasını önlemek için seçeneklere sahiptir. Şu soruna bakın: bugs.python.org/issue3136 , sorununuzdan birkaç ay sonra gelen bugs.python.org/issue2697 - her neyse, Haziran 2008'den beri
çözüldü

zaten eklenmiş bir null_handler ile günlükçüyü logger = someutils.getLogger(__name__)nereden someutils.getLoggerdöndürdüğünü yapmak daha iyi olmaz logging.getLoggermı?
7yl4r

1
@ 7yl4r Her kaydedicinin bir NullHandlereklenmesi gerekmez - genellikle paket hiyerarşiniz için yalnızca en üst düzey kaydedicidir. Yani bu fazla olur, IMO.
Vinay Sajip

123

Bunun zaten çözülmüş bir cevap olduğunu biliyorum, ancak django> = 1.3'e göre yeni bir kayıt ayarı var.

Eskiden yeniye geçmek otomatik değildir, bu yüzden buraya yazacağımı düşündüm.

Ve elbette biraz daha fazlası için django belgesine bakın.

Bu, django-admin createproject v1.3 ile varsayılan olarak oluşturulan temel yapılandırmadır - kilometre, en son django sürümleriyle değişebilir:

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

Bu yapı, aşağıdaki blokları dikte eden standart Python günlük kaydı dictConfig'e dayanmaktadır :

  • formatters - karşılık gelen değer, her anahtarın bir biçimlendirici kimliği ve her bir değerin karşılık gelen Biçimlendirici örneğinin nasıl yapılandırılacağını açıklayan bir dikte olacaktır.
  • filters - karşılık gelen değer, her anahtarın bir filtre kimliği ve her bir değerin karşılık gelen Filtre örneğinin nasıl yapılandırılacağını açıklayan bir kural olduğu bir kural olacaktır.
  • handlers- karşılık gelen değer, her anahtarın bir işleyici kimliği ve her bir değerin karşılık gelen İşleyici örneğinin nasıl yapılandırılacağını açıklayan bir kural olduğu bir kural olacaktır. Her işleyicide aşağıdaki anahtarlar bulunur:

    • class(zorunlu). Bu, işleyici sınıfının tam nitelikli adıdır.
    • level(isteğe bağlı). İşleyicinin seviyesi.
    • formatter(isteğe bağlı). Bu işleyici için biçimlendiricinin kimliği.
    • filters(isteğe bağlı). Bu işleyici için filtrelerin kimliklerinin listesi.

Genellikle en azından şunu yapıyorum:

  • .log dosyası ekle
  • uygulamalarımı bu günlüğe yazacak şekilde yapılandır

Bunun anlamı:

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

Düzenle

İstisnaları görün artık her zaman günlüğe kaydedilir ve Bilet # 16288 :

Yukarıdaki örnek conf'i mail_admins için doğru filtreyi açıkça içerecek şekilde güncelledim, böylece hata ayıklama True olduğunda e-postalar varsayılan olarak gönderilmez.

Bir filtre eklemelisiniz:

'filters': {
    'require_debug_false': {
        '()': 'django.utils.log.RequireDebugFalse'
    }
},

ve bunu mail_admins işleyicisine uygulayın:

    'mail_admins': {
        'level': 'ERROR',
        'filters': ['require_debug_false'],
        'class': 'django.utils.log.AdminEmailHandler',
        'include_html': True,
    }

Aksi takdirde django.core.handers.base.handle_uncaught_exceptionsettings.DEBUG True ise hataları 'django.request' günlükçüsüne iletmez.

Bunu Django 1.5'te yapmazsanız, bir

Kullanımdan kaldırma Uyarı: 'mail_admins' günlük işleyicisinde tanımlanmış hiçbir filtre yok: örtük hata ayıklama yalnızca yanlış filtre ekleme

ancak her şey yine de django 1.4 ve django 1.5'te düzgün çalışacaktır.

** düzenlemeyi bitir **

Bu conf, django belgesindeki örnek conf'den esinlenmiştir, ancak günlük dosyası kısmı eklenir.

Sık sık şunları da yaparım:

LOG_LEVEL = 'DEBUG' if DEBUG else 'INFO'

...
    'level': LOG_LEVEL
...

Daha sonra python kodumda, herhangi bir günlüğe kaydetme conf tanımlanmaması durumunda her zaman bir NullHandler eklerim. Bu, hiçbir İşleyici belirtilmemiş için uyarıları önler. Özellikle sadece Django'da çağrılması gerekmeyen kitaplıklar için kullanışlıdır ( ref )

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.')

Bu yardımcı olur umarım!


Stefano, detaylı cevap için çok teşekkürler, çok yardımcı oldu. Bu, 1.3'e yükseltmeyi değerli kılabilir.
Parand

Parand, kesinlikle (IMHO!) Django 1.3'e geçmeye değer, ancak sorunsuz bir geçiş için dikkat etmeniz gereken birkaç nokta var - başınız belaya girerse yeni bir SO sorusu açın ;-)
Stefano

bu arada: Hala bu tür ayarları ve dosya günlüğünü kullanıyorum, ancak üretim için nöbetçiye geçtim !
Stefano

@clime well Bunu cevabın kendisinde açıklamaya çalıştım: herhangi bir günlüğe kaydetme conf tanımlanmamışsa. Bu, hiçbir İşleyici belirtilmemiş için uyarıları önler. Özellikle sadece Django'da çağrılması gerekmeyen kitaplıklar için kullanışlıdır (ref)
Stefano

'Nullunkine: { 'django.utils.log.NullHandler', 'seviye': 'DEBUG', 'sınıf'} Sana bu tanım nasıl kullandıklarını görmüyorum
clime

9

urls.pyBir logging.inidosya kullanarak en üst düzeyde günlük kaydını başlatıyoruz .

Yeri logging.inisağlanır settings.py, ama hepsi bu.

Her modül daha sonra

logger = logging.getLogger(__name__)

Test, geliştirme ve üretim örneklerini ayırt etmek için farklı logging.ini dosyalarımız var. Çoğunlukla, sadece Hatalarla stderr'e giden bir "konsol günlüğümüz" var. Bir günlükler dizinine giden normal bir kayan günlük dosyası kullanan bir "uygulama günlüğümüz" var.



Logging.ini dosyanızdaki settings.py'deki ayarları nasıl kullanıyorsunuz? Örneğin, günlük dosyalarımı nerede saklayacağımı söyleyebilmek için BASE_DIR ayarına ihtiyacım var.
slypete

@slypete: logging.ini içindeki ayarları kullanmıyoruz. Günlük kaydı büyük ölçüde bağımsız olduğundan, Django ayarlarının hiçbirini kullanmıyoruz. Evet, bir şeyi tekrar etme olasılığı var. Hayır, pek pratik bir fark yaratmaz.
S.Lott

Bu durumda, uygulamamın her kurulumunda ayrı bir logging.ini dosyası olurum.
slypete

@slypete: Her kurulum için bir settings.py var. Ayrıca her kurulum için bir logging.ini dosyanız da vardır. Ayrıca, muhtemelen her kurulum için bir Apache conf dosyanız da vardır. Artı bir wsgi arayüz dosyası. Ne demek istediğinden emin değilim.
S.Lott

6

Şu anda kendim oluşturduğum bir kayıt sistemi kullanıyorum. Günlük kaydı için CSV formatını kullanır.

django-csvlog

Bu proje hala tam belgelere sahip değil, ancak üzerinde çalışıyorum.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.