console 1.29.3 → 1.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/console/capture.rb +26 -1
- data/lib/console/clock.rb +6 -1
- data/lib/console/compatible/logger.rb +30 -1
- data/lib/console/config.rb +93 -0
- data/lib/console/event/failure.rb +32 -3
- data/lib/console/event/generic.rb +14 -0
- data/lib/console/event/spawn.rb +38 -6
- data/lib/console/event.rb +6 -0
- data/lib/console/filter.rb +62 -2
- data/lib/console/format/safe.rb +35 -7
- data/lib/console/format.rb +3 -0
- data/lib/console/interface.rb +17 -9
- data/lib/console/logger.rb +22 -37
- data/lib/console/output/default.rb +11 -5
- data/lib/console/output/failure.rb +8 -1
- data/lib/console/output/null.rb +4 -1
- data/lib/console/output/sensitive.rb +41 -0
- data/lib/console/output/serialized.rb +25 -4
- data/lib/console/output/split.rb +11 -0
- data/lib/console/output/terminal.rb +66 -14
- data/lib/console/output/wrapper.rb +11 -0
- data/lib/console/output.rb +11 -0
- data/lib/console/progress.rb +55 -8
- data/lib/console/resolver.rb +18 -1
- data/lib/console/terminal/formatter/failure.rb +17 -5
- data/lib/console/terminal/formatter/progress.rb +15 -2
- data/lib/console/terminal/formatter/spawn.rb +15 -4
- data/lib/console/terminal/formatter.rb +16 -0
- data/lib/console/terminal/text.rb +60 -19
- data/lib/console/terminal/xterm.rb +16 -1
- data/lib/console/terminal.rb +6 -8
- data/lib/console/version.rb +1 -1
- data/lib/console/warn.rb +1 -1
- data/lib/console.rb +1 -0
- data/readme.md +7 -1
- data/releases.md +24 -1
- data.tar.gz.sig +0 -0
- metadata +4 -2
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 567d08376aa5cdd7b561679f5a5ff1d1fea42f69c0d3f78bc56f7e98fe712c35
|
4
|
+
data.tar.gz: 23131e3a9cf8812a62b07bca63189b83e127906ca7ed7eeaf6343bd6c2279fba
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 88aa81d06babd53bd475a01ea2c09949c5fb54a69d0cab8a8387fc1ce44d3567eab7ad99c9387ddf20c02ff0028b0adb685f17fffef48370099b0cc45548fc2f
|
7
|
+
data.tar.gz: 31af053996e9b306c0cf63e54181c84760ad72f8fb5562b51dc58caaae50c0c6d5189659e771df89ce2f94b252883cdf30b2ab95ee6ec8bcf7dba4d016a4c2f9
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/lib/console/capture.rb
CHANGED
@@ -7,13 +7,15 @@ require_relative "filter"
|
|
7
7
|
require_relative "output/failure"
|
8
8
|
|
9
9
|
module Console
|
10
|
-
# A
|
10
|
+
# A buffer which captures all logged messages into a buffer.
|
11
11
|
class Capture
|
12
|
+
# Create a new log capture buffer.
|
12
13
|
def initialize
|
13
14
|
@records = []
|
14
15
|
@verbose = false
|
15
16
|
end
|
16
17
|
|
18
|
+
# @attribute [Array(Hash)] All records captured by this buffer.
|
17
19
|
attr :records
|
18
20
|
|
19
21
|
# @deprecated Use {#records} instead of {#buffer}.
|
@@ -21,44 +23,67 @@ module Console
|
|
21
23
|
|
22
24
|
alias to_a records
|
23
25
|
|
26
|
+
# @attribute [Boolean] If true, the buffer will capture verbose messages.
|
24
27
|
attr :verbose
|
25
28
|
|
29
|
+
# Whether the buffer includes any records with the given subject or message pattern.
|
30
|
+
#
|
31
|
+
# @returns [Boolean] True if the buffer includes any records with the given pattern.
|
26
32
|
def include?(pattern)
|
27
33
|
@records.any? do |record|
|
28
34
|
record[:subject].to_s&.match?(pattern) or record[:message].to_s&.match?(pattern)
|
29
35
|
end
|
30
36
|
end
|
31
37
|
|
38
|
+
# Iterate over all records in the buffer.
|
39
|
+
#
|
40
|
+
# @yields {|record| ...} each record in the buffer.
|
41
|
+
# @parameter record [Hash] The record itself.
|
32
42
|
def each(&block)
|
33
43
|
@records.each(&block)
|
34
44
|
end
|
35
45
|
|
36
46
|
include Enumerable
|
37
47
|
|
48
|
+
# @returns [Hash] The first record in the buffer.
|
38
49
|
def first
|
39
50
|
@records.first
|
40
51
|
end
|
41
52
|
|
53
|
+
# @returns [Hash] The last record in the buffer.
|
42
54
|
def last
|
43
55
|
@records.last
|
44
56
|
end
|
45
57
|
|
58
|
+
# Clear all records from the buffer.
|
46
59
|
def clear
|
47
60
|
@records.clear
|
48
61
|
end
|
49
62
|
|
63
|
+
# @returns [Boolean] True if the buffer is empty.
|
50
64
|
def empty?
|
51
65
|
@records.empty?
|
52
66
|
end
|
53
67
|
|
68
|
+
# Sets the verbose flag which controls whether verbose messages are captured.
|
54
69
|
def verbose!(value = true)
|
55
70
|
@verbose = value
|
56
71
|
end
|
57
72
|
|
73
|
+
# @returns [Boolean] True if the buffer is capturing verbose messages.
|
58
74
|
def verbose?
|
59
75
|
@verbose
|
60
76
|
end
|
61
77
|
|
78
|
+
# Record a log message in the buffer.
|
79
|
+
#
|
80
|
+
# @parameter subject [Object] The subject of the log message.
|
81
|
+
# @parameter arguments [Array] The arguments to the log message.
|
82
|
+
# @parameter severity [Symbol] The severity of the log message.
|
83
|
+
# @parameter event [Event] The event associated with the log message.
|
84
|
+
# @parameter options [Hash] Additional options to pass to the log message.
|
85
|
+
# @yields {|buffer| ...} A block which can be used to write additional information to the log message.
|
86
|
+
# @parameter buffer [IO] The (optional) buffer to write to.
|
62
87
|
def call(subject = nil, *arguments, severity: UNKNOWN, event: nil, **options, &block)
|
63
88
|
record = {
|
64
89
|
time: ::Time.now.iso8601,
|
data/lib/console/clock.rb
CHANGED
@@ -4,7 +4,12 @@
|
|
4
4
|
# Copyright, 2021-2022, by Samuel Williams.
|
5
5
|
|
6
6
|
module Console
|
7
|
+
# A simple clock utility for tracking and formatting time.
|
7
8
|
module Clock
|
9
|
+
# Format a duration in seconds as a human readable string.
|
10
|
+
#
|
11
|
+
# @parameter duration [Numeric] The duration in seconds.
|
12
|
+
# @returns [String] The formatted duration.
|
8
13
|
def self.formatted_duration(duration)
|
9
14
|
if duration < 60.0
|
10
15
|
return "#{duration.round(2)}s"
|
@@ -27,7 +32,7 @@ module Console
|
|
27
32
|
return "#{duration.floor}d"
|
28
33
|
end
|
29
34
|
|
30
|
-
#
|
35
|
+
# @returns [Time] The current monotonic time.
|
31
36
|
def self.now
|
32
37
|
::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
|
33
38
|
end
|
@@ -6,30 +6,49 @@
|
|
6
6
|
require "logger"
|
7
7
|
|
8
8
|
module Console
|
9
|
+
# @namespace
|
9
10
|
module Compatible
|
10
11
|
# A compatible interface for {::Logger} which can be used with {Console}.
|
11
12
|
class Logger < ::Logger
|
13
|
+
# A compatible log device which can be used with {Console}. Suitable for use with code which (incorrectly) assumes that the log device a public interface and has certain methods/behaviours.
|
12
14
|
class LogDevice
|
15
|
+
# Create a new log device.
|
16
|
+
#
|
17
|
+
# @parameter subject [String] The subject of the log messages.
|
18
|
+
# @parameter output [Console::Interface] The output interface.
|
13
19
|
def initialize(subject, output)
|
14
20
|
@subject = subject
|
15
21
|
@output = output
|
16
22
|
end
|
17
23
|
|
24
|
+
# Write a message to the log device.
|
25
|
+
#
|
26
|
+
# @parameter message [String] The message to write.
|
18
27
|
def write(message)
|
19
28
|
@output.call(@subject, message)
|
20
29
|
end
|
21
30
|
|
31
|
+
# Log a message with the given severity.
|
32
|
+
#
|
33
|
+
# @paraemter arguments [Array] The arguments to log.
|
34
|
+
# @parameter options [Hash] Additional options.
|
22
35
|
def call(*arguments, **options)
|
23
36
|
@output.call(*arguments, **options)
|
24
37
|
end
|
25
38
|
|
39
|
+
# Reopen the log device. This is a no-op.
|
26
40
|
def reopen
|
27
41
|
end
|
28
42
|
|
43
|
+
# Close the log device. This is a no-op.
|
29
44
|
def close
|
30
45
|
end
|
31
46
|
end
|
32
|
-
|
47
|
+
|
48
|
+
# Create a new (compatible) logger.
|
49
|
+
#
|
50
|
+
# @parameter subject [String] The subject of the log messages.
|
51
|
+
# @parameter output [Console::Interface] The output interface.
|
33
52
|
def initialize(subject, output = Console)
|
34
53
|
super(nil)
|
35
54
|
|
@@ -37,6 +56,12 @@ module Console
|
|
37
56
|
@logdev = LogDevice.new(subject, output)
|
38
57
|
end
|
39
58
|
|
59
|
+
# Log a message with the given severity.
|
60
|
+
#
|
61
|
+
# @parameter severity [Integer] The severity of the message.
|
62
|
+
# @parameter message [String] The message to log.
|
63
|
+
# @parameter progname [String] The program name.
|
64
|
+
# @returns [Boolean] True if the message was logged.
|
40
65
|
def add(severity, message = nil, progname = nil)
|
41
66
|
severity ||= UNKNOWN
|
42
67
|
|
@@ -65,6 +90,10 @@ module Console
|
|
65
90
|
return true
|
66
91
|
end
|
67
92
|
|
93
|
+
# Format the severity.
|
94
|
+
#
|
95
|
+
# @parameter value [Integer] The severity value.
|
96
|
+
# @returns [Symbol] The formatted severity.
|
68
97
|
def format_severity(value)
|
69
98
|
super.downcase.to_sym
|
70
99
|
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2025, by Samuel Williams.
|
5
|
+
|
6
|
+
require_relative "filter"
|
7
|
+
require_relative "event"
|
8
|
+
require_relative "resolver"
|
9
|
+
require_relative "output"
|
10
|
+
require_relative "logger"
|
11
|
+
|
12
|
+
module Console
|
13
|
+
# Represents a configuration for the traces library.
|
14
|
+
class Config
|
15
|
+
PATH = ENV.fetch("CONSOLE_CONFIG_PATH", "config/console.rb")
|
16
|
+
|
17
|
+
# Load the configuration from the given path.
|
18
|
+
# @parameter path [String] The path to the configuration file.
|
19
|
+
# @returns [Config] The loaded configuration.
|
20
|
+
def self.load(path)
|
21
|
+
config = self.new
|
22
|
+
|
23
|
+
if File.exist?(path)
|
24
|
+
config.instance_eval(File.read(path), path)
|
25
|
+
end
|
26
|
+
|
27
|
+
return config
|
28
|
+
end
|
29
|
+
|
30
|
+
# Load the default configuration.
|
31
|
+
# @returns [Config] The default configuration.
|
32
|
+
def self.default
|
33
|
+
@default ||= self.load(PATH)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Set the default log level based on `$DEBUG` and `$VERBOSE`.
|
37
|
+
# You can also specify CONSOLE_LEVEL=debug or CONSOLE_LEVEL=info in environment.
|
38
|
+
# https://mislav.net/2011/06/ruby-verbose-mode/ has more details about how it all fits together.
|
39
|
+
def log_level(env = ENV)
|
40
|
+
Logger.default_log_level(env)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Controls verbose output using `$VERBOSE`.
|
44
|
+
def verbose?(env = ENV)
|
45
|
+
!$VERBOSE.nil? || env["CONSOLE_VERBOSE"]
|
46
|
+
end
|
47
|
+
|
48
|
+
# Create an output with the given output and options.
|
49
|
+
#
|
50
|
+
# @parameter output [IO] The output to write log messages to.
|
51
|
+
# @parameter env [Hash] The environment to read configuration from.
|
52
|
+
# @parameter options [Hash] Additional options to pass to the output.
|
53
|
+
# @returns [Output] The created output.
|
54
|
+
def make_output(io = nil, env = ENV, **options)
|
55
|
+
Output.new(io, env, **options)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Create a resolver with the given logger.
|
59
|
+
#
|
60
|
+
# @parameter logger [Logger] The logger to set the log levels on.
|
61
|
+
# @returns [Resolver | Nil] The created resolver.
|
62
|
+
def make_resolver(logger)
|
63
|
+
Resolver.default_resolver(logger)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Create a logger with the given output and options.
|
67
|
+
#
|
68
|
+
# @parameter output [IO] The output to write log messages to.
|
69
|
+
# @parameter env [Hash] The environment to read configuration from.
|
70
|
+
# @parameter options [Hash] Additional options to pass to the logger.
|
71
|
+
# @returns [Logger] The created logger.
|
72
|
+
def make_logger(io = $stderr, env = ENV, **options)
|
73
|
+
if options[:verbose].nil?
|
74
|
+
options[:verbose] = self.verbose?(env)
|
75
|
+
end
|
76
|
+
|
77
|
+
if options[:level].nil?
|
78
|
+
options[:level] = self.log_level(env)
|
79
|
+
end
|
80
|
+
|
81
|
+
output = self.make_output(io, env, **options)
|
82
|
+
|
83
|
+
logger = Logger.new(output, **options)
|
84
|
+
|
85
|
+
make_resolver(logger)
|
86
|
+
|
87
|
+
return logger
|
88
|
+
end
|
89
|
+
|
90
|
+
# Load the default configuration.
|
91
|
+
DEFAULT = self.default
|
92
|
+
end
|
93
|
+
end
|
@@ -9,33 +9,58 @@ require_relative "generic"
|
|
9
9
|
|
10
10
|
module Console
|
11
11
|
module Event
|
12
|
-
# Represents a failure
|
12
|
+
# Represents a failure of some kind, usually with an attached exception.
|
13
13
|
#
|
14
14
|
# ```ruby
|
15
|
-
#
|
15
|
+
# begin
|
16
|
+
# raise "Something went wrong!"
|
17
|
+
# rescue => exception
|
18
|
+
# Console::Event::Failure.log("Something went wrong!", exception)
|
19
|
+
# end
|
16
20
|
# ```
|
21
|
+
#
|
22
|
+
# Generally, you should use the {Console.error} method to log failures, as it will automatically create a failure event for you.
|
17
23
|
class Failure < Generic
|
24
|
+
# For the purpose of efficiently formatting backtraces, we need to know the root directory of the project.
|
25
|
+
#
|
26
|
+
# @returns [String | Nil] The root directory of the project, or nil if it could not be determined.
|
18
27
|
def self.default_root
|
19
28
|
Dir.getwd
|
20
29
|
rescue # e.g. Errno::EMFILE
|
21
30
|
nil
|
22
31
|
end
|
23
32
|
|
33
|
+
# Create a new failure event for the given exception.
|
34
|
+
#
|
35
|
+
# @parameter exception [Exception] The exception to log.
|
24
36
|
def self.for(exception)
|
25
37
|
self.new(exception, self.default_root)
|
26
38
|
end
|
27
39
|
|
40
|
+
# Log a failure event with the given exception.
|
41
|
+
#
|
42
|
+
# @parameter subject [String] The subject of the log message.
|
43
|
+
# @parameter exception [Exception] The exception to log.
|
44
|
+
# @parameter options [Hash] Additional options pass to the logger output.
|
28
45
|
def self.log(subject, exception, **options)
|
29
46
|
Console.error(subject, **self.for(exception).to_hash, **options)
|
30
47
|
end
|
31
48
|
|
49
|
+
# @attribute [Exception] The exception which caused the failure.
|
32
50
|
attr_reader :exception
|
33
51
|
|
34
|
-
|
52
|
+
# Create a new failure event for the given exception.
|
53
|
+
#
|
54
|
+
# @parameter exception [Exception] The exception to log.
|
55
|
+
# @parameter root [String] The root directory of the project.
|
56
|
+
def initialize(exception, root = self.class.default_root)
|
35
57
|
@exception = exception
|
36
58
|
@root = root
|
37
59
|
end
|
38
60
|
|
61
|
+
# Convert the failure event to a hash.
|
62
|
+
#
|
63
|
+
# @returns [Hash] The hash representation of the failure event.
|
39
64
|
def to_hash
|
40
65
|
Hash.new.tap do |hash|
|
41
66
|
hash[:type] = :failure
|
@@ -44,6 +69,10 @@ module Console
|
|
44
69
|
end
|
45
70
|
end
|
46
71
|
|
72
|
+
# Log the failure event.
|
73
|
+
#
|
74
|
+
# @parameter arguments [Array] The arguments to log.
|
75
|
+
# @parameter options [Hash] Additional options to pass to the logger output.
|
47
76
|
def emit(*arguments, **options)
|
48
77
|
options[:severity] ||= :error
|
49
78
|
|
@@ -5,19 +5,33 @@
|
|
5
5
|
|
6
6
|
module Console
|
7
7
|
module Event
|
8
|
+
# A generic event which can be used to represent structured data.
|
8
9
|
class Generic
|
10
|
+
# Convert the event to a hash suitable for JSON serialization.
|
11
|
+
#
|
12
|
+
# @returns [Hash] The hash representation of the event.
|
9
13
|
def as_json(...)
|
10
14
|
to_hash
|
11
15
|
end
|
12
16
|
|
17
|
+
# Serialize the event to JSON.
|
18
|
+
#
|
19
|
+
# @returns [String] The JSON representation of the event.
|
13
20
|
def to_json(...)
|
14
21
|
JSON.generate(as_json, ...)
|
15
22
|
end
|
16
23
|
|
24
|
+
# Convert the event to a string (JSON).
|
25
|
+
#
|
26
|
+
# @returns [String] The string representation of the event.
|
17
27
|
def to_s
|
18
28
|
to_json
|
19
29
|
end
|
20
30
|
|
31
|
+
# Log the event using the given output interface.
|
32
|
+
#
|
33
|
+
# @parameter arguments [Array] The arguments to log.
|
34
|
+
# @parameter options [Hash] Additional options to pass to the logger output.
|
21
35
|
def emit(*arguments, **options)
|
22
36
|
Console.call(*arguments, event: self, **options)
|
23
37
|
end
|
data/lib/console/event/spawn.rb
CHANGED
@@ -8,7 +8,7 @@ require_relative "../clock"
|
|
8
8
|
|
9
9
|
module Console
|
10
10
|
module Event
|
11
|
-
# Represents a spawn event.
|
11
|
+
# Represents a child process spawn event.
|
12
12
|
#
|
13
13
|
# ```ruby
|
14
14
|
# Console.info(self, **Console::Event::Spawn.for("ls", "-l"))
|
@@ -17,6 +17,11 @@ module Console
|
|
17
17
|
# event.status = Process.wait
|
18
18
|
# ```
|
19
19
|
class Spawn < Generic
|
20
|
+
# Create a new spawn event.
|
21
|
+
#
|
22
|
+
# @parameter arguments [Array] The arguments to the command, similar to how you would pass them to `Kernel.system` or `Process.spawn`.
|
23
|
+
# @parameter options [Hash] The options to pass to the command, similar to how you would pass them to `Kernel.system` or `Process.spawn`.
|
24
|
+
# @returns [Spawn] The new spawn event representing the command.
|
20
25
|
def self.for(*arguments, **options)
|
21
26
|
# Extract out the command environment:
|
22
27
|
if arguments.first.is_a?(Hash)
|
@@ -27,6 +32,11 @@ module Console
|
|
27
32
|
end
|
28
33
|
end
|
29
34
|
|
35
|
+
# Create a new spawn event.
|
36
|
+
#
|
37
|
+
# @parameter environment [Hash] The environment to use when running the command.
|
38
|
+
# @parameter arguments [Array] The arguments used for command execution.
|
39
|
+
# @parameter options [Hash] The options to pass to the command, similar to how you would pass them to `Kernel.system` or `Process.spawn`.
|
30
40
|
def initialize(environment, arguments, options)
|
31
41
|
@environment = environment
|
32
42
|
@arguments = arguments
|
@@ -38,12 +48,35 @@ module Console
|
|
38
48
|
@status = nil
|
39
49
|
end
|
40
50
|
|
51
|
+
# @attribute [Numeric] The start time of the command.
|
52
|
+
attr :start_time
|
53
|
+
|
54
|
+
# @attribute [Numeric] The end time of the command.
|
55
|
+
attr :end_time
|
56
|
+
|
57
|
+
# @attribute [Process::Status] The status of the command, if it has completed.
|
58
|
+
attr :status
|
59
|
+
|
60
|
+
# Set the status of the command, and record the end time.
|
61
|
+
#
|
62
|
+
# @parameter status [Process::Status] The status of the command.
|
63
|
+
def status=(status)
|
64
|
+
@end_time = Time.now
|
65
|
+
@status = status
|
66
|
+
end
|
67
|
+
|
68
|
+
# Calculate the duration of the command, if it has completed.
|
69
|
+
#
|
70
|
+
# @returns [Numeric] The duration of the command.
|
41
71
|
def duration
|
42
72
|
if @end_time
|
43
73
|
@end_time - @start_time
|
44
74
|
end
|
45
75
|
end
|
46
76
|
|
77
|
+
# Convert the spawn event to a hash suitable for JSON serialization.
|
78
|
+
#
|
79
|
+
# @returns [Hash] The hash representation of the spawn event.
|
47
80
|
def to_hash
|
48
81
|
Hash.new.tap do |hash|
|
49
82
|
hash[:type] = :spawn
|
@@ -59,15 +92,14 @@ module Console
|
|
59
92
|
end
|
60
93
|
end
|
61
94
|
|
95
|
+
# Log the spawn event.
|
96
|
+
#
|
97
|
+
# @parameter arguments [Array] The arguments to log.
|
98
|
+
# @parameter options [Hash] Additional options to pass to the logger output.
|
62
99
|
def emit(*arguments, **options)
|
63
100
|
options[:severity] ||= :info
|
64
101
|
super
|
65
102
|
end
|
66
|
-
|
67
|
-
def status=(status)
|
68
|
-
@end_time = Time.now
|
69
|
-
@status = status
|
70
|
-
end
|
71
103
|
end
|
72
104
|
end
|
73
105
|
end
|
data/lib/console/event.rb
CHANGED
data/lib/console/filter.rb
CHANGED
@@ -9,18 +9,28 @@
|
|
9
9
|
module Console
|
10
10
|
UNKNOWN = :unknown
|
11
11
|
|
12
|
+
# A log filter which can be used to filter log messages based on severity, subject, and other criteria.
|
12
13
|
class Filter
|
13
14
|
if Object.const_defined?(:Ractor) and RUBY_VERSION >= "3.1"
|
15
|
+
# Define a method which can be shared between ractors.
|
14
16
|
def self.define_immutable_method(name, &block)
|
15
17
|
block = Ractor.make_shareable(block)
|
16
18
|
self.define_method(name, &block)
|
17
19
|
end
|
18
20
|
else
|
21
|
+
# Define a method.
|
19
22
|
def self.define_immutable_method(name, &block)
|
20
23
|
define_method(name, &block)
|
21
24
|
end
|
22
25
|
end
|
23
26
|
|
27
|
+
# Create a new log filter with specific log levels.
|
28
|
+
#
|
29
|
+
# ```ruby
|
30
|
+
# class MyLogger < Console::Filter[debug: 0, okay: 1, bad: 2, terrible: 3]
|
31
|
+
# ```
|
32
|
+
#
|
33
|
+
# @parameter levels [Hash(Symbol, Integer)] A hash of log levels.
|
24
34
|
def self.[] **levels
|
25
35
|
klass = Class.new(self)
|
26
36
|
minimum_level, maximum_level = levels.values.minmax
|
@@ -54,6 +64,12 @@ module Console
|
|
54
64
|
return klass
|
55
65
|
end
|
56
66
|
|
67
|
+
# Create a new log filter.
|
68
|
+
#
|
69
|
+
# @parameter output [Console::Output] The output destination.
|
70
|
+
# @parameter verbose [Boolean] Enable verbose output.
|
71
|
+
# @parameter level [Integer] The log level.
|
72
|
+
# @parameter options [Hash] Additional options.
|
57
73
|
def initialize(output, verbose: true, level: self.class::DEFAULT_LEVEL, **options)
|
58
74
|
@output = output
|
59
75
|
@verbose = verbose
|
@@ -64,6 +80,12 @@ module Console
|
|
64
80
|
@options = options
|
65
81
|
end
|
66
82
|
|
83
|
+
# Create a new log filter with the given options, from an existing log filter.
|
84
|
+
#
|
85
|
+
# @parameter level [Integer] The log level.
|
86
|
+
# @parameter verbose [Boolean] Enable verbose output.
|
87
|
+
# @parameter options [Hash] Additional options.
|
88
|
+
# @returns [Console::Filter] The new log filter.
|
67
89
|
def with(level: @level, verbose: @verbose, **options)
|
68
90
|
dup.tap do |logger|
|
69
91
|
logger.level = level
|
@@ -72,14 +94,24 @@ module Console
|
|
72
94
|
end
|
73
95
|
end
|
74
96
|
|
97
|
+
# @attribute [Console::Output] The output destination.
|
75
98
|
attr_accessor :output
|
99
|
+
|
100
|
+
# @attribute [Boolean] Whether to enable verbose output.
|
76
101
|
attr :verbose
|
102
|
+
|
103
|
+
# @attribute [Integer] The current log level.
|
77
104
|
attr :level
|
78
105
|
|
106
|
+
# @attribute [Hash(Module, Integer)] The log levels for specific subject (classes).
|
79
107
|
attr :subjects
|
80
108
|
|
109
|
+
# @attribute [Hash] Additional options.
|
81
110
|
attr_accessor :options
|
82
111
|
|
112
|
+
# Set the log level.
|
113
|
+
#
|
114
|
+
# @parameter level [Integer | Symbol] The log level.
|
83
115
|
def level= level
|
84
116
|
if level.is_a? Symbol
|
85
117
|
@level = self.class::LEVELS[level]
|
@@ -88,19 +120,30 @@ module Console
|
|
88
120
|
end
|
89
121
|
end
|
90
122
|
|
123
|
+
# Set verbose output (enable by default with no arguments).
|
124
|
+
#
|
125
|
+
# @parameter value [Boolean] Enable or disable verbose output.
|
91
126
|
def verbose!(value = true)
|
92
127
|
@verbose = value
|
93
128
|
@output.verbose!(value)
|
94
129
|
end
|
95
130
|
|
131
|
+
# Disable all logging.
|
96
132
|
def off!
|
97
133
|
@level = self.class::MAXIMUM_LEVEL + 1
|
98
134
|
end
|
99
135
|
|
136
|
+
# Enable all logging.
|
100
137
|
def all!
|
101
138
|
@level = self.class::MINIMUM_LEVEL - 1
|
102
139
|
end
|
103
140
|
|
141
|
+
# Filter log messages based on the subject and log level.
|
142
|
+
#
|
143
|
+
# You must provide the subject's class, not an instance of the class.
|
144
|
+
#
|
145
|
+
# @parameter subject [Module] The subject to filter.
|
146
|
+
# @parameter level [Integer] The log level.
|
104
147
|
def filter(subject, level)
|
105
148
|
unless subject.is_a?(Module)
|
106
149
|
raise ArgumentError, "Expected a class, got #{subject.inspect}"
|
@@ -109,8 +152,13 @@ module Console
|
|
109
152
|
@subjects[subject] = level
|
110
153
|
end
|
111
154
|
|
155
|
+
# Whether logging is enabled for the given subject and log level.
|
156
|
+
#
|
112
157
|
# You can enable and disable logging for classes. This function checks if logging for a given subject is enabled.
|
113
|
-
#
|
158
|
+
#
|
159
|
+
# @parameter subject [Module] The subject to check.
|
160
|
+
# @parameter level [Integer] The log level.
|
161
|
+
# @returns [Boolean] Whether logging is enabled.
|
114
162
|
def enabled?(subject, level = self.class::MINIMUM_LEVEL)
|
115
163
|
subject = subject.class unless subject.is_a?(Module)
|
116
164
|
|
@@ -124,19 +172,24 @@ module Console
|
|
124
172
|
end
|
125
173
|
|
126
174
|
# Enable specific log level for the given class.
|
175
|
+
#
|
127
176
|
# @parameter name [Module] The class to enable.
|
128
177
|
def enable(subject, level = self.class::MINIMUM_LEVEL)
|
129
178
|
# Set the filter level of logging for a given subject which passes all log messages:
|
130
179
|
filter(subject, level)
|
131
180
|
end
|
132
181
|
|
182
|
+
# Disable logging for the given class.
|
183
|
+
#
|
184
|
+
# @parameter name [Module] The class to disable.
|
133
185
|
def disable(subject)
|
134
186
|
# Set the filter level of the logging for a given subject which filters all log messages:
|
135
187
|
filter(subject, self.class::MAXIMUM_LEVEL + 1)
|
136
188
|
end
|
137
189
|
|
138
190
|
# Clear any specific filters for the given class.
|
139
|
-
#
|
191
|
+
#
|
192
|
+
# @parameter subject [Module] The class to disable.
|
140
193
|
def clear(subject)
|
141
194
|
unless subject.is_a?(Module)
|
142
195
|
raise ArgumentError, "Expected a class, got #{subject.inspect}"
|
@@ -145,6 +198,13 @@ module Console
|
|
145
198
|
@subjects.delete(subject)
|
146
199
|
end
|
147
200
|
|
201
|
+
# Log a message with the given severity.
|
202
|
+
#
|
203
|
+
# @parameter subject [Object] The subject of the log message.
|
204
|
+
# @parameter arguments [Array] The arguments to log.
|
205
|
+
# @parameter options [Hash] Additional options to pass to the output.
|
206
|
+
# @parameter block [Proc] A block passed to the output.
|
207
|
+
# @returns [Nil] Always returns nil.
|
148
208
|
def call(subject, *arguments, **options, &block)
|
149
209
|
severity = options[:severity] || UNKNOWN
|
150
210
|
level = self.class::LEVELS[severity]
|