semantic_logger 3.0.1 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/semantic_logger.rb +29 -13
  4. data/lib/semantic_logger/ansi_colors.rb +27 -0
  5. data/lib/semantic_logger/appender/base.rb +54 -128
  6. data/lib/semantic_logger/appender/bugsnag.rb +29 -19
  7. data/lib/semantic_logger/appender/elasticsearch.rb +9 -9
  8. data/lib/semantic_logger/appender/file.rb +40 -18
  9. data/lib/semantic_logger/appender/graylog.rb +30 -26
  10. data/lib/semantic_logger/appender/http.rb +14 -19
  11. data/lib/semantic_logger/appender/mongodb.rb +20 -20
  12. data/lib/semantic_logger/appender/new_relic.rb +15 -15
  13. data/lib/semantic_logger/appender/splunk.rb +1 -1
  14. data/lib/semantic_logger/appender/splunk_http.rb +28 -25
  15. data/lib/semantic_logger/appender/syslog.rb +41 -42
  16. data/lib/semantic_logger/appender/wrapper.rb +19 -17
  17. data/lib/semantic_logger/base.rb +57 -32
  18. data/lib/semantic_logger/concerns/compatibility.rb +51 -0
  19. data/lib/semantic_logger/debug_as_trace_logger.rb +6 -2
  20. data/lib/semantic_logger/formatters/color.rb +66 -0
  21. data/lib/semantic_logger/formatters/default.rb +39 -0
  22. data/lib/semantic_logger/formatters/json.rb +16 -0
  23. data/lib/semantic_logger/jruby/garbage_collection_logger.rb +1 -1
  24. data/lib/semantic_logger/log.rb +13 -8
  25. data/lib/semantic_logger/loggable.rb +2 -2
  26. data/lib/semantic_logger/logger.rb +18 -13
  27. data/lib/semantic_logger/metrics/new_relic.rb +18 -0
  28. data/lib/semantic_logger/metrics/statsd.rb +48 -0
  29. data/lib/semantic_logger/semantic_logger.rb +122 -55
  30. data/lib/semantic_logger/version.rb +1 -1
  31. data/test/appender/bugsnag_test.rb +12 -3
  32. data/test/appender/mongodb_test.rb +6 -5
  33. data/test/appender/new_relic_test.rb +1 -1
  34. data/test/appender/splunk_http_test.rb +1 -0
  35. data/test/concerns/compatibility_test.rb +106 -0
  36. data/test/debug_as_trace_logger_test.rb +1 -1
  37. data/test/loggable_test.rb +1 -1
  38. data/test/logger_test.rb +183 -24
  39. metadata +12 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 50213eafcd6560b8240844cfb686a2a954537091
4
- data.tar.gz: d6df1d6905b315ccef4915cf59b819e62d2697bf
3
+ metadata.gz: 7010f9d28a473c9cd0c9fb9d52608216bad68043
4
+ data.tar.gz: 052152f47b9eb211a26c47a2bbbff8742f497449
5
5
  SHA512:
6
- metadata.gz: 048295e8e5a07f91ffe44a2108cb12135fbcfb25d604ad3ec0656e41cc0435689dc215de8bd0c994b81ec1fcf4e850e46d7733c7e2a5676e3b2e92ecc42971e5
7
- data.tar.gz: ce6f018889578dc8a44855e2bfc528d939cf5b8c0bd4872c41f55b5e1537adb8e99cd231c86e4829164bea1a5f1c2b728c2df52c566d79d73bcbf7bf578370b5
6
+ metadata.gz: 17d21c7f8bc35b93e52074cfac26bb0c350c989b589a8fb4a096c43a71148b4e245ace66ef36c8af9693355dc3741623896afb48bc2a01473b062a3ee1b6111a
7
+ data.tar.gz: 43eaa8a554e95b8936e4a595593977e30a98b849dcaa9d419762420a0f3edcd03d9f1f923cdeda2897b48332c1b5bcd89a9500f1df181d57283e56c11cc296ac
data/README.md CHANGED
@@ -65,7 +65,7 @@ require 'semantic_logger'
65
65
  SemanticLogger.default_level = :trace
66
66
 
67
67
  # Log to a file, and use the colorized formatter
68
- SemanticLogger.add_appender('development.log', &SemanticLogger::Appender::Base.colorized_formatter)
68
+ SemanticLogger.add_appender(file: 'development.log', formatter: :color)
69
69
  ```
70
70
 
71
71
  If running rails, see: [Semantic Logger Rails](http://rocketjob.github.io/semantic_logger/rails.html)
@@ -4,6 +4,7 @@ require 'semantic_logger/semantic_logger'
4
4
 
5
5
  # @formatter:off
6
6
  module SemanticLogger
7
+ autoload :AnsiColors, 'semantic_logger/ansi_colors'
7
8
  autoload :Base, 'semantic_logger/base'
8
9
  autoload :DebugAsTraceLogger, 'semantic_logger/debug_as_trace_logger'
9
10
  autoload :Log, 'semantic_logger/log'
@@ -11,20 +12,34 @@ module SemanticLogger
11
12
  autoload :Loggable, 'semantic_logger/loggable'
12
13
 
13
14
  module Appender
14
- autoload :Base, 'semantic_logger/appender/base'
15
- autoload :Bugsnag, 'semantic_logger/appender/bugsnag'
16
- autoload :Elasticsearch, 'semantic_logger/appender/elasticsearch'
17
- autoload :File, 'semantic_logger/appender/file'
18
- autoload :Graylog, 'semantic_logger/appender/graylog'
19
- autoload :Http, 'semantic_logger/appender/http'
20
- autoload :MongoDB, 'semantic_logger/appender/mongodb'
21
- autoload :NewRelic, 'semantic_logger/appender/new_relic'
22
- autoload :Splunk, 'semantic_logger/appender/splunk'
23
- autoload :SplunkHttp, 'semantic_logger/appender/splunk_http'
24
- autoload :Syslog, 'semantic_logger/appender/syslog'
25
- autoload :Wrapper, 'semantic_logger/appender/wrapper'
15
+ autoload :Base, 'semantic_logger/appender/base'
16
+ autoload :Bugsnag, 'semantic_logger/appender/bugsnag'
17
+ autoload :Elasticsearch, 'semantic_logger/appender/elasticsearch'
18
+ autoload :File, 'semantic_logger/appender/file'
19
+ autoload :Graylog, 'semantic_logger/appender/graylog'
20
+ autoload :Http, 'semantic_logger/appender/http'
21
+ autoload :MongoDB, 'semantic_logger/appender/mongodb'
22
+ autoload :NewRelic, 'semantic_logger/appender/new_relic'
23
+ autoload :Splunk, 'semantic_logger/appender/splunk'
24
+ autoload :SplunkHttp, 'semantic_logger/appender/splunk_http'
25
+ autoload :Syslog, 'semantic_logger/appender/syslog'
26
+ autoload :Wrapper, 'semantic_logger/appender/wrapper'
27
+ end
28
+
29
+ module Concerns
30
+ autoload :Compatibility, 'semantic_logger/concerns/compatibility'
31
+ end
32
+
33
+ module Formatters
34
+ autoload :Color, 'semantic_logger/formatters/color'
35
+ autoload :Default, 'semantic_logger/formatters/default'
36
+ autoload :Json, 'semantic_logger/formatters/json'
37
+ end
38
+
39
+ module Metrics
40
+ autoload :NewRelic, 'semantic_logger/metrics/new_relic'
41
+ autoload :Statsd, 'semantic_logger/metrics/statsd'
26
42
  end
27
- # @formatter:on
28
43
 
29
44
  if defined?(JRuby)
30
45
  module JRuby
@@ -32,6 +47,7 @@ module SemanticLogger
32
47
  end
33
48
  end
34
49
  end
50
+ # @formatter:on
35
51
 
36
52
  # Flush all appenders at exit, waiting for outstanding messages on the queue
37
53
  # to be written first
@@ -0,0 +1,27 @@
1
+ module SemanticLogger
2
+ # Formatting & colors used by optional color formatter
3
+ module AnsiColors
4
+ CLEAR = "\e[0m"
5
+ BOLD = "\e[1m"
6
+ BLACK = "\e[30m"
7
+ RED = "\e[31m"
8
+ GREEN = "\e[32m"
9
+ YELLOW = "\e[33m"
10
+ BLUE = "\e[34m"
11
+ MAGENTA = "\e[35m"
12
+ CYAN = "\e[36m"
13
+ WHITE = "\e[37m"
14
+
15
+ # Maps the log level to a color for colorized formatters
16
+ # Since this map is not frozen, it can be modified as needed
17
+ LEVEL_MAP = {
18
+ trace: MAGENTA,
19
+ debug: GREEN,
20
+ info: CYAN,
21
+ warn: BOLD,
22
+ error: RED,
23
+ fatal: RED
24
+ }
25
+ end
26
+
27
+ end
@@ -1,10 +1,3 @@
1
- require 'json'
2
- # Load AwesomePrint if available
3
- begin
4
- require 'awesome_print'
5
- rescue LoadError
6
- end
7
-
8
1
  # Base appender
9
2
  #
10
3
  # Abstract base class for appenders
@@ -16,128 +9,42 @@ end
16
9
  module SemanticLogger
17
10
  module Appender
18
11
 
19
- # Formatting & colors used by optional colorized_formatter
20
- module AnsiColors
21
- CLEAR = "\e[0m"
22
- BOLD = "\e[1m"
23
- BLACK = "\e[30m"
24
- RED = "\e[31m"
25
- GREEN = "\e[32m"
26
- YELLOW = "\e[33m"
27
- BLUE = "\e[34m"
28
- MAGENTA = "\e[35m"
29
- CYAN = "\e[36m"
30
- WHITE = "\e[37m"
31
-
32
- # Maps the log level to a color for colorized formatters
33
- # Since this map is not frozen, it can be modified as needed
34
- LEVEL_MAP = {
35
- trace: MAGENTA,
36
- debug: GREEN,
37
- info: CYAN,
38
- warn: BOLD,
39
- error: RED,
40
- fatal: RED
41
- }
42
- end
12
+ # DEPRECATED, use SemanticLogger::AnsiColors
13
+ AnsiColors = SemanticLogger::AnsiColors
43
14
 
44
15
  class Base < SemanticLogger::Base
16
+ # Every logger has its own formatter
45
17
  attr_accessor :formatter
46
18
 
47
- # Default log formatter
48
- # Replace this formatter by supplying a Block to the initializer
49
- # Generates logs of the form:
50
- # 2011-07-19 14:36:15.660 D [1149:ScriptThreadProcess] Rails -- Hello World
51
- def default_formatter
52
- Proc.new do |log, logger|
53
- # Header with date, time, log level and process info
54
- entry = "#{log.formatted_time} #{log.level_to_s} [#{log.process_info}]"
55
-
56
- # Tags
57
- entry << ' ' << log.tags.collect { |tag| "[#{tag}]" }.join(' ') if log.tags && (log.tags.size > 0)
58
-
59
- # Duration
60
- entry << " (#{log.duration_human})" if log.duration
61
-
62
- # Class / app name
63
- entry << " #{log.name}"
64
-
65
- # Log message
66
- entry << " -- #{log.message}" if log.message
67
-
68
- # Payload
69
- if payload = log.payload_to_s(false)
70
- entry << ' -- ' << payload
71
- end
72
-
73
- # Exceptions
74
- if log.exception
75
- entry << " -- Exception: #{log.exception.class}: #{log.exception.message}\n"
76
- entry << log.backtrace_to_s
77
- end
78
- entry
79
- end
19
+ # Returns the current log level if set, otherwise it logs everything it receives
20
+ def level
21
+ @level || :trace
80
22
  end
81
23
 
82
- # Optional log formatter to colorize log output
83
- # To use this formatter
84
- # SemanticLogger.add_appender($stdout, &SemanticLogger::Appender::Base.colorized_formatter)
85
- #
86
- # 2011-07-19 14:36:15.660 D [1149:ScriptThreadProcess] Rails -- Hello World
87
- def self.colorized_formatter
88
- Proc.new do |log, logger|
89
- colors = SemanticLogger::Appender::AnsiColors
90
- level_color = colors::LEVEL_MAP[log.level]
91
-
92
- # Header with date, time, log level and process info
93
- entry = "#{log.formatted_time} #{level_color}#{log.level_to_s}#{colors::CLEAR} [#{log.process_info}]"
94
-
95
- # Tags
96
- entry << ' ' << log.tags.collect { |tag| "[#{level_color}#{tag}#{colors::CLEAR}]" }.join(' ') if log.tags && (log.tags.size > 0)
97
-
98
- # Duration
99
- entry << " (#{colors::BOLD}#{log.duration_human}#{colors::CLEAR})" if log.duration
100
-
101
- # Class / app name
102
- entry << " #{level_color}#{log.name}#{colors::CLEAR}"
103
-
104
- # Log message
105
- entry << " -- #{log.message}" if log.message
106
-
107
- # Payload
108
- if payload = log.payload_to_s(true)
109
- entry << ' -- ' << payload
110
- end
111
-
112
- # Exceptions
113
- if log.exception
114
- entry << " -- Exception: #{colors::BOLD}#{log.exception.class}: #{log.exception.message}#{colors::CLEAR}\n"
115
- entry << log.backtrace_to_s
116
- end
117
- entry
118
- end
24
+ # An appender can implement a flush method if it is able to.
25
+ def flush
26
+ # NOOP
119
27
  end
120
28
 
121
- # Optional log formatter to output data in a hash format
122
- # To use this formatter
123
- # SemanticLogger.add_appender($stdout, &SemanticLogger::Appender::Base.json_formatter)
124
- def self.json_formatter
125
- Proc.new do |log, logger|
126
- h = log.to_h
127
- h.delete(:time)
128
- h[:timestamp] = log.time.utc.iso8601(defined?(JRuby) ? 3 : 6)
129
- h.to_json
130
- end
29
+ # DEPRECATED: use SemanticLogger::Formatters::Default.new
30
+ def default_formatter
31
+ warn '[DEPRECATION] SemanticLogger::Appender::Base.default_level is deprecated. Please use SemanticLogger::Formatters::Default.new instead.'
32
+ formatter = SemanticLogger::Formatters::Default.new
33
+ Proc.new { |log, logger| formatter.call(log, logger) }
131
34
  end
132
35
 
133
- def flush
134
- # An appender can implement a flush method if it supports it.
36
+ # DEPRECATED: use SemanticLogger::Formatters::Color.new
37
+ def self.colorized_formatter
38
+ warn '[DEPRECATION] SemanticLogger::Appender::Base.colorized_formatter is deprecated. Please use SemanticLogger::Formatters::Color.new instead.'
39
+ formatter = SemanticLogger::Formatters::Color.new
40
+ Proc.new { |log, logger| formatter.call(log, logger) }
135
41
  end
136
42
 
137
- # Returns the current log level if set, otherwise it returns the global
138
- # default log level
139
- def level
140
- @level || :trace
43
+ # DEPRECATED: use SemanticLogger::Formatters::Json.new
44
+ def self.json_formatter
45
+ warn '[DEPRECATION] SemanticLogger::Appender::Base.json_formatter is deprecated. Please use SemanticLogger::Formatters::Json.new instead.'
46
+ formatter = SemanticLogger::Formatters::Json.new
47
+ Proc.new { |log, logger| formatter.call(log, logger) }
141
48
  end
142
49
 
143
50
  private
@@ -145,18 +52,32 @@ module SemanticLogger
145
52
  # Initializer for Abstract Class SemanticLogger::Appender
146
53
  #
147
54
  # Parameters
148
- # level [Symbol]
149
- # Only allow log entries of this level or higher to be written to this appender
150
- # For example if set to :warn, this appender would only log :warn and :fatal
151
- # log messages when other appenders could be logging :info and lower
55
+ # level: [:trace | :debug | :info | :warn | :error | :fatal]
56
+ # Override the log level for this appender.
57
+ # Default: :error
58
+ #
59
+ # formatter: [Object|Proc]
60
+ # An instance of a class that implements #call, or a Proc to be used to format
61
+ # the output from this appender
62
+ # Default: Use the built-in formatter (See: #call)
152
63
  #
153
- # filter [RegExp|Proc]
154
- # Optional regular expression to filter log entries based on the class name
155
- # When filter is a proc, it is passed the entire log struct and must return
156
- # true or false indicating whether to log the message
157
- def initialize(level=nil, filter=nil, &block)
158
- # Set the formatter to the supplied block
159
- @formatter = block || default_formatter
64
+ # filter: [Regexp|Proc]
65
+ # RegExp: Only include log messages where the class name matches the supplied.
66
+ # regular expression. All other messages will be ignored.
67
+ # Proc: Only include log messages where the supplied Proc returns true
68
+ # The Proc must return true or false.
69
+ def initialize(options={}, &block)
70
+ # Backward compatibility
71
+ options = {level: options} unless options.is_a?(Hash)
72
+ options = options.dup
73
+ level = options.delete(:level)
74
+ filter = options.delete(:filter)
75
+ @formatter = options.delete(:formatter)
76
+ @formatter = self.class.extract_formatter(@formatter) if @formatter.is_a?(Symbol)
77
+ @formatter ||= block
78
+ # Default to #call method for formatting if defined for an appender
79
+ @formatter ||= (respond_to?(:call) ? self : SemanticLogger::Formatters::Default.new)
80
+ raise(ArgumentError, "Unknown options: #{options.inspect}") if options.size > 0
160
81
 
161
82
  # Appenders don't take a class name, so use this class name if an appender
162
83
  # is logged to directly
@@ -170,6 +91,11 @@ module SemanticLogger
170
91
  @level_index || 0
171
92
  end
172
93
 
94
+ # Return formatter for supplied Symbol
95
+ def self.extract_formatter(formatter)
96
+ SemanticLogger.send(:named_formatter, formatter).new
97
+ end
98
+
173
99
  end
174
100
  end
175
101
  end
@@ -7,51 +7,53 @@ end
7
7
  # Send log messages to Bugsnag
8
8
  #
9
9
  # Example:
10
- # SemanticLogger.add_appender(SemanticLogger::Appender::Bugsnag.new)
10
+ # SemanticLogger.add_appender(appender: :bugsnag)
11
11
  #
12
12
  class SemanticLogger::Appender::Bugsnag < SemanticLogger::Appender::Base
13
- # Create Appender
13
+ # Create Bugsnag Error / Exception Appender
14
14
  #
15
15
  # Parameters
16
16
  # level: [:trace | :debug | :info | :warn | :error | :fatal]
17
17
  # Override the log level for this appender.
18
18
  # Default: :error
19
19
  #
20
+ # formatter: [Object|Proc]
21
+ # An instance of a class that implements #call, or a Proc to be used to format
22
+ # the output from this appender
23
+ # Default: Use the built-in formatter (See: #call)
24
+ #
20
25
  # filter: [Regexp|Proc]
21
26
  # RegExp: Only include log messages where the class name matches the supplied.
22
27
  # regular expression. All other messages will be ignored.
23
28
  # Proc: Only include log messages where the supplied Proc returns true
24
29
  # The Proc must return true or false.
25
30
  def initialize(options = {}, &block)
26
- options = {level: options} unless options.is_a?(Hash)
27
- @options = options.dup
28
- level = @options.delete(:level) || :error
29
- filter = @options.delete(:filter)
31
+ # Backward compatibility
32
+ options = {level: options} unless options.is_a?(Hash)
33
+ options = options.dup
34
+ options[:level] = :error unless options.has_key?(:level)
30
35
 
31
- raise 'Bugsnag only supports :info, :warn, or :error log levels' unless [:info, :warn, :error].include?(level)
36
+ raise 'Bugsnag only supports :info, :warn, or :error log levels' unless [:info, :warn, :error].include?(options[:level])
32
37
 
33
38
  # Replace the Bugsnag logger so that we can identify its log messages and not forward them to Bugsnag
34
39
  Bugsnag.configure { |config| config.logger = SemanticLogger[Bugsnag] }
35
- super(level, &block)
40
+
41
+ super(options, &block)
36
42
  end
37
43
 
38
44
  # Returns [Hash] of parameters to send to Bugsnag.
39
- def default_formatter
40
- Proc.new do |log|
41
- h = log.to_h
42
- h[:severity] = log_level(log)
43
- h.delete(:time)
44
- h.delete(:exception)
45
- h
46
- end
45
+ def call(log, logger)
46
+ h = log.to_h
47
+ h[:severity] = log_level(log)
48
+ h.delete(:time)
49
+ h.delete(:exception)
50
+ h
47
51
  end
48
52
 
49
53
  # Send an error notification to Bugsnag
50
54
  def log(log)
51
55
  # Only log if level is warn, or error.
52
56
  return false if (level_index > (log.level_index || 0)) ||
53
- # We don't want to send fatal as those are already captured by Bugsnag.
54
- #(log.level == :fatal) ||
55
57
  # Ignore logs coming from Bugsnag itself
56
58
  (log.name == 'Bugsnag') ||
57
59
  # Filtered out?
@@ -75,7 +77,15 @@ class SemanticLogger::Appender::Bugsnag < SemanticLogger::Appender::Base
75
77
 
76
78
  private
77
79
 
80
+ # Bugsnag supports: error, warning or info
78
81
  def log_level(log)
79
- log.level == :warn ? 'warning' : log.level.to_s
82
+ case log.level
83
+ when :error, :fatal
84
+ 'error'
85
+ when :warn
86
+ 'warning'
87
+ else
88
+ 'info'
89
+ end
80
90
  end
81
91
  end
@@ -2,15 +2,10 @@ require 'date'
2
2
  # Forward all log messages to Elasticsearch.
3
3
  #
4
4
  # Example:
5
- # appender = SemanticLogger::Appender::Elasticsearch.new(
6
- # url: 'http://localhost:9200'
5
+ # SemanticLogger.add_appender(
6
+ # appender: :elasticsearch,
7
+ # url: 'http://localhost:9200'
7
8
  # )
8
- #
9
- # # Optional: Exclude health_check log entries
10
- # appender.filter = Proc.new { |log| log.message !~ /(health_check|Not logged in)/}
11
- #
12
- # SemanticLogger.add_appender(appender)
13
- #
14
9
  class SemanticLogger::Appender::Elasticsearch < SemanticLogger::Appender::Http
15
10
  attr_accessor :index, :type
16
11
 
@@ -31,6 +26,11 @@ class SemanticLogger::Appender::Elasticsearch < SemanticLogger::Appender::Http
31
26
  # Override the log level for this appender.
32
27
  # Default: SemanticLogger.default_level
33
28
  #
29
+ # formatter: [Object|Proc]
30
+ # An instance of a class that implements #call, or a Proc to be used to format
31
+ # the output from this appender
32
+ # Default: Use the built-in formatter (See: #call)
33
+ #
34
34
  # filter: [Regexp|Proc]
35
35
  # RegExp: Only include log messages where the class name matches the supplied.
36
36
  # regular expression. All other messages will be ignored.
@@ -38,7 +38,7 @@ class SemanticLogger::Appender::Elasticsearch < SemanticLogger::Appender::Http
38
38
  # The Proc must return true or false.
39
39
  def initialize(options, &block)
40
40
  options = options.dup
41
- @index = options.delete(:index) || "semantic_logger"
41
+ @index = options.delete(:index) || 'semantic_logger'
42
42
  @type = options.delete(:type) || 'log'
43
43
  options[:url] ||= 'http://localhost:9200'
44
44