semantic_logger 4.7.1 → 4.8.1

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: 53de576d3dea3ae2099d237648a027026469632dda0f8c3840557c648ddb0626
4
- data.tar.gz: a2fe41e466fd682cc536f33331698a74b19d9026cde7604db93f859e70686d25
3
+ metadata.gz: c969376e41c290b01fd22a111b1eca500ab4a01e80e13d4fbf18b800b9c50c9e
4
+ data.tar.gz: 4319e88ebd250dd524add711cd16508d8f825686cfa28731f19d52c35854d738
5
5
  SHA512:
6
- metadata.gz: c9c53adbda24e55a427945f9c5953c6e53c244af0c00b4f81ba59c92c3e052d9f7306fc8941bbf0960d665757c56b4089bbc1214255fdfc5ec085fdda24b601e
7
- data.tar.gz: 700143b4c0b34e347539b7b2fccd363683b45577a5520accd55a308175f92975ca041152ca03353f7e23ec71eb9189e6de54ff8f985eecf414d51b8900b2ad96
6
+ metadata.gz: 435ada2480d22e98e3e4467086167411f0620f9a0fd4d9210bb715c7a7ef3defe08986afaf8b174aeb55a5bde8ba46dfefea1c8d693c78623495755d2a41c6e2
7
+ data.tar.gz: bb2a64552713ae4fcb3b3ae59133e4a5241ecb4692ddc7304e77f72bc76ef47e219cfd481dbebd482385e7b53e161d15b245b644c01030e9cb021c65ec222d0a
data/README.md CHANGED
@@ -1,15 +1,13 @@
1
1
  # Semantic Logger
2
- [![Gem Version](https://img.shields.io/gem/v/semantic_logger.svg)](https://rubygems.org/gems/semantic_logger) [![Build Status](https://travis-ci.org/rocketjob/semantic_logger.svg?branch=master)](https://travis-ci.org/rocketjob/semantic_logger) [![Downloads](https://img.shields.io/gem/dt/semantic_logger.svg)](https://rubygems.org/gems/semantic_logger) [![License](https://img.shields.io/badge/license-Apache%202.0-brightgreen.svg)](http://opensource.org/licenses/Apache-2.0) ![](https://img.shields.io/badge/status-Production%20Ready-blue.svg) [![Gitter chat](https://img.shields.io/badge/IRC%20(gitter)-Support-brightgreen.svg)](https://gitter.im/rocketjob/support)
2
+ [![Gem Version](https://img.shields.io/gem/v/semantic_logger.svg)](https://rubygems.org/gems/semantic_logger) [![Build Status](https://github.com/reidmorrison/semantic_logger/workflows/build/badge.svg)](https://github.com/reidmorrison/semantic_logger/actions?query=workflow%3Abuild) [![Downloads](https://img.shields.io/gem/dt/semantic_logger.svg)](https://rubygems.org/gems/semantic_logger) [![License](https://img.shields.io/badge/license-Apache%202.0-brightgreen.svg)](http://opensource.org/licenses/Apache-2.0) ![](https://img.shields.io/badge/status-Production%20Ready-blue.svg)
3
3
 
4
4
  Semantic Logger is a feature rich logging framework, and replacement for existing Ruby & Rails loggers.
5
5
 
6
- * https://rocketjob.github.io/semantic_logger/
6
+ * https://logger.rocketjob.io/
7
7
 
8
8
  ## Documentation
9
9
 
10
- [Semantic Logger Guide](http://rocketjob.github.io/semantic_logger)
11
-
12
- [Reference Documentation](http://www.rubydoc.info/gems/semantic_logger/)
10
+ [Semantic Logger Guide](https://logger.rocketjob.io/)
13
11
 
14
12
  ## Upgrading to Semantic Logger v4.4
15
13
 
@@ -50,7 +48,7 @@ handles saving log information to multiple destinations / appenders.
50
48
 
51
49
  ## Rails
52
50
 
53
- When running Rails, use [rails_semantic_logger](http://github.com/rocketjob/rails_semantic_logger)
51
+ When running Rails, use [rails_semantic_logger](http://github.com/reidmorrison/rails_semantic_logger)
54
52
  instead of Semantic Logger directly since it will automatically replace the Rails default logger with Semantic Logger.
55
53
 
56
54
  ## Rocket Job
@@ -129,13 +127,13 @@ SemanticLogger.default_level = :trace
129
127
  SemanticLogger.add_appender(file_name: 'development.log', formatter: :color)
130
128
  ~~~
131
129
 
132
- If running rails, see: [Semantic Logger Rails](http://rocketjob.github.io/semantic_logger/rails.html)
130
+ If running rails, see: [Semantic Logger Rails](https://logger.rocketjob.io/rails.html)
133
131
 
134
132
  ## Author
135
133
 
136
134
  [Reid Morrison](https://github.com/reidmorrison)
137
135
 
138
- [Contributors](https://github.com/rocketjob/semantic_logger/graphs/contributors)
136
+ [Contributors](https://github.com/reidmorrison/semantic_logger/graphs/contributors)
139
137
 
140
138
  ## Versioning
141
139
 
@@ -66,7 +66,8 @@ module SemanticLogger
66
66
  elsif appender.is_a?(Subscriber)
67
67
  appender
68
68
  else
69
- raise(ArgumentError, "Parameter :appender must be either a Symbol or an object derived from SemanticLogger::Subscriber, not: #{appender.inspect}")
69
+ raise(ArgumentError,
70
+ "Parameter :appender must be either a Symbol or an object derived from SemanticLogger::Subscriber, not: #{appender.inspect}")
70
71
  end
71
72
  elsif metric
72
73
  if metric.is_a?(Symbol)
@@ -74,10 +75,12 @@ module SemanticLogger
74
75
  elsif metric.is_a?(Subscriber)
75
76
  metric
76
77
  else
77
- raise(ArgumentError, "Parameter :metric must be either a Symbol or an object derived from SemanticLogger::Subscriber, not: #{appender.inspect}")
78
+ raise(ArgumentError,
79
+ "Parameter :metric must be either a Symbol or an object derived from SemanticLogger::Subscriber, not: #{appender.inspect}")
78
80
  end
79
81
  else
80
- raise(ArgumentError, "To create an appender it must supply one of the following: :io, :file_name, :appender, :metric, or :logger")
82
+ raise(ArgumentError,
83
+ "To create an appender it must supply one of the following: :io, :file_name, :appender, :metric, or :logger")
81
84
  end
82
85
  end
83
86
 
@@ -53,7 +53,7 @@ module SemanticLogger
53
53
  # Re-open appender after a fork
54
54
  def reopen
55
55
  # Workaround CRuby crash on fork by recreating queue on reopen
56
- # https://github.com/rocketjob/semantic_logger/issues/103
56
+ # https://github.com/reidmorrison/semantic_logger/issues/103
57
57
  @queue&.close
58
58
  create_queue
59
59
 
@@ -40,42 +40,55 @@ module SemanticLogger
40
40
 
41
41
  # Returns [Hash] of parameters to send to Bugsnag.
42
42
  def call(log, logger)
43
- h = SemanticLogger::Formatters::Raw.new.call(log, logger)
44
- h[:severity] = log_level(log)
45
- h.delete(:message) if h[:exception] && (h[:message] == h[:exception][:message])
46
- h.delete(:time)
47
- h.delete(:exception)
48
- h
43
+ hash = SemanticLogger::Formatters::Raw.new.call(log, logger)
44
+ hash.delete(:message) if hash[:exception] && (hash[:message] == hash[:exception][:message])
45
+ hash.delete(:time)
46
+ hash.delete(:level_index)
47
+ hash.delete(:exception)
48
+ hash[:file] = "#{hash[:file]}:#{hash.delete(:line)}" if hash.key?(:file)
49
+ hash
49
50
  end
50
51
 
51
- # Send an error notification to Bugsnag
52
52
  def log(log)
53
53
  # Ignore logs coming from Bugsnag itself
54
54
  return false if log.name == "Bugsnag"
55
55
 
56
56
  # Send error messages as Runtime exceptions
57
- exception =
58
- if log.exception
59
- # Manually constructed Exception, without a backtrace.
60
- log.exception.set_backtrace(log.backtrace) if !log.exception.backtrace && log.backtrace
61
- log.exception
62
- else
63
- error = RuntimeError.new(log.message)
64
- error.set_backtrace(log.backtrace) if log.backtrace
65
- error
66
- end
67
-
68
- # For more documentation on the Bugsnag.notify method see:
69
- # https://bugsnag.com/docs/notifiers/ruby#sending-handled-exceptions
70
- ::Bugsnag.notify(exception, formatter.call(log, self))
57
+ exception = extract_exception(log)
58
+ hash = formatter.call(log, self)
59
+ bugsnag_notify(exception, hash, log_level(log.level))
71
60
  true
72
61
  end
73
62
 
74
63
  private
75
64
 
65
+ def bugsnag_notify(exception, hash, level)
66
+ if ::Bugsnag::VERSION.to_i >= 6
67
+ ::Bugsnag.notify(exception) do |report|
68
+ report.severity = level
69
+ hash.each_pair { |key, value| report.add_tab(key, value) }
70
+ end
71
+ else
72
+ hash[:severity] = level
73
+ ::Bugsnag.notify(exception, hash)
74
+ end
75
+ end
76
+
77
+ def extract_exception(log)
78
+ if log.exception
79
+ # Manually constructed Exception, without a backtrace.
80
+ log.exception.set_backtrace(log.backtrace) if !log.exception.backtrace && log.backtrace
81
+ return log.exception
82
+ end
83
+
84
+ error = RuntimeError.new(log.message)
85
+ error.set_backtrace(log.backtrace) if log.backtrace
86
+ error
87
+ end
88
+
76
89
  # Bugsnag supports: error, warning or info
77
- def log_level(log)
78
- case log.level
90
+ def log_level(level)
91
+ case level
79
92
  when :error, :fatal
80
93
  "error"
81
94
  when :warn
@@ -1,7 +1,8 @@
1
1
  begin
2
2
  require "elasticsearch"
3
3
  rescue LoadError
4
- raise LoadError, 'Gem elasticsearch is required for logging to Elasticsearch. Please add the gem "elasticsearch" to your Gemfile.'
4
+ raise LoadError,
5
+ 'Gem elasticsearch is required for logging to Elasticsearch. Please add the gem "elasticsearch" to your Gemfile.'
5
6
  end
6
7
 
7
8
  require "date"
@@ -17,7 +18,8 @@ require "date"
17
18
  module SemanticLogger
18
19
  module Appender
19
20
  class Elasticsearch < SemanticLogger::Subscriber
20
- attr_accessor :url, :index, :date_pattern, :type, :client, :flush_interval, :timeout_interval, :batch_size, :elasticsearch_args
21
+ attr_accessor :url, :index, :date_pattern, :type, :client, :flush_interval, :timeout_interval, :batch_size,
22
+ :elasticsearch_args
21
23
 
22
24
  # Create Elasticsearch appender over persistent HTTP(S)
23
25
  #
@@ -36,7 +36,7 @@ module SemanticLogger
36
36
  # SemanticLogger.default_level = :info
37
37
  #
38
38
  # # Log to screen
39
- # SemanticLogger.add_appender(io: STDOUT, formatter: :color)
39
+ # SemanticLogger.add_appender(io: $stdout, formatter: :color)
40
40
  #
41
41
  # # And log to a file at the same time
42
42
  # SemanticLogger.add_appender(file_name: 'application.log', formatter: :color)
@@ -52,7 +52,7 @@ module SemanticLogger
52
52
  # SemanticLogger.default_level = :trace
53
53
  #
54
54
  # # Log to screen but only display :info and above
55
- # SemanticLogger.add_appender(io: STDOUT, level: :info)
55
+ # SemanticLogger.add_appender(io: $stdout, level: :info)
56
56
  #
57
57
  # # And log to a file at the same time, including all :trace level data
58
58
  # SemanticLogger.add_appender(file_name: 'application.log')
@@ -105,6 +105,10 @@ module SemanticLogger
105
105
  def flush
106
106
  @log.flush if @log.respond_to?(:flush)
107
107
  end
108
+
109
+ def console_output?
110
+ [$stderr, $stdout].include?(@log)
111
+ end
108
112
  end
109
113
  end
110
114
  end
@@ -183,6 +183,10 @@ module SemanticLogger
183
183
  delivery_interval: delivery_interval
184
184
  )
185
185
  end
186
+
187
+ private
188
+
189
+ attr_reader :producer
186
190
  end
187
191
  end
188
192
  end
@@ -1,7 +1,8 @@
1
1
  begin
2
2
  require "splunk-sdk-ruby"
3
3
  rescue LoadError
4
- raise LoadError, 'Gem splunk-sdk-ruby is required for logging to Splunk. Please add the gem "splunk-sdk-ruby" to your Gemfile.'
4
+ raise LoadError,
5
+ 'Gem splunk-sdk-ruby is required for logging to Splunk. Please add the gem "splunk-sdk-ruby" to your Gemfile.'
5
6
  end
6
7
 
7
8
  # Splunk log appender.
@@ -89,8 +89,9 @@ module SemanticLogger
89
89
  # For splunk format requirements see:
90
90
  # https://docs.splunk.com/Documentation/Splunk/latest/Data/FormateventsforHTTPEventCollector
91
91
  def call(log, logger)
92
- h = SemanticLogger::Formatters::Raw.new(time_format: :seconds).call(log, logger)
93
- message = {
92
+ h = SemanticLogger::Formatters::Raw.new(time_format: :seconds).call(log, logger)
93
+ h.delete(:host)
94
+ message = {
94
95
  source: logger.application,
95
96
  host: logger.host,
96
97
  time: h.delete(:time),
@@ -31,7 +31,7 @@ require "socket"
31
31
  module SemanticLogger
32
32
  module Appender
33
33
  class Syslog < SemanticLogger::Subscriber
34
- attr_reader :remote_syslog, :url, :server, :port, :protocol, :facility, :options, :level_map
34
+ attr_reader :remote_syslog, :url, :server, :port, :protocol, :facility, :options, :level_map, :max_size
35
35
 
36
36
  # Create a Syslog appender instance.
37
37
  #
@@ -57,7 +57,7 @@ module SemanticLogger
57
57
  # Only used with the TCP protocol.
58
58
  # Specify custom parameters to pass into Net::TCPClient.new
59
59
  # For a list of options see the net_tcp_client documentation:
60
- # https://github.com/rocketjob/net_tcp_client/blob/master/lib/net/tcp_client/tcp_client.rb
60
+ # https://github.com/reidmorrison/net_tcp_client/blob/master/lib/net/tcp_client/tcp_client.rb
61
61
  #
62
62
  # level: [:trace | :debug | :info | :warn | :error | :fatal]
63
63
  # Override the log level for this appender.
@@ -73,6 +73,10 @@ module SemanticLogger
73
73
  # Identity of the program.
74
74
  # Default: SemanticLogger.application
75
75
  #
76
+ # max_size: [Integer]
77
+ # Set your own packet size.
78
+ # Default: 1024 bytes
79
+ #
76
80
  # options: [Integer]
77
81
  # Default: ::Syslog::LOG_PID | ::Syslog::LOG_CONS
78
82
  # Any of the following (options can be logically OR'd together)
@@ -121,6 +125,7 @@ module SemanticLogger
121
125
  # SemanticLogger.add_appender(appender: :syslog, level_map: {warn: ::Syslog::LOG_NOTICE})
122
126
  def initialize(url: "syslog://localhost",
123
127
  facility: ::Syslog::LOG_USER,
128
+ max_size: 1024,
124
129
  level_map: SemanticLogger::Formatters::Syslog::LevelMap.new,
125
130
  options: ::Syslog::LOG_PID | ::Syslog::LOG_CONS,
126
131
  tcp_client: {},
@@ -129,6 +134,7 @@ module SemanticLogger
129
134
 
130
135
  @options = options
131
136
  @facility = facility
137
+ @max_size = max_size
132
138
  @level_map = level_map
133
139
  @url = url
134
140
  uri = URI(@url)
@@ -145,7 +151,8 @@ module SemanticLogger
145
151
  begin
146
152
  require "syslog_protocol"
147
153
  rescue LoadError
148
- raise LoadError, "Missing gem: syslog_protocol. This gem is required when logging over TCP or UDP. To fix this error: gem install syslog_protocol"
154
+ raise LoadError,
155
+ "Missing gem: syslog_protocol. This gem is required when logging over TCP or UDP. To fix this error: gem install syslog_protocol"
149
156
  end
150
157
 
151
158
  # The net_tcp_client gem is required when logging over TCP.
@@ -153,7 +160,8 @@ module SemanticLogger
153
160
  begin
154
161
  require "net/tcp_client"
155
162
  rescue LoadError
156
- raise LoadError, "Missing gem: net_tcp_client. This gem is required when logging over TCP. To fix this error: gem install net_tcp_client"
163
+ raise LoadError,
164
+ "Missing gem: net_tcp_client. This gem is required when logging over TCP. To fix this error: gem install net_tcp_client"
157
165
  end
158
166
  end
159
167
  end
@@ -209,7 +217,7 @@ module SemanticLogger
209
217
  # Format is text output without the time
210
218
  SemanticLogger::Formatters::Default.new(time_format: nil)
211
219
  else
212
- SemanticLogger::Formatters::Syslog.new(facility: facility, level_map: level_map)
220
+ SemanticLogger::Formatters::Syslog.new(facility: facility, level_map: level_map, max_size: max_size)
213
221
  end
214
222
  end
215
223
  end
@@ -32,7 +32,7 @@ module SemanticLogger
32
32
  # require 'logger'
33
33
  # require 'semantic_logger'
34
34
  #
35
- # ruby_logger = Logger.new(STDOUT)
35
+ # ruby_logger = Logger.new($stdout)
36
36
  # SemanticLogger.add_appender(logger: ruby_logger)
37
37
  #
38
38
  # logger = SemanticLogger['test']
@@ -45,7 +45,8 @@ module SemanticLogger
45
45
  # Check if the custom appender responds to all the log levels. For example Ruby ::Logger
46
46
  does_not_implement = LEVELS[1..-1].find { |i| !@logger.respond_to?(i) }
47
47
  if does_not_implement
48
- raise(ArgumentError, "Supplied logger does not implement:#{does_not_implement}. It must implement all of #{LEVELS[1..-1].inspect}")
48
+ raise(ArgumentError,
49
+ "Supplied logger does not implement:#{does_not_implement}. It must implement all of #{LEVELS[1..-1].inspect}")
49
50
  end
50
51
 
51
52
  super(**args, &block)
@@ -10,42 +10,48 @@ module SemanticLogger
10
10
 
11
11
  def add(**args, &block)
12
12
  appender = SemanticLogger::Appender.factory(**args, &block)
13
+
14
+ if appender.respond_to?(:console_output?) && appender.console_output? && console_output?
15
+ logger.warn "Ignoring attempt to add a second console appender: #{appender.class.name} since it would result in duplicate console output."
16
+ return
17
+ end
18
+
13
19
  self << appender
14
20
  appender
15
21
  end
16
22
 
23
+ # Whether any of the existing appenders already output to the console?
24
+ # I.e. Writes to stdout or stderr.
25
+ def console_output?
26
+ any? { |appender| appender.respond_to?(:console_output?) && appender.console_output? }
27
+ end
28
+
17
29
  def log(log)
18
30
  each do |appender|
19
- begin
20
- appender.log(log) if appender.should_log?(log)
21
- rescue Exception => e
22
- logger.error "Failed to log to appender: #{appender.name}", e
23
- end
31
+ appender.log(log) if appender.should_log?(log)
32
+ rescue Exception => e
33
+ logger.error "Failed to log to appender: #{appender.name}", e
24
34
  end
25
35
  end
26
36
 
27
37
  def flush
28
38
  each do |appender|
29
- begin
30
- logger.trace "Flushing appender: #{appender.name}"
31
- appender.flush
32
- rescue Exception => e
33
- logger.error "Failed to flush appender: #{appender.name}", e
34
- end
39
+ logger.trace "Flushing appender: #{appender.name}"
40
+ appender.flush
41
+ rescue Exception => e
42
+ logger.error "Failed to flush appender: #{appender.name}", e
35
43
  end
36
44
  logger.trace "All appenders flushed"
37
45
  end
38
46
 
39
47
  def close
40
- each do |appender|
41
- begin
42
- logger.trace "Closing appender: #{appender.name}"
43
- appender.flush
44
- appender.close
45
- delete(appender)
46
- rescue Exception => e
47
- logger.error "Failed to close appender: #{appender.name}", e
48
- end
48
+ to_a.each do |appender|
49
+ logger.trace "Closing appender: #{appender.name}"
50
+ delete(appender)
51
+ appender.flush
52
+ appender.close
53
+ rescue Exception => e
54
+ logger.error "Failed to close appender: #{appender.name}", e
49
55
  end
50
56
  logger.trace "All appenders closed and removed from appender list"
51
57
  end
@@ -53,14 +59,12 @@ module SemanticLogger
53
59
  # After a fork the appender thread is not running, start it if it is not running.
54
60
  def reopen
55
61
  each do |appender|
56
- begin
57
- next unless appender.respond_to?(:reopen)
62
+ next unless appender.respond_to?(:reopen)
58
63
 
59
- logger.trace "Reopening appender: #{appender.name}"
60
- appender.reopen
61
- rescue Exception => e
62
- logger.error "Failed to re-open appender: #{appender.name}", e
63
- end
64
+ logger.trace "Reopening appender: #{appender.name}"
65
+ appender.reopen
66
+ rescue Exception => e
67
+ logger.error "Failed to re-open appender: #{appender.name}", e
64
68
  end
65
69
  logger.trace "All appenders re-opened"
66
70
  end
@@ -63,7 +63,7 @@ module SemanticLogger
63
63
  # SemanticLogger.default_level = :info
64
64
  #
65
65
  # # Log to screen
66
- # SemanticLogger.add_appender(io: STDOUT, formatter: :color)
66
+ # SemanticLogger.add_appender(io: $stdout, formatter: :color)
67
67
  #
68
68
  # # And log to a file at the same time
69
69
  # SemanticLogger.add_appender(file_name: 'application.log', formatter: :color)
@@ -136,7 +136,7 @@ module SemanticLogger
136
136
 
137
137
  backtrace =
138
138
  if thread == Thread.current
139
- Utils.extract_backtrace
139
+ Utils.extract_backtrace(caller)
140
140
  else
141
141
  log.thread_name = thread.name
142
142
  log.tags = (thread[:semantic_logger_tags] || []).clone
@@ -263,14 +263,22 @@ module SemanticLogger
263
263
  # For example if set to :warn, this appender would only log :warn and :fatal
264
264
  # log messages when other appenders could be logging :info and lower
265
265
  #
266
- # filter [Regexp|Proc]
266
+ # filter [Regexp|Proc|Module]
267
267
  # RegExp: Only include log messages where the class name matches the supplied
268
268
  # regular expression. All other messages will be ignored
269
269
  # Proc: Only include log messages where the supplied Proc returns true
270
270
  # The Proc must return true or false
271
+ # Module: A module that implements `.call`. For example:
272
+ # module ComplexFilter
273
+ # def self.call(log)
274
+ # (/\AExclude/ =~ log.message).nil?
275
+ # end
276
+ # end
271
277
  def initialize(klass, level = nil, filter = nil)
272
- # Support filtering all messages to this logger using a Regular Expression or Proc
273
- raise ":filter must be a Regexp or Proc" unless filter.nil? || filter.is_a?(Regexp) || filter.is_a?(Proc)
278
+ # Support filtering all messages to this logger instance.
279
+ unless filter.nil? || filter.is_a?(Regexp) || filter.is_a?(Proc) || filter.respond_to?(:call)
280
+ raise ":filter must be a Regexp, Proc, or implement :call"
281
+ end
274
282
 
275
283
  @filter = filter.is_a?(Regexp) ? filter.freeze : filter
276
284
  @name = klass.is_a?(String) ? klass : klass.name
@@ -368,7 +376,7 @@ module SemanticLogger
368
376
  exception = e
369
377
  ensure
370
378
  # Must use ensure block otherwise a `return` in the yield above will skip the log entry
371
- log = Log.new(name, level, index)
379
+ log = Log.new(name, level, index)
372
380
  exception ||= params[:exception]
373
381
  message = params[:message] if params[:message]
374
382
  duration =
@@ -1,16 +1,15 @@
1
1
  module SemanticLogger
2
2
  module Formatters
3
- # @formatter:off
4
- autoload :Base, "semantic_logger/formatters/base"
5
- autoload :Color, "semantic_logger/formatters/color"
6
- autoload :Default, "semantic_logger/formatters/default"
7
- autoload :Json, "semantic_logger/formatters/json"
8
- autoload :Raw, "semantic_logger/formatters/raw"
9
- autoload :OneLine, "semantic_logger/formatters/one_line"
10
- autoload :Signalfx, "semantic_logger/formatters/signalfx"
11
- autoload :Syslog, "semantic_logger/formatters/syslog"
12
- autoload :Fluentd, "semantic_logger/formatters/fluentd"
13
- # @formatter:on
3
+ autoload :Base, "semantic_logger/formatters/base"
4
+ autoload :Color, "semantic_logger/formatters/color"
5
+ autoload :Default, "semantic_logger/formatters/default"
6
+ autoload :Json, "semantic_logger/formatters/json"
7
+ autoload :Raw, "semantic_logger/formatters/raw"
8
+ autoload :OneLine, "semantic_logger/formatters/one_line"
9
+ autoload :Signalfx, "semantic_logger/formatters/signalfx"
10
+ autoload :Syslog, "semantic_logger/formatters/syslog"
11
+ autoload :Fluentd, "semantic_logger/formatters/fluentd"
12
+ autoload :Logfmt, "semantic_logger/formatters/logfmt"
14
13
 
15
14
  # Return formatter that responds to call.
16
15
  #
@@ -109,14 +109,14 @@ module SemanticLogger
109
109
  def payload
110
110
  return unless log.payload?
111
111
 
112
- if !log.payload.respond_to?(:ai)
113
- super
114
- else
112
+ if log.payload.respond_to?(:ai)
115
113
  begin
116
114
  "-- #{log.payload.ai(@ai_options)}"
117
115
  rescue StandardError
118
116
  super
119
117
  end
118
+ else
119
+ super
120
120
  end
121
121
  end
122
122
 
@@ -0,0 +1,54 @@
1
+ require "json"
2
+
3
+ module SemanticLogger
4
+ module Formatters
5
+ class Logfmt < Raw
6
+ def initialize(time_format: :iso_8601, time_key: :timestamp, **args)
7
+ super(time_format: time_format, time_key: time_key, **args)
8
+ end
9
+
10
+ def call(log, logger)
11
+ @raw = super(log, logger)
12
+
13
+ raw_to_logfmt
14
+ end
15
+
16
+ private
17
+
18
+ def raw_to_logfmt
19
+ @parsed = @raw.slice(:timestamp, :level, :name, :message, :duration).merge tag: "success"
20
+ handle_payload
21
+ handle_exception
22
+
23
+ flatten_log
24
+ end
25
+
26
+ def handle_payload
27
+ return unless @raw.key? :payload
28
+
29
+ @parsed = @parsed.merge(@raw[:payload])
30
+ end
31
+
32
+ def handle_exception
33
+ return unless @raw.key? :exception
34
+
35
+ @parsed[:tag] = "exception"
36
+ @parsed = @parsed.merge(@raw[:exception])
37
+ end
38
+
39
+ def flatten_log
40
+ flattened = @parsed.map do |key, value|
41
+ "#{key}=#{parse_value(value)}"
42
+ end
43
+
44
+ flattened.join(" ")
45
+ end
46
+
47
+ def parse_value(value)
48
+ return value.to_json if value.instance_of? String
49
+
50
+ value
51
+ end
52
+ end
53
+ end
54
+ end
@@ -1,13 +1,14 @@
1
1
  begin
2
2
  require "syslog_protocol"
3
3
  rescue LoadError
4
- raise LoadError, 'Gem syslog_protocol is required for remote logging using the Syslog protocol. Please add the gem "syslog_protocol" to your Gemfile.'
4
+ raise LoadError,
5
+ 'Gem syslog_protocol is required for remote logging using the Syslog protocol. Please add the gem "syslog_protocol" to your Gemfile.'
5
6
  end
6
7
 
7
8
  module SemanticLogger
8
9
  module Formatters
9
10
  class Syslog < Default
10
- attr_accessor :level_map, :facility
11
+ attr_accessor :level_map, :facility, :max_size
11
12
 
12
13
  # Default level map for every log level
13
14
  #
@@ -50,9 +51,10 @@ module SemanticLogger
50
51
  # Example:
51
52
  # # Change the warn level to LOG_NOTICE level instead of a the default of LOG_WARNING.
52
53
  # SemanticLogger.add_appender(appender: :syslog, level_map: {warn: ::Syslog::LOG_NOTICE})
53
- def initialize(facility: ::Syslog::LOG_USER, level_map: LevelMap.new)
54
+ def initialize(facility: ::Syslog::LOG_USER, level_map: LevelMap.new, max_size: Integer)
54
55
  @facility = facility
55
56
  @level_map = level_map.is_a?(LevelMap) ? level_map : LevelMap.new(level_map)
57
+ @max_size = max_size
56
58
  super()
57
59
  end
58
60
 
@@ -77,7 +79,7 @@ module SemanticLogger
77
79
  packet.content = message
78
80
  packet.time = log.time
79
81
  packet.severity = level_map[log.level]
80
- packet.to_s
82
+ packet.assemble(@max_size)
81
83
  end
82
84
  end
83
85
  end
@@ -1,13 +1,14 @@
1
1
  begin
2
2
  require "syslog_protocol"
3
3
  rescue LoadError
4
- raise LoadError, 'Gem syslog_protocol is required for remote logging using the Syslog protocol. Please add the gem "syslog_protocol" to your Gemfile.'
4
+ raise LoadError,
5
+ 'Gem syslog_protocol is required for remote logging using the Syslog protocol. Please add the gem "syslog_protocol" to your Gemfile.'
5
6
  end
6
7
 
7
8
  module SemanticLogger
8
9
  module Formatters
9
10
  class SyslogCee < Raw
10
- attr_accessor :level_map, :facility
11
+ attr_accessor :level_map, :facility, :max_size
11
12
 
12
13
  # CEE JSON Syslog format
13
14
  # Untested prototype code. Based on documentation only.
@@ -23,9 +24,10 @@ module SemanticLogger
23
24
  # Example:
24
25
  # # Log via udp to a remote syslog server on host: `server1` and port `8514`, using the CEE format.
25
26
  # SemanticLogger.add_appender(appender: :syslog, formatter: syslog_cee, url: 'udp://server1:8514')
26
- def initialize(facility: ::Syslog::LOG_USER, level_map: SemanticLogger::Formatters::Syslog::LevelMap.new)
27
+ def initialize(facility: ::Syslog::LOG_USER, level_map: SemanticLogger::Formatters::Syslog::LevelMap.new, max_size: Integer)
27
28
  @facility = facility
28
29
  @level_map = level_map.is_a?(SemanticLogger::Formatters::Syslog::LevelMap) ? level_map : SemanticLogger::Formatters::Syslog::LevelMap.new(level_map)
30
+ @max_size = max_size
29
31
  super()
30
32
  end
31
33
 
@@ -49,7 +51,7 @@ module SemanticLogger
49
51
  packet.content = message
50
52
  packet.time = log.time
51
53
  packet.severity = level_map[log.level]
52
- packet.to_s
54
+ packet.assemble(@max_size)
53
55
  end
54
56
  end
55
57
  end
@@ -114,14 +114,12 @@ module SemanticLogger
114
114
 
115
115
  # Elastic logging: Log when :duration exceeds :min_duration
116
116
  # Except if there is an exception when it will always be logged
117
- if duration
118
- return false if (duration < min_duration) && exception.nil?
119
- end
117
+ return false if duration && ((duration < min_duration) && exception.nil?)
120
118
 
121
119
  if backtrace
122
120
  self.backtrace = Utils.extract_backtrace(backtrace)
123
121
  elsif level_index >= SemanticLogger.backtrace_level_index
124
- self.backtrace = Utils.extract_backtrace
122
+ self.backtrace = Utils.extract_backtrace(caller)
125
123
  end
126
124
 
127
125
  true
@@ -8,7 +8,7 @@
8
8
  # Example:
9
9
  # require 'semantic_logger'
10
10
  # SemanticLogger.default_level = :debug
11
- # SemanticLogger.add_appender(io: STDOUT, formatter: :color)
11
+ # SemanticLogger.add_appender(io: $stdout, formatter: :color)
12
12
  #
13
13
  # class ExternalSupplier
14
14
  # # Create class and instance logger methods
@@ -21,7 +21,19 @@ module SemanticLogger
21
21
  end
22
22
 
23
23
  def self.processor
24
- @processor ||= SemanticLogger.sync? ? SyncProcessor.new : Processor.new
24
+ @processor ||= Processor.new
25
+ end
26
+
27
+ # Switch to the synchronous processor
28
+ def self.sync!
29
+ return if @processor.is_a?(SyncProcessor)
30
+
31
+ @processor = SyncProcessor.new(@processor&.appenders)
32
+ end
33
+
34
+ # Running without the background logging thread?
35
+ def self.sync?
36
+ processor.is_a?(SyncProcessor)
25
37
  end
26
38
 
27
39
  # Returns a Logger instance
@@ -70,11 +82,9 @@ module SemanticLogger
70
82
  return unless @subscribers
71
83
 
72
84
  @subscribers.each do |subscriber|
73
- begin
74
- subscriber.call(log)
75
- rescue Exception => e
76
- processor.logger.error("Exception calling :on_log subscriber", e)
77
- end
85
+ subscriber.call(log)
86
+ rescue Exception => e
87
+ processor.logger.error("Exception calling :on_log subscriber", e)
78
88
  end
79
89
  end
80
90
  end
@@ -1,7 +1,7 @@
1
1
  module SemanticLogger
2
2
  # Thread that submits and processes log requests
3
3
  class Processor < Appender::Async
4
- # Allow the internal logger to be overridden from its default of STDERR
4
+ # Allow the internal logger to be overridden from its default of $stderr
5
5
  # Can be replaced with another Ruby logger or Rails logger, but never to
6
6
  # SemanticLogger::Logger itself since it is for reporting problems
7
7
  # while trying to log to the various appenders
@@ -11,11 +11,11 @@ module SemanticLogger
11
11
 
12
12
  # Internal logger for SemanticLogger
13
13
  # For example when an appender is not working etc..
14
- # By default logs to STDERR
14
+ # By default logs to $stderr
15
15
  def self.logger
16
16
  @logger ||=
17
17
  begin
18
- l = SemanticLogger::Appender::File.new(io: STDERR, level: :warn)
18
+ l = SemanticLogger::Appender::File.new(io: $stderr, level: :warn)
19
19
  l.name = name
20
20
  l
21
21
  end
@@ -101,7 +101,7 @@ module SemanticLogger
101
101
  # Or,
102
102
  # io: [IO]
103
103
  # An IO Stream to log to.
104
- # For example STDOUT, STDERR, etc.
104
+ # For example $stdout, $stderr, etc.
105
105
  #
106
106
  # Or,
107
107
  # appender: [Symbol|SemanticLogger::Subscriber]
@@ -138,14 +138,14 @@ module SemanticLogger
138
138
  # Examples:
139
139
  #
140
140
  # # Send all logging output to Standard Out (Screen)
141
- # SemanticLogger.add_appender(io: STDOUT)
141
+ # SemanticLogger.add_appender(io: $stdout)
142
142
  #
143
143
  # # Send all logging output to a file
144
144
  # SemanticLogger.add_appender(file_name: 'logfile.log')
145
145
  #
146
146
  # # Send all logging output to a file and only :info and above to standard output
147
147
  # SemanticLogger.add_appender(file_name: 'logfile.log')
148
- # SemanticLogger.add_appender(io: STDOUT, level: :info)
148
+ # SemanticLogger.add_appender(io: $stdout, level: :info)
149
149
  #
150
150
  # Log to log4r, Logger, etc.:
151
151
  #
@@ -154,7 +154,7 @@ module SemanticLogger
154
154
  # require 'semantic_logger'
155
155
  #
156
156
  # # Built-in Ruby logger
157
- # log = Logger.new(STDOUT)
157
+ # log = Logger.new($stdout)
158
158
  # log.level = Logger::DEBUG
159
159
  #
160
160
  # SemanticLogger.default_level = :debug
@@ -173,7 +173,15 @@ module SemanticLogger
173
173
  # Remove an existing appender
174
174
  # Currently only supports appender instances
175
175
  def self.remove_appender(appender)
176
+ return unless appender
177
+
176
178
  Logger.processor.appenders.delete(appender)
179
+ appender.close
180
+ end
181
+
182
+ # Clear out all previously registered appenders
183
+ def self.clear_appenders!
184
+ Logger.processor.close
177
185
  end
178
186
 
179
187
  # Returns [SemanticLogger::Subscriber] a copy of the list of active
@@ -494,12 +502,12 @@ module SemanticLogger
494
502
  # I.e. Instead of logging messages in a separate thread for better performance,
495
503
  # log them using the current thread.
496
504
  def self.sync!
497
- @sync = true
505
+ Logger.sync!
498
506
  end
499
507
 
500
508
  # Running in synchronous mode?
501
509
  def self.sync?
502
- @sync
510
+ Logger.sync?
503
511
  end
504
512
 
505
513
  # Initial default Level for all new instances of SemanticLogger::Logger
@@ -10,7 +10,7 @@ module SemanticLogger
10
10
  def_delegator :@appenders, :close
11
11
  def_delegator :@appenders, :reopen
12
12
 
13
- # Allow the internal logger to be overridden from its default of STDERR
13
+ # Allow the internal logger to be overridden from its default of $stderr
14
14
  # Can be replaced with another Ruby logger or Rails logger, but never to
15
15
  # SemanticLogger::Logger itself since it is for reporting problems
16
16
  # while trying to log to the various appenders
@@ -20,11 +20,11 @@ module SemanticLogger
20
20
 
21
21
  # Internal logger for SemanticLogger
22
22
  # For example when an appender is not working etc..
23
- # By default logs to STDERR
23
+ # By default logs to $stderr
24
24
  def self.logger
25
25
  @logger ||=
26
26
  begin
27
- l = SemanticLogger::Appender::File.new(io: STDERR, level: :warn)
27
+ l = SemanticLogger::Appender::File.new(io: $stderr, level: :warn)
28
28
  l.name = name
29
29
  l
30
30
  end
@@ -32,8 +32,8 @@ module SemanticLogger
32
32
 
33
33
  attr_reader :appenders
34
34
 
35
- def initialize
36
- @appenders = Appenders.new(self.class.logger.dup)
35
+ def initialize(appenders = nil)
36
+ @appenders = appenders || Appenders.new(self.class.logger.dup)
37
37
  end
38
38
 
39
39
  def start
@@ -32,29 +32,48 @@ module SemanticLogger
32
32
  end
33
33
  end
34
34
 
35
- SELF_PATTERN = File.join("lib", "semantic_logger")
36
-
37
- # Extract the backtrace leaving out the last few Semantic Logger lines.
35
+ # Extract the backtrace stripping off the leading semantic logger entries.
36
+ # Leaves all other system and gem path entries in place.
38
37
  def self.extract_backtrace(stack = caller)
39
- while (first = stack.first) && first.include?(SELF_PATTERN)
38
+ while (first = stack.first) && extract_path?(first)
40
39
  stack.shift
41
40
  end
42
41
  stack
43
42
  end
44
43
 
45
- # Strips off all gems and built-in ruby code paths from the top of the stack until application code is found.
44
+ def self.extract_paths
45
+ @extract_paths ||= %w[lib/semantic_logger lib/rails_semantic_logger]
46
+ end
47
+
48
+ # Whether this path should be excluded from any cleansed backtrace
49
+ def self.extract_path?(path)
50
+ extract_paths.any? { |exclude| path.include?(exclude) }
51
+ end
52
+
53
+ # Try to strip everything off of the supplied backtrace, until the first application stack entry is at the top.
54
+ # For example all leading gem paths and built-in ruby code paths are removed from the top.
55
+ # Once the first application entry is found, the remaining stack is returned.
46
56
  def self.strip_backtrace(stack = caller)
47
- while (first = stack.first) && system_path?(first)
57
+ while (first = stack.first) && (strip_path?(first) || extract_path?(first))
48
58
  stack.shift
49
59
  end
50
60
  stack
51
61
  end
52
62
 
53
- GEM_ROOT = File.expand_path("../../..", __dir__) + "/"
63
+ # Paths to exclude in the stripped backtrace
64
+ # Includes Gems and built-in Ruby code paths
65
+ def self.strip_paths
66
+ @strip_paths ||=
67
+ begin
68
+ paths = Gem.path | [Gem.default_dir]
69
+ paths << RbConfig::CONFIG["rubylibdir"]
70
+ paths
71
+ end
72
+ end
54
73
 
55
- def self.system_path?(path)
56
- path.start_with?(GEM_ROOT) ||
57
- path.start_with?(RbConfig::CONFIG["rubylibdir"])
74
+ # Whether this path should be excluded from any cleansed backtrace
75
+ def self.strip_path?(path)
76
+ strip_paths.any? { |exclude| path.start_with?(exclude) }
58
77
  end
59
78
  end
60
79
  end
@@ -1,3 +1,3 @@
1
1
  module SemanticLogger
2
- VERSION = "4.7.1".freeze
2
+ VERSION = "4.8.1".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: semantic_logger
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.7.1
4
+ version: 4.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Reid Morrison
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-14 00:00:00.000000000 Z
11
+ date: 2021-06-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -24,9 +24,8 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.0'
27
- description:
27
+ description:
28
28
  email:
29
- - reidmo@gmail.com
30
29
  executables: []
31
30
  extensions: []
32
31
  extra_rdoc_files: []
@@ -68,6 +67,7 @@ files:
68
67
  - lib/semantic_logger/formatters/default.rb
69
68
  - lib/semantic_logger/formatters/fluentd.rb
70
69
  - lib/semantic_logger/formatters/json.rb
70
+ - lib/semantic_logger/formatters/logfmt.rb
71
71
  - lib/semantic_logger/formatters/one_line.rb
72
72
  - lib/semantic_logger/formatters/raw.rb
73
73
  - lib/semantic_logger/formatters/signalfx.rb
@@ -89,11 +89,11 @@ files:
89
89
  - lib/semantic_logger/sync_processor.rb
90
90
  - lib/semantic_logger/utils.rb
91
91
  - lib/semantic_logger/version.rb
92
- homepage: https://github.com/rocketjob/semantic_logger
92
+ homepage: https://logger.rocketjob.io
93
93
  licenses:
94
94
  - Apache-2.0
95
95
  metadata: {}
96
- post_install_message:
96
+ post_install_message:
97
97
  rdoc_options: []
98
98
  require_paths:
99
99
  - lib
@@ -101,15 +101,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
101
101
  requirements:
102
102
  - - ">="
103
103
  - !ruby/object:Gem::Version
104
- version: '2.3'
104
+ version: '2.5'
105
105
  required_rubygems_version: !ruby/object:Gem::Requirement
106
106
  requirements:
107
107
  - - ">="
108
108
  - !ruby/object:Gem::Version
109
109
  version: '0'
110
110
  requirements: []
111
- rubygems_version: 3.1.2
112
- signing_key:
111
+ rubygems_version: 3.2.15
112
+ signing_key:
113
113
  specification_version: 4
114
114
  summary: Feature rich logging framework, and replacement for existing Ruby & Rails
115
115
  loggers.