logjam 1.1.0 → 1.2.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.
- 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
|