• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

JuliaLang / julia / #37552

pending completion
#37552

push

local

web-flow
Abbreviate varinfo signature and re-order for consistency (#48860)

1 of 1 new or added line in 1 file covered. (100.0%)

72746 of 83846 relevant lines covered (86.76%)

34617131.18 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

68.13
/stdlib/Logging/src/ConsoleLogger.jl
1
# This file is a part of Julia. License is MIT: https://julialang.org/license
2

3
"""
4
    ConsoleLogger([stream,] min_level=Info; meta_formatter=default_metafmt,
5
                  show_limited=true, right_justify=0)
6

7
Logger with formatting optimized for readability in a text console, for example
8
interactive work with the Julia REPL.
9

10
Log levels less than `min_level` are filtered out.
11

12
Message formatting can be controlled by setting keyword arguments:
13

14
* `meta_formatter` is a function which takes the log event metadata
15
  `(level, _module, group, id, file, line)` and returns a color (as would be
16
  passed to printstyled), prefix and suffix for the log message.  The
17
  default is to prefix with the log level and a suffix containing the module,
18
  file and line location.
19
* `show_limited` limits the printing of large data structures to something
20
  which can fit on the screen by setting the `:limit` `IOContext` key during
21
  formatting.
22
* `right_justify` is the integer column which log metadata is right justified
23
  at. The default is zero (metadata goes on its own line).
24
"""
25
struct ConsoleLogger <: AbstractLogger
26
    stream::IO
481✔
27
    min_level::LogLevel
28
    meta_formatter
29
    show_limited::Bool
30
    right_justify::Int
31
    message_limits::Dict{Any,Int}
32
end
33
function ConsoleLogger(stream::IO, min_level=Info;
×
34
                       meta_formatter=default_metafmt, show_limited=true,
35
                       right_justify=0)
36
    ConsoleLogger(stream, min_level, meta_formatter,
×
37
                  show_limited, right_justify, Dict{Any,Int}())
38
end
39
function ConsoleLogger(min_level=Info;
962✔
40
                       meta_formatter=default_metafmt, show_limited=true,
41
                       right_justify=0)
42
    ConsoleLogger(closed_stream, min_level, meta_formatter,
481✔
43
                  show_limited, right_justify, Dict{Any,Int}())
44
end
45

46

47
shouldlog(logger::ConsoleLogger, level, _module, group, id) =
2✔
48
    get(logger.message_limits, id, 1) > 0
49

50
min_enabled_level(logger::ConsoleLogger) = logger.min_level
482✔
51

52
# Formatting of values in key value pairs
53
showvalue(io, msg) = show(io, "text/plain", msg)
×
54
function showvalue(io, e::Tuple{Exception,Any})
1✔
55
    ex,bt = e
1✔
56
    showerror(io, ex, bt; backtrace = bt!==nothing)
1✔
57
end
58
showvalue(io, ex::Exception) = showerror(io, ex)
×
59

60
function default_logcolor(level::LogLevel)
×
61
    level < Info  ? Base.debug_color() :
4✔
62
    level < Warn  ? Base.info_color()  :
63
    level < Error ? Base.warn_color()  :
64
                    Base.error_color()
65
end
66

67
function default_metafmt(level::LogLevel, _module, group, id, file, line)
2✔
68
    @nospecialize
×
69
    color = default_logcolor(level)
4✔
70
    prefix = string(level == Warn ? "Warning" : string(level), ':')
3✔
71
    suffix::String = ""
2✔
72
    Info <= level < Warn && return color, prefix, suffix
2✔
73
    _module !== nothing && (suffix *= string(_module)::String)
1✔
74
    if file !== nothing
1✔
75
        _module !== nothing && (suffix *= " ")
1✔
76
        suffix *= contractuser(file)::String
1✔
77
        if line !== nothing
1✔
78
            suffix *= ":$(isa(line, UnitRange) ? "$(first(line))-$(last(line))" : line)"
1✔
79
        end
80
    end
81
    !isempty(suffix) && (suffix = "@ " * suffix)
1✔
82
    return color, prefix, suffix
1✔
83
end
84

85
# Length of a string as it will appear in the terminal (after ANSI color codes
86
# are removed)
87
function termlength(str)
2✔
88
    N = 0
×
89
    in_esc = false
×
90
    for c in str
4✔
91
        if in_esc
33✔
92
            if c == 'm'
×
93
                in_esc = false
×
94
            end
95
        else
96
            if c == '\e'
33✔
97
                in_esc = true
×
98
            else
99
                N += 1
33✔
100
            end
101
        end
102
    end
64✔
103
    return N
2✔
104
end
105

106
function handle_message(logger::ConsoleLogger, level::LogLevel, message, _module, group, id,
5✔
107
                        filepath, line; kwargs...)
108
    @nospecialize
×
109
    hasmaxlog = haskey(kwargs, :maxlog) ? 1 : 0
2✔
110
    maxlog = get(kwargs, :maxlog, nothing)
4✔
111
    if maxlog isa Core.BuiltinInts
2✔
112
        remaining = get!(logger.message_limits, id, Int(maxlog)::Int)
×
113
        logger.message_limits[id] = remaining - 1
×
114
        remaining > 0 || return
×
115
    end
116

117
    # Generate a text representation of the message and all key value pairs,
118
    # split into lines.
119
    msglines = [(indent=0, msg=l) for l in split(chomp(convert(String, string(message))::String), '\n')]
2✔
120
    stream::IO = logger.stream
2✔
121
    if !(isopen(stream)::Bool)
2✔
122
        stream = stderr
2✔
123
    end
124
    dsize = displaysize(stream)::Tuple{Int,Int}
2✔
125
    nkwargs = length(kwargs)::Int
2✔
126
    if nkwargs > hasmaxlog
2✔
127
        valbuf = IOBuffer()
×
128
        rows_per_value = max(1, dsize[1] รท (nkwargs + 1 - hasmaxlog))
×
129
        valio = IOContext(IOContext(valbuf, stream),
×
130
                          :displaysize => (rows_per_value, dsize[2] - 5),
131
                          :limit => logger.show_limited)
132
        for (key, val) in kwargs
×
133
            key === :maxlog && continue
×
134
            showvalue(valio, val)
×
135
            vallines = split(String(take!(valbuf)), '\n')
×
136
            if length(vallines) == 1
×
137
                push!(msglines, (indent=2, msg=SubString("$key = $(vallines[1])")))
×
138
            else
139
                push!(msglines, (indent=2, msg=SubString("$key =")))
×
140
                append!(msglines, ((indent=3, msg=line) for line in vallines))
×
141
            end
142
        end
×
143
    end
144

145
    # Format lines as text with appropriate indentation and with a box
146
    # decoration on the left.
147
    color, prefix, suffix = logger.meta_formatter(level, _module, group, id, filepath, line)::Tuple{Union{Symbol,Int},String,String}
2✔
148
    minsuffixpad = 2
×
149
    buf = IOBuffer()
2✔
150
    iob = IOContext(buf, stream)
2✔
151
    nonpadwidth = 2 + (isempty(prefix) || length(msglines) > 1 ? 0 : length(prefix)+1) +
3✔
152
                  msglines[end].indent + termlength(msglines[end].msg) +
153
                  (isempty(suffix) ? 0 : length(suffix)+minsuffixpad)
154
    justify_width = min(logger.right_justify, dsize[2])
2✔
155
    if nonpadwidth > justify_width && !isempty(suffix)
2✔
156
        push!(msglines, (indent=0, msg=SubString("")))
1✔
157
        minsuffixpad = 0
×
158
        nonpadwidth = 2 + length(suffix)
1✔
159
    end
160
    for (i, (indent, msg)) in enumerate(msglines)
4✔
161
        boxstr = length(msglines) == 1 ? "[ " :
5✔
162
                 i == 1                ? "โ”Œ " :
163
                 i < length(msglines)  ? "โ”‚ " :
164
                                         "โ”” "
165
        printstyled(iob, boxstr, bold=true, color=color)
3✔
166
        if i == 1 && !isempty(prefix)
3✔
167
            printstyled(iob, prefix, " ", bold=true, color=color)
2✔
168
        end
169
        print(iob, " "^indent, msg)
3✔
170
        if i == length(msglines) && !isempty(suffix)
3✔
171
            npad = max(0, justify_width - nonpadwidth) + minsuffixpad
1✔
172
            print(iob, " "^npad)
1✔
173
            printstyled(iob, suffix, color=:light_black)
1✔
174
        end
175
        println(iob)
3✔
176
    end
4✔
177

178
    write(stream, take!(buf))
2✔
179
    nothing
2✔
180
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc