semantic_logger 3.4.1 → 4.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- 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)
|