diff options
author | Jay Mundrawala <jdmundrawala@gmail.com> | 2015-05-13 13:49:00 -0500 |
---|---|---|
committer | Jay Mundrawala <jdmundrawala@gmail.com> | 2015-05-13 13:49:00 -0500 |
commit | d85201ece21e3b534033072b5a5fb630aeb19339 (patch) | |
tree | 42a816ca484a5f397bfefbe72dfca6f2ca9b895a | |
parent | 0a48720d350ae8e537bf11309a005b949bb348de (diff) | |
parent | e57f5c1be36f97b7eca886a99d86fd207240bc34 (diff) | |
download | chef-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.man | 30 | ||||
-rw-r--r-- | lib/chef/event_loggers/windows_eventlog.rb | 12 | ||||
-rw-r--r-- | lib/chef/log.rb | 1 | ||||
-rw-r--r-- | lib/chef/log/syslog.rb | 10 | ||||
-rw-r--r-- | lib/chef/log/winevt.rb | 99 | ||||
-rw-r--r-- | lib/chef/mixin/unformatter.rb | 32 | ||||
-rw-r--r-- | lib/chef/win32/eventlog.rb | 31 | ||||
-rw-r--r-- | spec/unit/log/winevt_spec.rb | 55 | ||||
-rw-r--r-- | spec/unit/mixin/unformatter_spec.rb | 61 |
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 |