extended_logger 0.3.0 → 0.5.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
  SHA1:
3
- metadata.gz: 12acc57301fb31c71adadd859ed1e9227adf4e38
4
- data.tar.gz: 15e746abb842188e8c1f2d4786f9c7161d35dc60
3
+ metadata.gz: 47bdad0e0a33ecdf506b71aa4bb4784085583b19
4
+ data.tar.gz: 7e3ae841f32d58d983af5d7062e4e18145ddba1a
5
5
  SHA512:
6
- metadata.gz: 19703c7afe912c2c68227efc333641b5d520f98688f73ca23c05261f6bb5984d93e2e6796af3d4593006db05bcd631c9dc66e07bc4d7864358b0aa4c8f4813ec
7
- data.tar.gz: c32d52b617a488dd072899e87e2f1d09a268e4a3a71d4878bbd5186d20e060b9d97e8ea2f26fbc696451765414aa46d829ba40966d234843454920124d74ceb2
6
+ metadata.gz: 7f993016f5115afb6b3cf8a63a37dfc09209bdca075a1eff70666b0de2704502569325f811d1e7a61e9991091768615b11cc10b8c82ca81ff75e549ba21b3226
7
+ data.tar.gz: 998ee7a2958d74795175ff3e69e138651b6eeeb40df13d506f81b28e6c53f367e611c36f4737deba6d3918ea65ef78fe29809770d46460d7f5d45cbd6b312cb4
@@ -0,0 +1,124 @@
1
+ class ExtendedLogger
2
+ class ColorScheme
3
+ attr_reader :map
4
+
5
+ def initialize map
6
+ @map = map
7
+ end
8
+
9
+ def self.build symbol_map
10
+ code_map = {}
11
+
12
+ symbol_map.each do |label, (fg_sym, bg_sym)|
13
+ fg = Colors.index fg_sym
14
+ bg = Colors.index bg_sym
15
+
16
+ code_map[label] = [fg, bg]
17
+ end
18
+
19
+ new code_map
20
+ end
21
+
22
+ def color_code code
23
+ if code
24
+ code.to_s 16
25
+ else
26
+ '?'.freeze
27
+ end
28
+ end
29
+
30
+ def colorize severity, text
31
+ fg, bg = map[severity]
32
+
33
+ if bg
34
+ if bg > 8
35
+ text.insert 0, "\e[4#{bg - 8}m"
36
+ else
37
+ text.insert 0, "\e[4#{bg}m"
38
+ end
39
+ end
40
+
41
+ if fg
42
+ if fg > 8
43
+ text.insert 0, "\e[1;3#{fg - 8}m"
44
+ else
45
+ text.insert 0, "\e[0;3#{fg}m"
46
+ end
47
+ end
48
+
49
+ if fg or bg
50
+ text << "\e[0m"
51
+ end
52
+
53
+ text
54
+ end
55
+
56
+ def dump
57
+ output = ''
58
+ output.force_encoding 'US-ASCII'
59
+
60
+ map.each do |level, (fg, bg)|
61
+ fg_code = color_code fg
62
+ bg_code = color_code bg
63
+
64
+ output << ',' unless output.empty?
65
+ output << "#{level}=#{fg_code};#{bg_code}"
66
+ end
67
+
68
+ output
69
+ end
70
+
71
+ def self.decode code
72
+ return if code == '?'.freeze
73
+ code.to_i 16
74
+ end
75
+
76
+ def self.load data
77
+ map = {}
78
+
79
+ values = data.split ','.freeze
80
+
81
+ values.each do |assignment|
82
+ match_data = AssignmentPattern.match assignment
83
+
84
+ label = match_data[:label]
85
+ fg = decode match_data[:fg_code]
86
+ bg = decode match_data[:bg_code]
87
+
88
+ map[label] = [fg, bg]
89
+ end
90
+
91
+ new map
92
+ end
93
+
94
+ Colors = %i(
95
+ black
96
+ red
97
+ green
98
+ brown
99
+ blue
100
+ magenta
101
+ cyan
102
+ gray
103
+
104
+ dark_gray
105
+ bright_red
106
+ bright_green
107
+ yellow
108
+ bright_blue
109
+ bright_magenta
110
+ bright_cyan
111
+ white
112
+ )
113
+
114
+ AssignmentPattern = %r{\A
115
+ (?<label>[_A-Z]+)
116
+ =
117
+ (?<fg_code>[?[:xdigit:]])+
118
+ ;
119
+ (?<bg_code>[?[:xdigit:]]+)\z
120
+ }nx
121
+
122
+ Null = self.new Hash.new
123
+ end
124
+ end
@@ -0,0 +1,35 @@
1
+ class ExtendedLogger
2
+ module ConfigureLevels
3
+ def self.configure_levels target, labels
4
+ levels = []
5
+
6
+ labels.each_with_index do |label, severity|
7
+ level_name = label.upcase
8
+ levels << level_name
9
+
10
+ configure_level target, level_name, severity
11
+ end
12
+
13
+ target.const_set :UNKNOWN, labels.size
14
+
15
+ levels.each &:freeze
16
+ levels.freeze
17
+
18
+ target.send :define_singleton_method, :levels do levels end
19
+ end
20
+
21
+ def self.configure_level target, level_name, severity
22
+ method_name = level_name.downcase
23
+
24
+ target.send :define_method, "#{method_name}?" do
25
+ level <= severity
26
+ end
27
+
28
+ target.send :define_method, method_name do |progname=nil, &block|
29
+ add severity, nil, progname, &block
30
+ end
31
+
32
+ target.const_set level_name, severity
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,49 @@
1
+ class ExtendedLogger
2
+ module Controls
3
+ module ColorSchemes
4
+ def self.normal_verbose
5
+ color_scheme = ExtendedLogger::ColorScheme.build(
6
+ 'NORMAL' => [:gray, :none],
7
+ 'VERBOSE' => [:none, :gray],
8
+ )
9
+ end
10
+ end
11
+
12
+ module Loggers
13
+ class NormalVerbose < ExtendedLogger
14
+ self.levels = %w(VERBOSE NORMAL)
15
+ end
16
+ end
17
+
18
+ module Messages
19
+ def self.multiline
20
+ "crcrlf\r\r\n" +
21
+ "crlf\r\n" +
22
+ "cr\r" +
23
+ "lf\n" +
24
+ "\n\n" +
25
+ " \n" +
26
+ "\t\n" +
27
+ " \t\n" +
28
+ "\n"
29
+ end
30
+ end
31
+
32
+ module Output
33
+ def self.multiline
34
+ <<-TEXT
35
+ N, [2000-01-01##{$$}] NORMAL -- : crcrlf\\r\\r\\n
36
+ N, [2000-01-01##{$$}] NORMAL -- : crlf\\r\\n
37
+ N, [2000-01-01##{$$}] NORMAL -- : cr\\r
38
+ N, [2000-01-01##{$$}] NORMAL -- : lf\\n
39
+ N, [2000-01-01##{$$}] NORMAL -- : \\n
40
+ N, [2000-01-01##{$$}] NORMAL -- : \\n
41
+ N, [2000-01-01##{$$}] NORMAL -- : \\n
42
+ N, [2000-01-01##{$$}] NORMAL -- : \\t\\n
43
+ N, [2000-01-01##{$$}] NORMAL -- : \\t\\n
44
+ N, [2000-01-01##{$$}] NORMAL -- : \\n
45
+ TEXT
46
+ end
47
+ end
48
+ end
49
+ end
@@ -1,38 +1,46 @@
1
- class ExtendedLogger < Logger
2
- attr_accessor :always_evaluate
1
+ class ExtendedLogger
2
+ include LoggerSubstitute
3
+ extend PerClassLogging
3
4
 
4
- def initialize *;
5
- super
5
+ attr_accessor :always_interpolate
6
+ attr_writer :color_scheme
6
7
 
7
- formatter_cls = self.class.const_get :Formatter
8
- @formatter = formatter_cls.new @default_formatter
9
- end
8
+ def self.build io, always_interpolate: nil, color_scheme: nil
9
+ instance = new io
10
+
11
+ instance.always_interpolate = true if always_interpolate
12
+
13
+ if color_scheme
14
+ color_scheme = ColorScheme.load color_scheme if color_scheme.is_a? String
15
+ instance.color_scheme = color_scheme
16
+ end
10
17
 
11
- def self.build *arguments, initial_level: nil, **extensions
12
- instance = new *arguments
13
- instance.level = initial_level if initial_level
14
- instance.apply_extensions **extensions
15
18
  instance
16
19
  end
17
20
 
18
21
  def add severity, *, &block
19
- block.call if block_given? and always_evaluate and severity < @level
22
+ if always_interpolate and severity < level
23
+ block.() if block
24
+ end
25
+
20
26
  super
21
27
  end
22
28
 
23
- def apply_extensions always_evaluate: nil, color_swatch: nil
24
- always_evaluate ||= false
25
-
26
- self.always_evaluate = always_evaluate
29
+ def color_scheme
30
+ @color_scheme ||= ColorScheme::Null
31
+ end
27
32
 
28
- formatter.color_swatch = Colors.unpack color_swatch if color_swatch
33
+ def format severity, *arguments
34
+ formatted_message = super
35
+ color_scheme.colorize severity, formatted_message
29
36
  end
30
37
 
31
- def formatter= internal_formatter
32
- formatter.internal_formatter = internal_formatter
38
+ def self.levels= levels
39
+ ConfigureLevels.configure_levels self, levels
33
40
  end
34
41
 
35
- def self.define &block
36
- Define.(block)
42
+ # ExtendedLogger::Logger can be used in place of ::Logger
43
+ class Logger < ExtendedLogger
44
+ self.levels = %w(DEBUG INFO WARN ERROR FATAL)
37
45
  end
38
46
  end
@@ -1,39 +1,27 @@
1
1
  class ExtendedLogger
2
- class Formatter
3
- attr_writer :color_swatch
4
- attr_accessor :internal_formatter
5
-
6
- def initialize internal_formatter
7
- @internal_formatter = internal_formatter
8
- end
9
-
10
- def call severity, *arguments, message
11
- output = ''
12
-
13
- message = '(empty log message)' if message.empty?
14
-
15
- message.gsub! "\r".freeze, "\\r".freeze
16
-
17
- message.each_line do |line|
18
- line = $/.inspect[1...-1] if line == $/
19
- line.chomp! if line.end_with? $/
20
-
21
- formatted_line = internal_formatter.(severity, *arguments, line)
22
- output.concat formatted_line
2
+ class Formatter < ::Logger::Formatter
3
+ BlankLine = /\A[[:blank:]]*\z/n
4
+ LineEnding = /[[:blank:]]*\r*[\r\n]/n
5
+ Separator = "\n".freeze
6
+
7
+ def call *arguments, message
8
+ if BlankLine.match message.to_s
9
+ super *arguments, '(empty log message)'.freeze
10
+ else
11
+ message.gsub! LineEnding do |line_ending|
12
+ quoted = line_ending.inspect[1...-1]
13
+ quoted << Separator
14
+ quoted
15
+ end
16
+
17
+ lines = message.split Separator
18
+
19
+ lines.reduce String.new do |output, line|
20
+ formatted_line = super *arguments, line
21
+ output << formatted_line
22
+ output
23
+ end
23
24
  end
24
-
25
- color = color_swatch[severity] || color_swatch['ANY'.freeze]
26
- Colors.apply output, **color if color
27
-
28
- output
29
- end
30
-
31
- def color_swatch
32
- @color_swatch ||= {}
33
- end
34
-
35
- def datetime_format= value
36
- internal_formatter.datetime_format = value
37
25
  end
38
26
  end
39
27
  end
@@ -0,0 +1,97 @@
1
+ class ExtendedLogger
2
+ module LoggerSubstitute
3
+ attr_writer :clock
4
+ attr_reader :datetime_format
5
+ attr_writer :formatter
6
+ attr_reader :io
7
+ attr_accessor :progname
8
+
9
+ def initialize io
10
+ @io = io
11
+ end
12
+
13
+ def add severity, message=nil, progname=nil, &block
14
+ return if log_device.nil?
15
+
16
+ severity ||= self.class.const_get :UNKNOWN
17
+ return if severity < level
18
+
19
+ progname ||= self.progname
20
+
21
+ if message.nil?
22
+ if block
23
+ message = block.()
24
+ else
25
+ message = progname
26
+ progname = self.progname
27
+ end
28
+ end
29
+
30
+ severity_label = self.class.levels[severity] || 'ANY'.freeze
31
+
32
+ formatted_message = format severity_label, clock.now, progname, message
33
+
34
+ log_device.write formatted_message
35
+ end
36
+ alias_method :log, :add
37
+
38
+ def clock
39
+ @clock ||= Time
40
+ end
41
+
42
+ def close
43
+ log_device.close
44
+ end
45
+
46
+ def datetime_format= format
47
+ @datetime_format = format
48
+ default_formatter.datetime_format = format
49
+ end
50
+
51
+ def default_formatter
52
+ @default_formatter ||= Formatter.new
53
+ end
54
+
55
+ def format *arguments
56
+ formatter.(*arguments)
57
+ end
58
+
59
+ def formatter
60
+ @formatter ||= default_formatter
61
+ end
62
+
63
+ def level
64
+ @level ||= 0
65
+ end
66
+ alias_method :sev_threshold, :level
67
+
68
+ def level= severity_or_label
69
+ if severity_or_label.respond_to? :to_int
70
+ severity = severity_or_label.to_int
71
+ end
72
+
73
+ unless severity
74
+ label = severity_or_label
75
+ level = label.to_s.upcase
76
+
77
+ severity = self.class.levels.index level
78
+ end
79
+
80
+ unless severity
81
+ raise ArgumentError, "Not a severity: #{severity_or_label.inspect}"
82
+ end
83
+
84
+ @level = severity
85
+ end
86
+ alias_method :sev_threshold=, :level=
87
+
88
+ def log_device
89
+ return unless io
90
+ @log_device ||= ::Logger::LogDevice.new io
91
+ end
92
+
93
+ def unknown progname=nil, &block
94
+ add nil, nil, progname, &block
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,40 @@
1
+ class ExtendedLogger
2
+ module PerClassLogging
3
+ attr_writer :logger
4
+
5
+ def cache
6
+ @cache ||= Hash.new do |hash, mod|
7
+ logger = self.logger.dup
8
+
9
+ logger.progname = mod
10
+ logger.level -= verbosity
11
+
12
+ hash[mod] = logger
13
+ end
14
+ end
15
+
16
+ def configure logger
17
+ self.logger = logger
18
+
19
+ cache.clear
20
+ end
21
+
22
+ def get mod
23
+ cache[mod]
24
+ end
25
+
26
+ def logger
27
+ @logger ||= Logger.new $stderr
28
+ end
29
+
30
+ def verbosity
31
+ @verbosity ||= 0
32
+ end
33
+
34
+ def verbosity= value
35
+ @verbosity = value
36
+
37
+ cache.clear
38
+ end
39
+ end
40
+ end
@@ -1,9 +1,10 @@
1
1
  require 'logger'
2
+ require 'time'
2
3
 
3
- require 'extended_logger/extended_logger'
4
-
5
- require 'extended_logger/colors'
6
- require 'extended_logger/colors/pack'
7
- require 'extended_logger/colors/unpack'
8
- require 'extended_logger/define'
4
+ require 'extended_logger/color_scheme'
5
+ require 'extended_logger/configure_levels'
9
6
  require 'extended_logger/formatter'
7
+ require 'extended_logger/logger_substitute'
8
+ require 'extended_logger/per_class_logging'
9
+
10
+ require 'extended_logger/extended_logger'
metadata CHANGED
@@ -1,32 +1,34 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: extended_logger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan Ladd
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-09 00:00:00.000000000 Z
11
+ date: 2016-01-10 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: |
14
- extended-logger provides a richer logger implementation than the built in ruby
15
- logger, offering more log levels and colors. In addition, loggers can be
16
- constructed for your classes and modules, which include the constant name in
17
- output for easy filtering.
13
+ description: 'An extended logger that provides a (mostly) substitutable alternative
14
+ to ruby''s built in +Logger+ class. A number of useful extensions are provided,
15
+ including colorized output, the ability to define custom log levels, multi-line
16
+ formatting, and per-class logging.
17
+
18
+ '
18
19
  email: nathanladd+github@gmail.com
19
20
  executables: []
20
21
  extensions: []
21
22
  extra_rdoc_files: []
22
23
  files:
23
24
  - lib/extended_logger.rb
24
- - lib/extended_logger/colors.rb
25
- - lib/extended_logger/colors/pack.rb
26
- - lib/extended_logger/colors/unpack.rb
27
- - lib/extended_logger/define.rb
25
+ - lib/extended_logger/color_scheme.rb
26
+ - lib/extended_logger/configure_levels.rb
27
+ - lib/extended_logger/controls.rb
28
28
  - lib/extended_logger/extended_logger.rb
29
29
  - lib/extended_logger/formatter.rb
30
+ - lib/extended_logger/logger_substitute.rb
31
+ - lib/extended_logger/per_class_logging.rb
30
32
  homepage: https://github.com/ntl/extended-logger
31
33
  licenses:
32
34
  - MIT
@@ -47,9 +49,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
47
49
  version: '0'
48
50
  requirements: []
49
51
  rubyforge_project:
50
- rubygems_version: 2.4.5.1
52
+ rubygems_version: 2.5.1
51
53
  signing_key:
52
54
  specification_version: 4
53
- summary: Provides an extended logger offering more features than the ruby logger
55
+ summary: An alternative to the built-in Logger
54
56
  test_files: []
55
- has_rdoc:
@@ -1,47 +0,0 @@
1
- class ExtendedLogger
2
- module Colors
3
- class Pack
4
- attr_reader :mapping
5
-
6
- def initialize mapping
7
- @mapping = mapping
8
- end
9
-
10
- def self.call mapping=nil
11
- mapping ||= {}
12
-
13
- instance = new mapping
14
- instance.()
15
- end
16
-
17
- def call
18
- output = ''.encode 'US-ASCII'
19
-
20
- mapping.sort.each do |level_name, hash|
21
- fg, bg = hash.values_at(:fg, :bg).map do |color_name|
22
- color_code color_name
23
- end
24
-
25
- output << ',' unless output.empty?
26
- output << "#{level_name.upcase}=#{fg};#{bg}"
27
- end
28
-
29
- Unpack.(output)
30
-
31
- output
32
- end
33
-
34
- def color_code color_name
35
- return '?'.freeze if color_name == :none
36
-
37
- number = Colors.index color_name
38
-
39
- unless number
40
- raise ArgumentError, "#{color_name.inspect} is not a color code"
41
- end
42
-
43
- number.to_s 16
44
- end
45
- end
46
- end
47
- end
@@ -1,55 +0,0 @@
1
- class ExtendedLogger
2
- module Colors
3
- class Unpack
4
- attr_reader :data
5
-
6
- Pattern = %r{\A
7
- (?<level_name>[A-Z_]+) # DEBUG
8
- = # =
9
- (?<fg>[?[:xdigit:]])+ # f
10
- ; # ;
11
- (?<bg>[?[:xdigit:]])+ # 8
12
- \Z}xn
13
-
14
- def initialize data
15
- @data = data
16
- end
17
-
18
- def self.call string
19
- instance = new string
20
- instance.()
21
- end
22
-
23
- def call
24
- output = {}
25
- mappings = data.split ','.freeze
26
-
27
- mappings.each do |mapping|
28
- match_data = Pattern.match mapping
29
-
30
- unless match_data
31
- raise ArgumentError, "Invalid swatch #{data.inspect}"
32
- end
33
-
34
- level_name = match_data[:level_name]
35
-
36
- if match_data[:fg] == '?'.freeze
37
- fg = :none
38
- else
39
- fg = Colors.fetch match_data[:fg].to_i(16)
40
- end
41
-
42
- if match_data[:bg] == '?'.freeze
43
- bg = :none
44
- else
45
- bg = Colors.fetch match_data[:bg].to_i(16)
46
- end
47
-
48
- output[level_name] = { :fg => fg, :bg => bg }
49
- end
50
-
51
- output
52
- end
53
- end
54
- end
55
- end
@@ -1,50 +0,0 @@
1
- class ExtendedLogger
2
- module Colors
3
- extend self
4
-
5
- def apply text, fg:, bg:;
6
- fg = Colors.index fg
7
- bg = Colors.index bg
8
-
9
- if fg
10
- if fg > 8 then fg = "1;3#{fg - 8}" else fg = "0;3#{fg}" end
11
- text.insert 0, "\e[#{fg}m"
12
- end
13
-
14
- if bg
15
- if bg > 8 then bg = "4#{bg - 8}" else bg = "4#{bg}" end
16
- text.insert 0, "\e[#{bg}m"
17
- end
18
-
19
- text.insert -1, "\e[0m" if fg or bg
20
- end
21
-
22
- def pack mapping=nil
23
- Pack.(mapping)
24
- end
25
-
26
- def unpack data
27
- Unpack.(data)
28
- end
29
-
30
- Colors = %i(
31
- black
32
- red
33
- green
34
- brown
35
- blue
36
- magenta
37
- cyan
38
- gray
39
-
40
- dark_gray
41
- bright_red
42
- bright_green
43
- yellow
44
- bright_blue
45
- bright_magenta
46
- bright_cyan
47
- white
48
- )
49
- end
50
- end
@@ -1,55 +0,0 @@
1
- class ExtendedLogger
2
- class Define
3
- attr_reader :block
4
- attr_reader :cls
5
-
6
- DefaultLogLevels = %i(debug debug? error error? fatal fatal? info info? warn warn?)
7
-
8
- def initialize block, cls
9
- @block = block
10
- @cls = cls
11
- end
12
-
13
- def self.call block
14
- cls = Class.new ExtendedLogger
15
-
16
- instance = new block, cls
17
- instance.()
18
- end
19
-
20
- def call
21
- cls.send :undef_method, *DefaultLogLevels
22
-
23
- instance_exec &block
24
-
25
- null_logger = cls.new nil
26
- cls.const_set :NullLogger, null_logger
27
-
28
- cls
29
- end
30
-
31
- def default_formatter &block
32
- formatter_cls = Class.new Formatter
33
- formatter_cls.send :define_method, :call, &block
34
- cls.const_set :Formatter, formatter_cls
35
- end
36
-
37
- def levels const_names
38
- const_names.each_with_index do |const_name, level|
39
- cls.const_set const_name, level
40
-
41
- method_name = const_name.to_s.downcase
42
-
43
- cls.send :define_method, method_name do |progname=nil, &block|
44
- add level, nil, progname, &block
45
- end
46
-
47
- cls.send :define_method, "#{method_name}?" do
48
- @level <= level
49
- end
50
- end
51
-
52
- cls.const_set :UNKNOWN, const_names.size
53
- end
54
- end
55
- end