Skip to content

Commit

Permalink
logging: redirect closed streams to stderr/stdout
Browse files Browse the repository at this point in the history
This has the additional benefit of making the initial logger respect
changes to redirect_stderr/stdout, until the user explicitly sets
another stream as the logging destination.

Fix #26798
Fix #38482
Replaces #26920, which provided the idea and most of the implementation

Co-authored-by: Joe Petviashvili <[email protected]>
  • Loading branch information
vtjnash and Joe Petviashvili committed Apr 9, 2021
1 parent 54c7002 commit 171b95d
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 15 deletions.
20 changes: 14 additions & 6 deletions base/logging.jl
Original file line number Diff line number Diff line change
Expand Up @@ -611,21 +611,25 @@ attached to the task.
"""
current_logger() = current_logstate().logger

const closed_stream = IOBuffer(UInt8[])
close(closed_stream)

#-------------------------------------------------------------------------------
# SimpleLogger
"""
SimpleLogger(stream=stderr, min_level=Info)
SimpleLogger([stream,] min_level=Info)
Simplistic logger for logging all messages with level greater than or equal to
`min_level` to `stream`.
`min_level` to `stream`. If stream is closed then messages with log level
greater or equal to `Warn` will be logged to `stderr` and below to `stdout`.
"""
struct SimpleLogger <: AbstractLogger
stream::IO
min_level::LogLevel
message_limits::Dict{Any,Int}
end
SimpleLogger(stream::IO=stderr, level=Info) = SimpleLogger(stream, level, Dict{Any,Int}())
SimpleLogger(stream::IO, level=Info) = SimpleLogger(stream, level, Dict{Any,Int}())
SimpleLogger(level=Info) = SimpleLogger(closed_stream, level)

shouldlog(logger::SimpleLogger, level, _module, group, id) =
get(logger.message_limits, id, 1) > 0
Expand All @@ -644,7 +648,11 @@ function handle_message(logger::SimpleLogger, level::LogLevel, message, _module,
remaining > 0 || return
end
buf = IOBuffer()
iob = IOContext(buf, logger.stream)
stream = logger.stream
if !isopen(stream)
stream = level < Warn ? stdout : stderr
end
iob = IOContext(buf, stream)
levelstr = level == Warn ? "Warning" : string(level)
msglines = split(chomp(string(message)::String), '\n')
println(iob, "", levelstr, ": ", msglines[1])
Expand All @@ -656,10 +664,10 @@ function handle_message(logger::SimpleLogger, level::LogLevel, message, _module,
println(iob, "", key, " = ", val)
end
println(iob, "└ @ ", _module, " ", filepath, ":", line)
write(logger.stream, take!(buf))
write(stream, take!(buf))
nothing
end

_global_logstate = LogState(SimpleLogger(Core.stderr, CoreLogging.Info))
_global_logstate = LogState(SimpleLogger())

end # CoreLogging
23 changes: 17 additions & 6 deletions stdlib/Logging/src/ConsoleLogger.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

"""
ConsoleLogger(stream=stderr, min_level=Info; meta_formatter=default_metafmt,
ConsoleLogger([stream,] min_level=Info; meta_formatter=default_metafmt,
show_limited=true, right_justify=0)
Logger with formatting optimized for readability in a text console, for example
Expand Down Expand Up @@ -30,12 +30,19 @@ struct ConsoleLogger <: AbstractLogger
right_justify::Int
message_limits::Dict{Any,Int}
end
function ConsoleLogger(stream::IO=stderr, min_level=Info;
function ConsoleLogger(stream::IO, min_level=Info;
meta_formatter=default_metafmt, show_limited=true,
right_justify=0)
ConsoleLogger(stream, min_level, meta_formatter,
show_limited, right_justify, Dict{Any,Int}())
end
function ConsoleLogger(min_level=Info;
meta_formatter=default_metafmt, show_limited=true,
right_justify=0)
ConsoleLogger(closed_stream, min_level, meta_formatter,
show_limited, right_justify, Dict{Any,Int}())
end


shouldlog(logger::ConsoleLogger, level, _module, group, id) =
get(logger.message_limits, id, 1) > 0
Expand Down Expand Up @@ -110,12 +117,16 @@ function handle_message(logger::ConsoleLogger, level::LogLevel, message, _module
# Generate a text representation of the message and all key value pairs,
# split into lines.
msglines = [(indent=0, msg=l) for l in split(chomp(string(message)::String), '\n')]
dsize = displaysize(logger.stream)::Tuple{Int,Int}
stream = logger.stream
if !isopen(stream)
stream = level < Warn ? stdout : stderr
end
dsize = displaysize(stream)::Tuple{Int,Int}
nkwargs = length(kwargs)::Int
if nkwargs > hasmaxlog
valbuf = IOBuffer()
rows_per_value = max(1, dsize[1] ÷ (nkwargs + 1 - hasmaxlog))
valio = IOContext(IOContext(valbuf, logger.stream),
valio = IOContext(IOContext(valbuf, stream),
:displaysize => (rows_per_value, dsize[2] - 5),
:limit => logger.show_limited)
for (key, val) in kwargs
Expand All @@ -136,7 +147,7 @@ function handle_message(logger::ConsoleLogger, level::LogLevel, message, _module
color, prefix, suffix = logger.meta_formatter(level, _module, group, id, filepath, line)::Tuple{Union{Symbol,Int},String,String}
minsuffixpad = 2
buf = IOBuffer()
iob = IOContext(buf, logger.stream)
iob = IOContext(buf, stream)
nonpadwidth = 2 + (isempty(prefix) || length(msglines) > 1 ? 0 : length(prefix)+1) +
msglines[end].indent + termlength(msglines[end].msg) +
(isempty(suffix) ? 0 : length(suffix)+minsuffixpad)
Expand Down Expand Up @@ -164,6 +175,6 @@ function handle_message(logger::ConsoleLogger, level::LogLevel, message, _module
println(iob)
end

write(logger.stream, take!(buf))
write(stream, take!(buf))
nothing
end
5 changes: 4 additions & 1 deletion stdlib/Logging/src/Logging.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ for sym in [
@eval const $sym = Base.CoreLogging.$sym
end

using Base.CoreLogging:
closed_stream

export
AbstractLogger,
LogLevel,
Expand Down Expand Up @@ -56,7 +59,7 @@ include("ConsoleLogger.jl")
# handle_message, shouldlog, min_enabled_level, catch_exceptions,

function __init__()
global_logger(ConsoleLogger(stderr))
global_logger(ConsoleLogger())
end

end
32 changes: 30 additions & 2 deletions test/corelogging.jl
Original file line number Diff line number Diff line change
Expand Up @@ -341,15 +341,43 @@ end
String(take!(io))
end

function genmsg_out(level, message, _module, filepath, line; kws...)
fname = tempname()
f = open(fname, "w")
logger = SimpleLogger()
redirect_stdout(f) do
handle_message(logger, level, message, _module, :group, :id,
filepath, line; kws...)
end
close(f)
buf = read(fname)
rm(fname)
String(buf)
end

function genmsg_err(level, message, _module, filepath, line; kws...)
fname = tempname()
f = open(fname, "w")
logger = SimpleLogger()
redirect_stderr(f) do
handle_message(logger, level, message, _module, :group, :id,
filepath, line; kws...)
end
close(f)
buf = read(fname)
rm(fname)
String(buf)
end

# Simple
@test genmsg(Info, "msg", Main, "some/path.jl", 101) ==
@test genmsg_out(Info, "msg", Main, "some/path.jl", 101) ==
"""
┌ Info: msg
└ @ Main some/path.jl:101
"""

# Multiline message
@test genmsg(Warn, "line1\nline2", Main, "some/path.jl", 101) ==
@test genmsg_err(Warn, "line1\nline2", Main, "some/path.jl", 101) ==
"""
┌ Warning: line1
│ line2
Expand Down

0 comments on commit 171b95d

Please sign in to comment.