semantic_logger 0.7.0 → 0.7.1
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 +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:
|