sgeorgi-logging 1.4.2

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