Logging
Logging
modülü, bir hesaplamanın tarihini ve ilerlemesini olayların bir kaydı olarak kaydetmenin bir yolunu sağlar. Olaylar, kaynak koda bir günlük kaydı ifadesi ekleyerek oluşturulur, örneğin:
@warn "Abandon printf debugging, all ye who enter here!"
┌ Warning: Abandon printf debugging, all ye who enter here!
└ @ Main REPL[1]:1
Sistem, println()
çağrılarıyla kaynak kodunuzu karıştırmaktan daha fazla avantaj sunar. İlk olarak, kaynak kodunu düzenlemeden mesajların görünürlüğünü ve sunumunu kontrol etmenizi sağlar. Örneğin, yukarıdaki @warn
ile karşılaştırıldığında
@debug "The sum of some values $(sum(rand(100)))"
varsayılan olarak hiçbir çıktı üretmeyecektir. Ayrıca, bu tür hata ayıklama ifadelerini kaynak kodunda bırakmak çok ucuzdur çünkü sistem, mesajın daha sonra göz ardı edileceği durumlarda değerlendirilmesini önler. Bu durumda sum(rand(100))
ve ilgili dize işleme, hata ayıklama kaydı etkinleştirilmedikçe asla yürütülmeyecektir.
İkincisi, günlükleme araçları, her olaya bir dizi anahtar-değer çifti olarak rastgele veriler eklemenize olanak tanır. Bu, yerel değişkenleri ve diğer program durumlarını daha sonraki analizler için yakalamanızı sağlar. Örneğin, yerel dizi değişkeni A
ve bir vektör v
'nin toplamını s
anahtarı olarak eklemek için şunu kullanabilirsiniz:
A = ones(Int, 4, 4)
v = ones(100)
@info "Some variables" A s=sum(v)
# output
┌ Info: Some variables
│ A =
│ 4×4 Matrix{Int64}:
│ 1 1 1 1
│ 1 1 1 1
│ 1 1 1 1
│ 1 1 1 1
└ s = 100.0
Tüm günlükleme makroları @debug
, @info
, @warn
ve @error
ortak özellikler taşır ve bu özellikler daha genel makro @logmsg
için belgelerde ayrıntılı olarak açıklanmıştır.
Log event structure
Her bir etkinlik, kullanıcının sağladığı ve otomatik olarak çıkarılan bazı veriler de dahil olmak üzere birkaç veri parçası üretir. Öncelikle kullanıcı tanımlı verileri inceleyelim:
log seviyesi, erken filtreleme için kullanılan mesajın geniş bir kategorisidir.
LogLevel
türünde birkaç standart seviye vardır; kullanıcı tanımlı seviyeler de mümkündür. Her biri amacında farklıdır:Logging.Debug
(log seviyesi -1000) programın geliştiricisi için tasarlanmış bilgilerdir. Bu olaylar varsayılan olarak devre dışıdır.Logging.Info
(log seviyesi 0) kullanıcıya genel bilgi vermek içindir. Bunu,println
kullanmanın bir alternatifi olarak düşünün.Logging.Warn
(log seviyesi 1000) bir şeylerin yanlış olduğunu ve muhtemelen bir eylem gerektirdiğini, ancak şu anda programın hala çalıştığını ifade eder.Logging.Error
(log seviyesi 2000) bir şeylerin yanlış olduğunu ve bunun, en azından bu kod parçası tarafından, kurtarılmasının pek olası olmadığını ifade eder. Genellikle bu log seviyesi gereksizdir çünkü bir istisna fırlatmak gerekli tüm bilgileri iletebilir.
mesaj bir olayı tanımlayan bir nesnedir. Gelenek gereği, mesaj olarak geçirilen
AbstractString
'lerin markdown formatında olduğu varsayılır. Diğer türler, metin tabanlı çıktı içinprint(io, obj)
veyastring(obj)
kullanılarak ve muhtemelen kurulu günlüğü kullanarak diğer multimedya görüntülemeleri içinshow(io,mime,obj)
ile görüntülenecektir.Opsiyonel anahtar–değer çiftleri, her olaya rastgele verilerin eklenmesine olanak tanır. Bazı anahtarların, bir olayın nasıl yorumlandığını etkileyebilecek geleneksel anlamları vardır (bkz.
@logmsg
).
Sistem ayrıca her etkinlik için bazı standart bilgileri de üretir:
- Genişletilen
module
günlükleme makrosunun bulunduğu. - Kaynak kodda günlükleme makrosunun gerçekleştiği
dosya
vesatır
. - Bir
id
mesajı, günlükleme makrosunun göründüğü kaynak kodu ifadesi için benzersiz, sabit bir tanımlayıcıdır. Bu tanımlayıcı, dosyanın kaynak kodu değişse bile, günlükleme ifadesi kendisi aynı kaldığı sürece oldukça kararlı olacak şekilde tasarlanmıştır. - Bir etkinlik için
grup
, varsayılan olarak dosyanın uzantısı olmadan temel adı olarak ayarlanmıştır. Bu, mesajları log seviyesinden daha ince kategorilere ayırmak için kullanılabilir (örneğin, tüm kullanım dışı uyarılar:depwarn
grubuna sahiptir) veya modüller arasında veya içinde mantıksal gruplamalar yapmak için.
Dikkat edin ki, etkinlik zamanı gibi bazı yararlı bilgiler varsayılan olarak dahil edilmemiştir. Bunun nedeni, bu tür bilgilerin çıkarılmasının maliyetli olabilmesi ve ayrıca mevcut günlüğü tutucuya dinamik olarak erişilebilir olmasıdır. Gerekli olduğunda etkinlik verilerini zaman, geri izleme, küresel değişkenlerin değerleri ve diğer yararlı bilgilerle artırmak için bir custom logger tanımlamak basittir.
Processing log events
Gördüğünüz gibi örneklerde, günlükleme ifadeleri günlük olaylarının nereye gittiği veya nasıl işlendiği hakkında hiçbir şey belirtmiyor. Bu, sistemi bileşenler halinde birleştirilebilir ve eşzamanlı kullanım için doğal hale getiren önemli bir tasarım özelliğidir. Bu, iki farklı kaygıyı ayırarak yapılır:
- Oluşturma log olayları, olayların ne zaman tetikleneceğine ve hangi bilgilerin dahil edileceğine karar vermesi gereken modül yazarının sorumluluğudur.
- Log olaylarının işlenmesi — yani, görüntüleme, filtreleme, toplama ve kaydetme — birden fazla modülü bir araya getirip işbirliği yapan bir uygulama oluşturması gereken uygulama yazarının endişesidir.
Loggers
Olayların işlenmesi bir logger tarafından gerçekleştirilir; bu, olayı gören ilk kullanıcı yapılandırılabilir kod parçasıdır. Tüm logger'lar AbstractLogger
alt türleri olmalıdır.
Bir olay tetiklendiğinde, uygun günlüğü bulmak için global günlüğü yedek olarak kullanarak görev yerel günlüğüne bakılır. Buradaki fikir, uygulama kodunun günlük olaylarının nasıl işlenmesi gerektiğini bilmesidir ve bu, çağrı yığınında bir yerde üstte bulunur. Bu nedenle, günlüğü keşfetmek için çağrı yığınına yukarı doğru bakmalıyız — yani, günlük dinamik olarak kapsamlı olmalıdır. (Bu, günlüğün sözdizimsel olarak kapsamlı olduğu günlüğü çerçeveleri ile bir karşıtlık noktasıdır; modül yazarının açıkça sağladığı veya basit bir global değişken olarak. Böyle bir sistemde, birden fazla modülden işlevsellik oluştururken günlüğü kontrol etmek zorlayıcıdır.)
Küresel günlükleyici global_logger
ile ayarlanabilir ve görev yerel günlükleyicileri with_logger
kullanılarak kontrol edilir. Yeni oluşturulan görevler, ana görevin günlükleyicisini miras alır.
Kütüphane tarafından sağlanan üç logger türü vardır. ConsoleLogger
REPL'yi başlattığınızda gördüğünüz varsayılan logger'dır. Olayları okunabilir bir metin formatında görüntüler ve biçimlendirme ve filtreleme üzerinde basit ama kullanıcı dostu bir kontrol sağlamaya çalışır. NullLogger
gerektiğinde tüm mesajları atmanın pratik bir yoludur; bu, devnull
akışının logging eşdeğeridir. SimpleLogger
ise, esasen logging sisteminin kendisini hata ayıklamak için yararlı olan çok basit bir metin biçimlendirme logger'dır.
Özel günlükleyiciler, reference section tanımlanan işlevler için aşırı yüklemelerle birlikte gelmelidir.
Early filtering and message handling
Bir olay meydana geldiğinde, atılacak mesajların üretilmesini önlemek için birkaç erken filtreleme adımı gerçekleşir:
- Mesaj günlük seviyesi, bir global minimum seviye ile kontrol edilir (şu şekilde ayarlanmıştır:
disable_logging
). Bu, kaba ama son derece ucuz bir global ayardır. - Mevcut logger durumu kontrol edilir ve mesaj seviyesi,
Logging.min_enabled_level
çağrılarak bulunan logger'ın önbelleğe alınmış minimum seviyesi ile karşılaştırılır. Bu davranış, ortam değişkenleri aracılığıyla geçersiz kılınabilir (bununla ilgili daha fazla bilgi daha sonra). Logging.shouldlog
fonksiyonu, bazı minimal bilgileri (seviye, modül, grup, kimlik) alarak mevcut logger ile çağrılır; bu bilgiler statik olarak hesaplanabilir. En kullanışlı olanı,shouldlog
'a bir olaykimliği
geçilir; bu, önceden belirlenmiş bir koşula dayanarak olayları erken bir şekilde atmak için kullanılabilir.
Eğer bu kontrollerin hepsi geçerse, mesaj ve anahtar-değer çiftleri tam olarak değerlendirilir ve mevcut günlüğe Logging.handle_message
fonksiyonu aracılığıyla iletilir. handle_message()
gerektiğinde ek filtreleme yapabilir ve olayı ekranda gösterebilir, bir dosyaya kaydedebilir vb.
Oluşturma sırasında meydana gelen istisnalar, varsayılan olarak yakalanır ve kaydedilir. Bu, bireysel bozuk olayların uygulamayı çökertmesini önler; bu, üretim sisteminde az kullanılan hata ayıklama olaylarını etkinleştirirken faydalıdır. Bu davranış, Logging.catch_exceptions
uzantısını kullanarak her bir günlüğü kaydedici türü için özelleştirilebilir.
Testing log events
Log olayları, normal kodu çalıştırmanın bir yan etkisidir, ancak belirli bilgilendirici mesajları ve uyarıları test etmek isteyebilirsiniz. Test
modülü, günlük olay akışına karşı desen eşleştirmek için kullanılabilecek bir @test_logs
makrosu sağlar.
Environment variables
Mesaj filtreleme, JULIA_DEBUG
ortam değişkeni aracılığıyla etkilenebilir ve bir dosya veya modül için hata ayıklama günlüğünü etkinleştirmenin kolay bir yolunu sunar. JULIA_DEBUG=loading
ile julia yüklemek, loading.jl
dosyasında @debug
günlük mesajlarını etkinleştirecektir. Örneğin, Linux kabuklarında:
$ JULIA_DEBUG=loading julia -e 'using OhMyREPL'
┌ Debug: Rejecting cache file /home/user/.julia/compiled/v0.7/OhMyREPL.ji due to it containing an incompatible cache header
└ @ Base loading.jl:1328
[ Info: Recompiling stale cache file /home/user/.julia/compiled/v0.7/OhMyREPL.ji for module OhMyREPL
┌ Debug: Rejecting cache file /home/user/.julia/compiled/v0.7/Tokenize.ji due to it containing an incompatible cache header
└ @ Base loading.jl:1328
...
Windows'ta, aynı şey CMD
'de set JULIA_DEBUG="loading"
komutunu çalıştırarak ve Powershell
'da $env:JULIA_DEBUG="loading"
komutunu kullanarak gerçekleştirilebilir.
Benzer şekilde, ortam değişkeni Pkg
gibi modüllerin veya modül köklerinin hata ayıklama günlüklemesini etkinleştirmek için kullanılabilir (bkz. Base.moduleroot
). Tüm hata ayıklama günlüklemesini etkinleştirmek için özel değer all
kullanın.
REPL'den hata ayıklama günlüğünü açmak için ENV["JULIA_DEBUG"]
'yi ilgi alanındaki modülün adıyla ayarlayın. REPL'de tanımlanan fonksiyonlar Main
modülüne aittir; bunlar için günlüğü şu şekilde etkinleştirebilirsiniz:
julia> foo() = @debug "foo"
foo (generic function with 1 method)
julia> foo()
julia> ENV["JULIA_DEBUG"] = Main
Main
julia> foo()
┌ Debug: foo
└ @ Main REPL[1]:1
Birden fazla modül için hata ayıklamayı etkinleştirmek için virgül ayırıcı kullanın: JULIA_DEBUG=loading,Main
.
Examples
Example: Writing log events to a file
Bazen log olaylarını bir dosyaya yazmak faydalı olabilir. İşte bir görev yerel ve global günlüğü kullanarak bir metin dosyasına bilgi yazmanın bir örneği:
# Load the logging module
julia> using Logging
# Open a textfile for writing
julia> io = open("log.txt", "w+")
IOStream(<file log.txt>)
# Create a simple logger
julia> logger = SimpleLogger(io)
SimpleLogger(IOStream(<file log.txt>), Info, Dict{Any,Int64}())
# Log a task-specific message
julia> with_logger(logger) do
@info("a context specific log message")
end
# Write all buffered messages to the file
julia> flush(io)
# Set the global logger to logger
julia> global_logger(logger)
SimpleLogger(IOStream(<file log.txt>), Info, Dict{Any,Int64}())
# This message will now also be written to the file
julia> @info("a global log message")
# Close the file
julia> close(io)
Example: Enable debug-level messages
İşte ConsoleLogger
oluşturmanın bir örneği; bu, log seviyesi Logging.Debug
veya daha yüksek olan herhangi bir mesajı geçiren bir yapı sağlar.
julia> using Logging
# Create a ConsoleLogger that prints any log messages with level >= Debug to stderr
julia> debuglogger = ConsoleLogger(stderr, Logging.Debug)
# Enable debuglogger for a task
julia> with_logger(debuglogger) do
@debug "a context specific log message"
end
# Set the global logger
julia> global_logger(debuglogger)
Reference
Logging module
Logging.Logging
— ModuleLog olaylarının akışlarını yakalamak, filtrelemek ve sunmak için yardımcı programlar. Genellikle, log olayları oluşturmak için Logging
'i içe aktarmanıza gerek yoktur; bunun için standart loglama makroları, örneğin @info
, Base
tarafından zaten dışa aktarılmıştır ve varsayılan olarak mevcuttur.
Creating events
Logging.@logmsg
— Macro@debug mesaj [anahtar=değer | değer ...]
@info mesaj [anahtar=değer | değer ...]
@warn mesaj [anahtar=değer | değer ...]
@error mesaj [anahtar=değer | değer ...]
@logmsg seviye mesaj [anahtar=değer | değer ...]
Bilgilendirici bir `mesaj` ile bir log kaydı oluşturun. Kolaylık olması açısından, `Debug`, `Info`, `Warn` ve `Error` standart ciddiyet seviyelerinde log kaydı yapan dört logging makrosu `@debug`, `@info`, `@warn` ve `@error` tanımlanmıştır. `@logmsg`, `seviye`nin programatik olarak herhangi bir `LogLevel` veya özel log seviye türlerine ayarlanmasına olanak tanır.
`mesaj`, log olayının insan tarafından okunabilir bir tanımını içeren bir dizeye değerlendirilmesi gereken bir ifadedir. Geleneksel olarak, bu dize sunulduğunda markdown olarak biçimlendirilir.
İsteğe bağlı `anahtar=değer` çiftleri listesi, log kaydının bir parçası olarak loglama arka ucuna iletilecek key-value çiftleri için kullanıcı tanımlı meta verileri destekler. Sadece bir `değer` ifadesi sağlanırsa, ifade için bir anahtar [`Symbol`](@ref) kullanılarak oluşturulacaktır. Örneğin, `x` `x=x` olur ve `foo(10)` `Symbol("foo(10)")=foo(10)` olur. Anahtar değer çiftlerinin bir listesini splatlamak için normal splatlama sözdizimini kullanın, `@info "blah" kws...`.
Otomatik olarak üretilen log verilerini geçersiz kılmak için bazı anahtarlar vardır:
* `_module=mod`, mesajın kaynak konumundan farklı bir köken modülü belirtmek için kullanılabilir.
* `_group=symbol`, mesaj grubunu geçersiz kılmak için kullanılabilir (bu genellikle kaynak dosyasının temel adından türetilir).
* `_id=symbol`, otomatik olarak üretilen benzersiz mesaj tanımlayıcısını geçersiz kılmak için kullanılabilir. Bu, farklı kaynak satırlarında üretilen mesajları çok yakından ilişkilendirmek istiyorsanız yararlıdır.
* `_file=string` ve `_line=integer`, bir log mesajının görünür kaynak konumunu geçersiz kılmak için kullanılabilir.
Ayrıca, geleneksel anlamı olan bazı anahtar değer çiftleri vardır:
* `maxlog=integer`, mesajın en fazla `maxlog` kez görüntülenmesi gerektiği konusunda arka uca bir ipucu olarak kullanılmalıdır.
* `exception=ex`, genellikle `@error` ile kullanılan bir log mesajıyla bir istisna taşımak için kullanılmalıdır. İlgili bir geri izleme `bt`, `exception=(ex,bt)` tuple'ı kullanılarak eklenebilir.
# Örnekler
julia @debug "Ayrıntılı hata ayıklama bilgisi. Varsayılan olarak görünmez" @info "Bilgilendirici bir mesaj" @warn "Bir şey garipti. Dikkat etmelisin" @error "Ölümcül olmayan bir hata oluştu"
x = 10 @info "Mesaja ekli bazı değişkenler" x a=42.0
@debug begin sA = sum(A) "sum(A) = sA pahalı bir işlemdir, yalnızca shouldlog
true döndüğünde değerlendirilir" end
for i=1:10000 @info "Varsayılan arka uç ile yalnızca (i = i) on kez göreceksiniz" maxlog=10 @debug "Algoritma1" i ilerleme=i/10000 end ```
Logging.LogLevel
— TypeLogLevel(level)
Bir log kaydının ciddiyeti/ayrıntı seviyesi.
Log seviyesi, potansiyel log kayıtlarının filtrelenebileceği bir anahtar sağlar; bu, log kaydı veri yapısını oluşturmak için başka bir iş yapılmadan önce gerçekleşir.
Örnekler
julia> Logging.LogLevel(0) == Logging.Info
true
Logging.Debug
— ConstantDebug
LogLevel(-1000)
için takma ad.
Logging.Info
— ConstantBilgi
LogLevel(0)
için takma ad.
Logging.Warn
— ConstantUyarı
LogLevel(1000)
için takma ad.
Logging.Error
— ConstantHata
LogLevel(2000)
için takma ad.
Logging.BelowMinLevel
— ConstantBelowMinLevel
LogLevel(-1_000_001)
için takma ad.
Logging.AboveMaxLevel
— ConstantAboveMaxLevel
LogLevel(1_000_001)
için takma ad.
Processing events with AbstractLogger
Olay işleme, AbstractLogger
ile ilişkili işlevlerin geçersiz kılınmasıyla kontrol edilir:
Methods to implement | Brief description | |
---|---|---|
Logging.handle_message | Handle a log event | |
Logging.shouldlog | Early filtering of events | |
Logging.min_enabled_level | Lower bound for log level of accepted events | |
Optional methods | Default definition | Brief description |
Logging.catch_exceptions | true | Catch exceptions during event evaluation |
Logging.AbstractLogger
— TypeBir günlüğü kaydedici, günlük kayıtlarının nasıl filtreleneceğini ve dağıtılacağını kontrol eder. Bir günlük kaydı oluşturulduğunda, günlüğü kaydedici, kaydı inceleyen ve onunla ne yapılacağına karar veren ilk kullanıcı yapılandırılabilir kod parçasıdır.
Logging.handle_message
— Functionhandle_message(logger, level, message, _module, group, id, file, line; key1=val1, ...)
logger
'a level
seviyesinde bir mesaj kaydedin. Mesajın oluşturulduğu mantıksal konum _module
ve group
ile, kaynak konumu ise file
ve line
ile verilmektedir. id
, filtreleme sırasında log ifadesini tanımlamak için kullanılacak rastgele bir benzersiz değerdir (tipik olarak bir Symbol
).
Logging.shouldlog
— Functionshouldlog(logger, level, _module, group, id)
logger
bir mesajı level
seviyesinde, _module
, group
için ve benzersiz bir günlük tanımlayıcı id
ile kabul ediyorsa true
döner.
Logging.min_enabled_level
— Functionmin_enabled_level(logger)
logger
için erken filtreleme amacıyla minimum etkin seviyeyi döndürür. Yani, tüm mesajların filtrelendiği seviye veya daha düşük olan log seviyesi.
Logging.catch_exceptions
— Functioncatch_exceptions(logger)
Logger'ın log kaydı oluşturma sırasında meydana gelen istisnaları yakalayıp yakalamayacağını belirtmek için true
döner. Varsayılan olarak, mesajlar yakalanır.
Varsayılan olarak, programın çökmesine neden olmamak için tüm istisnalar yakalanır. Bu, kullanıcıların üretim sisteminde nadiren kullanılan işlevselliği - örneğin hata ayıklama kaydı - güvenle açıp kapatmalarını sağlar.
Eğer günlüğü bir denetim izi olarak kullanmak istiyorsanız, bu durumu logger türünüz için devre dışı bırakmalısınız.
Logging.disable_logging
— Functiondisable_logging(level)
level
seviyesine eşit veya daha düşük log seviyelerindeki tüm log mesajlarını devre dışı bırakır. Bu, devre dışı bırakıldığında hata ayıklama loglamasını son derece ucuz hale getirmek için tasarlanmış küresel bir ayardır.
Örnekler
Logging.disable_logging(Logging.Info) # Hata ayıklama ve bilgi loglamasını devre dışı bırak
Using Loggers
Logger kurulumu ve denetimi:
Logging.global_logger
— Functionglobal_logger()
Mevcut görev için belirli bir günlükleyici yoksa, mesajları almak için kullanılan küresel günlükleyiciyi döndürür.
global_logger(logger)
Küresel günlükleyiciyi logger
olarak ayarlayın ve önceki küresel günlükleyiciyi döndürün.
Logging.with_logger
— Functionwith_logger(function, logger)
function
'ı çalıştırın, tüm günlük mesajlarını logger
'a yönlendirin.
Örnekler
function test(x)
@info "x = $x"
end
with_logger(logger) do
test(1)
test([1,2])
end
Logging.current_logger
— Functioncurrent_logger()
Mevcut görev için günlüğü döndürür veya görevle ilişkilendirilmiş bir günlüğü yoksa global günlüğü döndürür.
Sisteme ile birlikte sağlanan loglayıcılar:
Logging.NullLogger
— TypeNullLogger()
Tüm mesajları devre dışı bırakan ve hiçbir çıktı üretmeyen bir günlükleyici - /dev/null'ın günlükleyici eşdeğeri.
Base.CoreLogging.ConsoleLogger
— TypeConsoleLogger([stream,] min_level=Info; meta_formatter=default_metafmt,
show_limited=true, right_justify=0)
Metin konsolda okunabilirlik için optimize edilmiş bir Logger, örneğin Julia REPL ile etkileşimli çalışma için.
min_level
'den daha düşük log seviyeleri filtrelenir.
Mesaj formatı, anahtar argümanlar ayarlanarak kontrol edilebilir:
meta_formatter
, log olayı meta verilerini(level, _module, group, id, file, line)
alanlarını alıp log mesajı için bir renk (printstyled'e geçilecek şekilde) ve ön ek ve son ek döndüren bir işlevdir. Varsayılan, log seviyesinin ön eki ve modül, dosya ve satır konumunu içeren bir son ek ile ön eklemektir.show_limited
, büyük veri yapılarını ekrana sığacak bir şeyle sınırlayarak yazdırmayı sınırlar; bu, formatlama sırasında:limit
IOContext
anahtarını ayarlayarak yapılır.right_justify
, log meta verilerinin sağa yaslandığı tam sayı sütunudur. Varsayılan sıfırdır (meta veriler kendi satırında yer alır).
Logging.SimpleLogger
— TypeSimpleLogger([stream,] min_level=Info)
min_level
'e eşit veya daha büyük seviyedeki tüm mesajları stream
'e kaydeden basit bir günlüğü kaydedici. Eğer akış kapalıysa, Warn
seviyesinden büyük veya eşit olan mesajlar stderr
'ye, daha düşük seviyedekiler ise stdout
'ya kaydedilecektir.