logging 1.8.2 → 2.0.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.
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
-