logging 2.1.0 → 2.2.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.
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