* 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 <digimer@alteeve.ca>
main
Digimer 5 years ago
parent f750e087f6
commit 934c9b1286
  1. 3
      Anvil/Tools.pm
  2. 101
      Anvil/Tools/Log.pm
  3. 2
      ocf/alteeve/server
  4. 5
      rpm/SPECS/anvil.spec
  5. 4
      share/words.xml

@ -1160,7 +1160,8 @@ sub _set_paths
database => "/tmp/anvil-tools.database.lock", database => "/tmp/anvil-tools.database.lock",
}, },
'log' => { 'log' => {
file => "/var/log/anvil.log", main => "/var/log/anvil.log",
alert => "/var/log/anvil.alert.log",
}, },
proc => { proc => {
uptime => "/proc/uptime", uptime => "/proc/uptime",

@ -88,7 +88,9 @@ sub parent
=head2 entry =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. 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) =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. 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 * 0 = notice
@ -251,7 +261,7 @@ sub entry
$anvil->data->{loop}{count} = 0 if not defined $anvil->data->{loop}{count}; $anvil->data->{loop}{count} = 0 if not defined $anvil->data->{loop}{count};
$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")) if (($test) && (ref($variables) eq "HASH"))
{ {
foreach my $key (sort {$a cmp $b} keys %{$variables}) foreach my $key (sort {$a cmp $b} keys %{$variables})
@ -310,10 +320,24 @@ sub entry
} }
# Build the priority, if not set by the user. # Build the priority, if not set by the user.
my $log_to_alert = "";
my $priority_string = $secure ? "authpriv" : $facility; my $priority_string = $secure ? "authpriv" : $facility;
if ($priority) if ($priority)
{ {
$priority_string .= ".$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") elsif ($level eq "0")
{ {
@ -355,6 +379,12 @@ sub entry
} }
print $THIS_FILE." ".__LINE__."; loop::count: [".$anvil->data->{loop}{count}."] " if $test; 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. # If I have a raw string, do no more processing.
print $THIS_FILE." ".__LINE__."; raw: [".$raw."], key: [".$key."]\n" if $test; print $THIS_FILE." ".__LINE__."; raw: [".$raw."], key: [".$key."]\n" if $test;
if ($raw) if ($raw)
@ -363,6 +393,12 @@ sub entry
$print_string .= $raw; $print_string .= $raw;
print $THIS_FILE." ".__LINE__."; string: ..... [".$string."]\n" if $test; print $THIS_FILE." ".__LINE__."; string: ..... [".$string."]\n" if $test;
print $THIS_FILE." ".__LINE__."; print_string: [".$print_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) elsif ($key)
{ {
@ -381,11 +417,19 @@ sub entry
$print_string .= $message; $print_string .= $message;
print $THIS_FILE." ".__LINE__."; string: ..... [".$string."]\n" if $test; print $THIS_FILE." ".__LINE__."; string: ..... [".$string."]\n" if $test;
print $THIS_FILE." ".__LINE__."; print_string: [".$print_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. # 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; print $THIS_FILE." ".__LINE__."; path::log::main: [".$anvil->data->{path}{'log'}{main}."]\n" if $test;
if ($anvil->data->{path}{'log'}{file}) if ($anvil->data->{path}{'log'}{main})
{ {
# TODO: Switch back to journald later, using a file for testing for now # TODO: Switch back to journald later, using a file for testing for now
if ($string !~ /\n$/) if ($string !~ /\n$/)
@ -393,6 +437,11 @@ sub entry
$string .= "\n"; $string .= "\n";
print $THIS_FILE." ".__LINE__."; string: [".$string."]\n" if $test; 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 ### 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 (not $anvil->data->{HANDLE}{'log'}{main})
{ {
# If the file doesn't start with a '/', we'll put it under /var/log. # 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 =~ /^(\/.*)\/(.*)$/); my ($directory, $file) = ($log_file =~ /^(\/.*)\/(.*)$/);
print $THIS_FILE." ".__LINE__."; log_file: [".$log_file."]. directory: [".$directory."], file: [".$file."]\n" if $test; 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}) if (not $anvil->data->{HANDLE}{'log'}{main})
{ {
# NOTE: This can't be a normal error because we can't write to the logs. # 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 # 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; 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; $anvil->data->{loop}{count} = 0;
} }
else else

@ -642,7 +642,7 @@ sub server_status
{ {
# Set a sane default of 20 seconds. # Set a sane default of 20 seconds.
$anvil->data->{environment}{OCF_RESKEY_CRM_meta_timeout} = 20000; $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}); $anvil->nice_exit({exit_code => 0});

@ -3,7 +3,7 @@
%define anvilgroup admin %define anvilgroup admin
Name: anvil Name: anvil
Version: 3.0 Version: 3.0
Release: 27%{?dist} Release: 28%{?dist}
Summary: Alteeve Anvil! complete package. Summary: Alteeve Anvil! complete package.
License: GPLv2+ License: GPLv2+
@ -287,6 +287,9 @@ firewall-cmd --add-service=postgresql --permanent
%changelog %changelog
* tbd Madison Kelly <mkelly@alteeve.ca> 3.0-28
- Updated source
* Sun Oct 20 2019 Madison Kelly <mkelly@alteeve.ca> 3.0-27 * Sun Oct 20 2019 Madison Kelly <mkelly@alteeve.ca> 3.0-27
- Updated source - Updated source

@ -985,6 +985,10 @@ If you are comfortable that the target has changed for a known reason, you can s
<key name="suffix_0010">Days</key> <!-- Long suffix for 'days'. --> <key name="suffix_0010">Days</key> <!-- Long suffix for 'days'. -->
<key name="suffix_0011">Weeks</key> <!-- Long suffix for 'days'. --> <key name="suffix_0011">Weeks</key> <!-- Long suffix for 'days'. -->
<key name="prefix_0001">[ Error ] - </key>
<key name="prefix_0002">[ Warning ] - </key>
<key name="prefix_0003">[ Note ] - </key>
<!-- Strings used by jobs --> <!-- Strings used by jobs -->
<key name="job_0001">Configure Network</key> <key name="job_0001">Configure Network</key>
<key name="job_0002">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.</key> <key name="job_0002">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.</key>

Loading…
Cancel
Save