@@ -254,6 +254,7 @@ _log_record_ids = Set{Symbol}()
254
254
# across versions of the originating module, provided the log generating
255
255
# statement itself doesn't change.
256
256
function log_record_id (_module, level, message, log_kws)
257
+ @nospecialize
257
258
modname = _module === nothing ? " " : join (fullname (_module), " _" )
258
259
# Use an arbitrarily chosen eight hex digits here. TODO : Figure out how to
259
260
# make the id exactly the same on 32 and 64 bit systems.
@@ -274,48 +275,112 @@ end
274
275
275
276
default_group (file) = Symbol (splitext (basename (file))[1 ])
276
277
278
+ function issimple (@nospecialize val)
279
+ val isa String && return true
280
+ val isa Symbol && return true
281
+ val isa QuoteNode && return true
282
+ val isa Number && return true
283
+ val isa Char && return true
284
+ if val isa Expr
285
+ val. head === :quote && issimple (val[1 ]) && return true
286
+ val. head === :inert && return true
287
+ end
288
+ return false
289
+ end
290
+ function issimplekw (@nospecialize val)
291
+ if val isa Expr
292
+ if val. head === :kw
293
+ val = val. args[2 ]
294
+ if val isa Expr && val. head === :escape
295
+ issimple (val. args[1 ]) && return true
296
+ end
297
+ end
298
+ end
299
+ return false
300
+ end
301
+
277
302
# Generate code for logging macros
278
303
function logmsg_code (_module, file, line, level, message, exs... )
304
+ @nospecialize
279
305
log_data = process_logmsg_exs (_module, file, line, level, message, exs... )
280
- quote
281
- let
282
- level = $ level
283
- std_level = convert (LogLevel, level)
284
- if std_level >= getindex (_min_enabled_level)
285
- group = $ (log_data. _group)
286
- _module = $ (log_data. _module)
287
- logger = current_logger_for_env (std_level, group, _module)
288
- if ! (logger === nothing )
289
- id = $ (log_data. _id)
290
- # Second chance at an early bail-out (before computing the message),
291
- # based on arbitrary logger-specific logic.
292
- if _invoked_shouldlog (logger, level, _module, group, id)
293
- file = $ (log_data. _file)
294
- line = $ (log_data. _line)
295
- try
296
- msg = $ (esc (message))
297
- handle_message (
306
+ if ! isa (message, Symbol) && issimple (message) && isempty (log_data. kwargs)
307
+ logrecord = quote
308
+ msg = $ (message)
309
+ kwargs = (;)
310
+ true
311
+ end
312
+ elseif issimple (message) && all (issimplekw, log_data. kwargs)
313
+ # if message and kwargs are just values and variables, we can avoid try/catch
314
+ # complexity by adding the code for testing the UndefVarError by hand
315
+ checkerrors = nothing
316
+ for kwarg in reverse (log_data. kwargs)
317
+ if isa (kwarg. args[2 ]. args[1 ], Symbol)
318
+ checkerrors = Expr (:if , Expr (:isdefined , kwarg. args[2 ]), checkerrors, Expr (:call , Expr (:core , :UndefVarError ), QuoteNode (kwarg. args[2 ]. args[1 ])))
319
+ end
320
+ end
321
+ if isa (message, Symbol)
322
+ message = esc (message)
323
+ checkerrors = Expr (:if , Expr (:isdefined , message), checkerrors, Expr (:call , Expr (:core , :UndefVarError ), QuoteNode (message. args[1 ])))
324
+ end
325
+ logrecord = quote
326
+ let err = $ checkerrors
327
+ if err === nothing
328
+ msg = $ (message)
329
+ kwargs = (;$ (log_data. kwargs... ))
330
+ true
331
+ else
332
+ logging_error (logger, level, _module, group, id, file, line, err, false )
333
+ false
334
+ end
335
+ end
336
+ end
337
+ else
338
+ logrecord = quote
339
+ try
340
+ msg = $ (esc (message))
341
+ kwargs = (;$ (log_data. kwargs... ))
342
+ true
343
+ catch err
344
+ logging_error (logger, level, _module, group, id, file, line, err, true )
345
+ false
346
+ end
347
+ end
348
+ end
349
+ return quote
350
+ let
351
+ level = $ level
352
+ std_level = convert (LogLevel, level)
353
+ if std_level >= getindex (_min_enabled_level)
354
+ group = $ (log_data. _group)
355
+ _module = $ (log_data. _module)
356
+ logger = current_logger_for_env (std_level, group, _module)
357
+ if ! (logger === nothing )
358
+ id = $ (log_data. _id)
359
+ # Second chance at an early bail-out (before computing the message),
360
+ # based on arbitrary logger-specific logic.
361
+ if _invoked_shouldlog (logger, level, _module, group, id)
362
+ file = $ (log_data. _file)
363
+ line = $ (log_data. _line)
364
+ local msg, kwargs
365
+ $ (logrecord) && handle_message (
298
366
logger, level, msg, _module, group, id, file, line;
299
- $ (log_data. kwargs... )
300
- )
301
- catch err
302
- logging_error (logger, level, _module, group, id, file, line, err)
367
+ kwargs... )
303
368
end
304
369
end
305
370
end
371
+ nothing
306
372
end
307
- nothing
308
- end
309
373
end
310
374
end
311
375
312
376
function process_logmsg_exs (_orig_module, _file, _line, level, message, exs... )
377
+ @nospecialize
313
378
local _group, _id
314
379
_module = _orig_module
315
380
kwargs = Any[]
316
381
for ex in exs
317
382
if ex isa Expr && ex. head === :(= ) && ex. args[1 ] isa Symbol
318
- k,v = ex. args
383
+ k, v = ex. args
319
384
if ! (k isa Symbol)
320
385
throw (ArgumentError (" Expected symbol for key in key value pair `$ex `" ))
321
386
end
@@ -352,6 +417,7 @@ function process_logmsg_exs(_orig_module, _file, _line, level, message, exs...)
352
417
end
353
418
354
419
function default_group_code (file)
420
+ @nospecialize
355
421
if file isa String && isdefined (Base, :basename )
356
422
QuoteNode (default_group (file)) # precompute if we can
357
423
else
@@ -361,39 +427,34 @@ function default_group_code(file)
361
427
end
362
428
363
429
364
- # Report an error in log message creation (or in the logger itself).
430
+ # Report an error in log message creation
365
431
@noinline function logging_error (logger, level, _module, group, id,
366
- filepath, line, @nospecialize (err))
432
+ filepath, line, @nospecialize (err), real:: Bool )
433
+ @nospecialize
367
434
if ! _invoked_catch_exceptions (logger)
368
- rethrow (err)
369
- end
370
- try
371
- msg = " Exception while generating log record in module $_module at $filepath :$line "
372
- handle_message (
373
- logger, Error, msg, _module, :logevent_error , id, filepath, line;
374
- exception= (err,catch_backtrace ())
375
- )
376
- catch err2
377
- try
378
- # Give up and write to stderr, in three independent calls to
379
- # increase the odds of it getting through.
380
- print (stderr , " Exception handling log message: " )
381
- println (stderr , err)
382
- println (stderr , " module=$_module file=$filepath line=$line " )
383
- println (stderr , " Second exception: " , err2)
384
- catch
385
- end
435
+ real ? rethrow (err) : throw (err)
386
436
end
437
+ msg = try
438
+ " Exception while generating log record in module $_module at $filepath :$line "
439
+ catch ex
440
+ " Exception handling log message: $ex "
441
+ end
442
+ bt = real ? catch_backtrace () : backtrace ()
443
+ handle_message (
444
+ logger, Error, msg, _module, :logevent_error , id, filepath, line;
445
+ exception= (err,bt))
387
446
nothing
388
447
end
389
448
390
449
# Log a message. Called from the julia C code; kwargs is in the format
391
450
# Any[key1,val1, ...] for simplicity in construction on the C side.
392
451
function logmsg_shim (level, message, _module, group, id, file, line, kwargs)
393
- real_kws = Any[(kwargs[i],kwargs[i+ 1 ]) for i in 1 : 2 : length (kwargs)]
452
+ @nospecialize
453
+ real_kws = Any[(kwargs[i], kwargs[i+ 1 ]) for i in 1 : 2 : length (kwargs)]
394
454
@logmsg (convert (LogLevel, level), message,
395
455
_module= _module, _id= id, _group= group,
396
456
_file= String (file), _line= line, real_kws... )
457
+ nothing
397
458
end
398
459
399
460
# Global log limiting mechanism for super fast but inflexible global log limiting.
@@ -574,8 +635,10 @@ min_enabled_level(logger::SimpleLogger) = logger.min_level
574
635
catch_exceptions (logger:: SimpleLogger ) = false
575
636
576
637
function handle_message (logger:: SimpleLogger , level, message, _module, group, id,
577
- filepath, line; maxlog= nothing , kwargs... )
578
- if maxlog != = nothing && maxlog isa Integer
638
+ filepath, line; kwargs... )
639
+ @nospecialize
640
+ maxlog = get (kwargs, :maxlog , nothing )
641
+ if maxlog isa Integer
579
642
remaining = get! (logger. message_limits, id, maxlog)
580
643
logger. message_limits[id] = remaining - 1
581
644
remaining > 0 || return
@@ -589,6 +652,7 @@ function handle_message(logger::SimpleLogger, level, message, _module, group, id
589
652
println (iob, " │ " , msglines[i])
590
653
end
591
654
for (key, val) in kwargs
655
+ key === :maxlog && continue
592
656
println (iob, " │ " , key, " = " , val)
593
657
end
594
658
println (iob, " └ @ " , something (_module, " nothing" ), " " ,
0 commit comments