console 1.8.0 → 1.10.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eb8134534352969dd1f48e568f92e3ee1b6a8bcde97be1e44ef6e941e0437ead
4
- data.tar.gz: 5992182d9ed1f729ee350703f7a591b67a5f8b101ef420159f8d35bb40c2e0d4
3
+ metadata.gz: 640269ce4b1afa8413ce60f657ab3c3ed01a036a32e554c8643aa599a0052422
4
+ data.tar.gz: b5fa60cc24de752c16af2160856fe0cfe3c038f24a409e9d3069d701afbfcb9b
5
5
  SHA512:
6
- metadata.gz: 8f70f82899ad1e7fd31969ff98ca8b15604aff8b4749fdd31dafa5ae2a1959d6c507a0d1a9e048920c629aeea4990358bf6658baccd87bd656e691daa9b11a53
7
- data.tar.gz: 2d590c94668bbdfcd29d2457c99dc169855aa3294c3ae3978b27f658cb99e98b41cb3a7faa8662f7d6ab1824dd2e2f7d6312c120e2db61c35480d58ebd0b9a35
6
+ metadata.gz: 78b6e1c53280b26a315a422a418f36d228a583f095b41a406a33c67808ac2c299ab33399641880d5d3b7753d0ad88262fc536deac6ddd1ef6c8edf970b7d591e
7
+ data.tar.gz: d24238b81168471f70c4404badf944b24f01a92101b841513cb0ced7c6998b4a63efabb88bad49c042e72c174b1c56f2cd51cf385f7814d41d709cde040e1ab3
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Increase the verbosity of the logger to info.
4
+ def info
5
+ require_relative '../lib/console'
6
+
7
+ Console.logger.info!
8
+ end
9
+
10
+ # Increase the verbosity of the logger to debug.
11
+ def debug
12
+ require_relative '../lib/console'
13
+
14
+ Console.logger.debug!
15
+ end
@@ -21,64 +21,22 @@
21
21
  # THE SOFTWARE.
22
22
 
23
23
  require_relative 'console/logger'
24
- require_relative 'console/resolver'
25
- require_relative 'console/terminal/logger'
26
24
 
27
25
  module Console
28
- class << self
29
- attr_accessor :logger
30
-
31
- # Set the default log level based on `$DEBUG` and `$VERBOSE`.
32
- # You can also specify CONSOLE_LEVEL=debug or CONSOLE_LEVEL=info in environment.
33
- # https://mislav.net/2011/06/ruby-verbose-mode/ has more details about how it all fits together.
34
- def default_log_level(env = ENV)
35
- if level = (env['CONSOLE_LEVEL'] || env['CONSOLE_LOG_LEVEL'])
36
- Logger::LEVELS[level.to_sym] || Logger.warn
37
- elsif $DEBUG
38
- Logger::DEBUG
39
- elsif $VERBOSE.nil?
40
- Logger::WARN
41
- else
42
- Logger::INFO
43
- end
44
- end
45
-
46
- def default_resolver(logger, env = ENV)
47
- if names = env['CONSOLE_DEBUG']&.split(',')
48
- resolver = Resolver.new
49
-
50
- resolver.bind(names) do |klass|
51
- logger.enable(klass, Logger::DEBUG)
52
- end
53
-
54
- return resolver
55
- end
56
- end
57
-
58
- # Controls verbose output using `$VERBOSE`.
59
- def verbose?
60
- !$VERBOSE.nil?
61
- end
62
-
63
- def build(output, verbose: self.verbose?, level: self.default_log_level)
64
- terminal = Terminal::Logger.new(output, verbose: verbose)
65
-
66
- logger = Logger.new(terminal, verbose: verbose, level: level)
67
-
68
- return logger
69
- end
26
+ def self.logger
27
+ Logger.instance
70
28
  end
71
29
 
72
- # Create the logger instance:
73
- @logger = self.build($stderr)
74
- @resolver = self.default_resolver(@logger)
30
+ def self.logger= instance
31
+ Logger.instance= instance
32
+ end
75
33
 
76
34
  def logger= logger
77
35
  @logger = logger
78
36
  end
79
37
 
80
38
  def logger
81
- @logger || Console.logger
39
+ @logger || Logger.instance
82
40
  end
83
41
 
84
42
  def self.extended(klass)
@@ -21,15 +21,20 @@
21
21
  require_relative 'filter'
22
22
 
23
23
  module Console
24
+ # A general sink which captures all events into a buffer.
24
25
  class Capture
25
26
  def initialize
26
- @events = []
27
+ @buffer = []
27
28
  end
28
29
 
29
- attr :events
30
+ attr :buffer
30
31
 
31
32
  def last
32
- @events.last
33
+ @buffer.last
34
+ end
35
+
36
+ def clear
37
+ @buffer.clear
33
38
  end
34
39
 
35
40
  def verbose!(value = true)
@@ -37,7 +42,7 @@ module Console
37
42
 
38
43
  def call(subject = nil, *arguments, severity: UNKNOWN, **options, &block)
39
44
  message = {
40
- time: Time.now.iso8601,
45
+ time: ::Time.now.iso8601,
41
46
  severity: severity,
42
47
  **options,
43
48
  }
@@ -60,7 +65,7 @@ module Console
60
65
  end
61
66
  end
62
67
 
63
- @events << message
68
+ @buffer << message
64
69
  end
65
70
  end
66
71
  end
@@ -20,3 +20,5 @@
20
20
 
21
21
  require_relative 'event/spawn'
22
22
  require_relative 'event/failure'
23
+ require_relative 'event/metric'
24
+ require_relative 'event/progress'
@@ -49,6 +49,10 @@ module Console
49
49
  terminal[:exception_backtrace] ||= terminal.style(:red)
50
50
  end
51
51
 
52
+ def to_h
53
+ {exception: @exception, root: @root}
54
+ end
55
+
52
56
  def format(output, terminal, verbose)
53
57
  format_exception(@exception, nil, output, terminal, verbose)
54
58
  end
@@ -24,6 +24,13 @@ module Console
24
24
  def self.register(terminal)
25
25
  end
26
26
 
27
+ def to_h
28
+ end
29
+
30
+ def as_json
31
+ to_h
32
+ end
33
+
27
34
  def format(buffer, terminal)
28
35
  end
29
36
  end
@@ -0,0 +1,49 @@
1
+ # Copyright, 2017, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require_relative 'generic'
22
+
23
+ module Console
24
+ module Event
25
+ class Metric < Generic
26
+ def self.[](**parameters)
27
+ parameters.map(&self.method(:new))
28
+ end
29
+
30
+ def initialize(name, value, **tags)
31
+ @name = name
32
+ @value = value
33
+ @tags = tags
34
+ end
35
+
36
+ attr :name
37
+ attr :value
38
+ attr :tags
39
+
40
+ def to_h
41
+ {name: @name, value: @value, tags: @tags}
42
+ end
43
+
44
+ def format(output, terminal, verbose)
45
+ output.puts "#{@name}=#{@value} #{@tags.inspect}"
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,75 @@
1
+ # Copyright, 2017, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require_relative 'generic'
22
+
23
+ module Console
24
+ module Event
25
+ class Progress < Generic
26
+ BLOCK = [
27
+ " ",
28
+ "▏",
29
+ "▎",
30
+ "▍",
31
+ "▌",
32
+ "▋",
33
+ "▊",
34
+ "▉",
35
+ "█",
36
+ ]
37
+
38
+ def initialize(current, total)
39
+ @current = current
40
+ @total = total
41
+ end
42
+
43
+ attr :current
44
+ attr :total
45
+
46
+ def value
47
+ @current.to_f / @total.to_f
48
+ end
49
+
50
+ def bar(value = self.value, width = 70)
51
+ blocks = width * value
52
+ full_blocks = blocks.floor
53
+ partial_block = ((blocks - full_blocks) * BLOCK.size).floor
54
+
55
+ if partial_block.zero?
56
+ BLOCK.last * full_blocks
57
+ else
58
+ "#{BLOCK.last * full_blocks}#{BLOCK[partial_block]}"
59
+ end.ljust(width)
60
+ end
61
+
62
+ def self.register(terminal)
63
+ terminal[:progress_bar] ||= terminal.style(:blue, :white)
64
+ end
65
+
66
+ def to_h
67
+ {current: @current, total: @total}
68
+ end
69
+
70
+ def format(output, terminal, verbose)
71
+ output.puts "#{terminal[:progress_bar]}#{self.bar}#{terminal.reset} #{sprintf('%6.2f', self.value * 100)}%"
72
+ end
73
+ end
74
+ end
75
+ end
@@ -24,6 +24,7 @@ module Console
24
24
  module Event
25
25
  class Spawn < Generic
26
26
  def self.for(*arguments, **options)
27
+ # Extract out the command environment:
27
28
  if arguments.first.is_a?(Hash)
28
29
  self.new(*arguments, **options)
29
30
  else
@@ -51,6 +52,10 @@ module Console
51
52
  terminal[:shell_command] ||= terminal.style(:blue, nil, :bold)
52
53
  end
53
54
 
55
+ def to_h
56
+ {environment: @environment, arguments: @arguments, options: @options}
57
+ end
58
+
54
59
  def format(output, terminal, verbose)
55
60
  arguments = @arguments.flatten.collect(&:to_s)
56
61
 
@@ -46,7 +46,7 @@ module Console
46
46
  end
47
47
 
48
48
  define_method("#{name}?") do
49
- @level >= level
49
+ @level <= level
50
50
  end
51
51
  end
52
52
  end
@@ -19,13 +19,65 @@
19
19
  # THE SOFTWARE.
20
20
 
21
21
  require_relative 'filter'
22
+ require_relative 'progress'
23
+
24
+ require_relative 'resolver'
25
+ require_relative 'terminal/logger'
26
+
27
+ require 'fiber/local'
22
28
 
23
29
  module Console
24
30
  class Logger < Filter[debug: 0, info: 1, warn: 2, error: 3, fatal: 4]
31
+ extend Fiber::Local
32
+
33
+ # Set the default log level based on `$DEBUG` and `$VERBOSE`.
34
+ # You can also specify CONSOLE_LEVEL=debug or CONSOLE_LEVEL=info in environment.
35
+ # https://mislav.net/2011/06/ruby-verbose-mode/ has more details about how it all fits together.
36
+ def self.default_log_level(env = ENV)
37
+ if level = (env['CONSOLE_LEVEL'] || env['CONSOLE_LOG_LEVEL'])
38
+ LEVELS[level.to_sym] || level.to_i
39
+ elsif $DEBUG
40
+ DEBUG
41
+ elsif $VERBOSE.nil?
42
+ WARN
43
+ else
44
+ INFO
45
+ end
46
+ end
47
+
48
+ # Controls verbose output using `$VERBOSE`.
49
+ def self.verbose?(env = ENV)
50
+ !$VERBOSE.nil? || env['CONSOLE_VERBOSE']
51
+ end
52
+
53
+ def self.default_logger(output, verbose: self.verbose?, level: self.default_log_level)
54
+ terminal = Terminal::Logger.new(output, verbose: verbose)
55
+
56
+ logger = self.new(terminal, verbose: verbose, level: level)
57
+ resolver = Resolver.default_resolver(logger)
58
+
59
+ return logger
60
+ end
61
+
62
+ def self.local
63
+ self.default_logger($stderr)
64
+ end
65
+
25
66
  DEFAULT_LEVEL = 1
26
67
 
27
68
  def initialize(output, **options)
28
69
  super(output, **options)
29
70
  end
71
+
72
+ def progress(subject, total, **options)
73
+ Progress.new(self, subject, total, **options)
74
+ end
75
+
76
+ # @deprecated Please use {progress}.
77
+ alias measure progress
78
+
79
+ def failure(subject, exception, *arguments, &block)
80
+ fatal(subject, *arguments, Event::Failure.new(exception), &block)
81
+ end
30
82
  end
31
83
  end
@@ -0,0 +1,140 @@
1
+ # Copyright, 2019, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require_relative 'event/progress'
22
+
23
+ module Console
24
+ class Progress
25
+ def self.now
26
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
27
+ end
28
+
29
+ def initialize(output, subject, total = 0, minimum_output_duration: 1.0)
30
+ @output = output
31
+ @subject = subject
32
+
33
+ @start_time = Progress.now
34
+
35
+ @last_output_time = nil
36
+ @minimum_output_duration = 0.1
37
+
38
+ @current = 0
39
+ @total = total
40
+ end
41
+
42
+ attr :subject
43
+ attr :current
44
+ attr :total
45
+
46
+ def duration
47
+ Progress.now - @start_time
48
+ end
49
+
50
+ def progress
51
+ @current.to_f / @total.to_f
52
+ end
53
+
54
+ def remaining
55
+ @total - @current
56
+ end
57
+
58
+ def average_duration
59
+ if @current > 0
60
+ duration / @current
61
+ end
62
+ end
63
+
64
+ def estimated_remaining_time
65
+ if average_duration = self.average_duration
66
+ average_duration * remaining
67
+ end
68
+ end
69
+
70
+ def increment(amount = 1)
71
+ @current += amount
72
+
73
+ if output?
74
+ @output.info(@subject, self) {Event::Progress.new(@current, @total)}
75
+ @last_output_time = Progress.now
76
+ end
77
+
78
+ return self
79
+ end
80
+
81
+ def resize(total)
82
+ @total = total
83
+
84
+ @output.info(@subject, self) {Event::Progress.new(@current, @total)}
85
+ @last_output_time = Progress.now
86
+
87
+ return self
88
+ end
89
+
90
+ def mark(*arguments)
91
+ @output.info(@subject, *arguments)
92
+ end
93
+
94
+ def to_s
95
+ if estimated_remaining_time = self.estimated_remaining_time
96
+ "#{@current}/#{@total} completed in #{self.formatted_duration self.duration}, #{self.formatted_duration estimated_remaining_time} remaining."
97
+ else
98
+ "#{@current}/#{@total} completed, waiting for estimate..."
99
+ end
100
+ end
101
+
102
+ private
103
+
104
+ def duration_since_last_output
105
+ if @last_output_time
106
+ Progress.now - @last_output_time
107
+ end
108
+ end
109
+
110
+ def output?
111
+ if duration = duration_since_last_output
112
+ return duration > @minimum_output_duration
113
+ else
114
+ return true
115
+ end
116
+ end
117
+
118
+ def formatted_duration(duration)
119
+ if duration < 60.0
120
+ return "#{duration.round(2)}s"
121
+ end
122
+
123
+ duration /= 60.0
124
+
125
+ if duration < 60.0
126
+ return "#{duration.round}m"
127
+ end
128
+
129
+ duration /= 60.0
130
+
131
+ if duration < 60.0
132
+ return "#{duration.round(1)}h"
133
+ end
134
+
135
+ duration /= 24.0
136
+
137
+ return "#{duration.round(1)}d"
138
+ end
139
+ end
140
+ end
@@ -22,6 +22,36 @@ require_relative 'filter'
22
22
 
23
23
  module Console
24
24
  class Resolver
25
+ # You can change the log level for different classes using CONSOLE_<LEVEL> env vars.
26
+ #
27
+ # e.g. `CONSOLE_WARN=Acorn,Banana CONSOLE_DEBUG=Cat` will set the log level for the classes Acorn and Banana to `warn` and Cat to `debug`. This overrides the default log level.
28
+ #
29
+ # @parameter logger [Logger] A logger instance to set the logging levels on.
30
+ # @parameter env [Hash] The environment to read levels from.
31
+ #
32
+ # @returns [Nil] If there were no custom logging levels specified in the environment.
33
+ # @returns [Resolver] If there were custom logging levels, then the created resolver is returned.
34
+ def self.default_resolver(logger, env = ENV)
35
+ # Find all CONSOLE_<LEVEL> variables from environment:
36
+ levels = Logger::LEVELS
37
+ .map{|label, level| [level, env["CONSOLE_#{label.upcase}"]&.split(',')]}
38
+ .to_h
39
+ .compact
40
+
41
+ # If we have any levels, then create a class resolver, and each time a class is resolved, set the log level for that class to the specified level:
42
+ if levels.any?
43
+ resolver = Resolver.new
44
+
45
+ levels.each do |level, names|
46
+ resolver.bind(names) do |klass|
47
+ logger.enable(klass, level)
48
+ end
49
+ end
50
+
51
+ return resolver
52
+ end
53
+ end
54
+
25
55
  def initialize
26
56
  @names = {}
27
57
 
@@ -24,6 +24,8 @@ require_relative '../event'
24
24
  require_relative 'text'
25
25
  require_relative 'xterm'
26
26
 
27
+ require 'json'
28
+
27
29
  module Console
28
30
  module Terminal
29
31
  # This, and all related methods, is considered private.
@@ -77,7 +79,9 @@ module Console
77
79
  end
78
80
 
79
81
  attr :io
82
+
80
83
  attr_accessor :verbose
84
+
81
85
  attr :start
82
86
  attr :terminal
83
87
 
@@ -94,7 +98,7 @@ module Console
94
98
 
95
99
  UNKNOWN = 'unknown'
96
100
 
97
- def call(subject = nil, *arguments, name: nil, severity: UNKNOWN, &block)
101
+ def call(subject = nil, *arguments, name: nil, severity: UNKNOWN, **options, &block)
98
102
  prefix = build_prefix(name || severity.to_s)
99
103
  indent = " " * prefix.size
100
104
 
@@ -104,6 +108,10 @@ module Console
104
108
  format_subject(severity, prefix, subject, buffer)
105
109
  end
106
110
 
111
+ if options&.any?
112
+ format_options(options, buffer)
113
+ end
114
+
107
115
  arguments.each do |argument|
108
116
  format_argument(argument, buffer)
109
117
  end
@@ -121,6 +129,10 @@ module Console
121
129
 
122
130
  protected
123
131
 
132
+ def format_options(options, output)
133
+ format_value(options.to_json, output)
134
+ end
135
+
124
136
  def format_argument(argument, output)
125
137
  case argument
126
138
  when Exception
@@ -19,5 +19,5 @@
19
19
  # THE SOFTWARE.
20
20
 
21
21
  module Console
22
- VERSION = "1.8.0"
22
+ VERSION = "1.10.0"
23
23
  end
metadata CHANGED
@@ -1,17 +1,31 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: console
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.0
4
+ version: 1.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-02-01 00:00:00.000000000 Z
11
+ date: 2020-10-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: covered
14
+ name: fiber-local
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bake
15
29
  requirement: !ruby/object:Gem::Requirement
16
30
  requirements:
17
31
  - - ">="
@@ -38,6 +52,20 @@ dependencies:
38
52
  - - ">="
39
53
  - !ruby/object:Gem::Version
40
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: covered
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
41
69
  - !ruby/object:Gem::Dependency
42
70
  name: rake
43
71
  requirement: !ruby/object:Gem::Requirement
@@ -66,30 +94,25 @@ dependencies:
66
94
  - - "~>"
67
95
  - !ruby/object:Gem::Version
68
96
  version: '3.0'
69
- description:
97
+ description:
70
98
  email:
71
- - samuel.williams@oriontransfer.co.nz
72
99
  executables: []
73
100
  extensions: []
74
101
  extra_rdoc_files: []
75
102
  files:
76
- - ".editorconfig"
77
- - ".gitignore"
78
- - ".rspec"
79
- - ".travis.yml"
80
- - Gemfile
81
- - README.md
82
- - Rakefile
83
- - console.gemspec
103
+ - bake/console.rb
84
104
  - lib/console.rb
85
105
  - lib/console/buffer.rb
86
106
  - lib/console/capture.rb
87
107
  - lib/console/event.rb
88
108
  - lib/console/event/failure.rb
89
109
  - lib/console/event/generic.rb
110
+ - lib/console/event/metric.rb
111
+ - lib/console/event/progress.rb
90
112
  - lib/console/event/spawn.rb
91
113
  - lib/console/filter.rb
92
114
  - lib/console/logger.rb
115
+ - lib/console/progress.rb
93
116
  - lib/console/resolver.rb
94
117
  - lib/console/serialized/logger.rb
95
118
  - lib/console/split.rb
@@ -98,12 +121,11 @@ files:
98
121
  - lib/console/terminal/text.rb
99
122
  - lib/console/terminal/xterm.rb
100
123
  - lib/console/version.rb
101
- - proposal.md
102
124
  homepage: https://github.com/socketry/console
103
125
  licenses:
104
126
  - MIT
105
127
  metadata: {}
106
- post_install_message:
128
+ post_install_message:
107
129
  rdoc_options: []
108
130
  require_paths:
109
131
  - lib
@@ -111,7 +133,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
111
133
  requirements:
112
134
  - - ">="
113
135
  - !ruby/object:Gem::Version
114
- version: '0'
136
+ version: '2.5'
115
137
  required_rubygems_version: !ruby/object:Gem::Requirement
116
138
  requirements:
117
139
  - - ">="
@@ -119,7 +141,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
119
141
  version: '0'
120
142
  requirements: []
121
143
  rubygems_version: 3.1.2
122
- signing_key:
144
+ signing_key:
123
145
  specification_version: 4
124
146
  summary: Beautiful logging for Ruby.
125
147
  test_files: []
@@ -1,6 +0,0 @@
1
- root = true
2
-
3
- [*]
4
- indent_style = tab
5
- indent_size = 2
6
-
data/.gitignore DELETED
@@ -1,12 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /_yardoc/
4
- /coverage/
5
- /doc/
6
- /pkg/
7
- /spec/reports/
8
- /tmp/
9
-
10
- Gemfile.lock
11
- .rspec_status
12
- .covered.db
data/.rspec DELETED
@@ -1,4 +0,0 @@
1
- --format documentation
2
- --color
3
- --require spec_helper
4
- --warnings
@@ -1,19 +0,0 @@
1
- language: ruby
2
- dist: xenial
3
- cache: bundler
4
-
5
- matrix:
6
- include:
7
- - rvm: 2.4
8
- - rvm: 2.5
9
- - rvm: 2.6
10
- - rvm: 2.7
11
- - rvm: 2.6
12
- env: COVERAGE=PartialSummary,Coveralls
13
- - rvm: truffleruby
14
- - rvm: jruby-head
15
- - rvm: ruby-head
16
- allow_failures:
17
- - rvm: truffleruby
18
- - rvm: ruby-head
19
- - rvm: jruby-head
data/Gemfile DELETED
@@ -1,8 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
-
5
- # Specify your gem's dependencies in console.gemspec
6
- gemspec
7
-
8
- gem "pry"
data/README.md DELETED
@@ -1,212 +0,0 @@
1
- # Console
2
-
3
- Provides beautiful console logging for Ruby applications. Implements fast, buffered log output.
4
-
5
- [![Build Status](https://travis-ci.com/socketry/console.svg)](http://travis-ci.com/socketry/console)
6
- [![Coverage Status](https://coveralls.io/repos/socketry/console/badge.svg)](https://coveralls.io/r/socketry/console)
7
-
8
- ## Motivation
9
-
10
- When Ruby decided to reverse the order of exception backtraces, I finally gave up using the built in logging and decided restore sanity to the output of my programs once and for all!
11
-
12
- ## Installation
13
-
14
- Add this line to your application's Gemfile:
15
-
16
- ```ruby
17
- gem 'console'
18
- ```
19
-
20
- And then execute:
21
-
22
- $ bundle
23
-
24
- ## Usage
25
-
26
- As your code executes, it generates interesting events which you want to know about. The general approach is to use an `Console::Logger` which outputs text to the terminal. The text is generated by inspecting the console that occurred.
27
-
28
- Capturing structured information allows it to be used in different ways. These events can be sent to a logger or some other system (e.g. web browser, syslog) and analysed in more detail.
29
-
30
- ### Default Logger
31
-
32
- Generally speaking, use `Console.logger` which is suitable for logging to the user's terminal.
33
-
34
- ### Environment Variables
35
-
36
- #### `CONSOLE_LEVEL=debug`
37
-
38
- Control the default logger level. You can set it to any of the supported log levels: `debug`, `info`, `warn`, `error`, `fatal`.
39
-
40
- #### `CONSOLE_DEBUG=MyClass,MyModule::MyClass`
41
-
42
- Enable debug logging for the specified class names. You can specify one or more class names which will be resolved at runtime.
43
-
44
- ### Module Integration
45
-
46
- ```ruby
47
- require 'console'
48
-
49
- # Set the log level:
50
- Console.logger.debug!
51
-
52
- module MyModule
53
- extend Console
54
-
55
- def self.test_logger
56
- logger.debug "GOTO LINE 1."
57
- logger.info "5 things your doctor won't tell you!"
58
- logger.warn "Something didn't work as expected!"
59
- logger.error "The matrix has two cats!"
60
- end
61
-
62
- test_logger
63
- end
64
- ```
65
-
66
- ### Class Integration
67
-
68
- ```ruby
69
- require 'console'
70
-
71
- # Set the log level:
72
- Console.logger.debug!
73
-
74
- class MyObject
75
- include Console
76
-
77
- def test_logger
78
- logger.debug "GOTO LINE 1."
79
- logger.info "5 things your doctor won't tell you!"
80
- logger.warn "Something didn't work as expected!"
81
- logger.error "The matrix has two cats!"
82
- end
83
- end
84
-
85
- MyObject.new.test_logger
86
- ```
87
-
88
- ### Subject Logging
89
-
90
- The first argument to the log method is the subject.
91
-
92
- ```ruby
93
- class Thing
94
- def call
95
- Console.logger.info(self) {"Something is going on"}
96
- end
97
- end
98
- ```
99
-
100
- Using this approach, you can turn on and off specific subjects by using the class name:
101
-
102
- ```ruby
103
- $ CONSOLE_DEBUG=Thing ./script.rb
104
- ```
105
-
106
- This will conditionally enable all log statements which have a subject of class `Thing`.
107
-
108
- ### Console Formatting
109
-
110
- Console classes are used to wrap data which can generate structured log messages:
111
-
112
- ```ruby
113
- require 'console'
114
-
115
- class MyConsole < Console::Generic
116
- def format(output, terminal, verbose)
117
- output.puts "My console text!"
118
- end
119
- end
120
-
121
- Console.logger.info("My Console", MyConsole.new)
122
- ```
123
-
124
- #### Failure Events
125
-
126
- `Console::Event::Failure` represents an exception and will log the message and backtrace recursively.
127
-
128
- #### Spawn Events
129
-
130
- `Console::Event::Spawn` represents the execution of a command, and will log the environment, arguments and options used to execute it.
131
-
132
- ### Custom Log Levels
133
-
134
- `Console::Filter` implements support for multiple log levels.
135
-
136
- ```ruby
137
- require 'console'
138
-
139
- MyLogger = Console::Filter[noise: 0, stuff: 1, broken: 2]
140
-
141
- # verbose: true - log severity/name/pid etc.
142
- logger = MyLogger.new(Console.logger, name: "Java", verbose: true)
143
-
144
- logger.broken("It's so janky.")
145
- ```
146
-
147
- ### Multiple Outputs
148
-
149
- Use `Console::Split` to log to multiple destinations.
150
-
151
- ```ruby
152
- require 'console/terminal'
153
- require 'console/serialized/logger'
154
- require 'console/logger'
155
- require 'console/split'
156
-
157
- terminal = Console::Terminal::Logger.new
158
- file = Console::Serialized::Logger.new(File.open("log.json", "a"))
159
-
160
- logger = Console::Logger.new(Console::Split[terminal, file])
161
-
162
- logger.info "I can go everywhere!"
163
- ```
164
-
165
- ### Custom Logger Output
166
-
167
- `Console::Logger` provides a default interface which is a drop in replacemnet for `Logger` and other similar implementations. The only method required for output is `#call(*arguments, **options, &block)`.
168
-
169
- ```ruby
170
- require 'console/logger'
171
-
172
- output = proc do |*arguments, **options, &block|
173
- puts "arguments: #{arguments.inspect} options: #{options.inspect} block: #{block.call}"
174
- end
175
-
176
- logger = Console::Logger.new(output)
177
-
178
- logger.info("Hello World!", meta: "data") {"block"}
179
- # => arguments: ["Hello World!"] options: {:severity=>:info, :meta=>"data"} block: block
180
- ```
181
-
182
- ## Contributing
183
-
184
- 1. Fork it
185
- 2. Create your feature branch (`git checkout -b my-new-feature`)
186
- 3. Commit your changes (`git commit -am 'Add some feature'`)
187
- 4. Push to the branch (`git push origin my-new-feature`)
188
- 5. Create new Pull Request
189
-
190
- ## License
191
-
192
- Released under the MIT license.
193
-
194
- Copyright, 2019, by [Samuel Williams](https://www.codeotaku.com).
195
-
196
- Permission is hereby granted, free of charge, to any person obtaining a copy
197
- of this software and associated documentation files (the "Software"), to deal
198
- in the Software without restriction, including without limitation the rights
199
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
200
- copies of the Software, and to permit persons to whom the Software is
201
- furnished to do so, subject to the following conditions:
202
-
203
- The above copyright notice and this permission notice shall be included in
204
- all copies or substantial portions of the Software.
205
-
206
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
207
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
208
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
209
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
210
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
211
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
212
- THE SOFTWARE.
data/Rakefile DELETED
@@ -1,13 +0,0 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
3
-
4
- RSpec::Core::RakeTask.new(:spec)
5
-
6
- task :default => :spec
7
-
8
- task :console do
9
- require 'pry'
10
- require 'console'
11
-
12
- binding.pry
13
- end
@@ -1,25 +0,0 @@
1
-
2
- require_relative "lib/console/version"
3
-
4
- Gem::Specification.new do |spec|
5
- spec.name = "console"
6
- spec.version = Console::VERSION
7
- spec.licenses = ["MIT"]
8
- spec.authors = ["Samuel Williams"]
9
- spec.email = ["samuel.williams@oriontransfer.co.nz"]
10
-
11
- spec.summary = "Beautiful logging for Ruby."
12
- spec.homepage = "https://github.com/socketry/console"
13
-
14
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
15
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
16
- end
17
-
18
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
- spec.require_paths = ["lib"]
20
-
21
- spec.add_development_dependency "covered"
22
- spec.add_development_dependency "bundler"
23
- spec.add_development_dependency "rake", "~> 10.0"
24
- spec.add_development_dependency "rspec", "~> 3.0"
25
- end
@@ -1,84 +0,0 @@
1
- # Global Logger
2
-
3
- Configure what logging looks like globally:
4
-
5
- ```ruby
6
- Console.logger
7
- ```
8
-
9
- Other logger instances would inherit their initial configuration from the global logger.
10
-
11
- Rather than the output being configurable on the global logger, it would always route to `$stdout`. _Or perhaps no destinations should exist and you add one; there must be a way to attach a formatter to even the default destination._
12
-
13
- # Adding Destinations
14
-
15
- The global logger or any instance could log to multiple destinations:
16
-
17
- ```ruby
18
- Console.add(some_io, formatter: some_formatter)
19
- ```
20
-
21
- I _think_ that formatters would be defined on destinations. This would allow for writing in one format to `$stdout` and another to `syslog`, for example.
22
-
23
- # Logger Instances
24
-
25
- Named instances could be created with a given output:
26
-
27
- ```ruby
28
- connection_logger = Console.new(:connection, output: ...)
29
- ```
30
-
31
- Outputs would not reference an io object, but rather another named instance (defaulting to global). Again, Destinations + Formatters could be added to any instance. This would allow outputs to be chained.
32
-
33
- ## Instances As Subjects
34
-
35
- Perhaps an interesting idea is letting logger instance names be subjects, controllable from the global logger. In the example above, `:connection` would become a known subject that could be enabled/disabled from the global logger:
36
-
37
- ```ruby
38
- Console.disable(:connection)
39
- ```
40
-
41
- This lets us very easily disable the logging of events of a particular type.
42
-
43
- ---
44
-
45
- In [Pakyow's logger](https://gist.github.com/bryanp/0329d58c753f1fa6e99d970960ad006d#file-logger-rb), instances are created in these cases:
46
-
47
- * Environment: Single logger for the environment, named `:pkyw`.
48
- * Connection: Per-Request logger containing the connection id, named `:http`.
49
- * WebSocket: Per-WebSocket logger containing the WebSocket id, named `:sock`.
50
- * Async: The logger that async is configured with, named `:asnc`.
51
-
52
- Instances could be initialized with metadata that is passed with the console to the formatter:
53
-
54
- ```ruby
55
- connection_logger = Console.new(:http, output: ..., connection_id: "123")
56
- ```
57
-
58
- # Formatters
59
-
60
- Just a class with a `format` method that accepts an `console`, which is a hash or simple object containing the console data along with attached metadata (e.g. timestamp, metadata from the instance). Returns a string, and/or writes directly to the buffer.
61
-
62
- # Custom Levels
63
-
64
- Pakyow's logger uses the following levels:
65
-
66
- * all
67
- * verbose
68
- * debug
69
- * info
70
- * warn
71
- * error
72
- * fatal
73
- * unknown
74
- * off
75
-
76
- `all` and `off` aren't turned into logging methods in `Pakyow::Logger`, but rather the log level can be set to either one as an easy way to guarantee that all or no logs will be written, without knowing what the lowest and highest level of logging are in the system.
77
-
78
- Projects often have different needs, so making this easily configurable on both the global logger and individual logger instances would be amazing:
79
-
80
- ```ruby
81
- Console.levels(
82
- %i(all verbose debug info warn error fatal unknown off)
83
- )
84
- ```