betterlog 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,21 +3,16 @@
3
3
  # thread-global, this will also attempt to update context of error reporting
4
4
  # tools etc.
5
5
 
6
- class GlobalMetadata
7
- include Tins::SexySingleton
6
+ module Betterlog
7
+ class GlobalMetadata
8
+ include Tins::SexySingleton
8
9
 
9
- def data
10
- Thread.current['BP_GLOBAL_METATDATA'] || {}
11
- end
12
-
13
- def add(data_hash)
14
- data = data_hash | data
15
- Honeybadger.context(data_hash)
16
- end
17
-
18
- private
10
+ thread_local(:data) { {} }
19
11
 
20
- def data=(value)
21
- Thread.current['BP_GLOBAL_METATDATA'] = value
12
+ def add(data_hash)
13
+ data = data_hash | data
14
+ Notifiers.context(data_hash)
15
+ self
16
+ end
22
17
  end
23
18
  end
@@ -1,163 +1,165 @@
1
- class Log
2
- class Event
3
- require 'socket'
4
-
5
- def self.ify(arg, severity: :debug, notify: nil, rest: {})
6
- notify ||= rest.delete(:notify)
7
- if e = arg.ask_and_send(:exception)
8
- ify(
9
- {
10
- error_class: e.class.name,
11
- message: "#{e.class.name}: #{e.message}",
12
- backtrace: e.backtrace,
13
- },
14
- severity: severity,
15
- rest: rest,
16
- notify: notify,
17
- )
18
- elsif s = arg.ask_and_send(:to_str)
19
- new(
20
- ({ notify: s } if notify).to_h |
21
- {
22
- message: s,
1
+ module Betterlog
2
+ class Log
3
+ class Event
4
+ require 'socket'
5
+
6
+ def self.ify(arg, severity: :debug, notify: nil, rest: {})
7
+ notify ||= rest.delete(:notify)
8
+ if e = arg.ask_and_send(:exception)
9
+ ify(
10
+ {
11
+ error_class: e.class.name,
12
+ message: "#{e.class.name}: #{e.message}",
13
+ backtrace: e.backtrace,
14
+ },
23
15
  severity: severity,
24
- } | rest
25
- )
26
- elsif h = arg.ask_and_send(:to_hash)
27
- arg = h | { severity: severity } | rest
28
- new(
29
- ({ notify: h[:message] || arg.to_s } if notify).to_h |
30
- arg
31
- )
32
- else
33
- message = "Logging #{arg.inspect}"
34
- new(
35
- ({ notify: message } if notify).to_h |
36
- {
37
- message: message,
38
- severity: severity,
39
- } | rest
40
- )
16
+ rest: rest,
17
+ notify: notify,
18
+ )
19
+ elsif s = arg.ask_and_send(:to_str)
20
+ new(
21
+ ({ notify: s } if notify).to_h |
22
+ {
23
+ message: s,
24
+ severity: severity,
25
+ } | rest
26
+ )
27
+ elsif h = arg.ask_and_send(:to_hash)
28
+ arg = h | { severity: severity } | rest
29
+ new(
30
+ ({ notify: h[:message] || arg.to_s } if notify).to_h |
31
+ arg
32
+ )
33
+ else
34
+ message = "Logging #{arg.inspect}"
35
+ new(
36
+ ({ notify: message } if notify).to_h |
37
+ {
38
+ message: message,
39
+ severity: severity,
40
+ } | rest
41
+ )
42
+ end
41
43
  end
42
- end
43
-
44
- def self.parse(json)
45
- new(JSON.parse(json))
46
- rescue JSON::ParserError
47
- end
48
44
 
49
- def self.is?(json)
50
- if json = json.ask_and_send(:to_str)
51
- data = JSON.parse(json).ask_and_send(:to_hash)
52
- data&.key?('emitter')
45
+ def self.parse(json)
46
+ new(JSON.parse(json))
47
+ rescue JSON::ParserError
53
48
  end
54
- rescue JSON::ParserError
55
- false
56
- end
57
49
 
58
- def initialize(data = {})
59
- data = data.symbolize_keys_recursive | meta
60
- unless data.key?(:message)
61
- data[:message] = "a #{data[:type]} type log message of severity #{data[:severity]}"
62
- end
63
- data[:severity] =
64
- begin
65
- Severity.new((data[:severity] || :debug))
66
- rescue
67
- Severity.new(:debug)
50
+ def self.is?(json)
51
+ if json = json.ask_and_send(:to_str)
52
+ data = JSON.parse(json).ask_and_send(:to_hash)
53
+ data&.key?('emitter')
68
54
  end
69
- @data = Hash[data.sort_by(&:first)]
70
- end
55
+ rescue JSON::ParserError
56
+ false
57
+ end
71
58
 
72
- class BreakCircles
73
- def initialize
74
- @seen = {}
59
+ def initialize(data = {})
60
+ data = data.symbolize_keys_recursive | meta
61
+ unless data.key?(:message)
62
+ data[:message] = "a #{data[:type]} type log message of severity #{data[:severity]}"
63
+ end
64
+ data[:severity] =
65
+ begin
66
+ Severity.new((data[:severity] || :debug))
67
+ rescue
68
+ Severity.new(:debug)
69
+ end
70
+ @data = Hash[data.sort_by(&:first)]
75
71
  end
76
72
 
77
- IN_JSON = Tins::ModuleGroup[
78
- Float, Integer, NilClass, FalseClass, TrueClass
79
- ]
73
+ class BreakCircles
74
+ def initialize
75
+ @seen = {}
76
+ end
80
77
 
81
- def perform(object)
82
- if @seen.key?(object.__id__)
83
- :circular
84
- else
85
- @seen[object.__id__] = true
86
- case
87
- when h = object.ask_and_send(:to_hash)
88
- h.each_with_object({}) { |(k, v), h| h[k.to_s.to_sym] = perform(v) }
89
- when a = object.ask_and_send(:to_ary)
90
- a.map { |o| perform(o) }
91
- when IN_JSON === object
92
- object
78
+ IN_JSON = Tins::ModuleGroup[
79
+ Float, Integer, NilClass, FalseClass, TrueClass
80
+ ]
81
+
82
+ def perform(object)
83
+ if @seen.key?(object.__id__)
84
+ :circular
93
85
  else
94
- object.to_s
86
+ @seen[object.__id__] = true
87
+ case
88
+ when h = object.ask_and_send(:to_hash)
89
+ h.each_with_object({}) { |(k, v), h| h[k.to_s.to_sym] = perform(v) }
90
+ when a = object.ask_and_send(:to_ary)
91
+ a.map { |o| perform(o) }
92
+ when IN_JSON === object
93
+ object
94
+ else
95
+ object.to_s
96
+ end
95
97
  end
96
98
  end
97
99
  end
98
- end
99
100
 
100
- def as_hash(*a)
101
- BreakCircles.new.perform(@data)
102
- end
101
+ def as_hash(*a)
102
+ BreakCircles.new.perform(@data)
103
+ end
103
104
 
104
- def to_json(*a)
105
- as_hash.to_json(*a)
106
- end
105
+ def to_json(*a)
106
+ as_hash.to_json(*a)
107
+ end
107
108
 
108
- def format(*args)
109
- Log::EventFormatter.new(self).format(*args)
110
- end
109
+ def format(*args)
110
+ Log::EventFormatter.new(self).format(*args)
111
+ end
111
112
 
112
- alias to_s format
113
+ alias to_s format
113
114
 
114
- def []=(name, value)
115
- @data[name.to_sym] = value
116
- end
115
+ def []=(name, value)
116
+ @data[name.to_sym] = value
117
+ end
117
118
 
118
- def [](name)
119
- @data[name.to_sym]
120
- end
119
+ def [](name)
120
+ @data[name.to_sym]
121
+ end
121
122
 
122
- def severity
123
- @data[:severity]
124
- end
123
+ def severity
124
+ @data[:severity]
125
+ end
125
126
 
126
- def emitter
127
- @data[:emitter]
128
- end
127
+ def emitter
128
+ @data[:emitter]
129
+ end
129
130
 
130
- def notify?
131
- @data[:notify]
132
- end
131
+ def notify?
132
+ @data[:notify]
133
+ end
133
134
 
134
- def eql?(other)
135
- @data.eql? other.instance_variable_get(:@data)
136
- end
135
+ def eql?(other)
136
+ @data.eql? other.instance_variable_get(:@data)
137
+ end
137
138
 
138
- alias == eql?
139
+ alias == eql?
139
140
 
140
- def hash
141
- @data.hash
142
- end
141
+ def hash
142
+ @data.hash
143
+ end
143
144
 
144
- private
145
-
146
- def meta
147
- m = {
148
- timestamp: Time.now.utc.iso8601(3),
149
- pid: $$,
150
- program: File.basename($0),
151
- severity: :debug,
152
- type: 'rails',
153
- facility: 'local0',
154
- host: (Socket.gethostname rescue nil),
155
- thread_id: Thread.current.object_id
156
- }
157
- if defined? GlobalMetadata
158
- m |= GlobalMetadata.data
159
- end
160
- m
145
+ private
146
+
147
+ def meta
148
+ m = {
149
+ timestamp: Time.now.utc.iso8601(3),
150
+ pid: $$,
151
+ program: File.basename($0),
152
+ severity: :debug,
153
+ type: 'rails',
154
+ facility: 'local0',
155
+ host: (Socket.gethostname rescue nil),
156
+ thread_id: Thread.current.object_id
157
+ }
158
+ if defined? GlobalMetadata
159
+ m |= GlobalMetadata.data
160
+ end
161
+ m
162
+ end
161
163
  end
162
164
  end
163
165
  end
@@ -1,116 +1,118 @@
1
- class Log
2
- class EventFormatter
3
- include Term::ANSIColor
1
+ module Betterlog
2
+ class Log
3
+ class EventFormatter
4
+ include Term::ANSIColor
4
5
 
5
- def initialize(event)
6
- @event = event
7
- end
6
+ def initialize(event)
7
+ @event = event
8
+ end
8
9
 
9
- def format(pretty: false, color: false, format: :default)
10
- old_coloring, Term::ANSIColor.coloring = Term::ANSIColor.coloring?, color
11
- f = cc.log.formats[format] and format = f
12
- case pretty
13
- when :format
14
- format_pattern(format: format)
15
- else
16
- @event.to_json
10
+ def format(pretty: false, color: false, format: :default)
11
+ old_coloring, Term::ANSIColor.coloring = Term::ANSIColor.coloring?, color
12
+ f = cc.log.formats[format] and format = f
13
+ case pretty
14
+ when :format
15
+ format_pattern(format: format)
16
+ else
17
+ @event.to_json
18
+ end
19
+ ensure
20
+ Term::ANSIColor.coloring = old_coloring
17
21
  end
18
- ensure
19
- Term::ANSIColor.coloring = old_coloring
20
- end
21
22
 
22
- private
23
+ private
23
24
 
24
- def colorize(key, value, string = key)
25
- case style = cc.log.styles[key]
26
- when nil, String, Array
27
- apply_style(style, string)
28
- when ComplexConfig::Settings
29
- apply_style(style[value], string)
25
+ def colorize(key, value, string = key)
26
+ case style = cc.log.styles[key]
27
+ when nil, String, Array
28
+ apply_style(style, string)
29
+ when ComplexConfig::Settings
30
+ apply_style(style[value], string)
31
+ end
30
32
  end
31
- end
32
33
 
33
- def apply_style(style, string)
34
- style.nil? and return string + Term::ANSIColor.reset
35
- string = Term::ANSIColor.uncolor(string)
36
- if style.respond_to?(:each)
37
- style.
38
- each.
39
- map { |s| -> v { __send__(:color, s, v) } }.
40
- inject(string) { |v, s| s.(v) }
41
- else
42
- __send__(:color, style, string)
34
+ def apply_style(style, string)
35
+ style.nil? and return string + Term::ANSIColor.reset
36
+ string = Term::ANSIColor.uncolor(string)
37
+ if style.respond_to?(:each)
38
+ style.
39
+ each.
40
+ map { |s| -> v { __send__(:color, s, v) } }.
41
+ inject(string) { |v, s| s.(v) }
42
+ else
43
+ __send__(:color, style, string)
44
+ end
43
45
  end
44
- end
45
46
 
46
- def format_pattern(format:)
47
- format.
48
- gsub('\n', "\n").
49
- gsub('\t', "\t").
50
- gsub(/\{(-)?(%[^%]+%)?([^}]+)\}/) {
51
- invisible = $1.full?
52
- directive = $2
53
- key = $3
54
- if value = @event[key]
55
- formatted_value =
56
- if directive
57
- case directive
58
- when /\A%O%/
59
- format_object(value)
60
- when /\A%([ulif])?t%/
61
- flag = $1
62
- t = case
63
- when v = value.ask_and_send(:to_str)
64
- Time.parse(v)
65
- when v = value.ask_and_send(:to_time)
66
- v
67
- else
68
- Time.at(0)
69
- end
70
- case flag
71
- when ?u then t.utc.iso8601(3)
72
- when ?l then t.localtime.iso8601(3)
73
- when ?i then t.to_i.to_s
74
- when ?f then t.to_f.to_s
75
- else t.utc.iso8601(3)
47
+ def format_pattern(format:)
48
+ format.
49
+ gsub('\n', "\n").
50
+ gsub('\t', "\t").
51
+ gsub(/\{(-)?(%[^%]+%)?([^}]+)\}/) {
52
+ invisible = $1.full?
53
+ directive = $2
54
+ key = $3
55
+ if value = @event[key]
56
+ formatted_value =
57
+ if directive
58
+ case directive
59
+ when /\A%O%/
60
+ format_object(value)
61
+ when /\A%([ulif])?t%/
62
+ flag = $1
63
+ t = case
64
+ when v = value.ask_and_send(:to_str)
65
+ Time.parse(v)
66
+ when v = value.ask_and_send(:to_time)
67
+ v
68
+ else
69
+ Time.at(0)
70
+ end
71
+ case flag
72
+ when ?u then t.utc.iso8601(3)
73
+ when ?l then t.localtime.iso8601(3)
74
+ when ?i then t.to_i.to_s
75
+ when ?f then t.to_f.to_s
76
+ else t.utc.iso8601(3)
77
+ end
78
+ else
79
+ begin
80
+ directive[0..-2] % value
81
+ rescue ArgumentError
82
+ value.to_s
83
+ end
76
84
  end
77
85
  else
78
- begin
79
- directive[0..-2] % value
80
- rescue ArgumentError
81
- value.to_s
82
- end
86
+ value.to_s
83
87
  end
84
- else
85
- value.to_s
88
+ colorize(key, value, formatted_value)
89
+ else
90
+ unless invisible
91
+ "{#{key}}"
86
92
  end
87
- colorize(key, value, formatted_value)
88
- else
89
- unless invisible
90
- "{#{key}}"
91
93
  end
92
- end
93
- }
94
- end
94
+ }
95
+ end
95
96
 
96
- def format_object(object, depth: 0, nl: ?\n)
97
- case
98
- when a = object.ask_and_send(:to_ary)
99
- result = ''
100
- depth += 2
101
- for v in a
102
- result << "\n#{' ' * depth}- #{format_object(v, depth: depth)}"
103
- end
104
- result
105
- when h = object.ask_and_send(:to_hash)
106
- result = ''
107
- depth += 2
108
- for k, v in h
109
- result << "\n#{' ' * depth}#{k}: #{format_object(v, depth: depth)}"
97
+ def format_object(object, depth: 0, nl: ?\n)
98
+ case
99
+ when a = object.ask_and_send(:to_ary)
100
+ result = ''
101
+ depth += 2
102
+ for v in a
103
+ result << "\n#{' ' * depth}- #{format_object(v, depth: depth)}"
104
+ end
105
+ result
106
+ when h = object.ask_and_send(:to_hash)
107
+ result = ''
108
+ depth += 2
109
+ for k, v in h
110
+ result << "\n#{' ' * depth}#{k}: #{format_object(v, depth: depth)}"
111
+ end
112
+ result
113
+ else
114
+ object.to_s
110
115
  end
111
- result
112
- else
113
- object.to_s
114
116
  end
115
117
  end
116
118
  end
@@ -1,49 +1,51 @@
1
- class Log
2
- class Severity
3
- include Comparable
4
-
5
- def initialize(name)
6
- @name = name.to_s.downcase.to_sym
7
- begin
8
- @level = ActiveSupport::Logger::Severity.const_get(@name.upcase)
9
- rescue NameError
10
- @name = :UNKNOWN
11
- @level = ActiveSupport::Logger::Severity::UNKNOWN
1
+ module Betterlog
2
+ class Log
3
+ class Severity
4
+ include Comparable
5
+
6
+ def initialize(name)
7
+ @name = name.to_s.downcase.to_sym
8
+ begin
9
+ @level = Logger::Severity.const_get(@name.upcase)
10
+ rescue NameError
11
+ @name = :UNKNOWN
12
+ @level = Logger::Severity::UNKNOWN
13
+ end
12
14
  end
13
- end
14
15
 
15
- def self.all
16
- ActiveSupport::Logger::Severity.constants.map { |c| new(c) }
17
- end
16
+ def self.all
17
+ @all_constants ||= Logger::Severity.constants.map { |c| new(c) }
18
+ end
18
19
 
19
- def to_i
20
- @level
21
- end
20
+ def to_i
21
+ @level
22
+ end
22
23
 
23
- def to_s
24
- @name.to_s.upcase
25
- end
24
+ def to_s
25
+ @name.to_s.upcase
26
+ end
26
27
 
27
- def to_sym
28
- @name
29
- end
28
+ def to_sym
29
+ @name
30
+ end
30
31
 
31
- def as_json(*)
32
- to_sym
33
- end
32
+ def as_json(*)
33
+ to_sym
34
+ end
34
35
 
35
- def <=>(other)
36
- to_i <=> other.to_i
37
- end
36
+ def <=>(other)
37
+ to_i <=> other.to_i
38
+ end
38
39
 
39
- def eql?(other)
40
- to_sym == other.to_sym
41
- end
40
+ def eql?(other)
41
+ to_sym == other.to_sym
42
+ end
42
43
 
43
- alias == eql?
44
+ alias == eql?
44
45
 
45
- def hash
46
- @name.hash
46
+ def hash
47
+ @name.hash
48
+ end
47
49
  end
48
50
  end
49
51
  end