diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | chef-expander/lib/chef/expander/configuration.rb | 7 | ||||
-rw-r--r-- | chef-expander/lib/chef/expander/loggable.rb | 20 | ||||
-rw-r--r-- | chef-expander/lib/chef/expander/logger.rb | 135 | ||||
-rw-r--r-- | chef-expander/spec/spec_helper.rb | 1 | ||||
-rw-r--r-- | chef-expander/spec/unit/configuration_spec.rb | 10 |
6 files changed, 156 insertions, 18 deletions
diff --git a/.gitignore b/.gitignore index 6ff48eeb33..b3768a5db0 100644 --- a/.gitignore +++ b/.gitignore @@ -30,4 +30,5 @@ features/data/repo/checksums/ .rvmrc .bundle chef-expander/conf/chef-expander.rb +chef-expander/spec/fixtures/expander.log diff --git a/chef-expander/lib/chef/expander/configuration.rb b/chef-expander/lib/chef/expander/configuration.rb index 70afe3a11f..5dcf85e497 100644 --- a/chef-expander/lib/chef/expander/configuration.rb +++ b/chef-expander/lib/chef/expander/configuration.rb @@ -161,6 +161,13 @@ module Chef level end + configurable :log_location, STDOUT + + # override the setter for log_location to re-init the logger + def log_location=(location) + Loggable::LOGGER.init(location) unless location.nil? + end + def initialize reset! end diff --git a/chef-expander/lib/chef/expander/loggable.rb b/chef-expander/lib/chef/expander/loggable.rb index 5bfb941ecb..5dd534dab5 100644 --- a/chef-expander/lib/chef/expander/loggable.rb +++ b/chef-expander/lib/chef/expander/loggable.rb @@ -18,32 +18,16 @@ # limitations under the License. # +require 'chef/expander/logger' require 'mixlib/log' module Chef module Expander module Loggable - class Logger - include Mixlib::Log - - def init(*args) - @logger = nil - super - end - - [:debug,:info,:warn,:error, :fatal].each do |level| - class_eval(<<-LOG_METHOD, __FILE__, __LINE__) - def #{level}(message=nil, &block) - @logger.#{level}(message, &block) - end - LOG_METHOD - end - end # TODO: it's admittedly janky to set up the default logging this way. STDOUT.sync = true - LOGGER = Logger.new - LOGGER.init + LOGGER = Logger.new(STDOUT) LOGGER.level = :debug def log diff --git a/chef-expander/lib/chef/expander/logger.rb b/chef-expander/lib/chef/expander/logger.rb new file mode 100644 index 0000000000..234344e0cb --- /dev/null +++ b/chef-expander/lib/chef/expander/logger.rb @@ -0,0 +1,135 @@ +# +# Author:: Daniel DeLeo (<dan@opscode.com>) +# Copyright:: Copyright (c) 2011 Opscode, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require 'logger' + +module Chef + module Expander + + class InvalidLogDevice < ArgumentError + end + + class InvalidLogLevel < ArgumentError + end + + # Customized Logger class that dispenses with the unnecessary mutexing. + # As long as you write one line at a time, the OS will take care of keeping + # your output in order. Expander commonly runs as a cluster of worker + # processes so the mutexing wasn't actually helping us anyway. + # + # We don't use the program name field in the logger, so support for that + # has been removed. The log format is also hardcoded since we don't ever + # change the format. + class Logger < ::Logger + + LEVELS = { :debug=>DEBUG, :info=>INFO, :warn=>WARN, :error=>ERROR, :fatal=>FATAL} + LEVEL_INTEGERS = LEVELS.invert + LEVEL_TO_STR = Hash[LEVEL_INTEGERS.map {|i,sym| [i,sym.to_s.upcase]}] + + LOG_DEVICES = [] + + at_exit do + LOG_DEVICES.each {|io| io.close if io.respond_to?(:closed?) && !io.closed?} + end + + attr_reader :log_device + + # (re-)initialize the Logger with a new IO object or file to log to. + def init(log_device) + @log_device = initialize_log_device(log_device) + end + + def initialize(log_device) + @level = DEBUG + init(log_device) + end + + def level=(new_level) + @level = if new_level.kind_of?(Fixnum) && LEVEL_INTEGERS.key?(new_level) + new + elsif LEVELS.key?(new_level) + LEVELS[new_level] + else + raise InvalidLogLevel, "#{new_level} is not a valid log level. Valid log levels are [#{LEVEL_INTEGERS.keys.join(',')}] and [#{LEVELS.join(',')}]" + end + end + + def <<(msg) + @log_device.print(msg) + end + + def add(severity=UNKNOWN, message = nil, progname = nil, &block) + return true unless severity >= @level + + message ||= progname # level methods (e.g, #debug) pass explicit message as progname + + if message.nil? && block_given? + message = yield + end + + self << sprintf("[%s] %s: %s\n", Time.new.rfc2822(), LEVEL_TO_STR[severity], msg2str(message)) + true + end + + alias :log :add + + private + + def msg2str(msg) + case msg + when ::String + msg + when ::Exception + "#{ msg.message } (#{ msg.class })\n" << + (msg.backtrace || []).join("\n") + else + msg.inspect + end + end + + def logging_at_severity?(severity=nil) + end + + def initialize_log_device(dev) + unless dev.respond_to? :sync= + assert_valid_path!(dev) + dev = File.open(dev.to_str, "a") + LOG_DEVICES << dev + end + + dev.sync = true + dev + end + + def assert_valid_path!(path) + enclosing_directory = File.dirname(path) + unless File.directory?(enclosing_directory) + raise InvalidLogDevice, "You must create the enclosing directory #{enclosing_directory} before the log file #{path} can be created." + end + if File.exist?(path) + unless File.writable?(path) + raise InvalidLogDevice, "The log file you specified (#{path}) is not writable by user #{Process.euid}" + end + elsif !File.writable?(enclosing_directory) + raise InvalidLogDevice, "You specified a log file #{path} but user #{Process.euid} is not permitted to create files there." + end + end + + end + end +end
\ No newline at end of file diff --git a/chef-expander/spec/spec_helper.rb b/chef-expander/spec/spec_helper.rb index a17bf4f939..578143fe92 100644 --- a/chef-expander/spec/spec_helper.rb +++ b/chef-expander/spec/spec_helper.rb @@ -73,3 +73,4 @@ EXPLAIN exit(2) end +FIXTURE_PATH = File.expand_path('../fixtures', __FILE__) diff --git a/chef-expander/spec/unit/configuration_spec.rb b/chef-expander/spec/unit/configuration_spec.rb index fa3f9d9be4..6f396c4102 100644 --- a/chef-expander/spec/unit/configuration_spec.rb +++ b/chef-expander/spec/unit/configuration_spec.rb @@ -82,6 +82,16 @@ describe Expander::Configuration do @config.config_file.should == '/etc/chef/solr.rb' end + it "sets the log location to an IO object" do + @config.log_location = STDERR + @config.log.log_device.should == STDERR + end + + it "sets the log location to a File" do + @config.log_location = File.join(FIXTURE_PATH, 'expander.log') + @config.log.log_device.path.should == File.join(FIXTURE_PATH, 'expander.log') + end + it "generates an AMQP configuration hash suitable for passing to Bunny.new or AMQP.start" do @config.amqp_config.should == {:host => '0.0.0.0', :port => '5672', :user => 'chef', :pass => 'testing', :vhost => '/chef'} end |