logjam 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/{README → README.md} +99 -136
- data/lib/logjam.rb +179 -3
- data/lib/logjam/configuration.rb +13 -0
- data/lib/logjam/exceptions.rb +6 -23
- data/lib/logjam/logger.rb +62 -0
- data/lib/logjam/object.rb +24 -24
- data/lib/logjam/version.rb +2 -2
- metadata +46 -22
- data/lib/logjam/logjam.rb +0 -395
- data/lib/logjam/logjam_logger.rb +0 -202
- data/lib/logjam/logjam_logger2.rb +0 -68
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e9535269f47ac5920a95577153acd06362603e8f
|
4
|
+
data.tar.gz: 22348c06754806f3418c6f6da2b497d3ca9cd40e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 16e5edda4ea08cb7ca7dcfb9befd04121cbae237d8eeacb9aa728ecaf8a3a66e5c1d9112936a83ca0f47cf858cfa96ebfa6f236a4dcbbd7dbadc3cd575d56816
|
7
|
+
data.tar.gz: 29097aca1db189e166b37155c6584a2f0e37d46ee724a74d410dd4dd7c3750ec032ea1737e01646399d2ebc0bac3bf380b1102076415dfec703ba3b85ec477f3
|
data/{README → README.md}
RENAMED
@@ -6,46 +6,61 @@ creating this library were...
|
|
6
6
|
|
7
7
|
* Easy of use. Fall back on defaults as much as possible and allow the
|
8
8
|
functionality to be integrated and used with the least amount of work.
|
9
|
-
|
9
|
+
|
10
10
|
* Flexibility. After easy of use is taken into consideration it should be
|
11
11
|
possible to use the library in a more advanced fashion if that is called
|
12
12
|
for.
|
13
|
-
|
13
|
+
|
14
14
|
* Minimize the code to use it. It shouldn't require a great deal of code to
|
15
15
|
deploy or use the facilities and there should be no code required to pass
|
16
16
|
entities such as loggers around.
|
17
|
-
|
17
|
+
|
18
18
|
* Usable in libraries. I found myself writing a lot of common logging code
|
19
19
|
when writing libraries and application and wanted to abstract that out. I
|
20
20
|
wanted to minimize the burden this placed on library users at the same
|
21
21
|
time.
|
22
22
|
|
23
|
+
## Release Log
|
24
|
+
|
25
|
+
* v1.2.0: This version sees a major rewrite of the internals of the library
|
26
|
+
while attempting to retain backward compatibility. Library configuration
|
27
|
+
has been changed to get greater flexibility and to allow for the logging
|
28
|
+
configuration to be folded into a larger configuration file. The tests were
|
29
|
+
all changed to rspec and more extensive tests written.
|
30
|
+
|
23
31
|
## Configuration & Setup
|
24
32
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
33
|
+
The simplest setup to use with this library is to create a YAML file in the
|
34
|
+
called ```logging.yml```, either in the current working directory or in a
|
35
|
+
subdirectory of the working directory called ```config```. Place the following
|
36
|
+
contents into this file...
|
37
|
+
|
38
|
+
development:
|
39
|
+
loggers:
|
40
|
+
- default: true
|
41
|
+
file: STDOUT
|
42
|
+
name: devlog
|
43
|
+
production:
|
44
|
+
loggers:
|
45
|
+
- default: true
|
46
|
+
file: ./logs/production.log
|
47
|
+
name: prodlog
|
48
|
+
test:
|
49
|
+
loggers:
|
50
|
+
- default: true
|
51
|
+
file: STDOUT
|
52
|
+
name: testlog
|
53
|
+
|
54
|
+
By doing this you've now created a configuration that is environment dependent
|
55
|
+
and that the LogJam library will automatically pick up. When run in the
|
56
|
+
development (the default environment if no other is specified) or test
|
57
|
+
environments your application will now log to the standard output stream. For
|
58
|
+
the production environment the logging output will be written to a file called
|
59
|
+
```production.log``` which will be in the ```logs``` subdirectory.
|
60
|
+
|
61
|
+
The settings covered in the example configuration above are just some of the
|
62
|
+
parameters recognised for the definition of a logger. Here is a more complete
|
63
|
+
list of parameters that are used when creating loggers...
|
49
64
|
|
50
65
|
* default: A boolean indicating whether this logger is the default (i.e. the
|
51
66
|
one to be used when no other explicitly fits the bill). Only one logger
|
@@ -63,7 +78,7 @@ The meanings applied to these keys are as follows...
|
|
63
78
|
to DEBUG.
|
64
79
|
|
65
80
|
* max_size: When rotation is set to an integer value this value can be set to
|
66
|
-
indicate the maximum permitted file size for a log file.
|
81
|
+
indicate the maximum permitted file size for a log file in bytes.
|
67
82
|
|
68
83
|
* name: The name to associate with the logger. This allows loggers to be tied
|
69
84
|
to classes or for the creation of aliases that tie multiple names to a single
|
@@ -75,30 +90,33 @@ The meanings applied to these keys are as follows...
|
|
75
90
|
such as "daily", "weekly" or "monthly".
|
76
91
|
|
77
92
|
A note on logger names. Logger names (including alias names) aren't hierarchical
|
78
|
-
and should be unique.
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
93
|
+
and should be unique. Note that you may specify multiple logger definitions if
|
94
|
+
you wish, which would look like this...
|
95
|
+
|
96
|
+
development:
|
97
|
+
loggers:
|
98
|
+
- default: true
|
99
|
+
file: STDOUT
|
100
|
+
name: devlog
|
101
|
+
- file: ./logs/development.log
|
102
|
+
name: filelog
|
103
|
+
|
104
|
+
In addition to specifying logger definitions you can also specify logger
|
105
|
+
aliases. This is essentially a mechanism to allow a single logger to be
|
106
|
+
available under multiple names and a configuration including an alias definition
|
107
|
+
might look as follows...
|
108
|
+
|
109
|
+
development:
|
110
|
+
loggers:
|
111
|
+
- default: true
|
112
|
+
file: STDOUT
|
113
|
+
name: devlog
|
114
|
+
aliases:
|
115
|
+
database: devlog
|
116
|
+
|
117
|
+
If you don't provide a logging configuration then the LogJam library will fall
|
118
|
+
back on creating a single default logger that writes everything to the standard
|
119
|
+
output stream.
|
102
120
|
|
103
121
|
## Logging With The Library
|
104
122
|
|
@@ -109,85 +127,30 @@ Configuration & Setup section in which it's explained how to configure logging
|
|
109
127
|
from a single Hash or file. This section will provide details on how to deploy
|
110
128
|
loggers to various classes.
|
111
129
|
|
112
|
-
The LogJam library
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
definition. A typical call of this type might look like...
|
118
|
-
|
119
|
-
```
|
120
|
-
# Apply logging facilties to my class.
|
121
|
-
LogJam.apply(self, "my_logger")
|
122
|
-
```
|
123
|
-
|
124
|
-
This option remains available for backward compatibility but is no longer
|
125
|
-
needed. A line like this would appear somewhere inside the definition for the
|
126
|
-
class that will use logging. The first parameter to the call is the class that
|
127
|
-
is to be extended with the LogJam functionality. The second parameter is the
|
128
|
-
name of the logger that the class will use. Note that this parameter is optional
|
129
|
-
and, if notspecified or if a matching logger does not exist, the class will fall
|
130
|
-
back in using the default logger.
|
131
|
-
|
132
|
-
From version 1.1.0 onward you no longer need to call apply. Instead LogJams
|
133
|
-
logging facilities are available in all objects. This change means that all
|
134
|
-
classes use the default logger as standard. If you want to continue to use an
|
135
|
-
explitictly named logger on a per class basis you can make a call to the
|
136
|
-
LogJam#set_logger_name() method within your class definitions. This is similar
|
137
|
-
in nature to how the apply method was used and so would look something like the
|
138
|
-
following...
|
130
|
+
The LogJam library extends the object class to make access to a logger available
|
131
|
+
at both the class and the instance level. The obtain a logger object you can
|
132
|
+
make a call to the ```#log()``` method. If you haven't explicitly configured a
|
133
|
+
logger for a class this will return an instance of the default logger. A version
|
134
|
+
of this method is also available at the instance level.
|
139
135
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
```
|
136
|
+
If you want to get more advanced and configure a particular logger for a
|
137
|
+
specific class or group of classes then you have to explicitly set the logger
|
138
|
+
on those classes. To do that you define multiple loggers in your configuration
|
139
|
+
and then make a call to the ```#set_logger_name()``` method for the affected
|
140
|
+
class. For example, if you defined a logger called string_logger that you wanted
|
141
|
+
to use just for String objects you could do that like so...
|
144
142
|
|
145
|
-
|
146
|
-
and one called log=()) and an instance level method called log(). The log()
|
147
|
-
methods retrieve the Logger instance to be used by the class instances. The
|
148
|
-
log=() method allows the Logger instance associated with a class to be altered.
|
149
|
-
You should take care when assigning a logger in this fashion as assigning it
|
150
|
-
on one class may have an impact on many classes (e.g. if there is only a single
|
151
|
-
default logger defined in configuration).
|
143
|
+
String.set_logger_name("string_logger")
|
152
144
|
|
153
|
-
|
154
|
-
|
145
|
+
With your code you can obtain a logger instance and then use the method common
|
146
|
+
to Ruby's Logger class on the object returned. So, to log a statement at the
|
147
|
+
info level in a piece of code you would do something like this...
|
155
148
|
|
156
|
-
|
157
|
-
require 'rubygems'
|
158
|
-
require 'logjam'
|
159
|
-
|
160
|
-
class Writer
|
161
|
-
def initialize(stream=STDOUT)
|
162
|
-
@stream = stream
|
163
|
-
end
|
164
|
-
|
165
|
-
def echo(message)
|
166
|
-
log.debug("Echoed: #{message}")
|
167
|
-
@stream.puts message
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
|
-
begin
|
172
|
-
LogJam.configure({:loggers => [{:name => "echo",
|
173
|
-
:file => "echo.log"}]})
|
174
|
-
|
175
|
-
writer = Writer.new
|
176
|
-
writer.echo "This is a string containing my message."
|
177
|
-
rescue => error
|
178
|
-
puts "ERROR: #{error}\n" + error.backtrace.join("\n")
|
179
|
-
end
|
180
|
-
```
|
149
|
+
log.info("This is a statement that I am logging.")
|
181
150
|
|
182
|
-
|
183
|
-
|
184
|
-
call the log() method to get the class logger.
|
151
|
+
Consult the documentation of the Ruby Logger class for more information on the
|
152
|
+
methods and logging levels available.
|
185
153
|
|
186
|
-
In the later section of the code we configure the LogJam system to have a single
|
187
|
-
Logger that writes to the echo.log file. We then create a Writer instance and
|
188
|
-
use it to write a simple message. This message should appear on the standard
|
189
|
-
output stream and be logged to the echo.log file.
|
190
|
-
|
191
154
|
## Advanced Usage
|
192
155
|
|
193
156
|
The hope would be that this library can be used in the creation of other
|
@@ -257,7 +220,7 @@ Hash
|
|
257
220
|
|
258
221
|
YAML
|
259
222
|
```
|
260
|
-
:loggers:
|
223
|
+
:loggers:
|
261
224
|
- :default: true
|
262
225
|
:file: application.log
|
263
226
|
```
|
@@ -288,14 +251,14 @@ Hash
|
|
288
251
|
|
289
252
|
YAML
|
290
253
|
```
|
291
|
-
:loggers:
|
254
|
+
:loggers:
|
292
255
|
- :default: true
|
293
256
|
:file: STDOUT
|
294
257
|
:level: UNKNOWN
|
295
258
|
:name: silent
|
296
259
|
- :file: STDOUT
|
297
260
|
:name: verbose
|
298
|
-
:aliases:
|
261
|
+
:aliases:
|
299
262
|
database: verbose
|
300
263
|
```
|
301
264
|
|
@@ -330,13 +293,13 @@ Hash
|
|
330
293
|
|
331
294
|
YAML
|
332
295
|
```
|
333
|
-
:loggers:
|
296
|
+
:loggers:
|
334
297
|
- :default: true
|
335
298
|
:file: ./log/main.log
|
336
299
|
:name: main
|
337
300
|
- :file: ./log/secondary.log
|
338
301
|
:name: secondary
|
339
|
-
:aliases:
|
302
|
+
:aliases:
|
340
303
|
database: secondary
|
341
304
|
model: secondary
|
342
305
|
controller: main
|
@@ -356,20 +319,20 @@ JSON
|
|
356
319
|
|
357
320
|
## Testing
|
358
321
|
|
359
|
-
LogJam uses the
|
322
|
+
LogJam uses the RSpec Ruby library for testing. The best approach to running
|
360
323
|
the tests are to create a new gemset (assuming you're using RVM), do a bundle
|
361
324
|
install on this gemset from within the LogJam root directory and then use a
|
362
325
|
command such as the following to run the tests...
|
363
326
|
|
364
327
|
```
|
365
|
-
$>
|
328
|
+
$> rspec
|
366
329
|
```
|
367
330
|
|
368
|
-
Individual tests can be run by
|
369
|
-
|
331
|
+
Individual tests can be run by appending the path to the file that you want to
|
332
|
+
execute after the ```rspec``` command. For example...
|
370
333
|
|
371
334
|
```
|
372
|
-
$> rake
|
335
|
+
$> rake spec/logjam_spec.rb
|
373
336
|
```
|
374
337
|
|
375
|
-
...would run only the
|
338
|
+
...would run only the the tests in the logjam_spec.rb test file.
|
data/lib/logjam.rb
CHANGED
@@ -3,11 +3,187 @@
|
|
3
3
|
# Copyright (c), 2012 Peter Wood
|
4
4
|
# See the license.txt for details of the licensing of the code in this file.
|
5
5
|
|
6
|
+
require 'forwardable'
|
6
7
|
require 'logger'
|
8
|
+
require 'configurative'
|
7
9
|
require 'logjam/version'
|
8
10
|
require 'logjam/exceptions'
|
9
|
-
require 'logjam/
|
10
|
-
require 'logjam/
|
11
|
+
require 'logjam/configuration'
|
12
|
+
require 'logjam/logger'
|
11
13
|
require 'logjam/object'
|
12
14
|
|
13
|
-
LogJam
|
15
|
+
module LogJam
|
16
|
+
# Module constants.
|
17
|
+
LEVEL_MAP = {"debug" => Logger::DEBUG,
|
18
|
+
"info" => Logger::INFO,
|
19
|
+
"warn" => Logger::WARN,
|
20
|
+
"error" => Logger::ERROR,
|
21
|
+
"fatal" => Logger::FATAL,
|
22
|
+
"unknown" => Logger::UNKNOWN}
|
23
|
+
STREAM_MAP = {"stdout" => STDOUT,
|
24
|
+
"stderr" => STDERR}
|
25
|
+
|
26
|
+
# Module static properties.
|
27
|
+
@@logjam_modules = {}
|
28
|
+
@@logjam_loggers = {}
|
29
|
+
@@logjam_contexts = {}
|
30
|
+
|
31
|
+
# This method is used to configure the LogJam module with the various loggers
|
32
|
+
# it will use.
|
33
|
+
#
|
34
|
+
# ==== Parameters
|
35
|
+
# source:: Either a Hash containing the configuration to be used or nil to
|
36
|
+
# indicate the use of default configuration settings.
|
37
|
+
def self.configure(source=nil)
|
38
|
+
@@logjam_modules = {}
|
39
|
+
@@logjam_loggers = {}
|
40
|
+
LogJam.process_configuration(source ? source : Configuration.instance)
|
41
|
+
end
|
42
|
+
|
43
|
+
# This method is used to install logging facilities at the class level for a
|
44
|
+
# given class. Once 'logified' a class will possess two new methods. The
|
45
|
+
# first, #log(), retrieves the logger associated with the class. The second,
|
46
|
+
# #log=(), allows the assignment of the logger associated with the class.
|
47
|
+
# Note that changing the logger associated with a class will impact all other
|
48
|
+
# classes that use the same logger.
|
49
|
+
#
|
50
|
+
# ==== Parameters
|
51
|
+
# target:: The target class that is to be extended.
|
52
|
+
# name:: The name of the logger to be used by the class. Defaults to nil
|
53
|
+
# to indicate use of the default logger.
|
54
|
+
# context:: A Hash of additional parameters that are specific to the class
|
55
|
+
# to which LogJam is being applied.
|
56
|
+
def self.apply(target, name=nil, context={})
|
57
|
+
@@logjam_contexts[target] = {}.merge(context)
|
58
|
+
target.extend(LogJam.get_module(name, @@logjam_contexts[target]))
|
59
|
+
target.send(:define_method, :log) {LogJam.get_logger(name)} if !target.method_defined?(:log)
|
60
|
+
end
|
61
|
+
|
62
|
+
# This method attempts to fetch the logger for a specified name. If this
|
63
|
+
# logger does not exist then a default logger will be returned instead.
|
64
|
+
#
|
65
|
+
# ==== Parameters
|
66
|
+
# name:: The name of the logger to retrieve.
|
67
|
+
def self.get_logger(name=nil)
|
68
|
+
LogJam.process_configuration(nil) if @@logjam_loggers.empty?
|
69
|
+
@@logjam_loggers.fetch(name, @@logjam_loggers[nil])
|
70
|
+
end
|
71
|
+
|
72
|
+
# This method fetches a list of the names currently defined within the LogJam
|
73
|
+
# internal settings.
|
74
|
+
def self.names
|
75
|
+
@@logjam_loggers.keys.compact
|
76
|
+
end
|
77
|
+
|
78
|
+
# A convenience mechanism that provides an instance level access to the
|
79
|
+
# class level logger.
|
80
|
+
def log
|
81
|
+
self.class.log
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
# This method fetches the module associated with a name. If the module does
|
87
|
+
# not exist the default module is returned instead.
|
88
|
+
#
|
89
|
+
# ==== Parameters
|
90
|
+
# name:: The name associated with the module to return.
|
91
|
+
# context:: The context that applies to the module to be retrieved.
|
92
|
+
def self.get_module(name, context={})
|
93
|
+
LogJam.create_module(name)
|
94
|
+
end
|
95
|
+
|
96
|
+
# This method processes a logger configuration and generates the appropriate
|
97
|
+
# set of loggers and internal objects from it.
|
98
|
+
#
|
99
|
+
# ==== Parameters
|
100
|
+
# settings:: A collection of the settings to be processed.
|
101
|
+
def self.process_configuration(settings)
|
102
|
+
settings = Configurative::SettingsParser.new.parse(settings) if settings.kind_of?(Hash)
|
103
|
+
if settings && !settings.empty?
|
104
|
+
loggers = settings.loggers
|
105
|
+
if loggers
|
106
|
+
if loggers.kind_of?(Array)
|
107
|
+
loggers.each {|definition| LogJam.create_logger(definition)}
|
108
|
+
elsif loggers.kind_of?(Hash)
|
109
|
+
LogJam.create_logger(loggers)
|
110
|
+
else
|
111
|
+
raise Error, "The loggers configuration entry is in an "\
|
112
|
+
"unrecognised format. Must be either a Hash or an "\
|
113
|
+
"Array."
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
aliases = settings.aliases
|
118
|
+
if aliases
|
119
|
+
aliases.each do |name, equivalent|
|
120
|
+
@@logjam_loggers[name] = @@logjam_loggers[equivalent]
|
121
|
+
@@logjam_modules[name] = LogJam.get_module(equivalent)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# Create a default logger if one hasn't been specified.
|
127
|
+
LogJam.create_logger({default: true, file: "STDOUT"}) if @@logjam_loggers[nil].nil?
|
128
|
+
end
|
129
|
+
|
130
|
+
# This method is used to create an anonymous module under a given name (if it
|
131
|
+
# doesn't already exist) and return it to the caller.
|
132
|
+
#
|
133
|
+
# ==== Parameters
|
134
|
+
# name:: The name to create the module under.
|
135
|
+
def self.create_module(name)
|
136
|
+
if !@@logjam_modules.include?(name)
|
137
|
+
# Create the anonymous module and add methods to it.
|
138
|
+
@@logjam_modules[name] = Module.new
|
139
|
+
@@logjam_modules[name].send(:define_method, :log) do
|
140
|
+
LogJam.get_logger(name)
|
141
|
+
end
|
142
|
+
@@logjam_modules[name].send(:define_method, :log=) do |logger|
|
143
|
+
LogJam.get_logger(name).logger = logger
|
144
|
+
end
|
145
|
+
end
|
146
|
+
@@logjam_modules[name]
|
147
|
+
end
|
148
|
+
|
149
|
+
# This method creates a logger from a given definition. A definition should
|
150
|
+
# be a Hash containing the values that are used to configure the Logger with.
|
151
|
+
#
|
152
|
+
# ==== Parameters
|
153
|
+
# definition:: A Hash containing the configuration details for the logger.
|
154
|
+
def self.create_logger(definition)
|
155
|
+
# Fetch the configuration values.
|
156
|
+
definition = to_definition(definition)
|
157
|
+
rotation = definition.rotation
|
158
|
+
max_size = definition.max_size
|
159
|
+
device = STREAM_MAP.fetch(definition.file.downcase.strip, definition.file)
|
160
|
+
|
161
|
+
if rotation.kind_of?(String) && /^\s*\d+\s*$/ =~ rotation
|
162
|
+
rotation = rotation.to_i
|
163
|
+
rotation = 0 if rotation < 0
|
164
|
+
end
|
165
|
+
|
166
|
+
max_size = max_size.to_i if !max_size.nil? && max_size.kind_of?(String)
|
167
|
+
max_size = 1048576 if !max_size.nil? && max_size < 1024
|
168
|
+
|
169
|
+
# Create the actual logger and associated module.
|
170
|
+
logger = LogJam::Logger.new(device, rotation, max_size)
|
171
|
+
logger.level = LEVEL_MAP.fetch(definition.level.downcase.strip, Logger::DEBUG)
|
172
|
+
logger.name = definition.name
|
173
|
+
logger.progname = definition.name
|
174
|
+
@@logjam_loggers[definition.name] = logger
|
175
|
+
logger_module = LogJam.create_module(name)
|
176
|
+
if definition.default
|
177
|
+
@@logjam_loggers[nil] = logger
|
178
|
+
@@logjam_modules[nil] = logger_module
|
179
|
+
end
|
180
|
+
logger
|
181
|
+
end
|
182
|
+
|
183
|
+
def self.to_definition(settings)
|
184
|
+
settings = Configurative::SettingsParser.new.parse(settings) if settings.kind_of?(Hash)
|
185
|
+
settings.file = "stdout" if !settings.include?(:file) || settings.file == ""
|
186
|
+
settings.level = "debug" if !settings.include?(:level) || settings.level == ""
|
187
|
+
settings
|
188
|
+
end
|
189
|
+
end
|