semantic_logger 3.0.1 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/semantic_logger.rb +29 -13
- data/lib/semantic_logger/ansi_colors.rb +27 -0
- data/lib/semantic_logger/appender/base.rb +54 -128
- data/lib/semantic_logger/appender/bugsnag.rb +29 -19
- data/lib/semantic_logger/appender/elasticsearch.rb +9 -9
- data/lib/semantic_logger/appender/file.rb +40 -18
- data/lib/semantic_logger/appender/graylog.rb +30 -26
- data/lib/semantic_logger/appender/http.rb +14 -19
- data/lib/semantic_logger/appender/mongodb.rb +20 -20
- data/lib/semantic_logger/appender/new_relic.rb +15 -15
- data/lib/semantic_logger/appender/splunk.rb +1 -1
- data/lib/semantic_logger/appender/splunk_http.rb +28 -25
- data/lib/semantic_logger/appender/syslog.rb +41 -42
- data/lib/semantic_logger/appender/wrapper.rb +19 -17
- data/lib/semantic_logger/base.rb +57 -32
- data/lib/semantic_logger/concerns/compatibility.rb +51 -0
- data/lib/semantic_logger/debug_as_trace_logger.rb +6 -2
- data/lib/semantic_logger/formatters/color.rb +66 -0
- data/lib/semantic_logger/formatters/default.rb +39 -0
- data/lib/semantic_logger/formatters/json.rb +16 -0
- data/lib/semantic_logger/jruby/garbage_collection_logger.rb +1 -1
- data/lib/semantic_logger/log.rb +13 -8
- data/lib/semantic_logger/loggable.rb +2 -2
- data/lib/semantic_logger/logger.rb +18 -13
- data/lib/semantic_logger/metrics/new_relic.rb +18 -0
- data/lib/semantic_logger/metrics/statsd.rb +48 -0
- data/lib/semantic_logger/semantic_logger.rb +122 -55
- data/lib/semantic_logger/version.rb +1 -1
- data/test/appender/bugsnag_test.rb +12 -3
- data/test/appender/mongodb_test.rb +6 -5
- data/test/appender/new_relic_test.rb +1 -1
- data/test/appender/splunk_http_test.rb +1 -0
- data/test/concerns/compatibility_test.rb +106 -0
- data/test/debug_as_trace_logger_test.rb +1 -1
- data/test/loggable_test.rb +1 -1
- data/test/logger_test.rb +183 -24
- metadata +12 -3
@@ -11,8 +11,12 @@ module SemanticLogger
|
|
11
11
|
trace?
|
12
12
|
end
|
13
13
|
|
14
|
+
def measure_debug(*args, &block)
|
15
|
+
measure_trace(*args, &block)
|
16
|
+
end
|
17
|
+
|
14
18
|
def benchmark_debug(*args, &block)
|
15
|
-
|
19
|
+
measure_trace(*args, &block)
|
16
20
|
end
|
17
21
|
end
|
18
|
-
end
|
22
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# Load AwesomePrint if available
|
2
|
+
begin
|
3
|
+
require 'awesome_print'
|
4
|
+
rescue LoadError
|
5
|
+
end
|
6
|
+
|
7
|
+
module SemanticLogger
|
8
|
+
module Formatters
|
9
|
+
class Color
|
10
|
+
# Parameters:
|
11
|
+
# Any valid AwesomePrint option for rendering data.
|
12
|
+
# These options can also be changed be creating a `~/.aprc` file.
|
13
|
+
# See: https://github.com/michaeldv/awesome_print
|
14
|
+
#
|
15
|
+
# Note: The option :multiline is set to false if not supplied.
|
16
|
+
# Note: Has no effect if Awesome Print is not installed.
|
17
|
+
def initialize(options={})
|
18
|
+
@ai_options = options.dup
|
19
|
+
@ai_options[:multiline] = false unless @ai_options.has_key?(:multiline)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Adds color to the default log formatter
|
23
|
+
# Example:
|
24
|
+
# SemanticLogger.add_appender(io: $stdout, formatter: :color)
|
25
|
+
def call(log, logger)
|
26
|
+
colors = SemanticLogger::AnsiColors
|
27
|
+
level_color = colors::LEVEL_MAP[log.level]
|
28
|
+
|
29
|
+
# Header with date, time, log level and process info
|
30
|
+
message = "#{log.formatted_time} #{level_color}#{log.level_to_s}#{colors::CLEAR} [#{log.process_info}]"
|
31
|
+
|
32
|
+
# Tags
|
33
|
+
message << ' ' << log.tags.collect { |tag| "[#{level_color}#{tag}#{colors::CLEAR}]" }.join(' ') if log.tags && (log.tags.size > 0)
|
34
|
+
|
35
|
+
# Duration
|
36
|
+
message << " (#{colors::BOLD}#{log.duration_human}#{colors::CLEAR})" if log.duration
|
37
|
+
|
38
|
+
# Class / app name
|
39
|
+
message << " #{level_color}#{log.name}#{colors::CLEAR}"
|
40
|
+
|
41
|
+
# Log message
|
42
|
+
message << " -- #{log.message}" if log.message
|
43
|
+
|
44
|
+
# Payload: Colorize the payload if the AwesomePrint gem is loaded
|
45
|
+
if log.has_payload?
|
46
|
+
payload = log.payload
|
47
|
+
message << ' -- ' <<
|
48
|
+
if !defined?(AwesomePrint) || !payload.respond_to?(:ai)
|
49
|
+
payload.inspect
|
50
|
+
else
|
51
|
+
payload.ai(@ai_options) rescue payload.inspect
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Exceptions
|
56
|
+
if log.exception
|
57
|
+
message << " -- Exception: #{colors::BOLD}#{log.exception.class}: #{log.exception.message}#{colors::CLEAR}\n"
|
58
|
+
message << log.backtrace_to_s
|
59
|
+
end
|
60
|
+
message
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module SemanticLogger
|
2
|
+
module Formatters
|
3
|
+
class Default
|
4
|
+
# Default log formatter
|
5
|
+
# Generates logs of the form:
|
6
|
+
# 2011-07-19 14:36:15.660 D [1149:ScriptThreadProcess] Rails -- Hello World
|
7
|
+
def call(log, logger)
|
8
|
+
# Header with date, time, log level and process info
|
9
|
+
message = "#{log.formatted_time} #{log.level_to_s} [#{log.process_info}]"
|
10
|
+
|
11
|
+
# Tags
|
12
|
+
message << ' ' << log.tags.collect { |tag| "[#{tag}]" }.join(' ') if log.tags && (log.tags.size > 0)
|
13
|
+
|
14
|
+
# Duration
|
15
|
+
message << " (#{log.duration_human})" if log.duration
|
16
|
+
|
17
|
+
# Class / app name
|
18
|
+
message << " #{log.name}"
|
19
|
+
|
20
|
+
# Log message
|
21
|
+
message << " -- #{log.message}" if log.message
|
22
|
+
|
23
|
+
# Payload
|
24
|
+
if payload = log.payload_to_s
|
25
|
+
message << ' -- ' << payload
|
26
|
+
end
|
27
|
+
|
28
|
+
# Exceptions
|
29
|
+
if log.exception
|
30
|
+
message << " -- Exception: #{log.exception.class}: #{log.exception.message}\n"
|
31
|
+
message << log.backtrace_to_s
|
32
|
+
end
|
33
|
+
message
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'json'
|
2
|
+
module SemanticLogger
|
3
|
+
module Formatters
|
4
|
+
class Json
|
5
|
+
# Returns log messages in JSON format
|
6
|
+
def call(log, logger)
|
7
|
+
h = log.to_h
|
8
|
+
h.delete(:time)
|
9
|
+
h[:timestamp] = log.time.utc.iso8601(defined?(JRuby) ? 3 : 6)
|
10
|
+
h.to_json
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
@@ -18,7 +18,7 @@ module SemanticLogger
|
|
18
18
|
gc_info = info.gc_info
|
19
19
|
duration = gc_info.duration
|
20
20
|
if duration >= @min_microseconds
|
21
|
-
SemanticLogger['GarbageCollector'].
|
21
|
+
SemanticLogger['GarbageCollector'].measure_warn "Garbage Collection completed: #{info.gc_name} ##{gc_info.id}", duration: duration.to_f / 1000
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
data/lib/semantic_logger/log.rb
CHANGED
@@ -23,7 +23,7 @@ module SemanticLogger
|
|
23
23
|
# The time at which the log entry was created
|
24
24
|
#
|
25
25
|
# duration
|
26
|
-
# The time taken to complete a
|
26
|
+
# The time taken to complete a measure call
|
27
27
|
#
|
28
28
|
# tags
|
29
29
|
# Any tags active on the thread when the log call was made
|
@@ -35,11 +35,15 @@ module SemanticLogger
|
|
35
35
|
# Ruby Exception object to log
|
36
36
|
#
|
37
37
|
# metric [Object]
|
38
|
-
# Object supplied when
|
38
|
+
# Object supplied when measure_x was called
|
39
39
|
#
|
40
40
|
# backtrace [Array<String>]
|
41
41
|
# The backtrace captured at source when the log level >= SemanticLogger.backtrace_level
|
42
|
-
|
42
|
+
#
|
43
|
+
# metric_amount [Numeric]
|
44
|
+
# Used for numeric or counter metrics.
|
45
|
+
# For example, the number of inquiries or, the amount purchased etc.
|
46
|
+
Log = Struct.new(:level, :thread_name, :name, :message, :payload, :time, :duration, :tags, :level_index, :exception, :metric, :backtrace, :metric_amount) do
|
43
47
|
|
44
48
|
MAX_EXCEPTIONS_TO_UNWRAP = 5
|
45
49
|
# Call the block for exception and any nested exception
|
@@ -147,12 +151,13 @@ module SemanticLogger
|
|
147
151
|
|
148
152
|
# Return the payload in text form
|
149
153
|
# Returns nil if payload is missing or empty
|
150
|
-
def payload_to_s
|
151
|
-
|
152
|
-
|
154
|
+
def payload_to_s
|
155
|
+
payload.inspect if has_payload?
|
156
|
+
end
|
153
157
|
|
154
|
-
|
155
|
-
|
158
|
+
# Returns [true|false] whether the log entry has a payload
|
159
|
+
def has_payload?
|
160
|
+
!(payload.nil? || (payload.respond_to?(:empty?) && payload.empty?))
|
156
161
|
end
|
157
162
|
|
158
163
|
if defined? JRuby
|
@@ -9,7 +9,7 @@
|
|
9
9
|
#
|
10
10
|
# require 'semantic_logger'
|
11
11
|
# SemanticLogger.default_level = :debug
|
12
|
-
# SemanticLogger.add_appender(STDOUT)
|
12
|
+
# SemanticLogger.add_appender(io: STDOUT, formatter: :color)
|
13
13
|
#
|
14
14
|
# class ExternalSupplier
|
15
15
|
# # Create class and instance logger methods
|
@@ -19,7 +19,7 @@
|
|
19
19
|
# logger.debug "Calculating with amount", { amount: amount, name: name }
|
20
20
|
#
|
21
21
|
# # Measure and log on completion how long the call took to the external supplier
|
22
|
-
# logger.
|
22
|
+
# logger.measure_info "Calling external interface" do
|
23
23
|
# # Code to call the external supplier ...
|
24
24
|
# end
|
25
25
|
# end
|
@@ -3,6 +3,8 @@ module SemanticLogger
|
|
3
3
|
# Logger stores the class name to be used for all log messages so that every
|
4
4
|
# log message written by this instance will include the class name
|
5
5
|
class Logger < Base
|
6
|
+
include SemanticLogger::Concerns::Compatibility
|
7
|
+
|
6
8
|
# Returns a Logger instance
|
7
9
|
#
|
8
10
|
# Return the logger for a specific class, supports class specific log levels
|
@@ -95,18 +97,27 @@ module SemanticLogger
|
|
95
97
|
queue_size
|
96
98
|
end
|
97
99
|
|
98
|
-
# Supply a block to be called whenever a metric is seen during
|
100
|
+
# Supply a block to be called whenever a metric is seen during measure logging
|
99
101
|
#
|
100
102
|
# Parameters
|
101
103
|
# block
|
102
104
|
# The block to be called
|
103
105
|
#
|
104
106
|
# Example:
|
105
|
-
# SemanticLogger.on_metric do |
|
106
|
-
# puts "#{
|
107
|
+
# SemanticLogger.on_metric do |log|
|
108
|
+
# puts "#{log.metric} was received. Log Struct: #{log.inspect}"
|
107
109
|
# end
|
108
|
-
def self.on_metric(&block)
|
109
|
-
(
|
110
|
+
def self.on_metric(object = nil, &block)
|
111
|
+
raise('When supplying an object, it must support the #call method') if object && !object.respond_to?(:call)
|
112
|
+
(@@metric_subscribers ||= Concurrent::Array.new) << (object || block)
|
113
|
+
end
|
114
|
+
|
115
|
+
# Place log request on the queue for the Appender thread to write to each
|
116
|
+
# appender in the order that they were registered
|
117
|
+
def log(log, message = nil, progname = nil, &block)
|
118
|
+
# Compatibility with ::Logger
|
119
|
+
return add(log, message, progname, &block) unless log.is_a?(SemanticLogger::Log)
|
120
|
+
self.class.queue << log if @@appender_thread
|
110
121
|
end
|
111
122
|
|
112
123
|
private
|
@@ -120,12 +131,6 @@ module SemanticLogger
|
|
120
131
|
@@queue
|
121
132
|
end
|
122
133
|
|
123
|
-
# Place log request on the queue for the Appender thread to write to each
|
124
|
-
# appender in the order that they were registered
|
125
|
-
def log(log)
|
126
|
-
self.class.queue << log if @@appender_thread
|
127
|
-
end
|
128
|
-
|
129
134
|
# Internal logger for SemanticLogger
|
130
135
|
# For example when an appender is not working etc..
|
131
136
|
# By default logs to STDERR
|
@@ -219,13 +224,13 @@ module SemanticLogger
|
|
219
224
|
end
|
220
225
|
|
221
226
|
# Call Metric subscribers
|
222
|
-
def self.call_metric_subscribers(
|
227
|
+
def self.call_metric_subscribers(log)
|
223
228
|
# If no subscribers registered, then return immediately
|
224
229
|
return unless @@metric_subscribers
|
225
230
|
|
226
231
|
@@metric_subscribers.each do |subscriber|
|
227
232
|
begin
|
228
|
-
subscriber.call(
|
233
|
+
subscriber.call(log)
|
229
234
|
rescue Exception => exc
|
230
235
|
logger.error 'Exception calling metrics subscriber', exc
|
231
236
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module SemanticLogger
|
2
|
+
module Metrics
|
3
|
+
class NewRelic
|
4
|
+
def call(log)
|
5
|
+
metric = log.metric
|
6
|
+
# Add 'Custom/' prefix for NewRelic
|
7
|
+
metric = "Custom/#{metric}" unless metric.start_with?('Custom')
|
8
|
+
|
9
|
+
if duration = log.duration
|
10
|
+
# Convert duration to seconds
|
11
|
+
::NewRelic::Agent.record_metric(metric, duration / 1000.0)
|
12
|
+
else
|
13
|
+
::NewRelic::Agent.increment_metric(metric, log.metric_amount || 1)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'uri'
|
2
|
+
begin
|
3
|
+
require 'statsd-ruby'
|
4
|
+
rescue LoadError
|
5
|
+
raise 'Gem statsd-ruby is required for logging metrics. Please add the gem "statsd-ruby" to your Gemfile.'
|
6
|
+
end
|
7
|
+
|
8
|
+
module SemanticLogger
|
9
|
+
module Metrics
|
10
|
+
class Statsd
|
11
|
+
# Create Statsd metrics subscriber
|
12
|
+
#
|
13
|
+
# Parameters:
|
14
|
+
# url: [String]
|
15
|
+
# Valid URL to post to.
|
16
|
+
# Example:
|
17
|
+
# udp://localhost:8125
|
18
|
+
# Example, send all metrics to a particular namespace:
|
19
|
+
# udp://localhost:8125/namespace
|
20
|
+
# Default: udp://localhost:8125
|
21
|
+
def initialize(options = {})
|
22
|
+
options = options.dup
|
23
|
+
@url = options.delete(:url) || 'udp://localhost:8125'
|
24
|
+
uri = URI.parse(@url)
|
25
|
+
raise('Statsd only supports udp. Example: "udp://localhost:8125"') if uri.scheme != 'udp'
|
26
|
+
|
27
|
+
@statsd = ::Statsd.new(uri.host, uri.port)
|
28
|
+
path = uri.path.chomp('/')
|
29
|
+
@statsd.namespace = path.sub('/', '') if path != ''
|
30
|
+
end
|
31
|
+
|
32
|
+
def call(log)
|
33
|
+
metric = log.metric
|
34
|
+
if duration = log.duration
|
35
|
+
$statsd.timing(metric, duration)
|
36
|
+
else
|
37
|
+
amount = (log.metric_amount || 1).round
|
38
|
+
if amount < 0
|
39
|
+
amount.times { $statsd.decrement(metric) }
|
40
|
+
else
|
41
|
+
amount.times { $statsd.increment(metric) }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -81,40 +81,59 @@ module SemanticLogger
|
|
81
81
|
# more information on custom formatters
|
82
82
|
#
|
83
83
|
# Parameters
|
84
|
-
#
|
85
|
-
#
|
86
|
-
#
|
87
|
-
#
|
88
|
-
#
|
89
|
-
#
|
90
|
-
#
|
91
|
-
#
|
92
|
-
#
|
93
|
-
#
|
94
|
-
# A
|
95
|
-
#
|
96
|
-
#
|
97
|
-
#
|
98
|
-
#
|
99
|
-
#
|
100
|
-
#
|
101
|
-
#
|
102
|
-
#
|
103
|
-
#
|
84
|
+
# file_name: [String]
|
85
|
+
# File name to write log messages to.
|
86
|
+
#
|
87
|
+
# Or,
|
88
|
+
# io: [IO]
|
89
|
+
# An IO Stream to log to.
|
90
|
+
# For example STDOUT, STDERR, etc.
|
91
|
+
#
|
92
|
+
# Or,
|
93
|
+
# appender: [Symbol|SemanticLogger::Appender::Base]
|
94
|
+
# A symbol identifying the appender to create.
|
95
|
+
# For example:
|
96
|
+
# :bugsnag, :elasticsearch, :graylog, :http, :mongodb, :new_relic, :splunk_http, :syslog, :wrapper
|
97
|
+
# Or,
|
98
|
+
# An instance of an appender derived from SemanticLogger::Appender::Base
|
99
|
+
# For example:
|
100
|
+
# SemanticLogger::Appender::Http.new(url: 'http://localhost:8088/path')
|
101
|
+
#
|
102
|
+
# Or,
|
103
|
+
# logger: [Logger|Log4r]
|
104
|
+
# An instance of a Logger or a Log4r logger.
|
105
|
+
#
|
106
|
+
# level: [:trace | :debug | :info | :warn | :error | :fatal]
|
107
|
+
# Override the log level for this appender.
|
108
|
+
# Default: SemanticLogger.default_level
|
109
|
+
#
|
110
|
+
# formatter: [Symbol|Object|Proc]
|
111
|
+
# Any of the following symbol values: :default, :color, :json
|
112
|
+
# Or,
|
113
|
+
# An instance of a class that implements #call
|
114
|
+
# Or,
|
115
|
+
# A Proc to be used to format the output from this appender
|
116
|
+
# Default: :default
|
117
|
+
#
|
118
|
+
# filter: [Regexp|Proc]
|
119
|
+
# RegExp: Only include log messages where the class name matches the supplied.
|
120
|
+
# regular expression. All other messages will be ignored.
|
121
|
+
# Proc: Only include log messages where the supplied Proc returns true
|
122
|
+
# The Proc must return true or false.
|
104
123
|
#
|
105
124
|
# Examples:
|
106
125
|
#
|
107
126
|
# # Send all logging output to Standard Out (Screen)
|
108
|
-
# SemanticLogger.add_appender(STDOUT)
|
127
|
+
# SemanticLogger.add_appender(io: STDOUT)
|
109
128
|
#
|
110
129
|
# # Send all logging output to a file
|
111
|
-
# SemanticLogger.add_appender('logfile.log')
|
130
|
+
# SemanticLogger.add_appender(file_name: 'logfile.log')
|
112
131
|
#
|
113
132
|
# # Send all logging output to a file and only :info and above to standard output
|
114
|
-
# SemanticLogger.add_appender('logfile.log')
|
115
|
-
# SemanticLogger.add_appender(STDOUT, :info)
|
133
|
+
# SemanticLogger.add_appender(file_name: 'logfile.log')
|
134
|
+
# SemanticLogger.add_appender(io: STDOUT, level: :info)
|
116
135
|
#
|
117
|
-
# Log to
|
136
|
+
# Log to log4r, Logger, etc.:
|
118
137
|
#
|
119
138
|
# # Send Semantic logging output to an existing logger
|
120
139
|
# require 'logger'
|
@@ -125,37 +144,19 @@ module SemanticLogger
|
|
125
144
|
# log.level = Logger::DEBUG
|
126
145
|
#
|
127
146
|
# SemanticLogger.default_level = :debug
|
128
|
-
# SemanticLogger.add_appender(log)
|
147
|
+
# SemanticLogger.add_appender(logger: log)
|
129
148
|
#
|
130
149
|
# logger = SemanticLogger['Example']
|
131
150
|
# logger.info "Hello World"
|
132
151
|
# logger.debug("Login time", user: 'Joe', duration: 100, ip_address: '127.0.0.1')
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
# $stderr, STDOUT, other IO, or a filename
|
138
|
-
SemanticLogger::Appender::File.new(appender, level, &block)
|
139
|
-
elsif appender.is_a? Appender::Base
|
140
|
-
# Already an instance of an appender
|
141
|
-
appender.level = level if level
|
142
|
-
appender.formatter = block if block
|
143
|
-
appender
|
144
|
-
else
|
145
|
-
# Check if the custom appender responds to all the log levels. For example Ruby ::Logger
|
146
|
-
if does_not_implement = LEVELS[1..-1].find { |i| !appender.respond_to?(i) }
|
147
|
-
raise "Supplied appender does not implement:#{does_not_implement}. It must implement all of #{LEVELS[1..-1].inspect}"
|
148
|
-
end
|
149
|
-
|
150
|
-
raise "Change the log level to #{level}, update the log level directly against the supplied appender" if level
|
151
|
-
SemanticLogger::Appender::Wrapper.new(appender, &block)
|
152
|
-
end
|
153
|
-
@@appenders << appender_instance
|
152
|
+
def self.add_appender(options, deprecated_level = nil, &block)
|
153
|
+
options = options.is_a?(Hash) ? options.dup : convert_old_appender_args(options, deprecated_level)
|
154
|
+
appender = appender_from_options(options, &block)
|
155
|
+
@@appenders << appender
|
154
156
|
|
155
157
|
# Start appender thread if it is not already running
|
156
158
|
SemanticLogger::Logger.start_appender_thread
|
157
|
-
|
158
|
-
appender_instance
|
159
|
+
appender
|
159
160
|
end
|
160
161
|
|
161
162
|
# Remove an existing appender
|
@@ -188,18 +189,18 @@ module SemanticLogger
|
|
188
189
|
SemanticLogger::Logger.start_appender_thread
|
189
190
|
end
|
190
191
|
|
191
|
-
# Supply a block to be called whenever a metric is seen during
|
192
|
+
# Supply a block to be called whenever a metric is seen during measure logging
|
192
193
|
#
|
193
194
|
# Parameters
|
194
195
|
# block
|
195
196
|
# The block to be called
|
196
197
|
#
|
197
198
|
# Example:
|
198
|
-
# SemanticLogger.on_metric do |
|
199
|
-
# puts "#{
|
199
|
+
# SemanticLogger.on_metric do |log|
|
200
|
+
# puts "#{log.metric} was received. Log Struct: #{log.inspect}"
|
200
201
|
# end
|
201
|
-
def self.on_metric(&block)
|
202
|
-
SemanticLogger::Logger.on_metric(&block)
|
202
|
+
def self.on_metric(object = nil, &block)
|
203
|
+
SemanticLogger::Logger.on_metric(object, &block)
|
203
204
|
end
|
204
205
|
|
205
206
|
# Add signal handlers for Semantic Logger
|
@@ -279,7 +280,7 @@ module SemanticLogger
|
|
279
280
|
end
|
280
281
|
|
281
282
|
# Returns the symbolic level for the supplied level index
|
282
|
-
def index_to_level(level_index)
|
283
|
+
def self.index_to_level(level_index)
|
283
284
|
LEVELS[level_index]
|
284
285
|
end
|
285
286
|
|
@@ -309,6 +310,72 @@ module SemanticLogger
|
|
309
310
|
index
|
310
311
|
end
|
311
312
|
|
313
|
+
# Backward compatibility
|
314
|
+
def self.convert_old_appender_args(appender, level)
|
315
|
+
options = {}
|
316
|
+
options[:level] = level if level
|
317
|
+
|
318
|
+
if appender.is_a?(String)
|
319
|
+
options[:file_name] = appender
|
320
|
+
elsif appender.is_a?(IO)
|
321
|
+
options[:io] = appender
|
322
|
+
elsif appender.is_a?(Symbol) || appender.is_a?(Appender::Base)
|
323
|
+
options[:appender] = appender
|
324
|
+
else
|
325
|
+
options[:logger] = appender
|
326
|
+
end
|
327
|
+
warn "[DEPRECATED] SemanticLogger.add_appender parameters have changed. Please use: #{options.inspect}"
|
328
|
+
options
|
329
|
+
end
|
330
|
+
|
331
|
+
# Returns [SemanticLogger::Appender::Base] appender for the supplied options
|
332
|
+
def self.appender_from_options(options, &block)
|
333
|
+
if options[:io] || options[:file_name]
|
334
|
+
SemanticLogger::Appender::File.new(options, &block)
|
335
|
+
elsif appender = options.delete(:appender)
|
336
|
+
if appender.is_a?(Symbol)
|
337
|
+
named_appender(appender).new(options)
|
338
|
+
elsif appender.is_a?(Appender::Base)
|
339
|
+
appender
|
340
|
+
else
|
341
|
+
raise(ArgumentError, "Parameter :appender must be either a Symbol or an object derived from SemanticLogger::Appender::Base, not: #{appender.inspect}")
|
342
|
+
end
|
343
|
+
elsif options[:logger]
|
344
|
+
SemanticLogger::Appender::Wrapper.new(options, &block)
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
def self.named_appender(appender)
|
349
|
+
appender = appender.to_s
|
350
|
+
klass = appender.respond_to?(:camelize) ? appender.camelize : camelize(appender)
|
351
|
+
klass = "SemanticLogger::Appender::#{klass}"
|
352
|
+
begin
|
353
|
+
appender.respond_to?(:constantize) ? klass.constantize : eval(klass)
|
354
|
+
rescue NameError
|
355
|
+
raise(ArgumentError, "Could not find appender class: #{klass} for #{appender}")
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
def self.named_formatter(formatter)
|
360
|
+
formatter = formatter.to_s
|
361
|
+
klass = formatter.respond_to?(:camelize) ? formatter.camelize : camelize(formatter)
|
362
|
+
klass = "SemanticLogger::Formatters::#{klass}"
|
363
|
+
begin
|
364
|
+
formatter.respond_to?(:constantize) ? klass.constantize : eval(klass)
|
365
|
+
rescue NameError => exc
|
366
|
+
raise(ArgumentError, "Could not find formatter class: #{klass} for #{appender}")
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
# Borrow from Rails, when not running Rails
|
371
|
+
def self.camelize(term)
|
372
|
+
string = term.to_s
|
373
|
+
string = string.sub(/^[a-z\d]*/) { |match| match.capitalize }
|
374
|
+
string.gsub!(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{inflections.acronyms[$2] || $2.capitalize}" }
|
375
|
+
string.gsub!('/'.freeze, '::'.freeze)
|
376
|
+
string
|
377
|
+
end
|
378
|
+
|
312
379
|
# Initial default Level for all new instances of SemanticLogger::Logger
|
313
380
|
@@default_level = :info
|
314
381
|
@@default_level_index = level_to_index(@@default_level)
|