semantic_logger 0.7.0 → 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +128 -73
- data/lib/semantic_logger/logger.rb +6 -7
- data/lib/semantic_logger/version.rb +1 -1
- data/semantic_logger-0.7.0.gem +0 -0
- metadata +4 -3
data/README.md
CHANGED
@@ -21,7 +21,9 @@ that contain the necessary meta-data.
|
|
21
21
|
|
22
22
|
Example of current calls:
|
23
23
|
|
24
|
-
|
24
|
+
```ruby
|
25
|
+
logger.info("Queried users table in #{duration} ms, with a result code of #{result}")
|
26
|
+
```
|
25
27
|
|
26
28
|
For a machine to find all queries for table 'users' that took longer than
|
27
29
|
100 ms, would require using a regular expression just to extract the table name
|
@@ -31,16 +33,20 @@ similar text output.
|
|
31
33
|
|
32
34
|
This can be changed over time to:
|
33
35
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
36
|
+
```ruby
|
37
|
+
Rails.logger.info("Queried table",
|
38
|
+
:duration => duration,
|
39
|
+
:result => result,
|
40
|
+
:table => "users",
|
41
|
+
:action => "query")
|
42
|
+
```
|
39
43
|
|
40
44
|
Using the MongoDB appender, we can easily find all queries for table 'users'
|
41
45
|
that took longer than 100 ms:
|
42
46
|
|
43
|
-
|
47
|
+
```javascript
|
48
|
+
db.logs.find({"payload.table":"users", "payload.action":"query", "payload.duration":{$gt:100} })
|
49
|
+
```
|
44
50
|
|
45
51
|
Since SemanticLogger can call existing Loggers, it does not force end-users
|
46
52
|
to have to adopt a Semantic aware adapter. Although, such adapters create
|
@@ -53,20 +59,26 @@ tremendous value in the problem monitoring and determination processes.
|
|
53
59
|
The Semantic Logger logging API supports the existing logging interface for
|
54
60
|
the Rails and Ruby Loggers. For example:
|
55
61
|
|
56
|
-
|
62
|
+
```ruby
|
63
|
+
logger.info("Hello World")
|
64
|
+
```
|
57
65
|
|
58
66
|
Or to query whether a specific log level is set
|
59
67
|
|
60
|
-
|
68
|
+
```ruby
|
69
|
+
logger.info?
|
70
|
+
```
|
61
71
|
|
62
|
-
The following logging methods are
|
72
|
+
The following logging methods are available
|
63
73
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
74
|
+
```ruby
|
75
|
+
trace(message, payload=nil, &block)
|
76
|
+
debug(message, payload=nil, &block)
|
77
|
+
info(message, payload=nil, &block)
|
78
|
+
warn(message, payload=nil, &block)
|
79
|
+
error(message, payload=nil, &block)
|
80
|
+
fatal(message, payload=nil, &block)
|
81
|
+
```
|
70
82
|
|
71
83
|
Parameters
|
72
84
|
|
@@ -79,32 +91,37 @@ Parameters
|
|
79
91
|
|
80
92
|
Examples:
|
81
93
|
|
82
|
-
|
94
|
+
```ruby
|
95
|
+
logger.debug("Calling Supplier")
|
83
96
|
|
84
|
-
|
97
|
+
logger.debug("Calling Supplier", :request => 'update', :user => 'Jack')
|
85
98
|
|
86
|
-
|
99
|
+
logger.debug { "A total of #{result.inject(0) {|sum, i| i+sum }} were processed" }
|
100
|
+
```
|
87
101
|
|
88
102
|
### Exceptions
|
89
103
|
|
90
104
|
The Semantic Logger adds an extra parameter to the existing log methods so that
|
91
105
|
a corresponding Exception can be logged in a standard way
|
92
106
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
107
|
+
```ruby
|
108
|
+
begin
|
109
|
+
# ... Code that can raise an exception
|
110
|
+
rescue Exception => exception
|
111
|
+
logger.error("Oops external call failed", exception)
|
112
|
+
# Re-raise or handle the exception
|
113
|
+
raise exception
|
114
|
+
end
|
115
|
+
```
|
101
116
|
|
102
117
|
#### Payload
|
103
118
|
|
104
119
|
The Semantic Logger adds an extra parameter to the existing log methods so that
|
105
120
|
additional payload can be logged, such as a Hash or a Ruby Exception object.
|
106
121
|
|
107
|
-
|
122
|
+
```ruby
|
123
|
+
logger.info("Oops external call failed", :result => :failed, :reason_code => -10)
|
124
|
+
```
|
108
125
|
|
109
126
|
The additional payload is machine readable so that we don't have to write complex
|
110
127
|
regular expressions so that a program can analyze log output. With the MongoDB
|
@@ -116,25 +133,36 @@ is therefore fully searchable
|
|
116
133
|
Another common logging requirement is to measure the time it takes to execute a block
|
117
134
|
of code based on the log level. For example:
|
118
135
|
|
119
|
-
|
120
|
-
|
121
|
-
|
136
|
+
```ruby
|
137
|
+
Rails.logger.benchmark_info "Calling external interface" do
|
138
|
+
# Code to call external service ...
|
139
|
+
end
|
140
|
+
```
|
122
141
|
|
123
142
|
The following output will be written to file:
|
124
143
|
|
125
|
-
2012-08-30 15:37:29.474 I [48308:ScriptThreadProcess: script/rails] Rails -- Calling external interface
|
144
|
+
2012-08-30 15:37:29.474 I [48308:ScriptThreadProcess: script/rails] (5.2ms) Rails -- Calling external interface
|
126
145
|
|
127
146
|
If an exception is raised during the block the exception is logged
|
128
147
|
at the same log level as the benchmark along with the duration and message.
|
129
148
|
The exception will flow through to the caller unchanged
|
130
149
|
|
150
|
+
The following benchmarking methods are available
|
151
|
+
|
152
|
+
```ruby
|
153
|
+
benchmark_trace(message, params=nil, &block)
|
154
|
+
benchmark_debug(message, params=nil, &block)
|
155
|
+
benchmark_info(message, params=nil, &block)
|
156
|
+
benchmark_warn(message, params=nil, &block)
|
157
|
+
benchmark_error(message, params=nil, &block)
|
158
|
+
benchmark_fatal(message, params=nil, &block)
|
131
159
|
```
|
132
|
-
Parameters to benchmark_info, benchmark_debug, etc..
|
133
160
|
|
134
|
-
|
135
|
-
The message for this log entry
|
161
|
+
Parameters
|
136
162
|
|
137
|
-
|
163
|
+
- message: The mandatory text message to log.
|
164
|
+
- params:
|
165
|
+
```
|
138
166
|
:log_exception
|
139
167
|
Control whether or how an exception thrown in the block is
|
140
168
|
reported by SemanticLogger. Values:
|
@@ -148,9 +176,10 @@ params:
|
|
148
176
|
|
149
177
|
:min_duration
|
150
178
|
Only log if the block takes longer than this duration in ms
|
179
|
+
Default: 0.0
|
151
180
|
|
152
181
|
:payload
|
153
|
-
|
182
|
+
Optional, either a Ruby Exception object or a Hash
|
154
183
|
```
|
155
184
|
|
156
185
|
#### Logging levels
|
@@ -178,7 +207,9 @@ When Semantic Logger is included on a Rails project it automatically replaces th
|
|
178
207
|
loggers for Rails, ActiveRecord::Base, ActionController::Base, and ActiveResource::Base
|
179
208
|
with wrappers that set their Class name. For example in railtie.rb:
|
180
209
|
|
181
|
-
|
210
|
+
```ruby
|
211
|
+
ActiveRecord::Base.logger = SemanticLogger::Logger.new(ActiveRecord)
|
212
|
+
```
|
182
213
|
|
183
214
|
By replacing their loggers we now get the class name in the text logging output:
|
184
215
|
|
@@ -187,39 +218,51 @@ By replacing their loggers we now get the class name in the text logging output:
|
|
187
218
|
It is recommended to include a class specific logger for all major classes that will
|
188
219
|
be logging. For Example:
|
189
220
|
|
190
|
-
|
191
|
-
|
192
|
-
|
221
|
+
```ruby
|
222
|
+
require 'sync_attr'
|
223
|
+
require 'semantic_logger'
|
193
224
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
end
|
225
|
+
class ExternalSupplier
|
226
|
+
# Gem sync_attr is a dependency of semantic_logger so is already installed
|
227
|
+
include SyncAttr
|
198
228
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
229
|
+
# Lazy initializes the class logger on it's first call in a thread-safe way
|
230
|
+
sync_cattr_reader :logger do
|
231
|
+
SemanticLogger::Logger.new(self)
|
232
|
+
end
|
233
|
+
|
234
|
+
def call(params)
|
235
|
+
self.class.logger.benchmark_info "Calling external interface" do
|
236
|
+
# Code to call external service ...
|
204
237
|
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
```
|
205
241
|
|
206
|
-
This will result in the log output
|
242
|
+
This will result in the log output identifying the log entry as from the ExternalSupplier class
|
207
243
|
|
208
|
-
2012-08-30 15:37:29.474 I [48308:ScriptThreadProcess: script/rails] ExternalSupplier -- Calling external interface
|
244
|
+
2012-08-30 15:37:29.474 I [48308:ScriptThreadProcess: script/rails] (5.2ms) ExternalSupplier -- Calling external interface
|
245
|
+
|
246
|
+
[SyncAttr](https://github.com/ClarityServices/sync_attr) is a gem that supports
|
247
|
+
lazy loading and thread-safe initialization of class attributes
|
209
248
|
|
210
249
|
#### Tagged Logging
|
211
250
|
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
251
|
+
```ruby
|
252
|
+
logger.tagged(tracking_number) do
|
253
|
+
logger.debug("Hello World")
|
254
|
+
# ...
|
255
|
+
end
|
256
|
+
```
|
216
257
|
|
217
258
|
#### Payload injected logging
|
218
259
|
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
260
|
+
```ruby
|
261
|
+
logger.with_payload(:user => 'Jack') do
|
262
|
+
logger.debug("Hello World")
|
263
|
+
# ...
|
264
|
+
end
|
265
|
+
```
|
223
266
|
|
224
267
|
### Configuration
|
225
268
|
|
@@ -231,11 +274,15 @@ ActiveResource::BufferedLogger at the same time.
|
|
231
274
|
|
232
275
|
Add the following line to Gemfile
|
233
276
|
|
234
|
-
|
277
|
+
```ruby
|
278
|
+
gem 'semantic_logger'
|
279
|
+
```
|
235
280
|
|
236
281
|
Also add the following line to Gemfile if you want to log to MongoDB
|
237
282
|
|
238
|
-
|
283
|
+
```ruby
|
284
|
+
gem 'mongo'
|
285
|
+
```
|
239
286
|
|
240
287
|
Install required gems with bundler
|
241
288
|
|
@@ -248,21 +295,25 @@ By default Semantic Logger will detect the log level from Rails. To set the
|
|
248
295
|
log level explicitly, add the following line to
|
249
296
|
config/environments/production.rb inside the Application.configure block
|
250
297
|
|
251
|
-
|
298
|
+
```ruby
|
299
|
+
config.log_level = :trace
|
300
|
+
```
|
252
301
|
|
253
302
|
To log to both the Rails logger and MongoDB add the following lines to
|
254
303
|
config/environments/production.rb inside the Application.configure block
|
255
304
|
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
305
|
+
```ruby
|
306
|
+
config.after_initialize do
|
307
|
+
# Re-use the existing MongoDB connection, or create a new one here
|
308
|
+
db = Mongo::Connection.new['production_logging']
|
309
|
+
|
310
|
+
# Besides logging to the standard Rails logger, also log to MongoDB
|
311
|
+
config.semantic_logger.appenders << SemanticLogger::Appender::MongoDB.new(
|
312
|
+
:db => db,
|
313
|
+
:collection_size => 25.gigabytes
|
314
|
+
)
|
315
|
+
end
|
316
|
+
```
|
266
317
|
|
267
318
|
#### Custom Formatters
|
268
319
|
|
@@ -271,6 +322,7 @@ existing formatter supply a block of code when creating the appender.
|
|
271
322
|
|
272
323
|
For example to replace the Rails or Ruby text log formatter, in the environment configuration file:
|
273
324
|
|
325
|
+
```ruby
|
274
326
|
config.after_initialize do
|
275
327
|
# Since the Rails logger is already initialized, replace its default formatter
|
276
328
|
config.semantic_logger.appenders.first.formatter = Proc.new do |log|
|
@@ -319,9 +371,11 @@ For example to replace the Rails or Ruby text log formatter, in the environment
|
|
319
371
|
str
|
320
372
|
end
|
321
373
|
end
|
374
|
+
```
|
322
375
|
|
323
376
|
For example to replace the MongoDB formatter, in the environment configuration file:
|
324
377
|
|
378
|
+
```ruby
|
325
379
|
config.after_initialize do
|
326
380
|
# Log to MongoDB and supply a custom document formatter
|
327
381
|
mongodb_appender = SemanticLogger::Appender::MongoDB.new(
|
@@ -385,6 +439,7 @@ For example to replace the MongoDB formatter, in the environment configuration f
|
|
385
439
|
end
|
386
440
|
config.semantic_logger.appenders << mongodb_appender
|
387
441
|
end
|
442
|
+
```
|
388
443
|
|
389
444
|
### Architecture & Performance
|
390
445
|
|
@@ -161,7 +161,7 @@ module SemanticLogger
|
|
161
161
|
begin
|
162
162
|
logger.debug "SemanticLogger::Logger Appender thread started"
|
163
163
|
count = 0
|
164
|
-
while message=queue.pop
|
164
|
+
while message = queue.pop
|
165
165
|
if message.is_a? Log
|
166
166
|
appenders.each {|appender| appender.log(message) }
|
167
167
|
count += 1
|
@@ -176,12 +176,12 @@ module SemanticLogger
|
|
176
176
|
case message[:command]
|
177
177
|
when :shutdown
|
178
178
|
appenders.each {|appender| appender.flush }
|
179
|
-
message[:reply_queue] << true
|
179
|
+
message[:reply_queue] << true if message[:reply_queue]
|
180
180
|
logger.debug "SemanticLogger::Logger appenders flushed, now shutting down"
|
181
181
|
break
|
182
182
|
when :flush
|
183
183
|
appenders.each {|appender| appender.flush }
|
184
|
-
message[:reply_queue] << true
|
184
|
+
message[:reply_queue] << true if message[:reply_queue]
|
185
185
|
logger.debug "SemanticLogger::Logger appenders flushed"
|
186
186
|
end
|
187
187
|
end
|
@@ -201,13 +201,12 @@ module SemanticLogger
|
|
201
201
|
return false unless @@appender_thread.alive?
|
202
202
|
|
203
203
|
logger.debug "SemanticLogger::Logger Shutdown. Stopping appender thread"
|
204
|
-
|
205
|
-
|
206
|
-
result = reply_queue.pop
|
204
|
+
queue << { :command => :shutdown }
|
205
|
+
@@appender_thread.join
|
207
206
|
# Undefine the class variable for the queue since in test environments
|
208
207
|
# at_exit can be invoked multiple times
|
209
208
|
remove_class_variable(:@@queue)
|
210
|
-
|
209
|
+
true
|
211
210
|
end
|
212
211
|
|
213
212
|
# Formatting does not occur within this thread, it is done by each appender
|
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: semantic_logger
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-10-
|
12
|
+
date: 2012-10-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: sync_attr
|
@@ -72,6 +72,7 @@ files:
|
|
72
72
|
- nbproject/project.xml
|
73
73
|
- Rakefile
|
74
74
|
- README.md
|
75
|
+
- semantic_logger-0.7.0.gem
|
75
76
|
- test/appender_file_test.rb
|
76
77
|
- test/appender_mongodb_test.rb
|
77
78
|
- test/appender_wrapper_test.rb
|
@@ -91,7 +92,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
91
92
|
version: '0'
|
92
93
|
segments:
|
93
94
|
- 0
|
94
|
-
hash:
|
95
|
+
hash: 4306038405439856699
|
95
96
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
97
|
none: false
|
97
98
|
requirements:
|