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çin print(io, obj) veya string(obj) kullanılarak ve muhtemelen kurulu günlüğü kullanarak diğer multimedya görüntülemeleri için show(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 ve satı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:

  1. 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.
  2. 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).
  3. 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 olay kimliğ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.LoggingModule

Log 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.

source

Creating events

Logging.@logmsgMacro
@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 ```

source
Logging.LogLevelType
LogLevel(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
source

Processing events with AbstractLogger

Olay işleme, AbstractLogger ile ilişkili işlevlerin geçersiz kılınmasıyla kontrol edilir:

Methods to implementBrief description
Logging.handle_messageHandle a log event
Logging.shouldlogEarly filtering of events
Logging.min_enabled_levelLower bound for log level of accepted events
Optional methodsDefault definitionBrief description
Logging.catch_exceptionstrueCatch exceptions during event evaluation
Logging.AbstractLoggerType

Bir 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.

source
Logging.handle_messageFunction
handle_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).

source
Logging.shouldlogFunction
shouldlog(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.

source
Logging.min_enabled_levelFunction
min_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.

source
Logging.catch_exceptionsFunction
catch_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.

source
Logging.disable_loggingFunction
disable_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
source

Using Loggers

Logger kurulumu ve denetimi:

Logging.global_loggerFunction
global_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.

source
Logging.with_loggerFunction
with_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
source
Logging.current_loggerFunction
current_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.

source

Sisteme ile birlikte sağlanan loglayıcılar:

Logging.NullLoggerType
NullLogger()

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.

source
Base.CoreLogging.ConsoleLoggerType
ConsoleLogger([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).
source
Logging.SimpleLoggerType
SimpleLogger([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.

source