semantic_logger 3.4.1 → 4.0.0.beta1
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 +10 -0
- data/Rakefile +4 -8
- data/lib/semantic_logger.rb +2 -31
- data/lib/semantic_logger/appender.rb +76 -0
- data/lib/semantic_logger/appender/bugsnag.rb +3 -8
- data/lib/semantic_logger/appender/file.rb +1 -1
- data/lib/semantic_logger/appender/honeybadger.rb +1 -1
- data/lib/semantic_logger/appender/http.rb +1 -1
- data/lib/semantic_logger/appender/mongodb.rb +30 -28
- data/lib/semantic_logger/appender/sentry.rb +2 -2
- data/lib/semantic_logger/appender/splunk_http.rb +4 -4
- data/lib/semantic_logger/appender/syslog.rb +2 -2
- data/lib/semantic_logger/appender/tcp.rb +9 -5
- data/lib/semantic_logger/appender/udp.rb +1 -0
- data/lib/semantic_logger/base.rb +73 -140
- data/lib/semantic_logger/core_ext/thread.rb +4 -1
- data/lib/semantic_logger/formatters/color.rb +7 -0
- data/lib/semantic_logger/formatters/default.rb +7 -0
- data/lib/semantic_logger/formatters/syslog.rb +1 -1
- data/lib/semantic_logger/log.rb +115 -12
- data/lib/semantic_logger/logger.rb +6 -215
- data/lib/semantic_logger/metrics/new_relic.rb +1 -1
- data/lib/semantic_logger/metrics/statsd.rb +5 -1
- data/lib/semantic_logger/metrics/udp.rb +80 -0
- data/lib/semantic_logger/processor.rb +235 -0
- data/lib/semantic_logger/semantic_logger.rb +36 -65
- data/lib/semantic_logger/subscriber.rb +2 -2
- data/lib/semantic_logger/version.rb +1 -1
- data/test/appender/bugsnag_test.rb +10 -9
- data/test/appender/elasticsearch_test.rb +3 -2
- data/test/appender/graylog_test.rb +4 -3
- data/test/appender/honeybadger_test.rb +2 -2
- data/test/appender/http_test.rb +3 -2
- data/test/appender/mongodb_test.rb +24 -23
- data/test/appender/new_relic_test.rb +15 -8
- data/test/appender/sentry_test.rb +2 -2
- data/test/appender/splunk_http_test.rb +8 -7
- data/test/appender/splunk_test.rb +6 -5
- data/test/appender/tcp_test.rb +3 -4
- data/test/appender/udp_test.rb +4 -5
- data/test/appender/wrapper_test.rb +37 -38
- data/test/concerns/compatibility_test.rb +2 -2
- data/test/loggable_test.rb +1 -1
- data/test/logger_test.rb +149 -528
- data/test/measure_test.rb +249 -0
- data/test/semantic_logger_test.rb +257 -0
- metadata +24 -16
@@ -7,7 +7,7 @@ end
|
|
7
7
|
|
8
8
|
module SemanticLogger
|
9
9
|
module Metrics
|
10
|
-
class Statsd
|
10
|
+
class Statsd < Subscriber
|
11
11
|
# Create Statsd metrics subscriber
|
12
12
|
#
|
13
13
|
# Parameters:
|
@@ -18,6 +18,10 @@ module SemanticLogger
|
|
18
18
|
# Example, send all metrics to a particular namespace:
|
19
19
|
# udp://localhost:8125/namespace
|
20
20
|
# Default: udp://localhost:8125
|
21
|
+
#
|
22
|
+
# Example:
|
23
|
+
# subscriber = SemanticLogger::Metrics::Statsd.new(url: 'udp://localhost:8125')
|
24
|
+
# SemanticLogger.on_metric(subscriber)
|
21
25
|
def initialize(options = {})
|
22
26
|
options = options.dup
|
23
27
|
@url = options.delete(:url) || 'udp://localhost:8125'
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'socket'
|
2
|
+
module SemanticLogger
|
3
|
+
module Metrics
|
4
|
+
class Udp < Subscriber
|
5
|
+
attr_accessor :server, :separator, :udp_flags
|
6
|
+
attr_reader :socket
|
7
|
+
|
8
|
+
# Write metrics to in JSON format to Udp
|
9
|
+
#
|
10
|
+
# Parameters:
|
11
|
+
# server: [String]
|
12
|
+
# Host name and port to write UDP messages to
|
13
|
+
# Example:
|
14
|
+
# localhost:8125
|
15
|
+
#
|
16
|
+
# udp_flags: [Integer]
|
17
|
+
# Should be a bitwise OR of Socket::MSG_* constants.
|
18
|
+
# Default: 0
|
19
|
+
#
|
20
|
+
# Limitations:
|
21
|
+
# * UDP packet size is limited by the connected network and any routers etc
|
22
|
+
# that the message has to traverse. See https://en.wikipedia.org/wiki/Maximum_transmission_unit
|
23
|
+
#
|
24
|
+
# Example:
|
25
|
+
# subscriber = SemanticLogger::Metrics::Udp.new(server: 'localhost:8125')
|
26
|
+
# SemanticLogger.on_metric(subscriber)
|
27
|
+
def initialize(options = {}, &block)
|
28
|
+
options = options.dup
|
29
|
+
@server = options.delete(:server)
|
30
|
+
@udp_flags = options.delete(:udp_flags) || 0
|
31
|
+
raise(ArgumentError, 'Missing mandatory argument: :server') unless @server
|
32
|
+
|
33
|
+
super(options, &block)
|
34
|
+
reopen
|
35
|
+
end
|
36
|
+
|
37
|
+
# After forking an active process call #reopen to re-open
|
38
|
+
# open the handles to resources
|
39
|
+
def reopen
|
40
|
+
close
|
41
|
+
@socket = UDPSocket.new
|
42
|
+
host, port = server.split(':')
|
43
|
+
@socket.connect(host, port)
|
44
|
+
end
|
45
|
+
|
46
|
+
def call(log)
|
47
|
+
metric = log.metric
|
48
|
+
if duration = log.duration
|
49
|
+
@statsd.timing(metric, duration)
|
50
|
+
else
|
51
|
+
amount = (log.metric_amount || 1).round
|
52
|
+
if amount < 0
|
53
|
+
amount.times { @statsd.decrement(metric) }
|
54
|
+
else
|
55
|
+
amount.times { @statsd.increment(metric) }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
@socket.send(data, udp_flags)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Flush is called by the semantic_logger during shutdown.
|
62
|
+
def flush
|
63
|
+
@socket.flush if @socket
|
64
|
+
end
|
65
|
+
|
66
|
+
# Close is called during shutdown, or with reopen
|
67
|
+
def close
|
68
|
+
@socket.close if @socket
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
# Returns [SemanticLogger::Formatters::Default] formatter default for this Appender
|
74
|
+
def default_formatter
|
75
|
+
SemanticLogger::Formatters::Json.new
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,235 @@
|
|
1
|
+
module SemanticLogger
|
2
|
+
# Thread that submits and processes log requests
|
3
|
+
class Processor
|
4
|
+
# Start the appender thread
|
5
|
+
def self.start
|
6
|
+
return false if active?
|
7
|
+
@@thread = Thread.new { process_requests }
|
8
|
+
raise 'Failed to start Appender Thread' unless @@thread
|
9
|
+
true
|
10
|
+
end
|
11
|
+
|
12
|
+
# Returns true if the appender_thread is active
|
13
|
+
def self.active?
|
14
|
+
@@thread && @@thread.alive?
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns [Integer] the number of log entries waiting to be written to the appenders
|
18
|
+
def self.queue_size
|
19
|
+
queue.size
|
20
|
+
end
|
21
|
+
|
22
|
+
# Add log request to the queue for processing
|
23
|
+
def self.<<(log)
|
24
|
+
queue << log if active?
|
25
|
+
end
|
26
|
+
|
27
|
+
# Submit command and wait for reply
|
28
|
+
def self.submit_request(command)
|
29
|
+
return false unless active?
|
30
|
+
|
31
|
+
msg = "Too many queued log messages: #{queue_size}, running command: #{command}"
|
32
|
+
if queue_size > 1_000
|
33
|
+
logger.warn msg
|
34
|
+
elsif queue_size > 100
|
35
|
+
logger.info msg
|
36
|
+
elsif queue_size > 0
|
37
|
+
logger.trace msg
|
38
|
+
end
|
39
|
+
|
40
|
+
reply_queue = Queue.new
|
41
|
+
queue << {command: command, reply_queue: reply_queue}
|
42
|
+
reply_queue.pop
|
43
|
+
end
|
44
|
+
|
45
|
+
# Allow the internal logger to be overridden from its default of STDERR
|
46
|
+
# Can be replaced with another Ruby logger or Rails logger, but never to
|
47
|
+
# SemanticLogger::Logger itself since it is for reporting problems
|
48
|
+
# while trying to log to the various appenders
|
49
|
+
def self.logger=(logger)
|
50
|
+
@@logger = logger
|
51
|
+
end
|
52
|
+
|
53
|
+
# Returns the check_interval which is the number of messages between checks
|
54
|
+
# to determine if the appender thread is falling behind
|
55
|
+
def self.lag_check_interval
|
56
|
+
@@lag_check_interval
|
57
|
+
end
|
58
|
+
|
59
|
+
# Set the check_interval which is the number of messages between checks
|
60
|
+
# to determine if the appender thread is falling behind
|
61
|
+
def self.lag_check_interval=(lag_check_interval)
|
62
|
+
@@lag_check_interval = lag_check_interval
|
63
|
+
end
|
64
|
+
|
65
|
+
# Returns the amount of time in seconds
|
66
|
+
# to determine if the appender thread is falling behind
|
67
|
+
def self.lag_threshold_s
|
68
|
+
@@lag_threshold_s
|
69
|
+
end
|
70
|
+
|
71
|
+
# Supply a metrics appender to be called whenever a logging metric is encountered
|
72
|
+
#
|
73
|
+
# Parameters
|
74
|
+
# appender: [Symbol | Object | Proc]
|
75
|
+
# [Proc] the block to call.
|
76
|
+
# [Object] the block on which to call #call.
|
77
|
+
# [Symbol] :new_relic, or :statsd to forward metrics to
|
78
|
+
#
|
79
|
+
# block
|
80
|
+
# The block to be called
|
81
|
+
#
|
82
|
+
# Example:
|
83
|
+
# SemanticLogger.on_metric do |log|
|
84
|
+
# puts "#{log.metric} was received. Log: #{log.inspect}"
|
85
|
+
# end
|
86
|
+
#
|
87
|
+
# Note:
|
88
|
+
# * This callback is called in the logging thread.
|
89
|
+
# * Does not slow down the application.
|
90
|
+
# * Only context is what is passed in the log struct, the original thread context is not available.
|
91
|
+
def self.on_metric(options = {}, &block)
|
92
|
+
# Backward compatibility
|
93
|
+
options = options.is_a?(Hash) ? options.dup : {appender: options}
|
94
|
+
appender = block || options.delete(:appender)
|
95
|
+
|
96
|
+
# Convert symbolized metrics appender to an actual object
|
97
|
+
appender = SemanticLogger::Appender.constantize_symbol(appender, 'SemanticLogger::Metrics').new(options) if appender.is_a?(Symbol)
|
98
|
+
|
99
|
+
raise('When supplying a metrics appender, it must support the #call method') unless appender.is_a?(Proc) || appender.respond_to?(:call)
|
100
|
+
(@@metric_subscribers ||= Concurrent::Array.new) << appender
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
@@thread = nil
|
106
|
+
@@queue = Queue.new
|
107
|
+
@@lag_check_interval = 5000
|
108
|
+
@@lag_threshold_s = 30
|
109
|
+
@@metric_subscribers = nil
|
110
|
+
|
111
|
+
# Queue to hold messages that need to be logged to the various appenders
|
112
|
+
def self.queue
|
113
|
+
@@queue
|
114
|
+
end
|
115
|
+
|
116
|
+
# Internal logger for SemanticLogger
|
117
|
+
# For example when an appender is not working etc..
|
118
|
+
# By default logs to STDERR
|
119
|
+
def self.logger
|
120
|
+
@@logger ||= begin
|
121
|
+
l = SemanticLogger::Appender::File.new(STDERR, :warn)
|
122
|
+
l.name = name
|
123
|
+
l
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# Separate appender thread responsible for reading log messages and
|
128
|
+
# calling the appenders in it's thread
|
129
|
+
def self.process_requests
|
130
|
+
# This thread is designed to never go down unless the main thread terminates
|
131
|
+
# Before terminating at_exit is used to flush all the appenders
|
132
|
+
#
|
133
|
+
# Should any appender fail to log or flush, the exception is logged and
|
134
|
+
# other appenders will still be called
|
135
|
+
Thread.current.name = 'SemanticLogger::Processor'
|
136
|
+
logger.trace "V#{VERSION} Processor thread active"
|
137
|
+
begin
|
138
|
+
count = 0
|
139
|
+
while message = queue.pop
|
140
|
+
if message.is_a?(Log)
|
141
|
+
call_appenders(message)
|
142
|
+
call_metric_subscribers(message) if message.metric
|
143
|
+
count += 1
|
144
|
+
# Check every few log messages whether this appender thread is falling behind
|
145
|
+
if count > lag_check_interval
|
146
|
+
if (diff = Time.now - message.time) > lag_threshold_s
|
147
|
+
logger.warn "Appender thread has fallen behind by #{diff} seconds with #{queue_size} messages queued up. Consider reducing the log level or changing the appenders"
|
148
|
+
end
|
149
|
+
count = 0
|
150
|
+
end
|
151
|
+
else
|
152
|
+
case message[:command]
|
153
|
+
when :flush
|
154
|
+
flush_appenders
|
155
|
+
message[:reply_queue] << true if message[:reply_queue]
|
156
|
+
when :close
|
157
|
+
close_appenders
|
158
|
+
message[:reply_queue] << true if message[:reply_queue]
|
159
|
+
else
|
160
|
+
logger.warn "Appender thread: Ignoring unknown command: #{message[:command]}"
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
rescue Exception => exception
|
165
|
+
# This block may be called after the file handles have been released by Ruby
|
166
|
+
begin
|
167
|
+
logger.error 'Appender thread restarting due to exception', exception
|
168
|
+
rescue Exception
|
169
|
+
nil
|
170
|
+
end
|
171
|
+
retry
|
172
|
+
ensure
|
173
|
+
@@thread = nil
|
174
|
+
# This block may be called after the file handles have been released by Ruby
|
175
|
+
begin
|
176
|
+
logger.trace 'Appender thread has stopped'
|
177
|
+
rescue Exception
|
178
|
+
nil
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
# Call Metric subscribers
|
184
|
+
def self.call_metric_subscribers(log)
|
185
|
+
# If no subscribers registered, then return immediately
|
186
|
+
return unless @@metric_subscribers
|
187
|
+
|
188
|
+
@@metric_subscribers.each do |subscriber|
|
189
|
+
begin
|
190
|
+
subscriber.call(log)
|
191
|
+
rescue Exception => exc
|
192
|
+
logger.error 'Exception calling metrics subscriber', exc
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
# Call Appenders
|
198
|
+
def self.call_appenders(log)
|
199
|
+
SemanticLogger.appenders.each do |appender|
|
200
|
+
begin
|
201
|
+
appender.log(log)
|
202
|
+
rescue Exception => exc
|
203
|
+
logger.error "Appender thread: Failed to log to appender: #{appender.inspect}", exc
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def self.flush_appenders
|
209
|
+
SemanticLogger.appenders.each do |appender|
|
210
|
+
begin
|
211
|
+
logger.trace "Appender thread: Flushing appender: #{appender.name}"
|
212
|
+
appender.flush
|
213
|
+
rescue Exception => exc
|
214
|
+
logger.error "Appender thread: Failed to flush appender: #{appender.inspect}", exc
|
215
|
+
end
|
216
|
+
end
|
217
|
+
logger.trace 'Appender thread: All appenders flushed'
|
218
|
+
end
|
219
|
+
|
220
|
+
def self.close_appenders
|
221
|
+
SemanticLogger.appenders.each do |appender|
|
222
|
+
begin
|
223
|
+
logger.trace "Appender thread: Closing appender: #{appender.name}"
|
224
|
+
appender.flush
|
225
|
+
appender.close
|
226
|
+
SemanticLogger.remove_appender(appender)
|
227
|
+
rescue Exception => exc
|
228
|
+
logger.error "Appender thread: Failed to close appender: #{appender.inspect}", exc
|
229
|
+
end
|
230
|
+
end
|
231
|
+
logger.trace 'Appender thread: All appenders closed and removed from appender list'
|
232
|
+
end
|
233
|
+
|
234
|
+
end
|
235
|
+
end
|
@@ -153,11 +153,11 @@ module SemanticLogger
|
|
153
153
|
# logger.debug("Login time", user: 'Joe', duration: 100, ip_address: '127.0.0.1')
|
154
154
|
def self.add_appender(options, deprecated_level = nil, &block)
|
155
155
|
options = options.is_a?(Hash) ? options.dup : convert_old_appender_args(options, deprecated_level)
|
156
|
-
appender =
|
156
|
+
appender = SemanticLogger::Appender.create(options, &block)
|
157
157
|
@@appenders << appender
|
158
158
|
|
159
159
|
# Start appender thread if it is not already running
|
160
|
-
SemanticLogger::
|
160
|
+
SemanticLogger::Processor.start
|
161
161
|
appender
|
162
162
|
end
|
163
163
|
|
@@ -193,7 +193,7 @@ module SemanticLogger
|
|
193
193
|
def self.reopen
|
194
194
|
@@appenders.each { |appender| appender.reopen if appender.respond_to?(:reopen) }
|
195
195
|
# After a fork the appender thread is not running, start it if it is not running
|
196
|
-
SemanticLogger::
|
196
|
+
SemanticLogger::Processor.start
|
197
197
|
end
|
198
198
|
|
199
199
|
# Supply a block to be called whenever a metric is seen during measure logging
|
@@ -209,7 +209,7 @@ module SemanticLogger
|
|
209
209
|
#
|
210
210
|
# Example:
|
211
211
|
# SemanticLogger.on_metric do |log|
|
212
|
-
# puts "#{log.metric} was received. Log
|
212
|
+
# puts "#{log.metric} was received. Log: #{log.inspect}"
|
213
213
|
# end
|
214
214
|
#
|
215
215
|
# Note:
|
@@ -217,7 +217,7 @@ module SemanticLogger
|
|
217
217
|
# * Does not slow down the application.
|
218
218
|
# * Only context is what is passed in the log struct, the original thread context is not available.
|
219
219
|
def self.on_metric(options = {}, &block)
|
220
|
-
SemanticLogger::
|
220
|
+
SemanticLogger::Processor.on_metric(options, &block)
|
221
221
|
end
|
222
222
|
|
223
223
|
# Add signal handlers for Semantic Logger
|
@@ -267,14 +267,7 @@ module SemanticLogger
|
|
267
267
|
logger = SemanticLogger['Thread Dump']
|
268
268
|
Thread.list.each do |thread|
|
269
269
|
next if thread == Thread.current
|
270
|
-
|
271
|
-
if backtrace = thread.backtrace
|
272
|
-
message += "\n"
|
273
|
-
message << backtrace.join("\n")
|
274
|
-
end
|
275
|
-
tags = thread[:semantic_logger_tags]
|
276
|
-
tags = tags.nil? ? [] : tags.clone
|
277
|
-
logger.tagged(tags) { logger.warn(message) }
|
270
|
+
logger.backtrace(thread: thread)
|
278
271
|
end
|
279
272
|
end if thread_dump_signal
|
280
273
|
|
@@ -297,19 +290,6 @@ module SemanticLogger
|
|
297
290
|
Thread.current[:semantic_logger_tags].pop
|
298
291
|
end
|
299
292
|
|
300
|
-
# Add the supplied named tags to the list of tags to log for this thread whilst
|
301
|
-
# the supplied block is active.
|
302
|
-
#
|
303
|
-
# Returns result of block
|
304
|
-
#
|
305
|
-
# Example:
|
306
|
-
def self.named_tags(tag)
|
307
|
-
(Thread.current[:semantic_logger_tags] ||= []) << tag
|
308
|
-
yield
|
309
|
-
ensure
|
310
|
-
Thread.current[:semantic_logger_tags].pop
|
311
|
-
end
|
312
|
-
|
313
293
|
# Add the supplied tags to the list of tags to log for this thread whilst
|
314
294
|
# the supplied block is active.
|
315
295
|
# Returns result of block
|
@@ -344,6 +324,36 @@ module SemanticLogger
|
|
344
324
|
t.pop(quantity) unless t.nil?
|
345
325
|
end
|
346
326
|
|
327
|
+
# Add the supplied named tags to the list of tags to log for this thread whilst
|
328
|
+
# the supplied block is active.
|
329
|
+
#
|
330
|
+
# Add a payload to all log calls on This Thread within the supplied block
|
331
|
+
#
|
332
|
+
# SemanticLogger.named_tagged(tracking_number: 12345) do
|
333
|
+
# logger.debug('Hello World')
|
334
|
+
# end
|
335
|
+
#
|
336
|
+
# Returns result of block
|
337
|
+
def self.named_tagged(hash)
|
338
|
+
raise(ArgumentError, '#named_tagged only accepts named parameters (Hash)') unless hash.is_a?(Hash)
|
339
|
+
(Thread.current[:semantic_logger_named_tags] ||= []) << hash
|
340
|
+
yield
|
341
|
+
ensure
|
342
|
+
Thread.current[:semantic_logger_named_tags].pop
|
343
|
+
end
|
344
|
+
|
345
|
+
# Returns a copy of the [Hash] of named tags currently active for this thread
|
346
|
+
# Returns nil if no named tags are set
|
347
|
+
def self.named_tags
|
348
|
+
if (list = Thread.current[:semantic_logger_named_tags]) && !list.empty?
|
349
|
+
if list.size > 1
|
350
|
+
list.inject({}) { |h, sum| sum.merge(h) }
|
351
|
+
else
|
352
|
+
list.first.clone
|
353
|
+
end
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
347
357
|
# Silence noisy log levels by changing the default_level within the block
|
348
358
|
#
|
349
359
|
# This setting is thread-safe and only applies to the current thread
|
@@ -445,45 +455,6 @@ module SemanticLogger
|
|
445
455
|
options
|
446
456
|
end
|
447
457
|
|
448
|
-
# Returns [SemanticLogger::Subscriber] appender for the supplied options
|
449
|
-
def self.appender_from_options(options, &block)
|
450
|
-
if options[:io] || options[:file_name]
|
451
|
-
SemanticLogger::Appender::File.new(options, &block)
|
452
|
-
elsif appender = options.delete(:appender)
|
453
|
-
if appender.is_a?(Symbol)
|
454
|
-
constantize_symbol(appender).new(options)
|
455
|
-
elsif appender.is_a?(Subscriber)
|
456
|
-
appender
|
457
|
-
else
|
458
|
-
raise(ArgumentError, "Parameter :appender must be either a Symbol or an object derived from SemanticLogger::Subscriber, not: #{appender.inspect}")
|
459
|
-
end
|
460
|
-
elsif options[:logger]
|
461
|
-
SemanticLogger::Appender::Wrapper.new(options, &block)
|
462
|
-
end
|
463
|
-
end
|
464
|
-
|
465
|
-
def self.constantize_symbol(symbol, namespace = 'SemanticLogger::Appender')
|
466
|
-
klass = "#{namespace}::#{camelize(symbol.to_s)}"
|
467
|
-
begin
|
468
|
-
if RUBY_VERSION.to_i >= 2
|
469
|
-
Object.const_get(klass)
|
470
|
-
else
|
471
|
-
klass.split('::').inject(Object) { |o, name| o.const_get(name) }
|
472
|
-
end
|
473
|
-
rescue NameError
|
474
|
-
raise(ArgumentError, "Could not convert symbol: #{symbol} to a class in: #{namespace}. Looking for: #{klass}")
|
475
|
-
end
|
476
|
-
end
|
477
|
-
|
478
|
-
# Borrow from Rails, when not running Rails
|
479
|
-
def self.camelize(term)
|
480
|
-
string = term.to_s
|
481
|
-
string = string.sub(/^[a-z\d]*/) { |match| match.capitalize }
|
482
|
-
string.gsub!(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{$2.capitalize}" }
|
483
|
-
string.gsub!('/'.freeze, '::'.freeze)
|
484
|
-
string
|
485
|
-
end
|
486
|
-
|
487
458
|
# Initial default Level for all new instances of SemanticLogger::Logger
|
488
459
|
@@default_level = :info
|
489
460
|
@@default_level_index = level_to_index(@@default_level)
|