Module: Loggability

Extended by:
LogHost
Includes:
Constants
Defined in:
lib/loggability.rb

Overview

A mixin that provides a top-level logging subsystem based on Logger.

Defined Under Namespace

Modules: Constants, LogClient, LogHost, SpecHelpers Classes: Formatter, LogDevice, Logger, Override

Constant Summary collapse

VERSION =

Package version constant

'0.18.2'
GLOBAL_KEY =

The key for the global logger (Loggability’s own logger)

:__global__
AGGREGATE_METHODS =

The methods that are delegated across all loggers

[ :level=, :output_to, :write_to, :format_with, :format_as, :formatter= ]
CONFIG_DEFAULTS =

Configuration defaults

{
	:__default__ => 'warn STDERR',
}.freeze
LOGSPEC_PATTERN =

Regexp for parsing logspec lines in the config

%r{
	^
		\s*
		(?<severity>(?i:debug|info|warn|error|fatal))
	    (?:
			\s+
			(?<target>(?:[\w\-/:\.\[\]]|\\[ ])+)
		)?
		(?: \s+\(
			(?<format>\w+)
		\) )?
		\s*
	$
}x

Constants included from Constants

Constants::LOG_LEVELS, Constants::LOG_LEVEL_NAMES

Class Attribute Summary collapse

Attributes included from LogHost

#default_logger, #log_host_key, #logger

Class Method Summary collapse

Instance Method Summary collapse

Methods included from LogHost

inherited

Class Attribute Details

.configObject

Returns the value of attribute config.



60
61
62
# File 'lib/loggability.rb', line 60

def config
  @config
end

.log_hostsObject (readonly)

Returns the value of attribute log_hosts.



55
56
57
# File 'lib/loggability.rb', line 55

def log_hosts
  @log_hosts
end

Class Method Details

.[](logclient) ⇒ Object

Return the Loggability::Logger for the loghost associated with logclient.



128
129
130
131
# File 'lib/loggability.rb', line 128

def self::[]( logclient )
	loghost = self.log_host_for( logclient )
	return loghost.logger
end

.aggregate(methodname, *args, &block) ⇒ Object

Call the method with the given methodname across the loggers of all loghosts with the given arg and/or block.



149
150
151
152
153
154
155
156
# File 'lib/loggability.rb', line 149

def self::aggregate( methodname, *args, &block )
	# self.log.debug "Aggregating a call to %p with %p to %d log hosts" %
	#	[ methodname, arg, Loggability.log_hosts.length ]
	Loggability.log_hosts.values.each do |loghost|
		# self.log.debug "  %p.logger.%s( %p )" % [ loghost, methodname, arg ]
		loghost.logger.send( methodname, *args, &block )
	end
end

.apply_config(logger, logspec) ⇒ Object

Configure the specified logger (or anything that ducktypes the same) with the configuration specified by logspec.



308
309
310
311
312
313
# File 'lib/loggability.rb', line 308

def self::apply_config( logger, logspec )
	level, format, target = self.parse_config_spec( logspec )
	logger.level = level if level
	logger.format_with( format ) if format
	logger.output_to( target ) if target
end

.configure(new_config = nil) ⇒ Object

Configurability API – configure logging.



343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
# File 'lib/loggability.rb', line 343

def self::configure( new_config=nil )
	if new_config
		self.config = new_config.dup.freeze
		confighash = new_config.to_hash

		# Set up all loggers with defaults first
		if defaultspec = confighash.delete( :__default__ ) || confighash.delete( '__default__' )
			self.apply_config( self, defaultspec )
		end

		# Then let individual configs override.
		confighash.each do |key, logspec|
			unless Loggability.log_host?( key )
				self.log.debug "  no such log host %p; skipping" % [ key ]
				next
			end

			# self.log.debug "  configuring logger for %p: %s" % [ key, logspec ]
			self.apply_config( Loggability[key], logspec )
		end
	else
		self.config = self.defaults.dup.freeze
	end
end

.for_logger(*hosts, &block) ⇒ Object Also known as: for_loggers, for_log_host, for_log_hosts

Aggregate method: override one or more settings for the duration of the block for only the given hosts. If no block is given returns a Loggability::Override object that will override the specified log hosts whenever its #call method is called.



254
255
256
257
258
259
260
261
262
# File 'lib/loggability.rb', line 254

def self::for_logger( *hosts, &block )
	override = Loggability::Override.for_logger( *hosts )

	if block
		return override.call( &block )
	else
		return override
	end
end

.format_with(formatter) ⇒ Object Also known as: format_as, formatter=

:method: format_with :call-seq:

format_with( formatter )
format_as( formatter )
formatter = formatter

Aggregate method: set all loggers to log with the given formatter. See Loggability::Logger#format_with for more info.



226
227
228
# File 'lib/loggability.rb', line 226

def self::format_with( formatter )
	self.aggregate( :format_with, formatter )
end

.formatted_with(formatter, &block) ⇒ Object

Aggregate method: set all loggers to log with the given formatter for the duration of the block, restoring the original formatters afterward. If no block is given, returns a Loggability::Override object that will override all formatters whenever its #call method is called.



239
240
241
242
243
244
245
246
247
# File 'lib/loggability.rb', line 239

def self::formatted_with( formatter, &block )
	override = Loggability::Override.formatted_with( formatter )

	if block
		return override.call( &block )
	else
		return override
	end
end

.level=(newlevel) ⇒ Object

:method: level= :call-seq:

level = newlevel

Aggregate method: set the log level on all loggers to newlevel. See Loggability::Logger#level= for more info.



166
167
168
# File 'lib/loggability.rb', line 166

def self::level=( newlevel )
	self.aggregate( :level=, newlevel )
end

.log_host?(object) ⇒ Boolean

Returns true if there is a log host associated with the given object.

Returns:

  • (Boolean)


121
122
123
124
# File 'lib/loggability.rb', line 121

def self::log_host?( object )
	key = self.log_host_key_for( object ) or return false
	return self.log_hosts.key?( key )
end

.log_host_for(object) ⇒ Object

Return the log host for object, if any. Raises an ArgumentError if the object doesn’t have an associated log host.



109
110
111
112
113
114
115
116
117
# File 'lib/loggability.rb', line 109

def self::log_host_for( object )
	key = self.log_host_key_for( object )
	key ||= GLOBAL_KEY

	loghost = self.log_hosts[ key ] or
		raise ArgumentError, "no log host set up for %p yet." % [ key ]

	return loghost
end

.log_host_key_for(object) ⇒ Object

Return the log host key for object, using its #log_host_key method if it has one, or returning it as a Symbol if it responds to #to_sym. Returns nil if no key could be derived.



100
101
102
103
104
# File 'lib/loggability.rb', line 100

def self::log_host_key_for( object )
	return object.log_host_key if object.respond_to?( :log_host_key )
	return object.to_sym if object.respond_to?( :to_sym )
	return nil
end

.Logger(device) ⇒ Object

Cast the given device to a Loggability::Logger, if possible, and return it. If it can’t be converted, raises a ArgumentError.



68
69
70
71
72
# File 'lib/loggability.rb', line 68

def self::Logger( device )
	return device if device.is_a?( Loggability::Logger )
	return Loggability::Logger.from_std_logger( device ) if device.is_a?( ::Logger )
	return Loggability::Logger.new( device )
end

.output_to(newdevice, *args) ⇒ Object Also known as: write_to

:method: output_to :call-seq:

output_to( destination )
write_to( destination )

Aggregate method: set all loggers to log to destination. See Loggability::Logger#output_to for more info.



194
195
196
# File 'lib/loggability.rb', line 194

def self::output_to( newdevice, *args )
	self.aggregate( :output_to, newdevice, *args )
end

.outputting_to(newdevice, &block) ⇒ Object

Aggregate method: set all loggers to log to destination for the duration of the block, restoring the original destination afterward. If no block is given, returns a Loggability::Override object that will log to destination whenever its #call method is called.



206
207
208
209
210
211
212
213
214
# File 'lib/loggability.rb', line 206

def self::outputting_to( newdevice, &block )
	override = Loggability::Override.outputting_to( newdevice )

	if block
		return override.call( &block )
	else
		return override
	end
end

.parse_config_spec(spec) ⇒ Object

Parse the specified spec into level,



317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
# File 'lib/loggability.rb', line 317

def self::parse_config_spec( spec )
	match = LOGSPEC_PATTERN.match( spec ) or
		raise ArgumentError, "Couldn't parse logspec: %p" % [ spec ]
	# self.log.debug "  parsed config spec %p -> %p" % [ spec, match ]
	severity, target, format = match.captures

	target = case target
		when 'STDOUT' then $stdout
		when 'STDERR' then $stderr
		when /:/ then Loggability::LogDevice.parse_device_spec( target )
		else
			target
		end

	return severity, format, target
end

.register_loghost(host) ⇒ Object

Register the specified host as a log host. It should already have been extended with LogHostMethods.



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/loggability.rb', line 77

def self::register_loghost( host )
	key = host.log_host_key
	if self.log_hosts.key?( key )
		# raise "Can't set a log host for nil" if key.nil?
		self.logger.warn "Replacing existing log host for %p (%p) with %p" %
			[ key, self.log_hosts[key], host ]
	end

	#self.logger.debug "Registering %p log host: %p" % [ key, host ] if self.logger
	self.log_hosts[ key ] = host
	if (( logspec = Loggability.config[key] ))
		self.apply_config( host.logger, logspec )
	elsif (( defaultspec = (Loggability.config[:__default__] || Loggability.config['__default__']) ))
		self.apply_config( host.logger, defaultspec )
	else
		self.apply_config( host.logger, CONFIG_DEFAULTS[:__default__] )
	end
end

.resetObject

Clear out all registered log hosts and reset the default logger. This is mostly intended for facilitating tests.



136
137
138
139
140
# File 'lib/loggability.rb', line 136

def self::reset
	self.log_hosts.clear
	self.logger = self.default_logger = Loggability::Logger.new
	Loggability.register_loghost( self )
end

.with_level(level, &block) ⇒ Object

Aggregate method: set the log level on all loggers to level for the duration of the block, restoring the original levels afterward. If no block is given, returns a Loggability::Override object that set the log level to level while its #call method is being called.



175
176
177
178
179
180
181
182
183
# File 'lib/loggability.rb', line 175

def self::with_level( level, &block )
	override = Loggability::Override.with_level( level )

	if block
		return override.call( &block )
	else
		return override
	end
end

Instance Method Details

#log_as(key) ⇒ Object

Register as a log host associated with the given key, add the methods from LogHost, and install a Loggability::Logger.



276
277
278
279
280
281
282
283
# File 'lib/loggability.rb', line 276

def log_as( key )
	extend( Loggability::LogHost )
	include( Loggability::LogClient::InstanceMethods ) if self.is_a?( Class )

	self.log_host_key = key.to_sym
	self.logger = self.default_logger = Loggability::Logger.new
	Loggability.register_loghost( self )
end

#log_to(loghost) ⇒ Object

Register as a log client that will log to to the given loghost, which can be either the key the host registered with, or the log host object itself. Log messages can be written to the loghost via the LogClient API, which is automatically included.



293
294
295
296
297
298
# File 'lib/loggability.rb', line 293

def log_to( loghost )
	extend( Loggability::LogClient )
	include( Loggability::LogClient::InstanceMethods ) if self.is_a?( Class )

	self.log_host_key = Loggability.log_host_key_for( loghost )
end