From 934c9b1286c2858f58f7599aff10029e358db47e Mon Sep 17 00:00:00 2001 From: Digimer Date: Tue, 22 Oct 2019 21:17:30 -0400 Subject: [PATCH] * Updated logging to now log anything with 'priority' set to a new 'anvil.alert.log' file (while still also logging as normal to anvil.log). This should make it easier to watch for alert messages. Signed-off-by: Digimer --- Anvil/Tools.pm | 3 +- Anvil/Tools/Log.pm | 101 ++++++++++++++++++++++++++++++++++++++++--- ocf/alteeve/server | 2 +- rpm/SPECS/anvil.spec | 5 ++- share/words.xml | 4 ++ 5 files changed, 106 insertions(+), 9 deletions(-) diff --git a/Anvil/Tools.pm b/Anvil/Tools.pm index ef66f854..8342bed7 100644 --- a/Anvil/Tools.pm +++ b/Anvil/Tools.pm @@ -1160,7 +1160,8 @@ sub _set_paths database => "/tmp/anvil-tools.database.lock", }, 'log' => { - file => "/var/log/anvil.log", + main => "/var/log/anvil.log", + alert => "/var/log/anvil.alert.log", }, proc => { uptime => "/proc/uptime", diff --git a/Anvil/Tools/Log.pm b/Anvil/Tools/Log.pm index 768c3713..fefcb1df 100644 --- a/Anvil/Tools/Log.pm +++ b/Anvil/Tools/Log.pm @@ -88,7 +88,9 @@ sub parent =head2 entry -This method writes an entry to the journald logs, provided the log entry's level is equal to or higher than the active log level. The exception is if the log entry contains sensitive data, like a password, and 'C<< log::secure >> is set to 'C<< 0 >>' (the default). +This method writes an entry to either the log files or to the journald logs, provided the log entry's level is equal to or higher than the active log level. The exception is if the log entry contains sensitive data, like a password, and 'C<< log::secure >> is set to 'C<< 0 >>' (the default). In this case, the sensitive log / data will be listed as suppressed. + +B<< NOTE >>: Deciding if the logs go to a file or journald is determined by checking to see if C<< path::log::main >> is set. If it isn't, journald is used. If it is (default), the file is used. If writing to a log file, and if C<< path::log::alert >> is also set, any entry with a set C<< priority >> (see below) is logged to both files. Here is a simple example of writing a simple log entry at log log level 1. @@ -185,6 +187,14 @@ B<< NOTE >>: This honours the log level. That is to say, it will only print the =head3 priority (optional) +What this does depends on if we're logging to a file or not. + +=head4 File + +If set, the log entry will also be written to the C<< path::log::alert >> log file, with a prefix indicating 'Error', 'Warning' or 'Note'. This is meant to make it easier to filter out important messages from general log entries. Note that these log entries are also still written to C<< path::log::main >>, so that these messages can be seen in context. + +=head4 Journald + This is an optional log priority (level) name. By default, the following priorities will be used based on the log level of the message. * 0 = notice @@ -251,7 +261,7 @@ sub entry $anvil->data->{loop}{count} = 0 if not defined $anvil->data->{loop}{count}; $anvil->data->{loop}{count}++; - print $THIS_FILE." ".__LINE__."; [ Debug ] - level: [".$level."], defaults::log::level: [".$anvil->data->{defaults}{'log'}{level}."], logging secure? [".$anvil->Log->secure."], loop::count: [".$anvil->data->{loop}{count}."], source: [".$source."], line: [".$line."], key: [".$key."], variables: [".$variables."]\n" if $test; + print $THIS_FILE." ".__LINE__."; [ Debug ] - level: [".$level."], defaults::log::level: [".$anvil->data->{defaults}{'log'}{level}."], logging secure? [".$anvil->Log->secure."], priority: [".$priority."], source: [".$source."], line: [".$line."], key: [".$key."], variables: [".$variables."]\n" if $test; if (($test) && (ref($variables) eq "HASH")) { foreach my $key (sort {$a cmp $b} keys %{$variables}) @@ -310,10 +320,24 @@ sub entry } # Build the priority, if not set by the user. + my $log_to_alert = ""; my $priority_string = $secure ? "authpriv" : $facility; if ($priority) { $priority_string .= ".$priority"; + if ($priority =~ /^err/i) + { + $log_to_alert = $anvil->Words->string({test => $test, language => $language, key => "prefix_0001"}); + } + elsif ($priority =~ /^alert/i) + { + $log_to_alert = $anvil->Words->string({test => $test, language => $language, key => "prefix_0002"});; + } + elsif ($priority =~ /^info/i) + { + $log_to_alert = $anvil->Words->string({test => $test, language => $language, key => "prefix_0003"});; + } + print $THIS_FILE." ".__LINE__."; priority_string: [".$priority_string."], log_to_alert: [".$log_to_alert."]\n" if $test; } elsif ($level eq "0") { @@ -355,6 +379,12 @@ sub entry } print $THIS_FILE." ".__LINE__."; loop::count: [".$anvil->data->{loop}{count}."] " if $test; + if ($log_to_alert) + { + $log_to_alert = $string.$log_to_alert; + print $THIS_FILE." ".__LINE__."; log_to_alert: [".$log_to_alert."]\n" if $test; + } + # If I have a raw string, do no more processing. print $THIS_FILE." ".__LINE__."; raw: [".$raw."], key: [".$key."]\n" if $test; if ($raw) @@ -363,6 +393,12 @@ sub entry $print_string .= $raw; print $THIS_FILE." ".__LINE__."; string: ..... [".$string."]\n" if $test; print $THIS_FILE." ".__LINE__."; print_string: [".$print_string."]\n" if $test; + + if ($log_to_alert) + { + $log_to_alert .= $raw; + print $THIS_FILE." ".__LINE__."; log_to_alert: [".$log_to_alert."]\n" if $test; + } } elsif ($key) { @@ -381,11 +417,19 @@ sub entry $print_string .= $message; print $THIS_FILE." ".__LINE__."; string: ..... [".$string."]\n" if $test; print $THIS_FILE." ".__LINE__."; print_string: [".$print_string."]\n" if $test; + + if ($log_to_alert) + { + $log_to_alert .= $message; + print $THIS_FILE." ".__LINE__."; log_to_alert: [".$log_to_alert."]\n" if $test; + } } + ### TODO: Left off here - check priority and switch to 'anvil.errors' if set to 'warn' or 'err'. All + ### logs go to main still (so they can be seen in context). # If the user set a log file, log to that. Otherwise, log via Log::Journald. - print $THIS_FILE." ".__LINE__."; path::log::file: [".$anvil->data->{path}{'log'}{file}."]\n" if $test; - if ($anvil->data->{path}{'log'}{file}) + print $THIS_FILE." ".__LINE__."; path::log::main: [".$anvil->data->{path}{'log'}{main}."]\n" if $test; + if ($anvil->data->{path}{'log'}{main}) { # TODO: Switch back to journald later, using a file for testing for now if ($string !~ /\n$/) @@ -393,6 +437,11 @@ sub entry $string .= "\n"; print $THIS_FILE." ".__LINE__."; string: [".$string."]\n" if $test; } + if ($log_to_alert !~ /\n$/) + { + $log_to_alert .= "\n"; + print $THIS_FILE." ".__LINE__."; log_to_alert: [".$log_to_alert."]\n" if $test; + } ### TODO: Periodically check the log file size. If it's over a gigabyte, archive it @@ -402,7 +451,7 @@ sub entry if (not $anvil->data->{HANDLE}{'log'}{main}) { # If the file doesn't start with a '/', we'll put it under /var/log. - my $log_file = $anvil->data->{path}{'log'}{file} =~ /^\// ? $anvil->data->{path}{'log'}{file} : "/var/log/".$anvil->data->{path}{'log'}{file}; + my $log_file = $anvil->data->{path}{'log'}{main} =~ /^\// ? $anvil->data->{path}{'log'}{main} : "/var/log/".$anvil->data->{path}{'log'}{main}; my ($directory, $file) = ($log_file =~ /^(\/.*)\/(.*)$/); print $THIS_FILE." ".__LINE__."; log_file: [".$log_file."]. directory: [".$directory."], file: [".$file."]\n" if $test; @@ -427,11 +476,51 @@ sub entry if (not $anvil->data->{HANDLE}{'log'}{main}) { # NOTE: This can't be a normal error because we can't write to the logs. - die $THIS_FILE." ".__LINE__."; log file handle doesn't exist, but it should by now.\n"; + die $THIS_FILE." ".__LINE__."; log main file handle doesn't exist, but it should by now.\n"; } # The handle has to be wrapped in a block to make 'print' happy as it doesn't like non-scalars for file handles print { $anvil->data->{HANDLE}{'log'}{main} } $string; + + # Does this need to be logged to 'notice' as well? + if (($log_to_alert) && ($anvil->data->{path}{'log'}{alert})) + { + $anvil->data->{HANDLE}{'log'}{alert} = "" if not defined $anvil->data->{HANDLE}{'log'}{alert}; + print $THIS_FILE." ".__LINE__."; HANDLE::log::alert: [".$anvil->data->{HANDLE}{'log'}{alert}."]\n" if $test; + if (not $anvil->data->{HANDLE}{'log'}{alert}) + { + # If the file doesn't start with a '/', we'll put it under /var/log. + my $log_file = $anvil->data->{path}{'log'}{alert} =~ /^\// ? $anvil->data->{path}{'log'}{alert} : "/var/log/".$anvil->data->{path}{'log'}{alert}; + my ($directory, $file) = ($log_file =~ /^(\/.*)\/(.*)$/); + print $THIS_FILE." ".__LINE__."; log_file: [".$log_file."]. directory: [".$directory."], file: [".$file."]\n" if $test; + + ### WARNING: We MUST set the debug level really high, or else we'll go into a deep + ### recursion! + # Make sure the log directory exists. + $anvil->Storage->make_directory({test => $test, debug => 99, directory => $directory, mode => 755}); + + # Now open the log + my $shell_call = $log_file; + print $THIS_FILE." ".__LINE__."; shell_call: [".$shell_call."]\n" if $test; + # NOTE: Don't call '$anvil->Log->entry()' here, it will cause a loop! + open (my $file_handle, ">>", $shell_call) or die "Failed to open: [$shell_call] for writing. The error was: $!\n"; + $file_handle->autoflush(1); + $anvil->data->{HANDLE}{'log'}{alert} = $file_handle; + print $THIS_FILE." ".__LINE__."; HANDLE::log::alert: [".$anvil->data->{HANDLE}{'log'}{alert}."]\n" if $test; + + # Make sure it can be written to by apache. + $anvil->Storage->change_mode({test => $test, debug => $debug, path => $log_file, mode => "0666"}); + } + + if (not $anvil->data->{HANDLE}{'log'}{alert}) + { + # NOTE: This can't be a normal error because we can't write to the logs. + die $THIS_FILE." ".__LINE__."; log alert file handle doesn't exist, but it should by now.\n"; + } + + # The handle has to be wrapped in a block to make 'print' happy as it doesn't like non-scalars for file handles + print { $anvil->data->{HANDLE}{'log'}{alert} } $log_to_alert; + } $anvil->data->{loop}{count} = 0; } else diff --git a/ocf/alteeve/server b/ocf/alteeve/server index e96381c9..ea9569ec 100755 --- a/ocf/alteeve/server +++ b/ocf/alteeve/server @@ -642,7 +642,7 @@ sub server_status { # Set a sane default of 20 seconds. $anvil->data->{environment}{OCF_RESKEY_CRM_meta_timeout} = 20000; - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, priority => "warn", key => "log_0331", variables => { timeout => $anvil->data->{environment}{OCF_RESKEY_CRM_meta_timeout} }}); + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, priority => "alert", key => "log_0331", variables => { timeout => $anvil->data->{environment}{OCF_RESKEY_CRM_meta_timeout} }}); } $anvil->nice_exit({exit_code => 0}); diff --git a/rpm/SPECS/anvil.spec b/rpm/SPECS/anvil.spec index d417359c..655d2ae8 100644 --- a/rpm/SPECS/anvil.spec +++ b/rpm/SPECS/anvil.spec @@ -3,7 +3,7 @@ %define anvilgroup admin Name: anvil Version: 3.0 -Release: 27%{?dist} +Release: 28%{?dist} Summary: Alteeve Anvil! complete package. License: GPLv2+ @@ -287,6 +287,9 @@ firewall-cmd --add-service=postgresql --permanent %changelog +* tbd Madison Kelly 3.0-28 +- Updated source + * Sun Oct 20 2019 Madison Kelly 3.0-27 - Updated source diff --git a/share/words.xml b/share/words.xml index d976aea0..d5c87c34 100644 --- a/share/words.xml +++ b/share/words.xml @@ -985,6 +985,10 @@ If you are comfortable that the target has changed for a known reason, you can s Days Weeks + [ Error ] - + [ Warning ] - + [ Note ] - + Configure Network The network configuration will be updated based on the variables stored in the database. Reconnecting to the machine using the new IP address may be required.