logjam 1.0.0 → 1.2.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,390 +0,0 @@
1
- #! /usr/bin/env ruby
2
- #
3
- # Copyright (c), 2012 Peter Wood
4
- # See the license.txt for details of the licensing of the code in this file.
5
-
6
- require 'json'
7
- require 'logger'
8
- require 'stringio'
9
- require 'yaml'
10
-
11
- # This module defines the name space to be used by all code within the
12
- # LogJam library.
13
- module LogJam
14
- # Module constants.
15
- LOGGER_NAME = :name
16
- LOGGER_FILE = :file
17
- LOGGER_ROTATION = :rotation
18
- LOGGER_MAX_SIZE = :max_size
19
- LOGGER_LEVEL = :level
20
- LOGGER_DEFAULT = :default
21
- LOGGER_DATETIME_FORMAT = :datetime_format
22
- DEFAULT_FILE_NAMES = [".#{File::SEPARATOR}logging.yaml",
23
- ".#{File::SEPARATOR}logging.yml",
24
- ".#{File::SEPARATOR}logging.json",
25
- ".#{File::SEPARATOR}config#{File::SEPARATOR}logging.yaml",
26
- ".#{File::SEPARATOR}config#{File::SEPARATOR}logging.yml",
27
- ".#{File::SEPARATOR}config#{File::SEPARATOR}logging.json"]
28
-
29
- # Module static properties.
30
- @@logjam_modules = {}
31
- @@logjam_loggers = {}
32
-
33
- # This method is used to configure the LogJam module with the various loggers
34
- # it will use.
35
- #
36
- # ==== Parameters
37
- # source:: Either a String containing the path and name of the configuration
38
- # file containing the logging set up, an IO object from which the
39
- # configuration details can be read, a Hash containing a logging
40
- # configuration or nil.
41
- def self.configure(source)
42
- @@logjam_modules = {}
43
- @@logjam_loggers = {}
44
-
45
- # Check for default files if nil was passed in.
46
- source = LogJam.find_default_file if source.nil?
47
-
48
- if !source.kind_of?(Hash) && !source.nil?
49
- io = source.kind_of?(String) ? File.new(source) : source
50
- type = source.kind_of?(String) ? LogJam.guess_format(source) : nil
51
- LogJam.process_configuration(LogJam.load_configuration(io, type))
52
- elsif source.nil?
53
- LogJam.process_configuration({})
54
- else
55
- LogJam.process_configuration(source)
56
- end
57
- end
58
-
59
- # This method is used to install logging facilities at the class level for a
60
- # given class. Once 'logified' a class will possess two new methods. The
61
- # first, #log(), retrieves the logger associated with the class. The second,
62
- # #log=(), allows the assignment of the logger associated with the class.
63
- # Note that changing the logger associated with a class will impact all other
64
- # classes that use the same logger.
65
- #
66
- # ==== Parameters
67
- # target:: The target class that is to be extended.
68
- # name:: The name of the logger to be used by the class. Defaults to nil
69
- # to indicate use of the default logger.
70
- def self.apply(target, name=nil)
71
- target.extend(LogJam.get_module(name))
72
- target.send(:define_method, :log) {LogJam.get_logger(name)} if !target.method_defined?(:log)
73
- end
74
-
75
- # This method attempts to fetch the logger for a specified name. If this
76
- # logger does not exist then a default logger will be returned instead.
77
- #
78
- # ==== Parameters
79
- # name:: The name of the logger to retrieve.
80
- def self.get_logger(name=nil)
81
- LogJam.process_configuration(nil) if @@logjam_loggers.empty?
82
- @@logjam_loggers.fetch(name, @@logjam_loggers[nil])
83
- end
84
-
85
- # This method fetches a list of the names currently defined within the LogJam
86
- # internal settings.
87
- def self.names
88
- @@logjam_loggers.keys.compact
89
- end
90
-
91
- # A convenience mechanism that provides an instance level access to the
92
- # class level logger.
93
- def log
94
- self.class.log
95
- end
96
-
97
- private
98
-
99
- # This method fetches the module associated with a name. If the module does
100
- # not exist the default module is returned instead.
101
- #
102
- # ==== Parameters
103
- # name:: The name associated with the module to return.
104
- def self.get_module(name)
105
- LogJam.create_module(name)
106
- end
107
-
108
- # This method attempts to load a LogJam configuration from an IO object.
109
- #
110
- # ==== Parameters
111
- # source:: The IO object to read the configuration details from.
112
- # type:: An indicator of the format being used for the configuration. This
113
- # should be :yaml, :json or nil. Nil indicates that the library
114
- # will try to load the file in various formats.
115
- def self.load_configuration(source, type)
116
- configuration = nil
117
- if ![:yaml, :json].include?(type)
118
- begin
119
- # Read in the full details of the configuration.
120
- details = source.read
121
-
122
- # Try YAML format first.
123
- begin
124
- configuration = LogJam.load_yaml_configuration(StringIO.new(details))
125
- rescue LogJamError
126
- # Assume wrong format and ignore.
127
- configuration = nil
128
- end
129
-
130
- if configuration.nil?
131
- # Try JSON format second.
132
- begin
133
- configuration = LogJam.load_json_configuration(StringIO.new(details))
134
- rescue LogJamError
135
- # Assume wrong format and ignore.
136
- configuration = nil
137
- end
138
- end
139
- rescue => error
140
- raise LogJamError.new("Exception raised loading the LogJam "\
141
- "configuration.\nCause: #{error}", error)
142
- end
143
-
144
- # Check if the load was successful.
145
- if configuration.nil?
146
- raise LogJamError.new("Error loading the LogJam configuration. The "\
147
- "configuration is not in a recognised format "\
148
- "or contains errors. The configuration must "\
149
- "be in either YAML or JSON format.")
150
- end
151
- elsif type == :json
152
- configuration = LogJam.load_json_configuration(source)
153
- elsif type == :yaml
154
- configuration = LogJam.load_yaml_configuration(source)
155
- end
156
- configuration
157
- end
158
-
159
- # This method attempts to load a configuration for the LogJam library from
160
- # a file. The configuration is expected to be in YAML format.
161
- #
162
- # ==== Parameters
163
- # source:: An IO object from which the configuration will be read.
164
- def self.load_yaml_configuration(source)
165
- begin
166
- YAML.load(source)
167
- rescue => error
168
- raise LogJamError.new("Error loading LogJam configuration from YAML "\
169
- "source.\nCause: #{error}", error)
170
- end
171
- end
172
-
173
- # This method attempts to load a configuration for the LogJam library from
174
- # a file. The configuration is expected to be in JSON format.
175
- #
176
- # ==== Parameters
177
- # source:: An IO object from which the configuration will be read.
178
- def self.load_json_configuration(source)
179
- begin
180
- JSON.parse(source.read)
181
- rescue => error
182
- raise LogJamError.new("Error loading LogJam configuration from JSON "\
183
- "source.\nCause: #{error}", error)
184
- end
185
- end
186
-
187
- # This method processes a logger configuration and generates the appropriate
188
- # set of loggers and internal objects from it.
189
- #
190
- # ==== Parameters
191
- # configuration:: The configuration to be processed. If this is nil or empty
192
- # then a single default logger is generated that writes to the standard
193
- # output stream.
194
- def self.process_configuration(configuration)
195
- if !configuration.nil? && !configuration.empty?
196
- key = (configuration.include?(:loggers) ? :loggers : "loggers")
197
- if configuration.include?(key)
198
- loggers = configuration[key]
199
- if loggers.kind_of?(Array)
200
- configuration[key].each do |definition|
201
- LogJam.create_logger(definition)
202
- end
203
- elsif loggers.kind_of?(Hash)
204
- LogJam.create_logger(loggers)
205
- else
206
- raise LogJamError.new("The loggers configuration entry is in "\
207
- "an unrecognised format. Must be either "\
208
- "a Hash or an Array.")
209
- end
210
- end
211
- end
212
-
213
- # Set up any aliases that have been specified.
214
- if !@@logjam_loggers.empty? && !configuration.nil? && !configuration.empty?
215
- key = (configuration.include?(:loggers) ? :aliases : "aliases")
216
- if configuration.include?(key)
217
- configuration[key].each do |name, equivalent|
218
- @@logjam_loggers[name] = LogJam.get_logger(equivalent)
219
- @@logjam_modules[name] = LogJam.get_module(equivalent)
220
- end
221
- end
222
- end
223
-
224
- # Create a default logger if one hasn't been specified.
225
- if @@logjam_loggers[nil].nil?
226
- LogJam.create_logger({LOGGER_FILE => "STDOUT"})
227
- end
228
- end
229
-
230
- # This method is used to create an anonymous module under a given name (if it
231
- # doesn't already exist) and return it to the caller.
232
- #
233
- # ==== Parameters
234
- # name:: The name to create the module under.
235
- def self.create_module(name)
236
- if !@@logjam_modules.include?(name)
237
- # Create the anonymous module and add methods to it.
238
- @@logjam_modules[name] = Module.new
239
- @@logjam_modules[name].send(:define_method, :log) do
240
- LogJam.get_logger(name)
241
- end
242
- @@logjam_modules[name].send(:define_method, :log=) do |logger|
243
- LogJam.get_logger(name).logger = logger
244
- end
245
- end
246
- @@logjam_modules[name]
247
- end
248
-
249
- # This method extends a specified class with a named module.
250
- #
251
- # ==== Parameters
252
- # target:: The class that is to be extended.
253
- # name:: The name of the module to extend the class with.
254
- def self.extend_class(target, name)
255
- target.extend(LogJam.get_module(name))
256
- end
257
-
258
- # This method attempts to guess the format that configuration details will be
259
- # in given a file name. Guessing is done by looking at the file's extension.
260
- # Files ending in '.yaml' or '.yml' are considered YAML. Files ending '.json'
261
- # are considered JSON. The method returns nil if the path passed in has
262
- # neither of these extensions.
263
- #
264
- # ==== Parameters
265
- # path:: The path and name of the file to make the guess from.
266
- def self.guess_format(path)
267
- type = nil
268
- if path.nil? && path.include?(".")
269
- offset = path.length - path.reverse.index(".")
270
- extension = path[offset, path.length - offset].downcase
271
- case extension
272
- when 'yaml', 'yml'
273
- type = :yaml
274
-
275
- when 'json'
276
- type = :json
277
- end
278
- end
279
- type
280
- end
281
-
282
- # This method creates a logger from a given definition. A definition should
283
- # be a Hash containing the values that are used to configure the Logger with.
284
- #
285
- # ==== Parameters
286
- # definition:: A Hash containing the configuration details for the logger.
287
- def self.create_logger(definition)
288
- # Fetch the configuration values.
289
- name = LogJam.get_value(definition, LOGGER_NAME)
290
- path = LogJam.get_value(definition, LOGGER_FILE)
291
- rotation = LogJam.get_value(definition, LOGGER_ROTATION)
292
- max_size = LogJam.get_value(definition, LOGGER_MAX_SIZE)
293
- level = LogJam.get_value(definition, LOGGER_LEVEL)
294
- default = LogJam.get_value(definition, LOGGER_DEFAULT)
295
-
296
- device = nil
297
- if ["STDOUT", "STDERR"].include?(path)
298
- device = (path == "STDOUT" ? STDOUT : STDERR)
299
- else
300
- device = path
301
- end
302
-
303
- if rotation.kind_of?(String) && /^\s*\d+\s*$/ =~ rotation
304
- rotation = rotation.to_i
305
- rotation = 0 if rotation < 0
306
- end
307
-
308
- if !max_size.nil? && max_size.kind_of?(String)
309
- max_size = max_size.to_i
310
- end
311
- max_size = 1048576 if !max_size.nil? && max_size < 1024
312
-
313
- if !level.nil?
314
- case level.downcase
315
- when 'info'
316
- level = Logger::INFO
317
-
318
- when 'warn'
319
- level = Logger::WARN
320
-
321
- when 'error'
322
- level = Logger::ERROR
323
-
324
- when 'fatal'
325
- level = Logger::FATAL
326
-
327
- when 'unknown'
328
- level = Logger::UNKNOWN
329
-
330
- else
331
- level = Logger::DEBUG
332
- end
333
- else
334
- level = Logger::DEBUG
335
- end
336
-
337
- if default != true
338
- if default.kind_of?(String)
339
- default = ["true", "yes", "on", "1"].include?(default.downcase)
340
- else
341
- default = false
342
- end
343
- end
344
-
345
- # Create the actual logger and associated module.
346
- logger = LogJamLogger.new(device, rotation, max_size)
347
- logger.level = level
348
- logger.name = name
349
- logger.progname = name
350
- @@logjam_loggers[name] = logger
351
- logger_module = LogJam.create_module(name)
352
- if default
353
- @@logjam_loggers[nil] = logger
354
- @@logjam_modules[nil] = logger_module
355
- end
356
- logger
357
- end
358
-
359
- # This method attempts to fetch a value from a Hash. The key passed to the
360
- # method should be a symbol and this will be checked for first. If this is
361
- # not found then a check is made for the string equivalent. The first of
362
- # these that is present in the Hash generates the value returned. If neither
363
- # is present in the Hash then nil is returned.
364
- #
365
- # ==== Parameters
366
- # source:: The Hash that will be checked for the value.
367
- # key:: A symbol that will be checked as the key for the value.
368
- def self.get_value(source, key)
369
- if source.include?(key)
370
- source[key]
371
- elsif source.include?(key.to_s)
372
- source[key.to_s]
373
- else
374
- nil
375
- end
376
- end
377
-
378
- # This module level method is used to check for the existence of a
379
- # configuration file under one or a standard set of names. This method is
380
- # only used whenever the configure method is called and either passed nil
381
- # or no parameter.
382
- def self.find_default_file
383
- file_name = nil
384
- DEFAULT_FILE_NAMES.each do |name|
385
- file_name = name if File.exists?(name) && File.readable?(name)
386
- break if !file_name.nil?
387
- end
388
- file_name
389
- end
390
- end
@@ -1,202 +0,0 @@
1
- #! /usr/bin/env ruby
2
- #
3
- # Copyright (c), 2012 Peter Wood
4
- # See the license.txt for details of the licensing of the code in this file.
5
-
6
- module LogJam
7
- # This class represents a specialization of the Ruby Logger class. The class
8
- # retains a Ruby Logger instance within itself and delegates all standard
9
- # logger calls to this instance. This allows for changes to the underlying
10
- # logger without changing the containing one, thus bypassing people caching
11
- # an instance.
12
- class LogJamLogger < Logger
13
- # Constructor for the LogJamLogger class. All parameters are passed
14
- # straight through to create a standard Ruby Logger instance except
15
- # when the first parameter is a Logger instance. In this case the
16
- # Logger passed in is used rather than creating a new one.
17
- #
18
- # ==== Parameters
19
- # logdev:: The log device to be used by the logger. This should
20
- # either be a String containing a file path/name or an IO
21
- # object that the logging details will be written to.
22
- # shift_age:: The maximum number of old log files to retain or a String
23
- # containing the rotation frequency for the log.
24
- # shift_size:: The maximum size that the loggin output will be allowed
25
- # to grow to before rotation occurs.
26
- def initialize(logdev, shift_age=0, shift_size=1048576)
27
- if logdev.kind_of?(Logger)
28
- @log = logdev
29
- else
30
- @log = Logger.new(logdev, shift_age, shift_size)
31
- end
32
- @name = nil
33
- end
34
-
35
- # Attribute accessor/mutator declaration.
36
- attr_accessor :name
37
-
38
- # Overload of the property fetcher provided by the contained Logger
39
- # instance.
40
- def formatter
41
- @log.formatter
42
- end
43
-
44
- # Overload of the property updater provided by the contained Logger
45
- # instance.
46
- def formatter=(formatter)
47
- @log.formatter = formatter
48
- end
49
-
50
- # Overload of the property fetcher provided by the contained Logger
51
- # instance.
52
- def level
53
- @log.level
54
- end
55
-
56
- # Overload of the property updater provided by the contained Logger
57
- # instance.
58
- def level=(level)
59
- @log.level = level
60
- end
61
-
62
- # Overload of the property fetcher provided by the contained Logger
63
- # instance.
64
- def progname
65
- @log.progname
66
- end
67
-
68
- # Overload of the property updater provided by the contained Logger
69
- # instance.
70
- def progname=(name)
71
- @log.progname = name
72
- end
73
-
74
- # Overload of the property fetcher provided by the contained Logger
75
- # instance.
76
- def sev_threshold
77
- @log.sev_threshold
78
- end
79
-
80
- # Overload of the property updater provided by the contained Logger
81
- # instance.
82
- def sev_threshold=(threshold)
83
- @log.sev_threshold = threshold
84
- end
85
-
86
- # Overload of the corresponding method on the Logger class to pass the
87
- # call straight through to the contained logger.
88
- def <<(message)
89
- @log << message
90
- end
91
-
92
- # Overload of the corresponding method on the Logger class to pass the
93
- # call straight through to the contained logger.
94
- def add(severity, message=nil, program=nil, &block)
95
- @log.add(severity, message, program, &block)
96
- end
97
-
98
- # Overload of the corresponding method on the Logger class to pass the
99
- # call straight through to the contained logger.
100
- def close
101
- @log.close
102
- end
103
-
104
- # Overload of the corresponding method on the Logger class to pass the
105
- # call straight through to the contained logger.
106
- def datetime_format
107
- @log.datetime_format
108
- end
109
-
110
- # Overload of the corresponding method on the Logger class to pass the
111
- # call straight through to the contained logger.
112
- def datetime_format=(format)
113
- @log.datetime_format = format
114
- end
115
-
116
- # Overload of the corresponding method on the Logger class to pass the
117
- # call straight through to the contained logger.
118
- def debug(program=nil, &block)
119
- @log.debug(program, &block)
120
- end
121
-
122
- # Overload of the corresponding method on the Logger class to pass the
123
- # call straight through to the contained logger.
124
- def debug?
125
- @log.debug?
126
- end
127
-
128
- # Overload of the corresponding method on the Logger class to pass the
129
- # call straight through to the contained logger.
130
- def error(program=nil, &block)
131
- @log.error(program, &block)
132
- end
133
-
134
- # Overload of the corresponding method on the Logger class to pass the
135
- # call straight through to the contained logger.
136
- def error?
137
- @log.error?
138
- end
139
-
140
- # Overload of the corresponding method on the Logger class to pass the
141
- # call straight through to the contained logger.
142
- def fatal(program=nil, &block)
143
- @log.fatal(program, &block)
144
- end
145
-
146
- # Overload of the corresponding method on the Logger class to pass the
147
- # call straight through to the contained logger.
148
- def fatal?
149
- @log.fatal?
150
- end
151
-
152
- # Overload of the corresponding method on the Logger class to pass the
153
- # call straight through to the contained logger.
154
- def info(program=nil?, &block)
155
- @log.info(program, &block)
156
- end
157
-
158
- # Overload of the corresponding method on the Logger class to pass the
159
- # call straight through to the contained logger.
160
- def info?
161
- @log.info?
162
- end
163
-
164
- # Overload of the corresponding method on the Logger class to pass the
165
- # call straight through to the contained logger.
166
- def unknown(program=nil, &block)
167
- @log.unknown(program, &block)
168
- end
169
-
170
- # Overload of the corresponding method on the Logger class to pass the
171
- # call straight through to the contained logger.
172
- def warn(program=nil, &block)
173
- @log.warn(program, &block)
174
- end
175
-
176
- # Overload of the corresponding method on the Logger class to pass the
177
- # call straight through to the contained logger.
178
- def warn?
179
- @log.warn?
180
- end
181
-
182
- # This method fetches the standard Ruby Logger instance contained within
183
- # a LogJamLogger object.
184
- def logger
185
- @log
186
- end
187
-
188
- # This method updates the logger instance contained within a LogJamLogger
189
- # object.
190
- #
191
- # ==== Parameters
192
- # logger:: The object to set as the contained logger. This should be an
193
- # instance of the standard Ruby Logger class or something
194
- # compatible with this.
195
- def logger=(logger)
196
- @log = logger
197
- end
198
-
199
- # Aliases
200
- alias :log :add
201
- end
202
- end