Pass feedback to the user. Log levels are modeled after syslog’s, and it is expected that that will be the most common log destination. Supports multiple destinations, one of which is a remote server.
# File lib/puppet/util/log.rb, line 71 def Log.autoflush=(v) @destinations.each do |type, dest| dest.autoflush = v if dest.respond_to?(:autoflush=) end end
Reset log to basics. Basically just flushes and closes files and undefs other objects.
# File lib/puppet/util/log.rb, line 49 def Log.close(destination) if @destinations.include?(destination) @destinations[destination].flush if @destinations[destination].respond_to?(:flush) @destinations[destination].close if @destinations[destination].respond_to?(:close) @destinations.delete(destination) end end
# File lib/puppet/util/log.rb, line 57 def self.close_all destinations.keys.each { |dest| close(dest) } raise Puppet::DevError.new("Log.close_all failed to close #{@destinations.keys.inspect}") if !@destinations.empty? end
Create a new log message. The primary role of this method is to avoid creating log messages below the loglevel.
# File lib/puppet/util/log.rb, line 79 def Log.create(hash) raise Puppet::DevError, "Logs require a level" unless hash.include?(:level) raise Puppet::DevError, "Invalid log level #{hash[:level]}" unless @levels.index(hash[:level]) @levels.index(hash[:level]) >= @loglevel ? Puppet::Util::Log.new(hash) : nil end
# File lib/puppet/util/log.rb, line 85 def Log.destinations @destinations end
Yield each valid level in turn
# File lib/puppet/util/log.rb, line 90 def Log.eachlevel @levels.each { |level| yield level } end
Flush any log destinations that support such operations.
# File lib/puppet/util/log.rb, line 65 def Log.flush @destinations.each { |type, dest| dest.flush if dest.respond_to?(:flush) } end
# File lib/puppet/util/log.rb, line 165 def Log.flushqueue return unless @destinations.size >= 1 @queued.each do |msg| Log.newmessage(msg) end @queued.clear end
Flush the logging queue. If there are no destinations available,
adds in a console logger before flushing the queue.
This is mainly intended to be used as a last-resort attempt
to ensure that logging messages are not thrown away before the program is about to exit--most likely in a horrific error scenario.
@return nil
# File lib/puppet/util/log.rb, line 180 def Log.force_flushqueue() if (@destinations.empty? and !(@queued.empty?)) newdestination(:console) end flushqueue end
Return the current log level.
# File lib/puppet/util/log.rb, line 95 def Log.level @levels[@loglevel] end
Set the current log level.
# File lib/puppet/util/log.rb, line 100 def Log.level=(level) level = level.intern unless level.is_a?(Symbol) raise Puppet::DevError, "Invalid loglevel #{level}" unless @levels.include?(level) @loglevel = @levels.index(level) end
# File lib/puppet/util/log.rb, line 108 def Log.levels @levels.dup end
# File lib/puppet/util/log.rb, line 226 def initialize(args) self.level = args[:level] self.message = args[:message] self.source = args[:source] || "Puppet" @time = Time.now if tags = args[:tags] tags.each { |t| self.tag(t) } end [:file, :line].each do |attr| next unless value = args[attr] send(attr.to_s + "=", value) end Log.newmessage(self) end
Create a new log destination.
# File lib/puppet/util/log.rb, line 113 def Log.newdestination(dest) # Each destination can only occur once. if @destinations.find { |name, obj| obj.name == dest } return end name, type = @desttypes.find do |name, klass| klass.match?(dest) end if type.respond_to?(:suitable?) and not type.suitable?(dest) return end raise Puppet::DevError, "Unknown destination type #{dest}" unless type begin if type.instance_method(:initialize).arity == 1 @destinations[dest] = type.new(dest) else @destinations[dest] = type.new end flushqueue @destinations[dest] rescue => detail Puppet.log_exception(detail) # If this was our only destination, then add the console back in. newdestination(:console) if @destinations.empty? and (dest != :console and dest != "console") end end
Create a new destination type.
# File lib/puppet/util/log.rb, line 18 def self.newdesttype(name, options = {}, &block) dest = genclass( name, :parent => Puppet::Util::Log::Destination, :prefix => "Dest", :block => block, :hash => @desttypes, :attributes => options ) dest.match(dest.name) dest end
Route the actual message. FIXME There are lots of things this method should do, like caching and a bit more. It’s worth noting that there’s a potential for a loop here, if the machine somehow gets the destination set as itself.
# File lib/puppet/util/log.rb, line 149 def Log.newmessage(msg) return if @levels.index(msg.level) < @loglevel queuemessage(msg) if @destinations.length == 0 @destinations.each do |name, dest| threadlock(dest) do dest.handle(msg) end end end
# File lib/puppet/util/log.rb, line 161 def Log.queuemessage(msg) @queued.push(msg) end
Reopen all of our logs.
# File lib/puppet/util/log.rb, line 192 def Log.reopen Puppet.notice "Reopening log files" types = @destinations.keys @destinations.each { |type, dest| dest.close if dest.respond_to?(:close) } @destinations.clear # We need to make sure we always end up with some kind of destination begin types.each { |type| Log.newdestination(type) } rescue => detail if @destinations.empty? Log.setup_default Puppet.err detail.to_s end end end
# File lib/puppet/util/log.rb, line 187 def Log.sendlevel?(level) @levels.index(level) >= @loglevel end
# File lib/puppet/util/log.rb, line 212 def self.setup_default Log.newdestination( (Puppet.features.syslog? ? :syslog : (Puppet.features.eventlog? ? :eventlog : Puppet[:puppetdlog]))) end
Is the passed level a valid log level?
# File lib/puppet/util/log.rb, line 219 def self.validlevel?(level) @levels.include?(level) end
# File lib/puppet/util/log.rb, line 250 def level=(level) raise ArgumentError, "Puppet::Util::Log requires a log level" unless level raise ArgumentError, "Puppet::Util::Log requires a symbol or string" unless level.respond_to? "to_sym" @level = level.to_sym raise ArgumentError, "Invalid log level #{@level}" unless self.class.validlevel?(@level) # Tag myself with my log level tag(level) end
# File lib/puppet/util/log.rb, line 245 def message=(msg) raise ArgumentError, "Puppet::Util::Log requires a message" unless msg @message = msg.to_s end
If they pass a source in to us, we make sure it is a string, and we retrieve any tags we can.
# File lib/puppet/util/log.rb, line 262 def source=(source) if source.respond_to?(:source_descriptors) descriptors = source.source_descriptors @source = descriptors[:path] descriptors[:tags].each { |t| tag(t) } [:file, :line].each do |param| next unless descriptors[param] send(param.to_s + "=", descriptors[param]) end else @source = source.to_s end end
# File lib/puppet/util/log.rb, line 278 def to_report "#{time} #{source} (#{level}): #{to_s}" end
# File lib/puppet/util/log.rb, line 282 def to_s message end