Så här konfigurerar och använder du loggning¶
Django tillhandahåller en fungerande :ref:``standardkonfiguration för loggning <default-logging-configuration>` som lätt kan utökas.
Ringa ett grundläggande loggningssamtal¶
Om du vill skicka ett loggmeddelande från din kod placerar du ett loggningsanrop i den.
Låt dig inte frestas att använda loggningsanrop i settings.py
.
Det sätt på vilket Django-loggning konfigureras som en del av funktionen setup()
innebär att loggningsanrop som placeras i settings.py
kanske inte fungerar som förväntat, eftersom loggning inte kommer att konfigureras vid den tidpunkten. Om du vill utforska loggning kan du använda en view-funktion enligt exemplet nedan.
Importera först Pythons loggningsbibliotek och hämta sedan en logger-instans med logging.getLogger()
. Förse metoden getLogger()
med ett namn för att identifiera den och de poster den skickar ut. Ett bra alternativ är att använda __name__
(se Använd namnavstånd för logger nedan för mer om detta) som kommer att ge namnet på den aktuella Python-modulen som en prickad sökväg:
import logging
logger = logging.getLogger(__name__)
Det är en bra konvention att utföra denna deklaration på modulnivå.
Och sedan i en funktion, till exempel i en vy, skicka en post till loggaren:
def some_view(request):
...
if some_risky_state:
logger.warning("Platform is running at risk")
När den här koden körs kommer en LogRecord
som innehåller meddelandet att skickas till loggern. Om du använder Djangos standardkonfiguration för loggning kommer meddelandet att visas i konsolen.
Nivån WARNING
som används i exemplet ovan är en av flera logging severity levels: DEBUG
, INFO
, WARNING
, ERROR
, CRITICAL
. Så ett annat exempel kan vara:
logger.critical("Payment system is not responding")
Viktigt
Poster med en nivå lägre än VARNING
visas inte i konsolen som standard. För att ändra detta beteende krävs ytterligare konfiguration.
Anpassa konfigurationen för loggning¶
Även om Djangos loggningskonfiguration fungerar direkt, kan du styra exakt hur dina loggar skickas till olika destinationer - till loggfiler, externa tjänster, e-post och så vidare - med lite ytterligare konfiguration.
Du kan konfigurera:
loggermappningar för att bestämma vilka poster som ska skickas till vilka hanterare
handläggare, för att avgöra vad de gör med de handlingar de får
filter, för att ge ytterligare kontroll över överföringen av handlingar och till och med ändra handlingar på plats
formatters, för att konvertera
LogRecord
-objekt till en sträng eller annan form som kan användas av människor eller andra system
Det finns olika sätt att konfigurera loggning. I Django används oftast inställningen LOGGING
. Inställningen använder dictConfig-formatet, och utökar default logging configuration.
Se Konfigurera loggning för en förklaring av hur dina anpassade inställningar slås samman med Djangos standardinställningar.
Se Python logging documentation
för detaljer om andra sätt att konfigurera loggning. För enkelhetens skull kommer den här dokumentationen endast att behandla konfiguration via inställningen LOGGING
.
Grundläggande konfiguration av loggning¶
När du konfigurerar loggning är det klokt att
Skapa en LOGGING
-ordbok¶
I din `settings.py
:
LOGGING = {
"version": 1, # the dictConfig format version
"disable_existing_loggers": False, # retain the default loggers
}
Det är nästan alltid vettigt att behålla och utöka standardkonfigurationen för loggning genom att sätta disable_existing_loggers
till False
.
Konfigurera en hanterare¶
I det här exemplet konfigureras en enda hanterare med namnet file
som använder Pythons FileHandler
för att spara loggar på nivån DEBUG
och högre i filen general.log
(i projektets rot):
LOGGING = {
# ...
"handlers": {
"file": {
"class": "logging.FileHandler",
"filename": "general.log",
},
},
}
Olika hanterarklasser kräver olika konfigurationsalternativ. Mer information om tillgängliga hanterarklasser finns i AdminEmailHandler
som tillhandahålls av Django och de olika handler classes
som tillhandahålls av Python.
Loggningsnivåer kan också ställas in för hanterarna (som standard accepterar de loggmeddelanden på alla nivåer). Med hjälp av exemplet ovan kan du lägga till:
{
"class": "logging.FileHandler",
"filename": "general.log",
"level": "DEBUG",
}
skulle definiera en hanterarkonfiguration som endast accepterar poster på nivå DEBUG
och högre.
Konfigurera en loggermappning¶
Om du vill skicka poster till den här hanteraren konfigurerar du en loggermappning för att använda den, t.ex:
LOGGING = {
# ...
"loggers": {
"": {
"level": "DEBUG",
"handlers": ["file"],
},
},
}
Mappningens namn avgör vilka loggposter den kommer att bearbeta. Den här konfigurationen (''
) är onamngiven. Det innebär att den kommer att bearbeta poster från alla loggar (se Använd namnavstånd för logger nedan om hur du använder mappningsnamnet för att avgöra vilka loggar som den kommer att bearbeta poster för).
Den kommer att vidarebefordra meddelanden av nivå DEBUG
och högre till hanteraren med namnet file
.
Observera att en logger kan vidarebefordra meddelanden till flera handläggare, så relationen mellan loggar och handläggare är många-till-många.
Om du avrättar:
logger.debug("Attempting to connect to API")
i din kod, kommer du att hitta meddelandet i filen general.log
i roten av projektet.
Konfigurera en formaterare¶
Som standard innehåller den slutliga loggutmatningen meddelandedelen av varje log record
. Använd en formatterare om du vill inkludera ytterligare data. Namnge och definiera först dina formatterare - i det här exemplet definieras formatterare med namnen verbose
och simple
:
LOGGING = {
# ...
"formatters": {
"verbose": {
"format": "{name} {levelname} {asctime} {module} {process:d} {thread:d} {message}",
"style": "{",
},
"simple": {
"format": "{levelname} {message}",
"style": "{",
},
},
}
Med nyckelordet style
kan du ange {
för str.format()
eller $
för string.Template
-formatering; standard är $
.
Se LogRecord attributes för de LogRecord
-attribut som du kan inkludera.
Om du vill använda en formaterare i en hanterare lägger du till en formatter
-post i hanterarens dictionary som hänvisar till formateraren med namn, t.ex:
"handlers": {
"file": {
"class": "logging.FileHandler",
"filename": "general.log",
"formatter": "verbose",
},
}
Använd namnavstånd för logger¶
Den namnlösa loggningskonfigurationen ''
fångar upp loggar från alla Python-program. En namngiven loggningskonfiguration fångar endast loggar från loggar med matchande namn.
Namnrymden för en loggerinstans definieras med getLogger()
. Till exempel i views.py
i my_app
:
logger = logging.getLogger(__name__)
kommer att skapa en logger i namnrymden my_app.views
. med __name__
kan du automatiskt organisera loggmeddelanden enligt deras ursprung inom projektets applikationer. Det säkerställer också att du inte kommer att uppleva namnkollisioner.
En loggermappning med namnet my_app.views
kommer att samla in poster från denna logger:
LOGGING = {
# ...
"loggers": {
"my_app.views": {...},
},
}
En loggermappning med namnet my_app
är mer tillåtande och fångar upp poster från loggar var som helst inom namnrymden my_app
(inklusive my_app.views
, my_app.utils
och så vidare):
LOGGING = {
# ...
"loggers": {
"my_app": {...},
},
}
Du kan också definiera loggarnas namnavstånd explicit:
logger = logging.getLogger("project.payment")
och ställa in loggermappningar i enlighet med detta.
Användning av loggerhierarkier och spridning¶
Loggarnas namngivning är hierarkisk. my_app
är överordnad my_app.views
, som är överordnad my_app.views.private
. Om inget annat anges kommer loggermappningar att sprida de poster de bearbetar till sina föräldrar - en post från en logger i namnrymden my_app.views.private
kommer att hanteras av en mappning för både my_app
och my_app.views
.
Om du vill hantera detta beteende anger du propageringsknappen för de mappningar du definierar:
LOGGING = {
# ...
"loggers": {
"my_app": {
# ...
},
"my_app.views": {
# ...
},
"my_app.views.private": {
# ...
"propagate": False,
},
},
}
propagate
har som standard värdet True
. I det här exemplet kommer loggarna från my_app.views.private
inte att hanteras av föräldern, men det kommer loggarna från my_app.views
att göra.
Konfigurera responsiv loggning¶
Loggning är som mest användbar när den innehåller så mycket information som möjligt, men inte information som du inte behöver - och hur mycket du behöver beror på vad du gör. När du felsöker behöver du en informationsnivå som skulle vara överdriven och ohjälpsam om du var tvungen att hantera den i produktionen.
Du kan konfigurera loggningen så att den ger dig den detaljnivå du behöver, när du behöver den. I stället för att manuellt ändra konfigurationen för att uppnå detta, är det bättre att tillämpa konfigurationen automatiskt beroende på miljön.
Du kan till exempel ställa in miljövariabeln DJANGO_LOG_LEVEL
på rätt sätt i dina utvecklings- och stagingmiljöer och använda den i en loggermappning på följande sätt:
"level": os.getenv("DJANGO_LOG_LEVEL", "WARNING")
- så att om inte miljön anger en lägre loggnivå, kommer denna konfiguration endast att vidarebefordra poster med allvarlighetsgrad WARNING
och högre till sin hanterare.
Andra alternativ i konfigurationen (t.ex. alternativet level
eller formatter
för handläggare) kan hanteras på liknande sätt.