diff --git a/lib/vagrant/resource_logger.rb b/lib/vagrant/resource_logger.rb new file mode 100644 index 000000000..62fc24870 --- /dev/null +++ b/lib/vagrant/resource_logger.rb @@ -0,0 +1,51 @@ +module Vagrant + # Represents a logger for a specific resource within Vagrant. Each + # logger should be initialized and set to represent a single + # resource. Each logged message will then appear in the following + # format: + # + # [resource] message + # + # This class is thread safe. The backing class which actually does + # all the logging IO is protected. + class ResourceLogger + @@singleton_logger = nil + + # The resource which this logger represents. + attr_reader :resource + + # The environment that this logger is part of + attr_reader :env + + # The backing logger which actually handles the IO. This logger + # should be a subclass of the standard library Logger, in general. + # IMPORTANT: This logger must be thread-safe. + attr_reader :logger + + class << self + def singleton_logger(env=nil) + if env && env.config.loaded? + @@singleton_logger ||= Util::PlainLogger.new(env.config.vagrant.log_output) + else + Util::PlainLogger.new(nil) + end + end + + def reset_singleton_logger! + @@singleton_logger = nil + end + end + + def initialize(resource, env) + @resource = resource + @env = env + @logger = self.class.singleton_logger(env) + end + + # TODO: The other logging methods. + + def info(message) + logger.info("[#{resource}] #{message}") + end + end +end diff --git a/lib/vagrant/util/plain_logger.rb b/lib/vagrant/util/plain_logger.rb new file mode 100644 index 000000000..5d0a6c52b --- /dev/null +++ b/lib/vagrant/util/plain_logger.rb @@ -0,0 +1,12 @@ +module Vagrant + module Util + # Subclass of the standard library logger which has no format on + # its own. The message sent to the logger is outputted as-is. + class PlainLogger < ::Logger + def format_message(level, time, progname, msg) + # We do no formatting, its up to the user + msg + end + end + end +end diff --git a/test/vagrant/resource_logger_test.rb b/test/vagrant/resource_logger_test.rb new file mode 100644 index 000000000..62aa0a44f --- /dev/null +++ b/test/vagrant/resource_logger_test.rb @@ -0,0 +1,82 @@ +require File.join(File.dirname(__FILE__), '..', 'test_helper') + +class ResourceLoggerTest < Test::Unit::TestCase + setup do + @klass = Vagrant::ResourceLogger + end + + context "singleton logger" do + setup do + @klass.reset_singleton_logger! + + @result = mock("result") + end + + should "return a nil plain logger if no environment is given" do + Vagrant::Util::PlainLogger.expects(:new).with(nil).returns(@result) + assert_equal @result, @klass.singleton_logger + end + + should "return a nil plain logger if the config is not loaded" do + env = mock_environment + env.config.stubs(:loaded?).returns(false) + + Vagrant::Util::PlainLogger.expects(:new).with(nil).returns(@result) + assert_equal @result, @klass.singleton_logger(env) + end + + should "return a logger with the specified output if environment is ready" do + output = mock("output") + env = mock_environment + env.config.vagrant.log_output = output + + Vagrant::Util::PlainLogger.expects(:new).with(output).returns(@result) + assert_equal @result, @klass.singleton_logger(env) + end + + should "only load the logger once" do + output = mock("output") + env = mock_environment + env.config.vagrant.log_output = output + + Vagrant::Util::PlainLogger.expects(:new).with(output).returns(@result) + assert_equal @result, @klass.singleton_logger(env) + assert_equal @result, @klass.singleton_logger(env) + assert_equal @result, @klass.singleton_logger(env) + end + end + + context "initialization" do + should "setup the logger and attributes" do + env = mock_environment + resource = mock("resource") + result = mock("result") + + @klass.expects(:singleton_logger).with(env).returns(result) + instance = @klass.new(resource, env) + assert_equal resource, instance.resource + assert_equal env, instance.env + assert_equal result, instance.logger + end + end + + context "with an instance" do + setup do + @resource = "foo" + @env = mock_environment + @logger = mock("logger") + + @klass.stubs(:singleton_logger).returns(@logger) + @instance = @klass.new(@resource, @env) + end + + context "logging methods" do + should "log with the proper format" do + message = "bar" + @logger.expects(:info).with("[#{@resource}] #{message}").once + + @instance.info(message) + end + end + end +end diff --git a/test/vagrant/util/plain_logger_test.rb b/test/vagrant/util/plain_logger_test.rb new file mode 100644 index 000000000..5a9cc5346 --- /dev/null +++ b/test/vagrant/util/plain_logger_test.rb @@ -0,0 +1,17 @@ +require File.join(File.dirname(__FILE__), '..', '..', 'test_helper') + +class PlainLoggerUtilTest < Test::Unit::TestCase + setup do + @klass = Vagrant::Util::PlainLogger + @instance = @klass.new(nil) + end + + should "inherit from the standard logger" do + assert @instance.is_a?(::Logger) + end + + should "not attempt to format the message in any way" do + msg = "foo bar baz" + assert_equal msg, @instance.format_message("1", "2", "3", msg) + end +end