logging 2.1.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e350554eb562c0d216fa262c015afb4c2a68b82e
4
- data.tar.gz: 22820d111096e8c44e7d0908e1cb7cca27d49009
3
+ metadata.gz: ee30a5922d46012d8fc4e14db5cc86ea7dce9c6a
4
+ data.tar.gz: 7183a4f01f0dd1000ab86d05c8b40e605dbb4b10
5
5
  SHA512:
6
- metadata.gz: d8167665ad0871c41f053154f7d36686afd08d15d151a3d8c759a20ab9d845060494ed580fe6c95eeddccea69c57a6d94d464f6f3c463ed126b61c8021d05ac9
7
- data.tar.gz: e741f1bea9ca11f52a06ca5b2873007430f26b02d92262222b2e64a86ae0de9635c2482b57e40c0b512d6a180486d665b9e36196a39d418311437a855e0d5a7c
6
+ metadata.gz: 377702172ae965d27c082acd60914e0f3420a0e0bdfc5d981ac3cfad7c8f3bf46095007511075b6a9db9225963911967d3d63989a3ee6dc42588269092796a72
7
+ data.tar.gz: 1a6f33f20259879ca8cc9adcbd9a3bfb14c44f03a15311711f11ff4bf98edfd9821000e8b9afcb5401080a693e391bb83e56bd0055e1eedcbba6ce7ba4a92f2b
@@ -6,9 +6,9 @@ install: "rake gem:install_dependencies"
6
6
  script: "rake"
7
7
 
8
8
  rvm:
9
- - 1.9.3
10
- - 2.0.0
11
- - 2.1.5
12
- - 2.2.1
13
- - 2.3.0
14
- - jruby-9.0.4.0
9
+ - 2.0.0-p648
10
+ - 2.1.10
11
+ - 2.2.6
12
+ - 2.3.3
13
+ - 2.4.0
14
+ - jruby-9.1.8.0
@@ -1,3 +1,18 @@
1
+ == 2.2.0 / 2017-03-09
2
+
3
+ Enhancements
4
+ - diagnostic context inheritance is now optional [PR #160]
5
+ - add support for setting a UTC offset [PR #157]
6
+ - setting a basepath for call tracing [PR #154]
7
+
8
+ Bug Fixes
9
+ - use thread-local variables for diagnostic contexts [PR #162]
10
+ - replace `Fixnum` with `Integer` [PR #161]
11
+ - fixed a race condition in the rolling file appender [PR #151]
12
+
13
+ Deprecations
14
+ - dropped Ruby 1.9 support
15
+
1
16
  == 2.1.0 / 2016-03-13
2
17
 
3
18
  Enhancements
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2007-2016 Tim Pease
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ 'Software'), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,12 +1,12 @@
1
1
  ## Logging
2
- by Tim Pease [![](https://secure.travis-ci.org/TwP/logging.png)](https://travis-ci.org/TwP/logging)
2
+ by Tim Pease [![](https://secure.travis-ci.org/TwP/logging.svg)](https://travis-ci.org/TwP/logging)
3
3
 
4
4
  * [Homepage](http://rubygems.org/gems/logging)
5
5
  * [Github Project](https://github.com/TwP/logging)
6
6
 
7
7
  ### Description
8
8
 
9
- Logging is a flexible logging library for use in Ruby programs based on the
9
+ **Logging** is a flexible logging library for use in Ruby programs based on the
10
10
  design of Java's log4j library. It features a hierarchical logging system,
11
11
  custom level names, multiple output destinations per log event, custom
12
12
  formatting, and more.
@@ -82,23 +82,23 @@ class SecondClass
82
82
  end
83
83
  ```
84
84
 
85
- There are many more examples in the [examples folder](https://github.com/TwP/logging/tree/master/examples)
86
- of the logging package. The recommended reading order is the following:
87
-
88
- * [simple.rb](https://github.com/TwP/logging/blob/master/examples/simple.rb)
89
- * [rspec_integration.rb](https://github.com/TwP/logging/blob/master/examples/rspec_integration.rb)
90
- * [loggers.rb](https://github.com/TwP/logging/blob/master/examples/loggers.rb)
91
- * [classes.rb](https://github.com/TwP/logging/blob/master/examples/classes.rb)
92
- * [hierarchies.rb](https://github.com/TwP/logging/blob/master/examples/hierarchies.rb)
93
- * [names.rb](https://github.com/TwP/logging/blob/master/examples/names.rb)
94
- * [lazy.rb](https://github.com/TwP/logging/blob/master/examples/lazy.rb)
95
- * [appenders.rb](https://github.com/TwP/logging/blob/master/examples/appenders.rb)
96
- * [layouts.rb](https://github.com/TwP/logging/blob/master/examples/layouts.rb)
97
- * [formatting.rb](https://github.com/TwP/logging/blob/master/examples/formatting.rb)
98
- * [colorization.rb](https://github.com/TwP/logging/blob/master/examples/colorization.rb)
99
- * [consolidation.rb](https://github.com/TwP/logging/blob/master/examples/consolidation.rb)
100
- * [fork.rb](https://github.com/TwP/logging/blob/master/examples/fork.rb)
101
- * [mdc.rb](https://github.com/TwP/logging/blob/master/examples/mdc.rb)
85
+ There are many more examples in the [examples folder](/examples) of the logging
86
+ package. The recommended reading order is the following:
87
+
88
+ * [simple.rb](/examples/simple.rb)
89
+ * [rspec_integration.rb](/examples/rspec_integration.rb)
90
+ * [loggers.rb](/examples/loggers.rb)
91
+ * [classes.rb](/examples/classes.rb)
92
+ * [hierarchies.rb](/examples/hierarchies.rb)
93
+ * [names.rb](/examples/names.rb)
94
+ * [lazy.rb](/examples/lazy.rb)
95
+ * [appenders.rb](/examples/appenders.rb)
96
+ * [layouts.rb](/examples/layouts.rb)
97
+ * [reusing_layouts.rb](/examples/reusing_layouts.rb)
98
+ * [formatting.rb](/examples/formatting.rb)
99
+ * [colorization.rb](/examples/colorization.rb)
100
+ * [fork.rb](/examples/fork.rb)
101
+ * [mdc.rb](/examples/mdc.rb)
102
102
 
103
103
  ### Extending
104
104
 
@@ -135,25 +135,4 @@ After this is done you can rake `rake -T` to see the available rake tasks.
135
135
 
136
136
  ### License
137
137
 
138
- The MIT License
139
-
140
- Copyright (c) 2015 Tim Pease
141
-
142
- Permission is hereby granted, free of charge, to any person obtaining
143
- a copy of this software and associated documentation files (the
144
- 'Software'), to deal in the Software without restriction, including
145
- without limitation the rights to use, copy, modify, merge, publish,
146
- distribute, sublicense, and/or sell copies of the Software, and to
147
- permit persons to whom the Software is furnished to do so, subject to
148
- the following conditions:
149
-
150
- The above copyright notice and this permission notice shall be
151
- included in all copies or substantial portions of the Software.
152
-
153
- THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
154
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
155
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
156
- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
157
- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
158
- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
159
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
138
+ The MIT License - see the [LICENSE](/LICENSE) file for the full text.
@@ -33,7 +33,7 @@
33
33
  log.level = :debug
34
34
 
35
35
  log.debug "a very nice little debug message"
36
- log.info "things are operating nominally"
36
+ log.info "things are operating normally"
37
37
  log.warn "this is your last warning"
38
38
  log.error StandardError.new("something went horribly wrong")
39
39
  log.fatal "I Die!"
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # It happens sometimes that it is very expensive to construct a logging
4
4
  # message; for example, if a large object structure has to be traversed
5
- # during executing of an `object.to_s` method. It would be convenient to
5
+ # during execution of an `object.to_s` method. It would be convenient to
6
6
  # delay creation of the message until the log event actually takes place.
7
7
  #
8
8
  # For example, with a logger configured only to show WARN messages and higher,
@@ -0,0 +1,51 @@
1
+ # :stopdoc:
2
+ #
3
+ # The formatting of log messages is controlled by the layout given to the
4
+ # appender. By default all appenders use the Basic layout. It's pretty
5
+ # basic. However, a more sophisticated Pattern layout can be used or one of
6
+ # the Parseable layouts -- JSON or YAML.
7
+ #
8
+ # The available layouts are:
9
+ #
10
+ # Logging.layouts.basic
11
+ # Logging.layouts.pattern
12
+ # Logging.layouts.json
13
+ # Logging.layouts.yaml
14
+ #
15
+ # After you configure a layout, you can reuse that layout among different
16
+ # appenders if you so choose. This enables you to have some the style of log
17
+ # output being sent to multiple destinations.
18
+ #
19
+ # We will store a Layout instance in a local variable, and then pass that
20
+ # instance to each appender.
21
+ #
22
+
23
+ require 'logging'
24
+
25
+ # create our pattern layout instance
26
+ layout = Logging.layouts.pattern \
27
+ :pattern => '[%d] %-5l %c: %m\n',
28
+ :date_pattern => '%Y-%m-%d %H:%M:%S'
29
+
30
+ # only show "info" or higher messages on STDOUT using our layout
31
+ Logging.appenders.stdout \
32
+ :level => :info,
33
+ :layout => layout
34
+
35
+ # send all log events to the development log (including debug) using our layout
36
+ Logging.appenders.rolling_file \
37
+ 'development.log',
38
+ :age => 'daily',
39
+ :layout => layout
40
+
41
+ log = Logging.logger['Foo::Bar']
42
+ log.add_appenders 'stdout', 'development.log'
43
+ log.level = :debug
44
+
45
+ log.debug "a very nice little debug message"
46
+ log.info "things are operating normally"
47
+ log.warn "this is your last warning"
48
+ log.error StandardError.new("something went horribly wrong")
49
+ log.fatal "I Die!"
50
+
51
+ # :startdoc:
@@ -95,9 +95,9 @@ module Logging
95
95
  layout = ::Logging::Layouts::Pattern.new(l_opts)
96
96
 
97
97
  a_opts = Hash.new
98
- a_opts[:size] = size if size.instance_of?(Fixnum)
98
+ a_opts[:size] = size if size.is_a?(Integer)
99
99
  a_opts[:age] = age if age.instance_of?(String)
100
- a_opts[:keep] = keep if keep.instance_of?(Fixnum)
100
+ a_opts[:keep] = keep if keep.is_a?(Integer)
101
101
  a_opts[:filename] = dev if dev.instance_of?(String)
102
102
  a_opts[:layout] = layout
103
103
  a_opts.merge! opts
@@ -311,6 +311,53 @@ module Logging
311
311
  end
312
312
  end
313
313
 
314
+ # Set the default UTC offset used when formatting time values sent to the
315
+ # appenders. If left unset, the default local time zone will be used for
316
+ # time values. This method accepts the `utc_offset` format supported by the
317
+ # `Time#localtime` method in Ruby.
318
+ #
319
+ # Passing "UTC" or `0` as the UTC offset will cause all times to be reported
320
+ # in the UTC timezone.
321
+ #
322
+ # Logging.utc_offset = "-07:00" # Mountain Standard Time in North America
323
+ # Logging.utc_offset = "+01:00" # Central European Time
324
+ # Logging.utc_offset = "UTC" # UTC
325
+ # Logging.utc_offset = 0 # UTC
326
+ #
327
+ def utc_offset=( value )
328
+ @utc_offset = case value
329
+ when nil; nil
330
+ when "UTC", "GMT", 0; 0
331
+ else
332
+ Time.now.localtime(value)
333
+ value
334
+ end
335
+ end
336
+
337
+ attr_reader :utc_offset
338
+
339
+ # Used to define a `basepath` that will be removed from filenames when
340
+ # reporting tracing information for log events. Normally you would set this
341
+ # to the root of your project:
342
+ #
343
+ # Logging.basepath = "/home/user/nifty_project"
344
+ #
345
+ # Or if you are in a Rails environment:
346
+ #
347
+ # Logging.basepath = Rails.root.to_s
348
+ #
349
+ # The basepath is expanded to a full path with trailing slashes removed.
350
+ # This setting will be cleared by a call to `Logging.reset`.
351
+ def basepath=( path )
352
+ if path.nil? || path.to_s.empty?
353
+ @basepath = nil
354
+ else
355
+ @basepath = File.expand_path(path)
356
+ end
357
+ end
358
+
359
+ attr_reader :basepath
360
+
314
361
  # Returns the library path for the module. If any arguments are given,
315
362
  # they will be joined to the end of the library path using
316
363
  # <tt>File.join</tt>.
@@ -405,7 +452,7 @@ module Logging
405
452
  # to false. It uses its own appender to send messages to stderr.
406
453
  #
407
454
  def show_configuration( io = STDOUT, logger = 'root', indent = 0 )
408
- logger = ::Logging::Logger[logger] unless ::Logging::Logger === logger
455
+ logger = ::Logging::Logger[logger] unless logger.is_a?(::Logging::Logger)
409
456
 
410
457
  io << logger._dump_configuration(indent)
411
458
 
@@ -466,8 +513,10 @@ module Logging
466
513
  LEVELS.clear
467
514
  LNAMES.clear
468
515
  remove_instance_variable :@backtrace if defined? @backtrace
516
+ remove_instance_variable :@basepath if defined? @basepath
469
517
  remove_const :MAX_LEVEL_LENGTH if const_defined? :MAX_LEVEL_LENGTH
470
518
  remove_const :OBJ_FORMAT if const_defined? :OBJ_FORMAT
519
+ self.utc_offset = nil
471
520
  self
472
521
  end
473
522
 
@@ -114,7 +114,7 @@ class Appender
114
114
  #
115
115
  # Set the level for this appender; log events below this level will be
116
116
  # ignored by this appender. The level can be either a +String+, a
117
- # +Symbol+, or a +Fixnum+. An +ArgumentError+ is raised if this is not
117
+ # +Symbol+, or an +Integer+. An +ArgumentError+ is raised if this is not
118
118
  # the case.
119
119
  #
120
120
  # There are two special levels -- "all" and "off". The former will
@@ -138,7 +138,7 @@ class Appender
138
138
  def level=( level )
139
139
  lvl = case level
140
140
  when String, Symbol; ::Logging::level_num(level)
141
- when Fixnum; level
141
+ when Integer; level
142
142
  when nil; 0
143
143
  else
144
144
  raise ArgumentError,
@@ -24,7 +24,7 @@ module Logging::Appenders
24
24
  name = self.class.name.split("::").last.downcase
25
25
  io = Object.const_get(name.upcase)
26
26
 
27
- opts = Hash === args.last ? args.pop : {}
27
+ opts = args.last.is_a?(Hash) ? args.pop : {}
28
28
  name = args.shift unless args.empty?
29
29
 
30
30
  opts[:encoding] = io.external_encoding if io.respond_to? :external_encoding
@@ -141,6 +141,15 @@ module Logging::Appenders
141
141
  @roller.copy_file
142
142
  end
143
143
 
144
+ # Returns the modification time of the copy file if one exists. Otherwise
145
+ # returns `nil`.
146
+ def copy_file_mtime
147
+ return nil unless ::File.exist?(copy_file)
148
+ ::File.mtime(copy_file)
149
+ rescue Errno::ENOENT
150
+ nil
151
+ end
152
+
144
153
  # Write the given _event_ to the log file. The log file will be rolled
145
154
  # if the maximum file size is exceeded or if the file is older than the
146
155
  # maximum age.
@@ -166,7 +175,8 @@ module Logging::Appenders
166
175
 
167
176
  # Returns +true+ if the log file needs to be rolled.
168
177
  def roll_required?
169
- return false if ::File.exist?(copy_file) && (Time.now - ::File.mtime(copy_file)) < 180
178
+ mtime = copy_file_mtime
179
+ return false if mtime && (Time.now - mtime) < 180
170
180
 
171
181
  # check if max size has been exceeded
172
182
  s = @size ? ::File.size(filename) > @size : false
@@ -40,7 +40,7 @@ module Logging
40
40
  # Store a color scheme by name.
41
41
  #
42
42
  def []=( name, value )
43
- raise ArgumentError, "Silly! That's not a ColorSchmeme!" unless ColorScheme === value
43
+ raise ArgumentError, "Silly! That's not a ColorSchmeme!" unless value.is_a?(ColorScheme)
44
44
  @color_schemes[name.to_s] = value
45
45
  end
46
46
 
@@ -110,7 +110,7 @@ module Logging
110
110
  # Returns nil or the Hash removed from the stack.
111
111
  #
112
112
  def pop
113
- return unless Thread.current[STACK_NAME]
113
+ return unless Thread.current.thread_variable_get(STACK_NAME)
114
114
  return unless stack.length > 1
115
115
  clear_context
116
116
  stack.pop
@@ -125,7 +125,7 @@ module Logging
125
125
  #
126
126
  def clear
127
127
  clear_context
128
- Thread.current[STACK_NAME] = nil
128
+ Thread.current.thread_variable_set(STACK_NAME, nil)
129
129
  self
130
130
  end
131
131
 
@@ -140,15 +140,14 @@ module Logging
140
140
  def inherit( obj )
141
141
  case obj
142
142
  when Hash
143
- Thread.current[STACK_NAME] = [obj.dup]
143
+ Thread.current.thread_variable_set(STACK_NAME, [obj.dup])
144
144
  when Thread
145
145
  return if Thread.current == obj
146
- DIAGNOSTIC_MUTEX.synchronize {
147
- if obj[STACK_NAME]
148
- hash = flatten(obj[STACK_NAME])
149
- Thread.current[STACK_NAME] = [hash]
146
+ DIAGNOSTIC_MUTEX.synchronize do
147
+ if hash = obj.thread_variable_get(STACK_NAME)
148
+ Thread.current.thread_variable_set(STACK_NAME, [flatten(hash)])
150
149
  end
151
- }
150
+ end
152
151
  end
153
152
 
154
153
  self
@@ -159,12 +158,18 @@ module Logging
159
158
  # application.
160
159
  #
161
160
  def context
162
- c = Thread.current[NAME]
163
- return c unless c.nil?
161
+ c = Thread.current.thread_variable_get(NAME)
164
162
 
165
- return Thread.current[NAME] = {} unless Thread.current[STACK_NAME]
163
+ if c.nil?
164
+ c = if Thread.current.thread_variable_get(STACK_NAME)
165
+ flatten(stack)
166
+ else
167
+ Hash.new
168
+ end
169
+ Thread.current.thread_variable_set(NAME, c)
170
+ end
166
171
 
167
- Thread.current[NAME] = flatten(stack)
172
+ return c
168
173
  end
169
174
 
170
175
  # Returns the stack of Hash objects that are storing the diagnostic
@@ -172,7 +177,12 @@ module Logging
172
177
  # one Hash.
173
178
  #
174
179
  def stack
175
- Thread.current[STACK_NAME] ||= [{}]
180
+ s = Thread.current.thread_variable_get(STACK_NAME)
181
+ if s.nil?
182
+ s = [{}]
183
+ Thread.current.thread_variable_set(STACK_NAME, s)
184
+ end
185
+ return s
176
186
  end
177
187
 
178
188
  # Returns the most current Hash from the stack of contexts.
@@ -184,7 +194,7 @@ module Logging
184
194
  # Remove the flattened context.
185
195
  #
186
196
  def clear_context
187
- Thread.current[NAME] = nil
197
+ Thread.current.thread_variable_set(NAME, nil)
188
198
  self
189
199
  end
190
200
 
@@ -199,7 +209,7 @@ module Logging
199
209
  # Raises an ArgumentError if hash is not a Hash.
200
210
  #
201
211
  def sanitize( hash, target = {} )
202
- unless Hash === hash
212
+ unless hash.is_a?(Hash)
203
213
  raise ArgumentError, "Expecting a Hash but received a #{hash.class.name}"
204
214
  end
205
215
 
@@ -320,7 +330,7 @@ module Logging
320
330
  # Returns the NestedDiagnosticContext.
321
331
  #
322
332
  def clear
323
- Thread.current[NAME] = nil
333
+ Thread.current.thread_variable_set(NAME, nil)
324
334
  self
325
335
  end
326
336
 
@@ -335,12 +345,12 @@ module Logging
335
345
  def inherit( obj )
336
346
  case obj
337
347
  when Array
338
- Thread.current[NAME] = obj.dup
348
+ Thread.current.thread_variable_set(NAME, obj.dup)
339
349
  when Thread
340
350
  return if Thread.current == obj
341
- DIAGNOSTIC_MUTEX.synchronize {
342
- Thread.current[NAME] = obj[NAME].dup if obj[NAME]
343
- }
351
+ DIAGNOSTIC_MUTEX.synchronize do
352
+ Thread.current.thread_variable_set(NAME, obj.thread_variable_get(NAME).dup) if obj.thread_variable_get(NAME)
353
+ end
344
354
  end
345
355
 
346
356
  self
@@ -351,7 +361,12 @@ module Logging
351
361
  # running in the application.
352
362
  #
353
363
  def context
354
- Thread.current[NAME] ||= Array.new
364
+ c = Thread.current.thread_variable_get(NAME)
365
+ if c.nil?
366
+ c = Array.new
367
+ Thread.current.thread_variable_set(NAME, c)
368
+ end
369
+ return c
355
370
  end
356
371
  end # NestedDiagnosticContext
357
372
 
@@ -381,13 +396,13 @@ module Logging
381
396
  #
382
397
  def self.clear_diagnostic_contexts( all = false )
383
398
  if all
384
- DIAGNOSTIC_MUTEX.synchronize {
385
- Thread.list.each { |thread|
386
- thread[MappedDiagnosticContext::NAME] = nil if thread[MappedDiagnosticContext::NAME]
387
- thread[NestedDiagnosticContext::NAME] = nil if thread[NestedDiagnosticContext::NAME]
388
- thread[MappedDiagnosticContext::STACK_NAME] = nil if thread[MappedDiagnosticContext::STACK_NAME]
389
- }
390
- }
399
+ DIAGNOSTIC_MUTEX.synchronize do
400
+ Thread.list.each do |t|
401
+ t.thread_variable_set(MappedDiagnosticContext::NAME, nil) if t.thread_variable?(MappedDiagnosticContext::NAME)
402
+ t.thread_variable_set(NestedDiagnosticContext::NAME, nil) if t.thread_variable?(NestedDiagnosticContext::NAME)
403
+ t.thread_variable_set(MappedDiagnosticContext::STACK_NAME, nil) if t.thread_variable?(MappedDiagnosticContext::STACK_NAME)
404
+ end
405
+ end
391
406
  else
392
407
  MappedDiagnosticContext.clear
393
408
  NestedDiagnosticContext.clear
@@ -397,61 +412,71 @@ module Logging
397
412
  end
398
413
 
399
414
  DIAGNOSTIC_MUTEX = Mutex.new
400
-
401
- end # module Logging
402
-
415
+ end
403
416
 
404
417
  # :stopdoc:
405
- class Thread
406
- class << self
407
-
408
- %w[new start fork].each do |m|
409
- class_eval <<-__, __FILE__, __LINE__
410
- alias_method :_orig_#{m}, :#{m}
411
- private :_orig_#{m}
412
- def #{m}( *a, &b )
413
- create_with_logging_context(:_orig_#{m}, *a ,&b)
414
- end
415
- __
416
- end
418
+ Logging::INHERIT_CONTEXT =
419
+ if ENV.key?("LOGGING_INHERIT_CONTEXT")
420
+ case ENV["LOGGING_INHERIT_CONTEXT"].downcase
421
+ when 'false', 'no', '0'; false
422
+ when false, nil; false
423
+ else true end
424
+ else
425
+ true
426
+ end
417
427
 
418
- private
428
+ if Logging::INHERIT_CONTEXT
429
+ class Thread
430
+ class << self
419
431
 
420
- # In order for the diagnostic contexts to behave properly we need to
421
- # inherit state from the parent thread. The only way I have found to do
422
- # this in Ruby is to override `new` and capture the contexts from the
423
- # parent Thread at the time the child Thread is created. The code below does
424
- # just this. If there is a more idiomatic way of accomplishing this in Ruby,
425
- # please let me know!
426
- #
427
- # Also, great care is taken in this code to ensure that a reference to the
428
- # parent thread does not exist in the binding associated with the block
429
- # being executed in the child thread. The same is true for the parent
430
- # thread's mdc and ndc. If any of those references end up in the binding,
431
- # then they cannot be garbage collected until the child thread exits.
432
- #
433
- def create_with_logging_context( m, *a, &b )
434
- mdc, ndc = nil
435
-
436
- if Thread.current[Logging::MappedDiagnosticContext::STACK_NAME]
437
- mdc = Logging::MappedDiagnosticContext.context.dup
432
+ %w[new start fork].each do |m|
433
+ class_eval <<-__, __FILE__, __LINE__
434
+ alias_method :_orig_#{m}, :#{m}
435
+ private :_orig_#{m}
436
+ def #{m}( *a, &b )
437
+ create_with_logging_context(:_orig_#{m}, *a ,&b)
438
+ end
439
+ __
438
440
  end
439
441
 
440
- if Thread.current[Logging::NestedDiagnosticContext::NAME]
441
- ndc = Logging::NestedDiagnosticContext.context.dup
442
+ private
443
+
444
+ # In order for the diagnostic contexts to behave properly we need to
445
+ # inherit state from the parent thread. The only way I have found to do
446
+ # this in Ruby is to override `new` and capture the contexts from the
447
+ # parent Thread at the time the child Thread is created. The code below does
448
+ # just this. If there is a more idiomatic way of accomplishing this in Ruby,
449
+ # please let me know!
450
+ #
451
+ # Also, great care is taken in this code to ensure that a reference to the
452
+ # parent thread does not exist in the binding associated with the block
453
+ # being executed in the child thread. The same is true for the parent
454
+ # thread's mdc and ndc. If any of those references end up in the binding,
455
+ # then they cannot be garbage collected until the child thread exits.
456
+ #
457
+ def create_with_logging_context( m, *a, &b )
458
+ mdc, ndc = nil
459
+
460
+ if Thread.current.thread_variable_get(Logging::MappedDiagnosticContext::STACK_NAME)
461
+ mdc = Logging::MappedDiagnosticContext.context.dup
462
+ end
463
+
464
+ if Thread.current.thread_variable_get(Logging::NestedDiagnosticContext::NAME)
465
+ ndc = Logging::NestedDiagnosticContext.context.dup
466
+ end
467
+
468
+ # This calls the actual `Thread#new` method to create the Thread instance.
469
+ # If your memory profiling tool says this method is leaking memory, then
470
+ # you are leaking Thread instances somewhere.
471
+ self.send(m, *a) { |*args|
472
+ Logging::MappedDiagnosticContext.inherit(mdc)
473
+ Logging::NestedDiagnosticContext.inherit(ndc)
474
+ b.call(*args)
475
+ }
442
476
  end
443
477
 
444
- # This calls the actual `Thread#new` method to create the Thread instance.
445
- # If your memory profiling tool says this method is leaking memory, then
446
- # you are leaking Thread instances somewhere.
447
- self.send(m, *a) { |*args|
448
- Logging::MappedDiagnosticContext.inherit(mdc)
449
- Logging::NestedDiagnosticContext.inherit(ndc)
450
- b.call(*args)
451
- }
452
478
  end
453
-
454
479
  end
455
- end # Thread
480
+ end
456
481
  # :startdoc:
457
482