ottobar-logging 0.9.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/History.txt +158 -0
  2. data/README.rdoc +102 -0
  3. data/Rakefile +41 -0
  4. data/data/bad_logging_1.rb +13 -0
  5. data/data/bad_logging_2.rb +21 -0
  6. data/data/logging.rb +42 -0
  7. data/data/logging.yaml +63 -0
  8. data/data/simple_logging.rb +13 -0
  9. data/lib/logging.rb +408 -0
  10. data/lib/logging/appender.rb +303 -0
  11. data/lib/logging/appenders/buffering.rb +167 -0
  12. data/lib/logging/appenders/console.rb +62 -0
  13. data/lib/logging/appenders/email.rb +75 -0
  14. data/lib/logging/appenders/file.rb +54 -0
  15. data/lib/logging/appenders/growl.rb +197 -0
  16. data/lib/logging/appenders/io.rb +69 -0
  17. data/lib/logging/appenders/rolling_file.rb +291 -0
  18. data/lib/logging/appenders/syslog.rb +201 -0
  19. data/lib/logging/config/configurator.rb +190 -0
  20. data/lib/logging/config/yaml_configurator.rb +195 -0
  21. data/lib/logging/layout.rb +107 -0
  22. data/lib/logging/layouts/basic.rb +34 -0
  23. data/lib/logging/layouts/pattern.rb +296 -0
  24. data/lib/logging/log_event.rb +49 -0
  25. data/lib/logging/logger.rb +491 -0
  26. data/lib/logging/repository.rb +172 -0
  27. data/lib/logging/root_logger.rb +61 -0
  28. data/lib/logging/stats.rb +278 -0
  29. data/lib/logging/utils.rb +130 -0
  30. data/test/appenders/test_buffered_io.rb +183 -0
  31. data/test/appenders/test_console.rb +66 -0
  32. data/test/appenders/test_email.rb +171 -0
  33. data/test/appenders/test_file.rb +93 -0
  34. data/test/appenders/test_growl.rb +128 -0
  35. data/test/appenders/test_io.rb +142 -0
  36. data/test/appenders/test_rolling_file.rb +207 -0
  37. data/test/appenders/test_syslog.rb +191 -0
  38. data/test/benchmark.rb +87 -0
  39. data/test/config/test_configurator.rb +70 -0
  40. data/test/config/test_yaml_configurator.rb +40 -0
  41. data/test/layouts/test_basic.rb +43 -0
  42. data/test/layouts/test_pattern.rb +177 -0
  43. data/test/setup.rb +69 -0
  44. data/test/test_appender.rb +166 -0
  45. data/test/test_layout.rb +107 -0
  46. data/test/test_log_event.rb +80 -0
  47. data/test/test_logger.rb +734 -0
  48. data/test/test_logging.rb +267 -0
  49. data/test/test_repository.rb +126 -0
  50. data/test/test_root_logger.rb +81 -0
  51. data/test/test_stats.rb +274 -0
  52. data/test/test_utils.rb +114 -0
  53. metadata +152 -0
@@ -0,0 +1,190 @@
1
+
2
+ module Logging::Config
3
+
4
+ # The Configurator class is used to configure the Logging framework
5
+ # using information found in a block of Ruby code. This block is evaluated
6
+ # in the context of the configurator's DSL.
7
+ #
8
+ class Configurator
9
+
10
+ class Error < StandardError; end # :nodoc:
11
+
12
+ # call-seq:
13
+ # Configuraotr.process( &block )
14
+ #
15
+ def self.process( &block )
16
+ new.load(&block)
17
+ end
18
+
19
+ # call-seq:
20
+ # load { block }
21
+ #
22
+ # Loads the configuration from the _block_ and configures the Logging
23
+ # gem.
24
+ #
25
+ def load( &block )
26
+ raise Error, "missing configuration block" unless block
27
+
28
+ dsl = TopLevelDSL.new
29
+ dsl.__instance_eval(&block)
30
+
31
+ pre_config dsl.__pre_config
32
+ ::Logging::Logger[:root] # ensures the log levels are defined
33
+ appenders dsl.__appenders
34
+ loggers dsl.__loggers
35
+ end
36
+
37
+ # call-seq:
38
+ # pre_config( config )
39
+ #
40
+ # Configures the logging levels, object format style, and root logging
41
+ # level.
42
+ #
43
+ def pre_config( config )
44
+ if config.nil?
45
+ ::Logging.init unless ::Logging.const_defined? 'MAX_LEVEL_LENGTH'
46
+ return
47
+ end
48
+
49
+ # define levels
50
+ levels = config[:levels]
51
+ ::Logging.init(levels) unless levels.nil?
52
+
53
+ # format as
54
+ format = config[:format_as]
55
+ ::Logging.format_as(format) unless format.nil?
56
+
57
+ # backtrace
58
+ value = config[:backtrace]
59
+ ::Logging.backtrace(value) unless value.nil?
60
+ end
61
+
62
+ # call-seq:
63
+ # appenders( ary )
64
+ #
65
+ # Given an array of Appender configurations, this method will iterate
66
+ # over each and create the Appender(s).
67
+ #
68
+ def appenders( ary )
69
+ ary.each {|name, config| appender(name, config)}
70
+ end
71
+
72
+ # call-seq:
73
+ # loggers( ary )
74
+ #
75
+ # Given an array of Logger configurations, this method will iterate over
76
+ # each and create the Logger(s).
77
+ #
78
+ def loggers( ary )
79
+ ary.each do |name, config|
80
+ l = Logging::Logger[name]
81
+ l.level = config[:level] if config[:level]
82
+ l.additive = config[:additive] if l.respond_to? :additive=
83
+ l.trace = config[:trace]
84
+ l.appenders = Array(config[:appenders]).
85
+ map {|name| ::Logging::Appender[name]}
86
+ end
87
+ end
88
+
89
+ # call-seq:
90
+ # appender( name, config )
91
+ #
92
+ # Creates a new Appender based on the given _config_ options (a hash).
93
+ # The type of Appender created is determined by the 'type' option in the
94
+ # config. The remaining config options are passed to the Appender
95
+ # initializer.
96
+ #
97
+ # The config options can also contain a 'layout' option. This should be
98
+ # another set of options used to create a Layout for this Appender.
99
+ #
100
+ def appender( name, config )
101
+ type = config.delete(:type)
102
+ raise Error, "appender type not given for #{name.inspect}" if type.nil?
103
+
104
+ config[:layout] = layout(config[:layout]) if config.has_key? :layout
105
+
106
+ clazz = ::Logging::Appenders.const_get type
107
+ clazz.new(name, config)
108
+ rescue NameError => err
109
+ raise Error, "unknown appender class Logging::Appenders::#{type}"
110
+ end
111
+
112
+ # call-seq:
113
+ # layout( config )
114
+ #
115
+ # Creates a new Layout based on the given _config_ options (a hash).
116
+ # The type of Layout created is determined by the 'type' option in the
117
+ # config. The remaining config options are passed to the Layout
118
+ # initializer.
119
+ #
120
+ def layout( config )
121
+ return ::Logging::Layouts::Basic.new if config.nil?
122
+
123
+ type = config.delete(:type)
124
+ raise Error, 'layout type not given' if type.nil?
125
+
126
+ clazz = ::Logging::Layouts.const_get type
127
+ clazz.new config
128
+ rescue NameError => err
129
+ raise Error, "unknown layout class Logging::Layouts::#{type}"
130
+ end
131
+
132
+ class DSL
133
+ alias :__instance_eval :instance_eval
134
+
135
+ instance_methods.each do |m|
136
+ undef_method m unless m[%r/^__/]
137
+ end
138
+
139
+ def self.process( &block )
140
+ dsl = new
141
+ dsl.__instance_eval(&block)
142
+ dsl.__hash
143
+ end
144
+
145
+ def __hash
146
+ @hash ||= Hash.new
147
+ end
148
+
149
+ def method_missing( method, *args, &block )
150
+ args << DSL.process(&block) if block
151
+
152
+ key = method.to_sym
153
+ value = (1 == args.length ? args.first : args)
154
+ __store(key, value)
155
+ end
156
+
157
+ def __store( key, value )
158
+ __hash[key] = value
159
+ end
160
+ end
161
+
162
+ class TopLevelDSL < DSL
163
+ undef_method :method_missing
164
+
165
+ def initialize
166
+ @loggers = []
167
+ @appenders = []
168
+ end
169
+
170
+ def pre_config( &block )
171
+ __store(:preconfig, DSL.process(&block))
172
+ end
173
+
174
+ def logger( name, &block )
175
+ @loggers << [name, DSL.process(&block)]
176
+ end
177
+
178
+ def appender( name, &block )
179
+ @appenders << [name, DSL.process(&block)]
180
+ end
181
+
182
+ def __pre_config() __hash[:preconfig]; end
183
+ def __loggers() @loggers; end
184
+ def __appenders() @appenders; end
185
+ end
186
+
187
+ end # class Configurator
188
+ end # module Logging::Config
189
+
190
+ # EOF
@@ -0,0 +1,195 @@
1
+
2
+ require 'yaml'
3
+
4
+ module Logging
5
+ module Config
6
+
7
+ # The YamlConfigurator class is used to configure the Logging framework
8
+ # using information found in a YAML file.
9
+ #
10
+ class YamlConfigurator
11
+
12
+ class Error < StandardError; end # :nodoc:
13
+
14
+ class << self
15
+
16
+ # call-seq:
17
+ # YamlConfigurator.load( file, key = 'logging_config' )
18
+ #
19
+ # Load the given YAML _file_ and use it to configure the Logging
20
+ # framework. The file can be either a filename, and open File, or an
21
+ # IO object. If it is the latter two, the File / IO object will not be
22
+ # closed by this method.
23
+ #
24
+ # The configuration will be loaded from the given _key_ in the YAML
25
+ # stream.
26
+ #
27
+ def load( file, key = 'logging_config' )
28
+ io, close = nil, false
29
+ case file
30
+ when String
31
+ io = File.open(file, 'r')
32
+ close = true
33
+ when IO
34
+ io = file
35
+ else
36
+ raise Error, 'expecting a filename or a File'
37
+ end
38
+
39
+ begin
40
+ new(io, key).load
41
+ ensure
42
+ io.close if close
43
+ end
44
+ nil
45
+ end
46
+ end # class << self
47
+
48
+ # call-seq:
49
+ # YamlConfigurator.new( io, key )
50
+ #
51
+ # Creates a new YAML configurator that will load the Logging
52
+ # configuration from the given _io_ stream. The configuration will be
53
+ # loaded from the given _key_ in the YAML stream.
54
+ #
55
+ def initialize( io, key )
56
+ YAML.load_documents(io) do |doc|
57
+ @config = doc[key]
58
+ break if @config.instance_of?(Hash)
59
+ end
60
+
61
+ unless @config.instance_of?(Hash)
62
+ raise Error, "Key '#{key}' not defined in YAML configuration"
63
+ end
64
+ end
65
+
66
+ # call-seq:
67
+ # load
68
+ #
69
+ # Loads the Logging configuration from the data loaded from the YAML
70
+ # file.
71
+ #
72
+ def load
73
+ pre_config @config['pre_config']
74
+ ::Logging::Logger[:root] # ensures the log levels are defined
75
+ appenders @config['appenders']
76
+ loggers @config['loggers']
77
+ end
78
+
79
+ # call-seq:
80
+ # pre_config( config )
81
+ #
82
+ # Configures the logging levels, object format style, and root logging
83
+ # level.
84
+ #
85
+ def pre_config( config )
86
+ # if no pre_config section was given, just create an empty hash
87
+ # we do this to ensure that some logging levels are always defined
88
+ config ||= Hash.new
89
+
90
+ # define levels
91
+ levels = config['define_levels']
92
+ ::Logging.init(levels) unless levels.nil?
93
+
94
+ # format as
95
+ format = config['format_as']
96
+ ::Logging.format_as(format) unless format.nil?
97
+
98
+ # backtrace
99
+ value = config['backtrace']
100
+ ::Logging.backtrace(value) unless value.nil?
101
+
102
+ # grab the root logger and set the logging level
103
+ root = ::Logging::Logger.root
104
+ if config.has_key?('root')
105
+ root.level = config['root']['level']
106
+ end
107
+ end
108
+
109
+ # call-seq:
110
+ # appenders( ary )
111
+ #
112
+ # Given an array of Appender configurations, this method will iterate
113
+ # over each and create the Appender(s).
114
+ #
115
+ def appenders( ary )
116
+ return if ary.nil?
117
+
118
+ ary.each {|h| appender(h)}
119
+ end
120
+
121
+ # call-seq:
122
+ # loggers( ary )
123
+ #
124
+ # Given an array of Logger configurations, this method will iterate over
125
+ # each and create the Logger(s).
126
+ #
127
+ def loggers( ary )
128
+ return if ary.nil?
129
+
130
+ ary.each do |config|
131
+ name = config['name']
132
+ raise Error, 'Logger name not given' if name.nil?
133
+
134
+ l = Logging::Logger.new name
135
+ l.level = config['level'] if config.has_key?('level')
136
+ l.additive = config['additive'] if l.respond_to? :additive=
137
+ l.trace = config['trace'] if l.respond_to? :trace=
138
+
139
+ if config.has_key?('appenders')
140
+ l.appenders = config['appenders'].map {|n| ::Logging::Appender[n]}
141
+ end
142
+ end
143
+ end
144
+
145
+ # call-seq:
146
+ # appender( config )
147
+ #
148
+ # Creates a new Appender based on the given _config_ options (a hash).
149
+ # The type of Appender created is determined by the 'type' option in the
150
+ # config. The remaining config options are passed to the Appender
151
+ # initializer.
152
+ #
153
+ # The config options can also contain a 'layout' option. This should be
154
+ # another set of options used to create a Layout for this Appender.
155
+ #
156
+ def appender( config )
157
+ return if config.nil?
158
+ config = config.dup
159
+
160
+ type = config.delete('type')
161
+ raise Error, 'Appender type not given' if type.nil?
162
+
163
+ name = config.delete('name')
164
+ raise Error, 'Appender name not given' if name.nil?
165
+
166
+ config['layout'] = layout(config.delete('layout'))
167
+
168
+ clazz = ::Logging::Appenders.const_get type
169
+ clazz.new(name, config)
170
+ end
171
+
172
+ # call-seq:
173
+ # layout( config )
174
+ #
175
+ # Creates a new Layout based on the given _config_ options (a hash).
176
+ # The type of Layout created is determined by the 'type' option in the
177
+ # config. The remaining config options are passed to the Layout
178
+ # initializer.
179
+ #
180
+ def layout( config )
181
+ return if config.nil?
182
+ config = config.dup
183
+
184
+ type = config.delete('type')
185
+ raise Error, 'Layout type not given' if type.nil?
186
+
187
+ clazz = ::Logging::Layouts.const_get type
188
+ clazz.new config
189
+ end
190
+
191
+ end # class YamlConfigurator
192
+ end # module Config
193
+ end # module Logging
194
+
195
+ # EOF
@@ -0,0 +1,107 @@
1
+
2
+ require 'yaml'
3
+
4
+ module Logging
5
+
6
+ # The +Layout+ class provides methods for formatting log events into a
7
+ # string representation. Layouts are used by Appenders to format log
8
+ # events before writing them to the logging destination.
9
+ #
10
+ # All other Layouts inherit from this class which provides stub methods.
11
+ # Each subclass should provide a +format+ method. A layout can be used by
12
+ # more than one +Appender+ so all the methods need to be thread safe.
13
+ #
14
+ class Layout
15
+
16
+ # call-seq:
17
+ # Layout.new( :format_as => :string )
18
+ #
19
+ # Creates a new layout that will format objecs as strings using the
20
+ # given <tt>:format_as</tt> style. This can be one of <tt>:string</tt>,
21
+ # <tt>:inspect</tt>, or <tt>:yaml</tt>. These formatting commands map to
22
+ # the following object methods:
23
+ #
24
+ # * :string => to_s
25
+ # * :inspect => inspect
26
+ # * :yaml => to_yaml
27
+ #
28
+ # If the format is not specified then the global object format is used
29
+ # (see Logging#format_as). If the global object format is not specified
30
+ # then <tt>:string</tt> is used.
31
+ #
32
+ def initialize( opts = {} )
33
+ default = ::Logging.const_defined?('OBJ_FORMAT') ?
34
+ ::Logging::OBJ_FORMAT : nil
35
+
36
+ f = opts.getopt(:format_as, default)
37
+ f = f.intern if f.instance_of? String
38
+
39
+ @obj_format = case f
40
+ when :inspect, :yaml; f
41
+ else :string end
42
+
43
+ b = opts.getopt(:backtrace, ::Logging.backtrace)
44
+ @backtrace = case b
45
+ when :on, 'on', true; true
46
+ when :off, 'off', false; false
47
+ else
48
+ raise ArgumentError, "backtrace must be true or false"
49
+ end
50
+ end
51
+
52
+ # call-seq:
53
+ # format( event )
54
+ #
55
+ # Returns a string representation of the given loggging _event_. It is
56
+ # up to subclasses to implement this method.
57
+ #
58
+ def format( event ) nil end
59
+
60
+ # call-seq:
61
+ # header
62
+ #
63
+ # Returns a header string to be used at the beginning of a logging
64
+ # appender.
65
+ #
66
+ def header( ) '' end
67
+
68
+ # call-seq:
69
+ # footer
70
+ #
71
+ # Returns a footer string to be used at the end of a logging appender.
72
+ #
73
+ def footer( ) '' end
74
+
75
+ # call-seq:
76
+ # format_obj( obj )
77
+ #
78
+ # Return a string representation of the given object. Depending upon
79
+ # the configuration of the logger system the format will be an +inspect+
80
+ # based represenation or a +yaml+ based representation.
81
+ #
82
+ def format_obj( obj )
83
+ case obj
84
+ when String; obj
85
+ when Exception
86
+ str = "<#{obj.class.name}> #{obj.message}"
87
+ if @backtrace && !obj.backtrace.nil?
88
+ str << "\n\t" << obj.backtrace.join("\n\t")
89
+ end
90
+ str
91
+ when nil; "<#{obj.class.name}> nil"
92
+ else
93
+ str = "<#{obj.class.name}> "
94
+ str << case @obj_format
95
+ when :inspect; obj.inspect
96
+ when :yaml; "\n#{obj.to_yaml}"
97
+ else obj.to_s end
98
+ str
99
+ end
100
+ end
101
+
102
+ end # class Layout
103
+ end # module Logging
104
+
105
+ Logging.require_all_libs_relative_to(__FILE__, 'layouts')
106
+
107
+ # EOF