logging 1.8.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +3 -3
  3. data/History.txt +20 -0
  4. data/README.md +159 -0
  5. data/Rakefile +9 -5
  6. data/examples/appenders.rb +0 -4
  7. data/examples/layouts.rb +1 -8
  8. data/examples/names.rb +4 -4
  9. data/lib/logging.rb +24 -76
  10. data/lib/logging/appender.rb +71 -16
  11. data/lib/logging/appenders.rb +0 -2
  12. data/lib/logging/appenders/buffering.rb +32 -16
  13. data/lib/logging/appenders/file.rb +2 -2
  14. data/lib/logging/appenders/io.rb +1 -1
  15. data/lib/logging/appenders/rolling_file.rb +228 -165
  16. data/lib/logging/appenders/string_io.rb +1 -1
  17. data/lib/logging/appenders/syslog.rb +4 -4
  18. data/lib/logging/color_scheme.rb +20 -3
  19. data/lib/logging/diagnostic_context.rb +142 -17
  20. data/lib/logging/filter.rb +18 -0
  21. data/lib/logging/filters.rb +4 -0
  22. data/lib/logging/filters/level.rb +29 -0
  23. data/lib/logging/layout.rb +2 -2
  24. data/lib/logging/layouts/parseable.rb +5 -2
  25. data/lib/logging/layouts/pattern.rb +309 -168
  26. data/lib/logging/log_event.rb +5 -5
  27. data/lib/logging/logger.rb +55 -68
  28. data/lib/logging/repository.rb +24 -39
  29. data/lib/logging/root_logger.rb +1 -1
  30. data/lib/logging/utils.rb +4 -65
  31. data/lib/logging/version.rb +8 -0
  32. data/lib/rspec/logging_helper.rb +3 -3
  33. data/logging.gemspec +46 -0
  34. data/test/appenders/test_buffered_io.rb +29 -0
  35. data/test/appenders/test_file.rb +2 -2
  36. data/test/appenders/test_rolling_file.rb +62 -1
  37. data/test/layouts/test_color_pattern.rb +1 -1
  38. data/test/layouts/test_json.rb +3 -0
  39. data/test/layouts/test_pattern.rb +6 -2
  40. data/test/layouts/test_yaml.rb +4 -1
  41. data/test/test_appender.rb +56 -0
  42. data/test/test_filter.rb +33 -0
  43. data/test/test_layout.rb +4 -8
  44. data/test/test_log_event.rb +3 -3
  45. data/test/test_logger.rb +81 -57
  46. data/test/test_logging.rb +0 -59
  47. data/test/test_mapped_diagnostic_context.rb +49 -1
  48. data/test/test_nested_diagnostic_context.rb +16 -1
  49. data/test/test_repository.rb +24 -32
  50. data/test/test_utils.rb +14 -50
  51. metadata +35 -53
  52. data/README.rdoc +0 -143
  53. data/data/bad_logging_1.rb +0 -13
  54. data/data/bad_logging_2.rb +0 -21
  55. data/data/logging.rb +0 -42
  56. data/data/logging.yaml +0 -63
  57. data/data/simple_logging.rb +0 -13
  58. data/examples/consolidation.rb +0 -83
  59. data/lib/logging/appenders/email.rb +0 -178
  60. data/lib/logging/appenders/growl.rb +0 -200
  61. data/lib/logging/config/configurator.rb +0 -187
  62. data/lib/logging/config/yaml_configurator.rb +0 -190
  63. data/lib/logging/stats.rb +0 -277
  64. data/test/appenders/test_email.rb +0 -170
  65. data/test/appenders/test_growl.rb +0 -138
  66. data/test/config/test_configurator.rb +0 -69
  67. data/test/config/test_yaml_configurator.rb +0 -39
  68. data/test/test_consolidate.rb +0 -45
  69. data/test/test_stats.rb +0 -273
  70. data/version.txt +0 -1
@@ -1,200 +0,0 @@
1
-
2
- module Logging::Appenders
3
-
4
- # Accessor / Factory for the Growl appender.
5
- #
6
- def self.growl( *args )
7
- return ::Logging::Appenders::Growl if args.empty?
8
- ::Logging::Appenders::Growl.new(*args)
9
- end
10
-
11
- # This class provides an Appender that can send notifications to the Growl
12
- # notification system on Mac OS X.
13
- #
14
- # +growlnotify+ must be installed somewhere in the path in order for the
15
- # appender to function properly.
16
- #
17
- class Growl < ::Logging::Appender
18
-
19
- # :stopdoc:
20
- ColoredRegexp = %r/\e\[([34][0-7]|[0-9])m/
21
- # :startdoc:
22
-
23
- # call-seq:
24
- # Growl.new( name, opts = {} )
25
- #
26
- # Create an appender that will log messages to the Growl framework on a
27
- # Mac OS X machine.
28
- #
29
- def initialize( name, opts = {} )
30
- super
31
-
32
- @growl = "growlnotify -w -n \"#{@name}\" -t \"%s\" -m \"%s\" -p %d &"
33
-
34
- @coalesce = opts.getopt(:coalesce, false)
35
- @title_sep = opts.getopt(:separator)
36
-
37
- # provides a mapping from the default Logging levels
38
- # to the Growl notification levels
39
- @map = [-2, -1, 0, 1, 2]
40
-
41
- map = opts.getopt(:map)
42
- self.map = map unless map.nil?
43
- setup_coalescing if @coalesce
44
-
45
- # make sure the growlnotify command can be called
46
- unless system('growlnotify -v >> /dev/null 2>&1')
47
- self.level = :off
48
- ::Logging.log_internal {'growl notifications have been disabled'}
49
- end
50
- end
51
-
52
- # call-seq:
53
- # map = { logging_levels => growl_levels }
54
- #
55
- # Configure the mapping from the Logging levels to the Growl
56
- # notification levels. This is needed in order to log events at the
57
- # proper Growl level.
58
- #
59
- # Without any configuration, the following mapping will be used:
60
- #
61
- # :debug => -2
62
- # :info => -1
63
- # :warn => 0
64
- # :error => 1
65
- # :fatal => 2
66
- #
67
- def map=( levels )
68
- map = []
69
- levels.keys.each do |lvl|
70
- num = ::Logging.level_num(lvl)
71
- map[num] = growl_level_num(levels[lvl])
72
- end
73
- @map = map
74
- end
75
-
76
-
77
- private
78
-
79
- # call-seq:
80
- # write( event )
81
- #
82
- # Write the given _event_ to the growl notification facility. The log
83
- # event will be processed through the Layout associated with this
84
- # appender. The message will be logged at the level specified by the
85
- # event.
86
- #
87
- def write( event )
88
- title = ''
89
- priority = 0
90
- message = if event.instance_of?(::Logging::LogEvent)
91
- priority = @map[event.level]
92
- @layout.format(event)
93
- else
94
- event.to_s
95
- end
96
- return if message.empty?
97
-
98
- message = message.gsub(ColoredRegexp, '')
99
- if @title_sep
100
- title, message = message.split(@title_sep)
101
- title, message = '', title if message.nil?
102
- end
103
-
104
- growl(title.strip, message.strip, priority)
105
- self
106
- end
107
-
108
- # call-seq:
109
- # growl_level_num( level ) => integer
110
- #
111
- # Takes the given _level_ as a string or integer and returns the
112
- # corresponding Growl notification level number.
113
- #
114
- def growl_level_num( level )
115
- level = Integer(level)
116
- if level < -2 or level > 2
117
- raise ArgumentError, "level '#{level}' is not in range -2..2"
118
- end
119
- level
120
- end
121
-
122
- # call-seq:
123
- # growl( title, message, priority )
124
- #
125
- # Send the _message_ to the growl notifier using the given _title_ and
126
- # _priority_.
127
- #
128
- def growl( title, message, priority )
129
- message.tr!("`", "'")
130
- if @coalesce then coalesce(title, message, priority)
131
- else call_growl(title, message, priority) end
132
- end
133
-
134
- # call-seq:
135
- # coalesce( title, message, priority )
136
- #
137
- # Attempt to coalesce the given _message_ with any that might be pending
138
- # in the queue to send to the growl notifier. Messages are coalesced
139
- # with any in the queue that have the same _title_ and _priority_.
140
- #
141
- # There can be only one message in the queue, so if the _title_ and/or
142
- # _priority_ don't match, the message in the queue is sent immediately
143
- # to the growl notifier, and the current _message_ is queued.
144
- #
145
- def coalesce( *msg )
146
- @c_mutex.synchronize do
147
- if @c_queue.empty?
148
- @c_queue << msg
149
- @c_thread.run
150
-
151
- else
152
- qmsg = @c_queue.last
153
- if qmsg.first != msg.first or qmsg.last != msg.last
154
- @c_queue << msg
155
- else
156
- qmsg[1] << "\n" << msg[1]
157
- end
158
- end
159
- end
160
- end
161
-
162
- # call-seq:
163
- # setup_coalescing
164
- #
165
- # Setup the appender to handle coalescing of messages before sending
166
- # them to the growl notifier. This requires the creation of a thread and
167
- # mutex for passing messages from the appender thread to the growl
168
- # notifier thread.
169
- #
170
- def setup_coalescing
171
- @c_mutex = Mutex.new
172
- @c_queue = []
173
-
174
- @c_thread = Thread.new do
175
- loop do
176
- Thread.stop if @c_queue.empty?
177
- sleep 1
178
- @c_mutex.synchronize {
179
- call_growl(*@c_queue.shift) until @c_queue.empty?
180
- }
181
- end # loop
182
- end # Thread.new
183
- end
184
-
185
- # call-seq:
186
- # call_growl( title, message, priority )
187
- #
188
- # Call the growlnotify application with the given parameters. If the
189
- # system call fails, the growl appender will be disabled.
190
- #
191
- def call_growl( *args )
192
- unless system(@growl % args)
193
- self.level = :off
194
- ::Logging.log_internal {'growl notifications have been disabled'}
195
- end
196
- end
197
-
198
- end # Growl
199
- end # Logging::Appenders
200
-
@@ -1,187 +0,0 @@
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
- # Configurator.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.initialized?
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
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
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
-
@@ -1,190 +0,0 @@
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
-