semantic_logger 0.3.3 → 0.4.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.
- data/README.md +339 -18
- data/Rakefile +1 -0
- data/lib/semantic_logger.rb +1 -1
- data/lib/semantic_logger/appender/logger.rb +1 -0
- data/lib/semantic_logger/appender/mongodb.rb +13 -0
- data/lib/semantic_logger/logger.rb +37 -9
- data/lib/semantic_logger/version.rb +1 -1
- data/test/logger_test.rb +4 -4
- metadata +18 -6
data/README.md
CHANGED
@@ -3,11 +3,9 @@ semantic-logger-ruby
|
|
3
3
|
|
4
4
|
* http://github.com/ClarityServices/semantic-logger-ruby
|
5
5
|
|
6
|
-
Feedback is welcome and appreciated :)
|
7
|
-
|
8
6
|
### Introduction
|
9
7
|
|
10
|
-
SemanticLogger is a Logger that supports logging of meta-data,
|
8
|
+
SemanticLogger is a Logger that supports logging of meta-data, along with text messages
|
11
9
|
|
12
10
|
Machines can understand the logged data without having to use
|
13
11
|
complex Regular Expressions or other text parsing techniques
|
@@ -36,30 +34,348 @@ This can be changed over time to:
|
|
36
34
|
:table => "users",
|
37
35
|
:action => "query")
|
38
36
|
|
39
|
-
Using
|
40
|
-
|
37
|
+
Using the MongoDB appender, we can easily find all queries for table 'users'
|
38
|
+
that took longer than 100 ms:
|
41
39
|
|
42
|
-
db.logs.find({"
|
40
|
+
db.logs.find({"payload.table":"users", "payload.action":"query", "payload.duration":{$gt:100} })
|
43
41
|
|
44
42
|
Since SemanticLogger can call existing Loggers, it does not force end-users
|
45
43
|
to have to adopt a Semantic aware adapter. Although, such adapters create
|
46
44
|
tremendous value in the problem monitoring and determination processes.
|
47
45
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
46
|
+
### Logging API
|
47
|
+
|
48
|
+
#### Standard Logging methods
|
49
|
+
|
50
|
+
The Semantic Logger logging API supports the existing logging interface for
|
51
|
+
the Rails and Ruby Loggers. For example:
|
52
|
+
|
53
|
+
logger.info("Hello World")
|
54
|
+
|
55
|
+
Or to query whether a specific log level is set
|
56
|
+
|
57
|
+
logger.info?
|
58
|
+
|
59
|
+
The following logging methods are all available
|
60
|
+
|
61
|
+
logger.trace(message, payload) { # optional block }
|
62
|
+
logger.debug(message, payload) { # optional block }
|
63
|
+
logger.info(message, payload) { # optional block }
|
64
|
+
logger.warn(message, payload) { # optional block }
|
65
|
+
logger.error(message, payload) { # optional block }
|
66
|
+
logger.fatal(message, payload) { # optional block }
|
67
|
+
|
68
|
+
Parameters
|
69
|
+
|
70
|
+
- message: The text message to log.
|
71
|
+
Mandatory only if no block is supplied
|
72
|
+
- payload: Optional, either a Ruby Exception object or a Hash
|
73
|
+
- block: The optional block is executed only if the corresponding log level
|
74
|
+
is active. Can be used to prevent unnecessary calculations of debug data in
|
75
|
+
production.
|
76
|
+
|
77
|
+
Examples:
|
78
|
+
|
79
|
+
logger.debug("Calling Supplier")
|
80
|
+
|
81
|
+
logger.debug("Calling Supplier", :request => 'update', :user => 'Jack')
|
82
|
+
|
83
|
+
logger.debug { "A total of #{result.inject(0) {|sum, i| i+sum }} were processed" }
|
84
|
+
|
85
|
+
### Exceptions
|
86
|
+
|
87
|
+
The Semantic Logger adds an extra parameter to the existing log methods so that
|
88
|
+
a corresponding Exception can be logged in a standard way
|
89
|
+
|
90
|
+
begin
|
91
|
+
# ... Code that can raise an exception
|
92
|
+
rescue Exception => exception
|
93
|
+
logger.error("Oops external call failed", exception)
|
94
|
+
# Re-raise or handle the exception
|
95
|
+
raise exception
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
#### Payload
|
100
|
+
|
101
|
+
The Semantic Logger adds an extra parameter to the existing log methods so that
|
102
|
+
additional payload can be logged, such as a Hash or a Ruby Exception object.
|
103
|
+
|
104
|
+
logger.info("Oops external call failed", :result => :failed, :reason_code => -10)
|
105
|
+
|
106
|
+
The additional payload is machine readable so that we don't have to write complex
|
107
|
+
regular expressions so that a program can analyze log output. With the MongoDB
|
108
|
+
appender the payload is written directly to MongoDB as part of the document and
|
109
|
+
is therefore fully searchable
|
110
|
+
|
111
|
+
#### Benchmarking
|
112
|
+
|
113
|
+
Another common logging requirement is to measure the time it takes to execute a block
|
114
|
+
of code based on the log level. For example:
|
115
|
+
|
116
|
+
Rails.logger.benchmark_info "Calling external interface" do
|
117
|
+
# Code to call external service ...
|
118
|
+
end
|
119
|
+
|
120
|
+
The following output will be written to file:
|
121
|
+
|
122
|
+
2012-08-30 15:37:29.474 I [48308:ScriptThreadProcess: script/rails] Rails -- Calling external interface (5.2ms)
|
123
|
+
|
124
|
+
If an exception is raised during the block the exception is logged
|
125
|
+
at the same log level as the benchmark along with the duration and message
|
52
126
|
|
53
|
-
|
54
|
-
- Web Interface to view and search log information
|
55
|
-
- Override the log level at the appender level
|
127
|
+
#### Logging levels
|
56
128
|
|
57
|
-
|
129
|
+
The following logging levels are available through Semantic Logger
|
130
|
+
|
131
|
+
:trace, :debug, :info, :warn, :error, :fatal
|
132
|
+
|
133
|
+
The log levels are listed above in the order of precedence with the most detail to the least.
|
134
|
+
For example :debug would include :info, :warn, :error, :fatal levels but not :trace
|
135
|
+
And :fatal would only log :fatal error messages and nothing else
|
136
|
+
|
137
|
+
:unknown has been mapped to :fatal for Rails and Ruby Logger
|
138
|
+
|
139
|
+
:trace is a new level that is often used for tracing low level calls such
|
140
|
+
as the data sent or received to external web services. It is also commonly used
|
141
|
+
in the development environment for low level trace logging of methods calls etc.
|
142
|
+
|
143
|
+
If only the rails logger is being used, then :trace level calls will be logged
|
144
|
+
as debug calls only if the log level is set to trace
|
145
|
+
|
146
|
+
#### Changing the Class name for Log Entries
|
147
|
+
|
148
|
+
When Semantic Logger is included on a Rails project it automatically replaces the
|
149
|
+
loggers for Rails, ActiveRecord::Base, ActionController::Base, and ActiveResource::Base
|
150
|
+
with wrappers that set their Class name. For example in railtie.rb:
|
151
|
+
|
152
|
+
ActiveRecord::Base.logger = SemanticLogger::Logger.new(ActiveRecord)
|
153
|
+
|
154
|
+
By replacing their loggers we now get the class name in the text logging output:
|
155
|
+
|
156
|
+
2012-08-30 15:24:13.439 D [47900:main] ActiveRecord -- SQL (12.0ms) SELECT `schema_migrations`.`version` FROM `schema_migrations`
|
157
|
+
|
158
|
+
It is recommended to include a class specific logger for all major classes that will
|
159
|
+
be logging. For Example:
|
160
|
+
|
161
|
+
class ExternalSupplier
|
162
|
+
# Gem sync_attr is a dependency of semantic_logger so is already installed
|
163
|
+
include SyncAttr
|
164
|
+
|
165
|
+
# Lazy initializes the class logger on it's first call in a thread-safe way
|
166
|
+
sync_cattr_reader :logger do
|
167
|
+
SemanticLogger::Logger.new(self)
|
168
|
+
end
|
169
|
+
|
170
|
+
def call(params)
|
171
|
+
self.class.logger.benchmark_info "Calling external interface" do
|
172
|
+
# Code to call external service ...
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
This will result in the log output identitying the log entry as from the ExternalSupplier class
|
178
|
+
|
179
|
+
2012-08-30 15:37:29.474 I [48308:ScriptThreadProcess: script/rails] ExternalSupplier -- Calling external interface (5.2ms)
|
180
|
+
|
181
|
+
#### Tagged Logging
|
182
|
+
|
183
|
+
logger.with_tags(tracking_number) do
|
184
|
+
logger.debug("Hello World")
|
185
|
+
# ...
|
186
|
+
end
|
187
|
+
|
188
|
+
#### Payload injected logging
|
189
|
+
|
190
|
+
logger.with_payload(:user => 'Jack') do
|
191
|
+
logger.debug("Hello World")
|
192
|
+
# ...
|
193
|
+
end
|
194
|
+
|
195
|
+
### Configuration
|
58
196
|
|
59
197
|
The Semantic Logger follows the principle where multiple appenders can be active
|
60
198
|
at the same time. This allows one to log to MongoDB and the Rails
|
61
199
|
ActiveResource::BufferedLogger at the same time.
|
62
200
|
|
201
|
+
#### Rails Configuration
|
202
|
+
|
203
|
+
Add the following line to Gemfile
|
204
|
+
|
205
|
+
gem 'semantic_logger'
|
206
|
+
|
207
|
+
Also add the following line to Gemfile if you want to log to MongoDB
|
208
|
+
|
209
|
+
gem 'mongo'
|
210
|
+
|
211
|
+
Install required gems with bundler
|
212
|
+
|
213
|
+
bundle install
|
214
|
+
|
215
|
+
This will automatically replace the standard Rails logger with Semantic Logger
|
216
|
+
which will write all log data to the configured Rails logger.
|
217
|
+
|
218
|
+
By default Semantic Logger will detect the log level from Rails. To set the
|
219
|
+
log level explicitly, add the following line to
|
220
|
+
config/environments/production.rb inside the Application.configure block
|
221
|
+
|
222
|
+
config.log_level = :trace
|
223
|
+
|
224
|
+
To log to both the Rails logger and MongoDB add the following lines to
|
225
|
+
config/environments/production.rb inside the Application.configure block
|
226
|
+
|
227
|
+
config.after_initialize do
|
228
|
+
# Re-use the existing MongoDB connection, or create a new one here
|
229
|
+
db = Mongo::Connection.new['production_logging']
|
230
|
+
|
231
|
+
# Besides logging to the standard Rails logger, also log to MongoDB
|
232
|
+
config.semantic_logger.appenders << SemanticLogger::Appender::MongoDB.new(
|
233
|
+
:db => db,
|
234
|
+
:collection_size => 25.gigabytes
|
235
|
+
)
|
236
|
+
end
|
237
|
+
|
238
|
+
#### Custom Formatters
|
239
|
+
|
240
|
+
The formatting for each appender can be replaced with custom code. To replace the
|
241
|
+
existing formatter supply a block of code when creating the appender.
|
242
|
+
|
243
|
+
For example to replace the Rails or Ruby text log formatter, in the environment configuration file:
|
244
|
+
|
245
|
+
config.after_initialize do
|
246
|
+
# Since the Rails logger is already initialized, replace its default formatter
|
247
|
+
config.semantic_logger.appenders.first.formatter = Proc.new do |log|
|
248
|
+
# log is a struct with the following fields:
|
249
|
+
#
|
250
|
+
# level
|
251
|
+
# Log level of the supplied log call
|
252
|
+
# :trace, :debug, :info, :warn, :error, :fatal
|
253
|
+
#
|
254
|
+
# thread_name
|
255
|
+
# Name of the thread in which the logging call was called
|
256
|
+
#
|
257
|
+
# name
|
258
|
+
# Class name supplied to the logging instance
|
259
|
+
#
|
260
|
+
# message
|
261
|
+
# Text message to be logged
|
262
|
+
#
|
263
|
+
# payload
|
264
|
+
# Optional Hash or Ruby Exception object to be logged
|
265
|
+
#
|
266
|
+
# time
|
267
|
+
# The time at which the log entry was created
|
268
|
+
#
|
269
|
+
# duration
|
270
|
+
# The time taken to complete a benchmark call
|
271
|
+
#
|
272
|
+
# tags
|
273
|
+
# Any tags active on the thread when the log call was made
|
274
|
+
#
|
275
|
+
|
276
|
+
message = log.message.to_s
|
277
|
+
tags = log.tags.collect { |tag| "[#{tag}]" }.join(" ") + " " if log.tags && (log.tags.size > 0)
|
278
|
+
|
279
|
+
if log.payload
|
280
|
+
if log.payload.is_a?(Exception)
|
281
|
+
exception = log.payload
|
282
|
+
message << " -- " << "#{exception.class}: #{exception.message}\n#{(exception.backtrace || []).join("\n")}"
|
283
|
+
else
|
284
|
+
message << " -- " << log.payload.inspect
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
str = "#{log.time.strftime("%Y-%m-%d %H:%M:%S")}.#{"%03d" % (log.time.usec/1000)} #{log.level.to_s[0..0].upcase} [#{$$}:#{log.thread_name}] #{tags}#{log.name} -- #{message}"
|
289
|
+
str << " (#{'%.1f' % log.duration}ms)" if log.duration
|
290
|
+
str
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
For example to replace the MongoDB formatter, in the environment configuration file:
|
295
|
+
|
296
|
+
config.after_initialize do
|
297
|
+
# Log to MongoDB and supply a custom document formatter
|
298
|
+
mongodb_appender = SemanticLogger::Appender::MongoDB.new(
|
299
|
+
:db => Cache::Work.db,
|
300
|
+
:collection_size => 25.gigabytes
|
301
|
+
) do |log|
|
302
|
+
# log is a struct with the following fields:
|
303
|
+
# level
|
304
|
+
# Log level of the supplied log call
|
305
|
+
# :trace, :debug, :info, :warn, :error, :fatal
|
306
|
+
#
|
307
|
+
# thread_name
|
308
|
+
# Name of the thread in which the logging call was called
|
309
|
+
#
|
310
|
+
# name
|
311
|
+
# Class name supplied to the logging instance
|
312
|
+
#
|
313
|
+
# message
|
314
|
+
# Text message to be logged
|
315
|
+
#
|
316
|
+
# payload
|
317
|
+
# Optional Hash or Ruby Exception object to be logged
|
318
|
+
#
|
319
|
+
# time
|
320
|
+
# The time at which the log entry was created
|
321
|
+
#
|
322
|
+
# duration
|
323
|
+
# The time taken to complete a benchmark call
|
324
|
+
#
|
325
|
+
# tags
|
326
|
+
# Any tags active on the thread when the log call was made
|
327
|
+
#
|
328
|
+
|
329
|
+
# Return a document (Hash) of the data to be saved to MongoDB
|
330
|
+
document = {
|
331
|
+
:time => log.time,
|
332
|
+
:host_name => SemanticLogger::Appender::MongoDB.host_name,
|
333
|
+
:pid => $PID,
|
334
|
+
:thread_name => log.thread_name,
|
335
|
+
:name => log.name,
|
336
|
+
:level => log.level,
|
337
|
+
}
|
338
|
+
document[:application] = 'MyApplication'
|
339
|
+
document[:message] = SemanticLogger::Appender::MongoDB.strip_colorizing(log.message) if log.message
|
340
|
+
document[:duration] = log.duration if log.duration
|
341
|
+
document[:tags] = log.tags if log.tags && (log.tags.size > 0)
|
342
|
+
|
343
|
+
if log.payload
|
344
|
+
if log.payload.is_a?(Exception)
|
345
|
+
exception = log.payload
|
346
|
+
document[:payload] = {
|
347
|
+
:exception => exception.class.name,
|
348
|
+
:message => exception.message,
|
349
|
+
:backtrace => exception.backtrace
|
350
|
+
}
|
351
|
+
else
|
352
|
+
document[:payload] = log.payload
|
353
|
+
end
|
354
|
+
end
|
355
|
+
document
|
356
|
+
end
|
357
|
+
config.semantic_logger.appenders << mongodb_appender
|
358
|
+
end
|
359
|
+
|
360
|
+
### Architecture & Performance
|
361
|
+
|
362
|
+
In order to ensure that logging does not hinder the performance of the application
|
363
|
+
all log entries are written to thread-safe Queue. A separate thread is responsible
|
364
|
+
for writing the log entries to each of the appenders.
|
365
|
+
|
366
|
+
In this way formatting and disk or network write delays will not affect the
|
367
|
+
performance of the application. Also adding more than one appender does not affect
|
368
|
+
the runtime performance of the application
|
369
|
+
|
370
|
+
The additional thread is automatically started on initialization. When the program
|
371
|
+
terminates it will complete writing out all log data and flush the appenders before
|
372
|
+
the program exits.
|
373
|
+
|
374
|
+
Calling SemanticLogger::Logger#flush will wait until all outstanding log messages
|
375
|
+
have been written and flushed to their respective appenders before returning.
|
376
|
+
Since all logging is now from this thread calling flush is no longer thread
|
377
|
+
specific.
|
378
|
+
|
63
379
|
### Dependencies
|
64
380
|
|
65
381
|
- Ruby MRI 1.8.7 (or above) Or, JRuby 1.6.3 (or above)
|
@@ -68,7 +384,15 @@ ActiveResource::BufferedLogger at the same time.
|
|
68
384
|
|
69
385
|
### Install
|
70
386
|
|
71
|
-
|
387
|
+
gem install semantic-logger
|
388
|
+
|
389
|
+
To log to MongoDB
|
390
|
+
|
391
|
+
gem install mongo
|
392
|
+
|
393
|
+
### Future
|
394
|
+
|
395
|
+
- Web Interface to view and search log information stored in MongoDB
|
72
396
|
|
73
397
|
Development
|
74
398
|
-----------
|
@@ -94,9 +418,6 @@ Once you've made your great commits:
|
|
94
418
|
4. Create an [Issue](http://github.com/ClarityServices/semantic-logger/issues) with a link to your branch
|
95
419
|
5. That's it!
|
96
420
|
|
97
|
-
We are looking for volunteers to create implementations in other languages such as:
|
98
|
-
* Java, C# and Go
|
99
|
-
|
100
421
|
Meta
|
101
422
|
----
|
102
423
|
|
data/Rakefile
CHANGED
@@ -21,6 +21,7 @@ task :gem do |t|
|
|
21
21
|
spec.description = "Machine readable document oriented logging with support for MongoDB and text files"
|
22
22
|
spec.files = FileList["./**/*"].exclude('*.gem', 'nbproject').map{|f| f.sub(/^\.\//, '')}
|
23
23
|
spec.has_rdoc = true
|
24
|
+
spec.add_dependency 'sync_attr'
|
24
25
|
spec.add_development_dependency 'shoulda'
|
25
26
|
end
|
26
27
|
Gem::Builder.new(gemspec).build
|
data/lib/semantic_logger.rb
CHANGED
@@ -109,8 +109,11 @@ module SemanticLogger
|
|
109
109
|
# * Document updates cannot make them any larger
|
110
110
|
# * Documents are always stored in insertion order
|
111
111
|
# * A find will always return the documents in their insertion order
|
112
|
+
#
|
113
|
+
# Creates an index based on tags to support faster lookups
|
112
114
|
def create_indexes
|
113
115
|
db.create_collection(collection_name, {:capped => true, :size => @collection_size, :max => @collection_max})
|
116
|
+
collection.ensure_index('tags')
|
114
117
|
end
|
115
118
|
|
116
119
|
# Purge all data from the capped collection by dropping the collection
|
@@ -171,6 +174,16 @@ module SemanticLogger
|
|
171
174
|
message.to_s.gsub(/(\e(\[([\d;]*[mz]?))?)?/, '').strip
|
172
175
|
end
|
173
176
|
|
177
|
+
# Default host_name to use if none is supplied to the appenders initializer
|
178
|
+
def self.host_name
|
179
|
+
@@host_name ||= Socket.gethostname.split('.').first
|
180
|
+
end
|
181
|
+
|
182
|
+
# Override the default host_name
|
183
|
+
def self.host_name=(host_name)
|
184
|
+
@@host_name = host_name
|
185
|
+
end
|
186
|
+
|
174
187
|
# Log the message to MongoDB
|
175
188
|
def log(log)
|
176
189
|
# Insert log entry into Mongo
|
@@ -12,16 +12,23 @@
|
|
12
12
|
# log = Logger.new(STDOUT)
|
13
13
|
# log.level = Logger::DEBUG
|
14
14
|
#
|
15
|
-
# SemanticLogger::
|
15
|
+
# SemanticLogger::Logger.appenders << SemanticLogger::Appender::Logger.new(log)
|
16
16
|
#
|
17
17
|
# logger = SemanticLogger::Logger.new("my.app.class")
|
18
18
|
# logger.debug("Login time", :user => 'Joe', :duration => 100, :ip_address=>'127.0.0.1')
|
19
19
|
#
|
20
|
-
#
|
20
|
+
# # Now log to the Logger above as well as MongoDB at the same time
|
21
21
|
#
|
22
|
-
#
|
22
|
+
# db = Mongo::Connection.new['production_logging']
|
23
|
+
#
|
24
|
+
# SemanticLogger::Logger.appenders << SemanticLogger::Appender::MongoDB.new(
|
25
|
+
# :db => db,
|
26
|
+
# :collection_size => 25.gigabytes
|
27
|
+
# )
|
23
28
|
# ...
|
29
|
+
# # This will be logged to both the Ruby Logger and MongoDB
|
24
30
|
# logger.debug("Login time", :user => 'Mary', :duration => 230, :ip_address=>'192.168.0.1')
|
31
|
+
#
|
25
32
|
module SemanticLogger
|
26
33
|
class Logger
|
27
34
|
include SyncAttr
|
@@ -213,12 +220,6 @@ module SemanticLogger
|
|
213
220
|
queue.size
|
214
221
|
end
|
215
222
|
|
216
|
-
# Flush all pending log entry disk, database, etc.
|
217
|
-
# All pending log writes are completed and each appender is flushed in turn
|
218
|
-
def flush
|
219
|
-
self.class.flush
|
220
|
-
end
|
221
|
-
|
222
223
|
# Flush all pending log entry disk, database, etc.
|
223
224
|
# All pending log writes are completed and each appender is flushed in turn
|
224
225
|
def self.flush
|
@@ -251,6 +252,33 @@ module SemanticLogger
|
|
251
252
|
Queue.new
|
252
253
|
end
|
253
254
|
|
255
|
+
# Struct Log
|
256
|
+
#
|
257
|
+
# level
|
258
|
+
# Log level of the supplied log call
|
259
|
+
# :trace, :debug, :info, :warn, :error, :fatal
|
260
|
+
#
|
261
|
+
# thread_name
|
262
|
+
# Name of the thread in which the logging call was called
|
263
|
+
#
|
264
|
+
# name
|
265
|
+
# Class name supplied to the logging instance
|
266
|
+
#
|
267
|
+
# message
|
268
|
+
# Text message to be logged
|
269
|
+
#
|
270
|
+
# payload
|
271
|
+
# Optional Hash or Ruby Exception object to be logged
|
272
|
+
#
|
273
|
+
# time
|
274
|
+
# The time at which the log entry was created
|
275
|
+
#
|
276
|
+
# duration
|
277
|
+
# The time taken to complete a benchmark call
|
278
|
+
#
|
279
|
+
# tags
|
280
|
+
# Any tags active on the thread when the log call was made
|
281
|
+
#
|
254
282
|
Log = Struct.new(:level, :thread_name, :name, :message, :payload, :time, :duration, :tags)
|
255
283
|
|
256
284
|
# For JRuby include the Thread name rather than its id
|
data/test/logger_test.rb
CHANGED
@@ -33,7 +33,7 @@ class LoggerTest < Test::Unit::TestCase
|
|
33
33
|
SemanticLogger::Logger::LEVELS.each do |level|
|
34
34
|
should "log #{level} info" do
|
35
35
|
@logger.send(level, 'hello world', @hash) { "Calculations" }
|
36
|
-
|
36
|
+
SemanticLogger::Logger.flush
|
37
37
|
assert_match /\d+-\d+-\d+ \d+:\d+:\d+.\d+ \w \[\d+:.+\] LoggerTest -- hello world -- Calculations -- \{:session_id=>\"HSSKLEU@JDK767\", :tracking_number=>12345\}/, @mock_logger.message
|
38
38
|
end
|
39
39
|
end
|
@@ -42,7 +42,7 @@ class LoggerTest < Test::Unit::TestCase
|
|
42
42
|
should "add tags to log entries" do
|
43
43
|
@logger.with_tags('12345', 'DJHSFK') do
|
44
44
|
@logger.info('Hello world')
|
45
|
-
|
45
|
+
SemanticLogger::Logger.flush
|
46
46
|
assert_match /\d+-\d+-\d+ \d+:\d+:\d+.\d+ \w \[\d+:.+\] \[12345\] \[DJHSFK\] LoggerTest -- Hello world/, @mock_logger.message
|
47
47
|
end
|
48
48
|
end
|
@@ -51,7 +51,7 @@ class LoggerTest < Test::Unit::TestCase
|
|
51
51
|
@logger.with_tags('First Level', 'tags') do
|
52
52
|
@logger.with_tags('Second Level') do
|
53
53
|
@logger.info('Hello world')
|
54
|
-
|
54
|
+
SemanticLogger::Logger.flush
|
55
55
|
assert_match /\d+-\d+-\d+ \d+:\d+:\d+.\d+ \w \[\d+:.+\] \[First Level\] \[tags\] \[Second Level\] LoggerTest -- Hello world/, @mock_logger.message
|
56
56
|
end
|
57
57
|
end
|
@@ -61,7 +61,7 @@ class LoggerTest < Test::Unit::TestCase
|
|
61
61
|
@logger.with_payload(:tracking_number => '123456') do
|
62
62
|
@logger.with_payload(:more => 'data', :even => 2) do
|
63
63
|
@logger.info('Hello world')
|
64
|
-
|
64
|
+
SemanticLogger::Logger.flush
|
65
65
|
assert_match /\d+-\d+-\d+ \d+:\d+:\d+.\d+ \w \[\d+:.+\] LoggerTest -- Hello world -- \{:more=>\"data\", :even=>2, :tracking_number=>\"123456\"\}/, @mock_logger.message
|
66
66
|
end
|
67
67
|
end
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 4
|
8
|
+
- 0
|
9
|
+
version: 0.4.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Reid Morrison
|
@@ -14,11 +14,11 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2012-
|
17
|
+
date: 2012-09-05 00:00:00 -04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
|
-
name:
|
21
|
+
name: sync_attr
|
22
22
|
prerelease: false
|
23
23
|
requirement: &id001 !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
@@ -27,8 +27,20 @@ dependencies:
|
|
27
27
|
segments:
|
28
28
|
- 0
|
29
29
|
version: "0"
|
30
|
-
type: :
|
30
|
+
type: :runtime
|
31
31
|
version_requirements: *id001
|
32
|
+
- !ruby/object:Gem::Dependency
|
33
|
+
name: shoulda
|
34
|
+
prerelease: false
|
35
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
segments:
|
40
|
+
- 0
|
41
|
+
version: "0"
|
42
|
+
type: :development
|
43
|
+
version_requirements: *id002
|
32
44
|
description: Machine readable document oriented logging with support for MongoDB and text files
|
33
45
|
email:
|
34
46
|
- reidmo@gmail.com
|