summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJay Mundrawala <jdmundrawala@gmail.com>2015-05-13 13:49:00 -0500
committerJay Mundrawala <jdmundrawala@gmail.com>2015-05-13 13:49:00 -0500
commitd85201ece21e3b534033072b5a5fb630aeb19339 (patch)
tree42a816ca484a5f397bfefbe72dfca6f2ca9b895a
parent0a48720d350ae8e537bf11309a005b949bb348de (diff)
parente57f5c1be36f97b7eca886a99d86fd207240bc34 (diff)
downloadchef-d85201ece21e3b534033072b5a5fb630aeb19339.tar.gz
Merge pull request #3345 from chef/jdm/winevt
Added a logger for Windows Event Log
-rw-r--r--ext/win32-eventlog/chef-log.man30
-rw-r--r--lib/chef/event_loggers/windows_eventlog.rb12
-rw-r--r--lib/chef/log.rb1
-rw-r--r--lib/chef/log/syslog.rb10
-rw-r--r--lib/chef/log/winevt.rb99
-rw-r--r--lib/chef/mixin/unformatter.rb32
-rw-r--r--lib/chef/win32/eventlog.rb31
-rw-r--r--spec/unit/log/winevt_spec.rb55
-rw-r--r--spec/unit/mixin/unformatter_spec.rb61
9 files changed, 313 insertions, 18 deletions
diff --git a/ext/win32-eventlog/chef-log.man b/ext/win32-eventlog/chef-log.man
index 4b4a022d7f..10c28e739f 100644
--- a/ext/win32-eventlog/chef-log.man
+++ b/ext/win32-eventlog/chef-log.man
@@ -24,3 +24,33 @@ Exception type: %3%n
Exception message: %4%n
Exception backtrace: %5%n
.
+
+MessageId=10100
+SymbolicName=INFO
+Language=English
+[INFO] %1
+.
+
+MessageId=10101
+SymbolicName=WARN
+Language=English
+[WARN] %1
+.
+
+MessageId=10102
+SymbolicName=DEBUG
+Language=English
+[DEBUG] %1
+.
+
+MessageId=10103
+SymbolicName=ERROR
+Language=English
+[ERROR] %1
+.
+
+MessageId=10104
+SymbolicName=FATAL
+Language=English
+[FATAL] %1
+.
diff --git a/lib/chef/event_loggers/windows_eventlog.rb b/lib/chef/event_loggers/windows_eventlog.rb
index 37dcdc8693..7a3a28b61f 100644
--- a/lib/chef/event_loggers/windows_eventlog.rb
+++ b/lib/chef/event_loggers/windows_eventlog.rb
@@ -18,17 +18,7 @@
require 'chef/event_loggers/base'
require 'chef/platform/query_helpers'
-
-if Chef::Platform::windows? and not Chef::Platform::windows_server_2003?
- if defined? Windows::Constants
- [:INFINITE, :WAIT_FAILED, :FORMAT_MESSAGE_IGNORE_INSERTS, :ERROR_INSUFFICIENT_BUFFER].each do |c|
- # These are redefined in 'win32/eventlog'
- Windows::Constants.send(:remove_const, c) if Windows::Constants.const_defined? c
- end
- end
-
- require 'win32/eventlog'
-end
+require 'chef/win32/eventlog'
class Chef
module EventLoggers
diff --git a/lib/chef/log.rb b/lib/chef/log.rb
index a47002a2fc..9b27778a40 100644
--- a/lib/chef/log.rb
+++ b/lib/chef/log.rb
@@ -22,6 +22,7 @@ require 'chef/monologger'
require 'chef/exceptions'
require 'mixlib/log'
require 'chef/log/syslog' unless (RUBY_PLATFORM =~ /mswin|mingw|windows/)
+require 'chef/log/winevt'
class Chef
class Log
diff --git a/lib/chef/log/syslog.rb b/lib/chef/log/syslog.rb
index fcb3c972e8..0c8190797f 100644
--- a/lib/chef/log/syslog.rb
+++ b/lib/chef/log/syslog.rb
@@ -18,6 +18,7 @@
require 'logger'
require 'syslog-logger'
+require 'chef/mixin/unformatter'
class Chef
class Log
@@ -27,6 +28,8 @@ class Chef
# log_location Chef::Log::Syslog.new("chef-client", ::Syslog::LOG_DAEMON)
#
class Syslog < Logger::Syslog
+ include Chef::Mixin::Unformatter
+
attr_accessor :sync, :formatter
def initialize(program_name = 'chef-client', facility = ::Syslog::LOG_DAEMON, logopts=nil)
@@ -35,13 +38,6 @@ class Chef
::Logger::Syslog.const_set :SYSLOG, SYSLOG
end
- def write(message)
- data = message.match(/(\[.+?\]) ([\w]+):(.*)$/)
- self.send(data[2].downcase.to_sym, data[3].strip)
- rescue NoMethodError
- self.send(:info, message)
- end
-
def close
end
end
diff --git a/lib/chef/log/winevt.rb b/lib/chef/log/winevt.rb
new file mode 100644
index 0000000000..c5b7c3485a
--- /dev/null
+++ b/lib/chef/log/winevt.rb
@@ -0,0 +1,99 @@
+#
+# Author:: Jay Mundrawala (<jdm@chef.io>)
+#
+# Copyright:: 2015, Chef Software, Inc.
+#
+# 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 'chef/event_loggers/base'
+require 'chef/platform/query_helpers'
+require 'chef/mixin/unformatter'
+
+class Chef
+ class Log
+ #
+ # Chef::Log::WinEvt class.
+ # usage in client.rb:
+ # log_location Chef::Log::WinEvt.new
+ #
+ class WinEvt
+ # These must match those that are defined in the manifest file
+ INFO_EVENT_ID = 10100
+ WARN_EVENT_ID = 10101
+ DEBUG_EVENT_ID = 10102
+ ERROR_EVENT_ID = 10103
+ FATAL_EVENT_ID = 10104
+
+ # Since we must install the event logger, this is not really configurable
+ SOURCE = 'Chef'
+
+ include Chef::Mixin::Unformatter
+
+ attr_accessor :sync, :formatter, :level
+
+ def initialize(eventlog=nil)
+ @eventlog = eventlog || ::Win32::EventLog::open('Application')
+ end
+
+ def close
+ end
+
+ def info(msg)
+ @eventlog.report_event(
+ :event_type => ::Win32::EventLog::INFO_TYPE,
+ :source => SOURCE,
+ :event_id => INFO_EVENT_ID,
+ :data => [msg]
+ )
+ end
+
+ def warn(msg)
+ @eventlog.report_event(
+ :event_type => ::Win32::EventLog::WARN_TYPE,
+ :source => SOURCE,
+ :event_id => WARN_EVENT_ID,
+ :data => [msg]
+ )
+ end
+
+ def debug(msg)
+ @eventlog.report_event(
+ :event_type => ::Win32::EventLog::INFO_TYPE,
+ :source => SOURCE,
+ :event_id => DEBUG_EVENT_ID,
+ :data => [msg]
+ )
+ end
+
+ def error(msg)
+ @eventlog.report_event(
+ :event_type => ::Win32::EventLog::ERROR_TYPE,
+ :source => SOURCE,
+ :event_id => ERROR_EVENT_ID,
+ :data => [msg]
+ )
+ end
+
+ def fatal(msg)
+ @eventlog.report_event(
+ :event_type => ::Win32::EventLog::ERROR_TYPE,
+ :source => SOURCE,
+ :event_id => FATAL_EVENT_ID,
+ :data => [msg]
+ )
+ end
+
+ end
+ end
+end
diff --git a/lib/chef/mixin/unformatter.rb b/lib/chef/mixin/unformatter.rb
new file mode 100644
index 0000000000..aa5977edd7
--- /dev/null
+++ b/lib/chef/mixin/unformatter.rb
@@ -0,0 +1,32 @@
+#
+# Author:: Jay Mundrawala (<jdm@chef.io>)
+# Copyright:: Copyright (c) 2015 Chef Software
+# 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.
+#
+
+class Chef
+ module Mixin
+ module Unformatter
+
+ def write(message)
+ data = message.match(/(\[.+?\] )?([\w]+):(.*)$/)
+ self.send(data[2].downcase.chomp.to_sym, data[3].strip)
+ rescue NoMethodError
+ self.send(:info, message)
+ end
+
+ end
+ end
+end
diff --git a/lib/chef/win32/eventlog.rb b/lib/chef/win32/eventlog.rb
new file mode 100644
index 0000000000..24af2da0d6
--- /dev/null
+++ b/lib/chef/win32/eventlog.rb
@@ -0,0 +1,31 @@
+#
+# Author:: Jay Mundrawala (<jdm@chef.io>)
+#
+# Copyright:: 2015, Chef Software, Inc.
+#
+# 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.
+#
+
+if Chef::Platform::windows? and not Chef::Platform::windows_server_2003?
+ if !defined? Chef::Win32EventLogLoaded
+ if defined? Windows::Constants
+ [:INFINITE, :WAIT_FAILED, :FORMAT_MESSAGE_IGNORE_INSERTS, :ERROR_INSUFFICIENT_BUFFER].each do |c|
+ # These are redefined in 'win32/eventlog'
+ Windows::Constants.send(:remove_const, c) if Windows::Constants.const_defined? c
+ end
+ end
+
+ require 'win32/eventlog'
+ Chef::Win32EventLogLoaded = true
+ end
+end
diff --git a/spec/unit/log/winevt_spec.rb b/spec/unit/log/winevt_spec.rb
new file mode 100644
index 0000000000..867ef55900
--- /dev/null
+++ b/spec/unit/log/winevt_spec.rb
@@ -0,0 +1,55 @@
+#
+# Author:: Jay Mundrawala (jdm@chef.io)
+# Author:: SAWANOBORI Yukihiko (<sawanoboriyu@higanworks.com>)
+# Copyright:: Copyright (c) 2015 Chef Software, 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 'spec_helper'
+
+describe Chef::Log::WinEvt do
+ let(:evtlog) { instance_double("Win32::EventLog")}
+ let(:winevt) { Chef::Log::WinEvt.new(evtlog) }
+ let(:app) { Chef::Application.new }
+
+ before do
+
+ Chef::Log.init(MonoLogger.new(winevt))
+ @old_log_level = Chef::Log.level
+ Chef::Log.level = :info
+ @old_loggers = Chef::Log.loggers
+ Chef::Log.use_log_devices([winevt])
+ end
+
+ after do
+ Chef::Log.level = @old_log_level
+ Chef::Log.use_log_devices(@old_loggers)
+ end
+
+ it "should send message with severity info to Windows Event Log." do
+ expect(winevt).to receive(:info).with("*** Chef 12.4.0.dev.0 ***")
+ Chef::Log.info("*** Chef 12.4.0.dev.0 ***")
+ end
+
+ it "should send message with severity warning to Windows Event Log." do
+ expect(winevt).to receive(:warn).with("No config file found or specified on command line, using command line options.")
+ Chef::Log.warn("No config file found or specified on command line, using command line options.")
+ end
+
+ it "should fallback into send message with severity info to Windows Event Log when wrong format." do
+ expect(winevt).to receive(:info).with("chef message")
+ winevt.write("chef message")
+ end
+end
diff --git a/spec/unit/mixin/unformatter_spec.rb b/spec/unit/mixin/unformatter_spec.rb
new file mode 100644
index 0000000000..2eae0ac9bb
--- /dev/null
+++ b/spec/unit/mixin/unformatter_spec.rb
@@ -0,0 +1,61 @@
+#
+# Author:: Jay Mundrawala (<jdm@chef.io>)
+# Copyright:: Copyright (c) 2015 Chef Software
+# 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 'spec_helper'
+require 'chef/mixin/unformatter'
+
+class Chef::UnformatterTest
+ include Chef::Mixin::Unformatter
+
+ def foo
+ end
+
+end
+
+describe Chef::Mixin::Unformatter do
+ let (:unformatter) { Chef::UnformatterTest.new }
+ let (:message) { "Test Message" }
+
+ describe "#write" do
+ context "with a timestamp" do
+ it "sends foo to itself when the message is of severity foo" do
+ expect(unformatter).to receive(:foo).with(message)
+ unformatter.write("[time] foo: #{message}")
+ end
+
+ it "sends foo to itself when the message is of severity FOO" do
+ expect(unformatter).to receive(:foo).with(message)
+ unformatter.write("[time] FOO: #{message}")
+ end
+ end
+
+ context "without a timestamp" do
+ it "sends foo to itself when the message is of severity foo" do
+ expect(unformatter).to receive(:foo).with(message)
+ unformatter.write("foo: #{message}")
+ end
+
+ it "sends foo to itself when the message is of severity FOO" do
+ expect(unformatter).to receive(:foo).with(message)
+ unformatter.write("FOO: #{message}")
+ end
+ end
+
+ end
+
+end