########################################################################### # $Id$ ########################################################################### ########################################################################### # This was written and is maintained by: # Stefan Jakobs # # Please send all comments, suggestions, bug reports, # etc, to logwatch at localside.net. ########################################################################### # Copyright (c) 2011 Stefan Jakobs # Covered under the included MIT/X-Consortium License: # http://www.opensource.org/licenses/mit-license.php # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ########################################################################### #use warnings; use strict; my $Detail = $ENV{'LOGWATCH_DETAIL_LEVEL'} || 0; my $Version = "0.1-20110109"; # initialize logwatch variables my $ThisLine = ""; my %OtherList = (); # initialize variables which save the stats my ($Starts,%Stops,$Reloads,$Crashs,$Upgrades); my (%Warnings); my (%RSSfeeds, %RSSerrors); my (%SMTPclientRelay, %SMTPclientStats, %SMTPclientCMDS); my (%SMTPclientDelivery, %SMTPclientBounce, %SMTPclientConnect); my ($SMTPclient_queuerun, $SMTPclient_messages, $SMTPclientBounces) = (0, 0, 0); my ($SMTPclientTime) = (0); my (%SMTPserverStats, %SMTPserverRelay, %SMTPserverCMDS); my (%SMTPserverHELO, %SMTPserverRCPT, %SMTPserverFROM); my (%SMTPserverEval, %SMTPserverAuth, %SMTPSSLError); my ($SMTPBytesAccepted, $SMTPAccepted, $SMTPRejected) = (0, 0 ,0, 0); my ($SMTPserverStatsSum) = (0); my ($serv_extnotify_queuerun) = (0); my (%Threads); my (%IMAPCmds, %IMAPexpunge, %IMAPUserLogin); my ($IMAPCompletedCmds, $IMAPCmdDuration) = (0, 0); my (%Ctdlcmds, %CtdlCleanup, %Ctdlqp_encode, %CtdlValRcpt, %CtdlMsgCorrupted); my (%CtdlReplChecks, %CtdlAddContact, %CtdlFileOp, %CtdlGenerate); my (%CtdlWriteFail); my ($CtdlMsgDeleted) = (0); my (@CtdlLogDeleted, @CtdlUserDeleted, @CtdlUserCreated, @CtdlRoomDeleted); my ($NetProcessingTime, $NetProcessingCount) = (0, 0); my (%NetStarts, %NetNodes, %NetNoConnect, %NetFilesRemoved); my (%WebClientEngine, %WebClientHost, %WebLoginFailure, %WebUserLogin); my ($SieveMsgID, $SieveName, $SieveStarts, $SieveNoProcessing); my (%SieveMsg, %SieveExecute, %SieveProcFor); my (%POPCmds, %POPClientConnects, %POPErrors, %POPUserLogin); my ($POPCompletedCmds, $POPClientStarted, $POPClientEnded) = (0, 0, 0); my ($POPClientFetched, $POPClientProcessTime) = (0, 0); my (%POPDauth, %POPDCmds); my (%SessionStarted); my (%ClamdConnects); my ($ClamdIP) = ""; # status variables my ($NetNode, $NetHost); my $Session = ""; ### Functions ### sub print_asterisks() { printf "\n ******** Details (%2i) ***************************************\n", $Detail; } sub print_line() { print " -------- --------------------------------------------------\n"; } sub print_doubleline() { print " ======== ==================================================\n\n"; } sub print_hash($$) { my $out = ""; my $sum = 0; my %hash = %{$_[0]}; my $desc = $_[1]; foreach my $item (sort {$hash{$b} <=> $hash{$a}} keys %hash) { $out .= sprintf " %8i %s\n", $hash{$item}, $item; $sum += $hash{$item}; } printf "\n %8i %-36s\n", $sum, $desc; if ($Detail > 4) { printf "$out"; } } sub print_2xhash($$) { my $out = ""; my $sum = 0; my %hash = %{$_[0]}; my $desc = $_[1]; foreach my $item (sort {$a cmp $b} keys %hash) { my $out2 = ""; my $sum2 = ""; foreach my $item2 (sort {$hash{$item}{$b} <=> $hash{$item}{$a}} keys %{$hash{$item}}) { $out2 .= sprintf " %8i %s\n", $hash{$item}{$item2}, $item2; $sum2 += $hash{$item}{$item2}; } $out .= sprintf " %8i %s\n", $sum2, $item; $sum += $sum2; if ($Detail > 9) { $out .= $out2; } } printf "\n %8i %-36s\n", $sum, $desc; if ($Detail > 4) { printf "$out"; } } sub print_3xhash($$) { my $out = ""; my $sum = 0; my %hash = %{$_[0]}; my $desc = $_[1]; foreach my $item (sort {$a cmp $b} keys %hash) { my $out2 = ""; my $sum2 = 0; foreach my $item2 (sort {$a cmp $b} keys %{$hash{$item}}) { my $out3 = ""; my $sum3 = 0; foreach my $item3 (sort {$hash{$item}{$item2}{$b} <=> $hash{$item}{$item2}{$a}} keys %{$hash{$item}{$item2}}) { ## foreach my $nr (sort {$a cmp $b} keys %{$Threads{$action}{$thread}}) { ## printf "\t\t%-40s: %5i Time(s)\n", $nr, $Threads{$action}{$thread}{$nr}; $out3 .= sprintf " %8i %s\n", $hash{$item}{$item2}{$item3}, $item3; $sum3 += $hash{$item}{$item2}{$item3}; } $out2 .= sprintf " %8i %s\n", $sum3, $item2; $sum2 += $sum3; if ($Detail > 9) { $out2 .= $out3; } } $out .= sprintf " %8i %s\n", $sum2, $item; $sum += $sum2; if ($Detail > 4) { $out .= $out2; } } printf "\n %8i %-36s\n", $sum, $desc; if ($Detail > 4) { printf "$out"; } } ### Parse the lines ### while (defined($ThisLine = )) { chomp($ThisLine); # ignore general messages if ( ($ThisLine =~ /^-- db checkpoint --$/) || ($ThisLine =~ /^\s*$/) || ($ThisLine =~ /^This program is distributed under the terms/) || ($ThisLine =~ /^Copyright \(C\) [-\d]+ by the Citadel/) || ($ThisLine =~ /^(?:Sieve: )?libSieve is written and maintained by Aaron Stone/) || ($ThisLine =~ /^(?:CC\[\d+\])?<.*> \d+ new of \d+ total messages$/) || ($ThisLine =~ /^(?:TDAP_)?AdjRefCount\(\) msg -?\d+/) || ($ThisLine =~ /^Closing the AdjRefCount queue file/) || ($ThisLine =~ /^Closing (?:-\d+ )listener on/) || ($ThisLine =~ /^Called as: /) || ($ThisLine =~ /(?:zlib| libcurl|libssh2)\/\d/) || # ($ThisLine =~ /^\[\d+\]\[.+\]/) || # this conflics with the web stats ($ThisLine =~ /^Caught signal 15; shutting down/) || ($ThisLine =~ /^\$Id\$/) || ($ThisLine =~ /^errno is \d+$/) || ($ThisLine =~ /\[\d+\]\[\w+\(\d+\)\]\s+$/) ) { # ignore these lines } ### Start, Stop, Reload ### elsif ($ThisLine =~ /^\*\*\* Citadel server engine/) { $Starts++; } #TD: citserver: Exiting with status 15 elsif ($ThisLine =~ /^citserver: Exiting with status (\d+)$/) { $Stops{$1}++; } #TD: Posting crash message elsif ($ThisLine =~ /^Posting crash message$/) { $Crashs++; } #TD: upgrade elsif ($ThisLine =~ /^upgrade$/) { $Upgrades++; } ### Warnings (message) (reason) #TD: unable to change into directory [/var/run/citadel/]: No such file or directory elsif ($ThisLine =~ /^unable to change into directory \[(.*)\]: (.*)$/) { $Warnings{$2}{$1}++; } #TD: citserver: unable to lock /var/lib/citadel/data/citadel.control. elsif ($ThisLine =~ /^citserver: (unable to lock .+)\.$/ ) { $Warnings{$1}{""}++ } #TD: Is another citserver already running? elsif ($ThisLine =~ /^(Is another citserver already running\?)$/ ) { $Warnings{$1}{""}++; } #TD: This message has a zero length. Probable data corruption. elsif ($ThisLine =~ /^(This message has a zero length)\. {1,2}(Probable data corruption)\.$/) { $Warnings{$2}{$1}++; } #TD: pthread_create() : Cannot allocate memory elsif ($ThisLine =~ /^pthread_create\(\) : (Cannot allocate memory)$/) { $Warnings{$1}{""}++; } ### Thread processing ### elsif ( ($ThisLine =~ /^\S+_thread\(\) exiting/) || ($ThisLine =~ /^Garbage collection on own thread/) || ($ThisLine =~ /^Startup thread \d+ becoming garbage collector/) || ($ThisLine =~ /^Interrupted CtdlThreadSelect/) ) { # ignore lines } elsif ($ThisLine =~ /^(?:Thread|Created a new thread|Garbage Collection for thread|Waiting for thread)/) { if ( ($ThisLine =~ /^Thread system stopping thread/) || ($ThisLine =~ /^Waiting for thread/) || ($ThisLine =~ /^Thread .* caught signal/) ) { # ignore these lines } #TD: Created a new thread "SMTP Send" (0x40504950). elsif ($ThisLine =~ /Created a new thread "(.+)" \(([x0-9a-fA-F]+)\)/) { $Threads{"created"}{$1}{$2}++; } #TD: Thread "SMTP Send" (0x40504950) exited. #TD: Thread "RSS Client" (0x40605950) exited. elsif ($ThisLine =~ /^Thread "(.+)" \(([x0-9a-fA-F]+)\) exited/) { $Threads{"exited"}{$1}{$2}++; } #TD: Garbage Collection for thread "RSS Client" (0x40605950). elsif ($ThisLine =~ /^Garbage Collection for thread "(.+)" \(([x0-9a-fA-F]+)\)/) { $Threads{"garbage collection"}{$1}{$2}++; } else { # Report any unmatched entries... chomp($ThisLine); $OtherList{$ThisLine}++; } } ### Sessions ### elsif ( ($ThisLine =~ /^\[[ \d]+\] Session ended/) || ($ThisLine =~ /^Context: \[[ \d]+\]SRV\[(?:citadel-(?:TCP|UDS)|CitNetworker|rssclient|POP1aggr|POP3|POP3S|DICT_TCP|IMAP|IMAPS|LMTP|SMTP_Send|SMTP-MSA)\] Session ended/) || ($ThisLine =~ /^C(?:itadel c)?lient disconnected: ending session\.$/) || ($ThisLine =~ /^New client socket \d+$/) || ($ThisLine =~ /^Terminated \d+ idle sessions$/) || ($ThisLine =~ /^Context: Scheduled \d+ idle sessions for termination$/) || ($ThisLine =~ /^Context: Flushed \d+ stuck sessions$/) || ($ThisLine =~ /^Context: terminate_all_sessions\(\) is murdering/) || ($ThisLine =~ /^(Modules: )?\[(?:citadel-TCP|DICT_TCP)\] closing service$/) ) { # ignore these lines } #TD: Session (IMAPS) started from myhost (192.168.36.150) #TD: Session (citadel-TCP) started from localhost.localdomain (127.0.0.1). #TD: Session (LMTP) started via local socket UID:101. elsif ($ThisLine =~ /^Session \(([\w-]+)\) started (?:from (\S+) \(([\da-fA-F.:]+)\)|via (local socket) (UID:-?\d+))/) { $SessionStarted{$1}{"$2$4 [$3$5]"}++; $Session = "$1"; } ### RSS feed processing ### elsif ( ($ThisLine =~ /^\S+ has already been seen/) || ($ThisLine =~ /^RSS: XML Status \[\(null\)\]/) || ($ThisLine =~ /^RSS: This is an (?:RSS|RDF) feed/) || ($ThisLine =~ /^RSS: saving item/) || ($ThisLine =~ /^rssclient (?:started|ended)/) ) { # ignore these lines } #TD: Fetching RSS feed elsif ($ThisLine =~ /Fetching RSS feed <(\S+)>/) { $RSSfeeds{$1}++; } #TD: IO[968]CC[968][72]RSSPneed a 200, got a 302 ! elsif ($ThisLine =~ /^IO\[[ \d]+\]CC\[[ \d]+\]\[\d+\](RSS.?need a \d+, got a \d+)/) { $RSSerrors{"$1 (libcurl too old?)"}++; } ### serv_something processing ### elsif ($ThisLine =~ /^serv_extnotify: queue run completed/) { # ignore these lines } elsif ($ThisLine =~ /^serv_extnotify: processing notify queue/) { $serv_extnotify_queuerun++; } ### SMTP Client ### elsif ( ($ThisLine =~ /^SMTP(?:CQ| client): processing outbound queue/) || ($ThisLine =~ /^SMTP client: smtp_do_procmsg\(\d+\)$/) || ($ThisLine =~ /^SMTP(?:C| client): Trying <.*>/) || ($ThisLine =~ /^SMTP client: Attempting delivery to /) || ($ThisLine =~ /^SMTP client: connected!/) || ($ThisLine =~ /Number of MX hosts for /) || ($ThisLine =~ /^ addr=<.*> status=\d+ dsn=<.*>$/) || ($ThisLine =~ /^Done processing bounces$/) || ($ThisLine =~ /^SMTPCQ: Msg No \d+: already in progress!$/) ) { # ignore these lines } #TD: SMTP client: connecting to localhost : 25 ... #TD: SMTPC:IO[1025]CC[1025]S[198261][0] connecting to localhost [127.0.0.1]:25 ... elsif ($ThisLine =~ /^SMTP(?:C| client):(?:IO\[[ \d]+\]CC\[\d+\]S\[\d+\]\[\d+\])? connecting to (\S+) (?:\[[\.:\da-fA-F]*\])?: ?(\d+)/) { $SMTPclientConnect{"$1:$2"}++; } #TD: >EHLO valaskjalf.localside.net #TD: >MAIL FROM: #TD: >QUIT elsif ($ThisLine =~ /^>([A-Z ]+)(?::<(.+)>)?/) { $SMTPclientCMDS{$1}{$2}++; } #TD: SMTP client: delivery to @ (user) succeeded elsif ($ThisLine =~ /SMTP client: delivery to <(.*)> @ <(.*)> \(.*\) (\w+)$/) { $SMTPclientDelivery{$3}{$2}{$1}++; } #TD: SMTPC:IO[1025]CC[1025]S[198261][0] Delivery successful. Time[19.466858s] Recipient @ (name) Status message: 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as A61BE66B8008 elsif ($ThisLine =~ /^SMTPC:IO\[[ \d]+\]CC\[\d+\]S\[\d+\]\[\d+\] Delivery ([^.]+)\. Time\[([\d\.]+)s\] Recipient <(.*)> @ <(.*)> \(.*\) Status message: ([\d\.]{3,5}|[\s\w]+)/) { $SMTPclientDelivery{$1}{$4}{$3}++; $SMTPclientStats{$5}++; $SMTPclientTime+=$2; } #TD: 108319: to=, relay=localhost, stat=2.0.0 Ok, id=10168-06, from MTA([127.0.0.1]:10025): 250 2.0.0 Ok: queued as 2901498D0082 elsif ($ThisLine =~ /^\d+: to=<(.*)>, relay=(\S*), stat=([\d\.]{3,5}.*?),/) { if ($2 != "") { $SMTPclientRelay{$2}{$1}++; } $SMTPclientStats{$3}++; } #TD: key= addr= status=0 dsn=<> elsif ($ThisLine =~ /^key= addr=<(.*)> status=(\d+) dsn=<(.*)>$/) { $SMTPclientBounce{$1}{"$2: $3"}++; } #TD: num_bounces = 0 elsif ($ThisLine =~ /^num_bounces = (\d+)$/) { $SMTPclientBounces += $1; } #TD: SMTPCQ: queue run completed; 1 messages processed 1 activated elsif ($ThisLine =~ /^(?:SMTPCQ|SMTP client): queue run completed; (\d+) messages processed/) { $SMTPclient_queuerun++; $SMTPclient_messages += $1; } ### SMTP Server ### elsif ( ($ThisLine =~ /^Directory key is <.*>$/) || ($ThisLine =~ /is being forwarded to/) || ($ThisLine =~ /^[:\[] get \S*\]?$/) || ($ThisLine =~ /^<\d{3}[ -]\w+/) || ($ThisLine =~ /^SSL\/TLS using /) || ($ThisLine =~ /Ending SSL\/TLS$/) || ($ThisLine =~ /^(?:Performing|Finished) SMTP cleanup hook$/) || ($ThisLine =~ /^SMTP module clean up for shutdown/) || ($ThisLine =~ /^(Modules: )?\[LMTP(?:-UnF)?\] Closed UNIX domain socket/) || ($ThisLine =~ /^(Modules: )?\[SMTPs?-(?:MTA|MSA)\] closing service$/) || ($ThisLine =~ /^SMTP: client disconnected: ending session\.$/) || ($ThisLine =~ /^sending \d+ [A-Z]+ for the room/) # this belongs to validate_recipients() ) { # ignore these lines } elsif ($ThisLine =~ /^SMTP server:/) { #TD: SMTP server: LHLO vs243073.vserver.de if ($ThisLine =~ /^SMTP server: (?:LHLO|HELO|EHLO) (\S+)/i) { $SMTPserverHELO{$1}++; } #TD: SMTP server: RCPT TO: elsif ($ThisLine =~ /^SMTP server: RCPT TO: *]+)>?$/i) { $SMTPserverRCPT{$1}++; } #TD: SMTP server: MAIL FROM: SIZE=2982 BODY=7BIT elsif ($ThisLine =~ /^SMTP server: MAIL FROM: *]*)>?(?: SIZE=(\d+))?/i) { $SMTPserverFROM{$1}++; $SMTPBytesAccepted += $2; } #TD: SMTP server: DATA elsif ($ThisLine =~ /^SMTP server: (DATA|QUIT|STARTTLS|AUTH PLAIN|RSET)/i) { $SMTPserverCMDS{$1}++; } else { # Report any unmatched entries... chomp($ThisLine); $OtherList{$ThisLine}++; } } #TD: SMTP authenticated Stefan elsif ($ThisLine =~ /^SMTP authenticated (.*)$/) { $SMTPserverAuth{$1}++; } #TD: 108347: from=, nrcpts=1, relay= [], stat=250 Message accepted elsif ($ThisLine =~ /^\d+: from=<(.*)>, nrcpts=(\d+), relay=(.*) \[(\S*)\], stat=(\d{3})(.*)\./) { ## $SMTPserverNumRCPTs += $2; if ($4 != "") { $SMTPserverRelay{"$4 ($3)"}{$1}++; } $SMTPserverStats{$5}{$6}++; $SMTPserverStatsSum++; if ($5 =~ /^2\d\d$/) { $SMTPAccepted++; } if ($5 =~ /^[45]\d\d$/) { $SMTPRejected++; } } #TD: Evaluating recipient #0: stefan@localside.net elsif ($ThisLine =~ /^Evaluating recipient #\d+: (?:.*<)?([^\s<>]+)>?$/) { $SMTPserverEval{$1}++; } #TD: SSL_read got error 5 #TD: SSL_accept failed: retval=0, errval=5, err=error:00000005:lib(0):func(0):DH lib elsif ($ThisLine =~ /^SSL_(\S+) (?:got error |failed: retval=[-0-9]+, errval=)(\d+)/) { $SMTPSSLError{$1}{$2}++; } ### IMAP processing ### elsif ( ($ThisLine =~ /^\(That translates to/) || ($ThisLine =~ /^imap_do_expunge\(\) called/) || ($ThisLine =~ /^[\w ]+ already exists\.$/) || ($ThisLine =~ /^(?:before| after) update:/) || ($ThisLine =~ /^(?:Performing|Finished) IMAP cleanup hook$/) || ($ThisLine =~ /^Section is: \[.*\]/) || ($ThisLine =~ /^Converting CRLF to LF$/) || ($ThisLine =~ /^IMAP(?:CC\[[ \d]+\]|:) client disconnected: ending session/) || ($ThisLine =~ /^(Modules: )?\[IMAPS?\] closing service$/) ) { # ignore these lines } elsif ($ThisLine =~ /^IMAP/) { if ( ($ThisLine =~ /^IMAP(?:CC\[[ \d]+\]|:) $/) || ($ThisLine =~ /^IMAPCC\[[ \d]+\] not subordinate to inbox$/) ) { # ignore these lines } # improve: IMAPCmdDuration per Command. #TD: IMAP command completed in 0.1437 seconds elsif ($ThisLine =~ /^IMAP command completed in (\d+\.\d+) seconds/) { $IMAPCompletedCmds++; $IMAPCmdDuration += $1; } #TD: IMAP: 10117 NOOP #TD: IMAP: 10120 LIST "" "Server Level/%" #TD: IMAP: a003 LOGOUT elsif ($ThisLine =~ /^IMAP: \w?\d+ ([A-Z ]+)/) { $IMAPCmds{$1}++; } #TD: IMAP: LOGIN... #TD: IMAPCC[51121] LOGIN... elsif ($ThisLine =~ /^IMAP(?:CC\[[ \d]+\]|:) (LOGIN)/) { $IMAPCmds{$1}++; } else { # Report any unmatched entries... chomp($ThisLine); $OtherList{$ThisLine}++; } } #TD: logged in #TD: Context: logged in elsif ($ThisLine =~ /^(?:Context: )?<(.+)> logged in$/) { # this can be a POP or IMAP login my $user = lc($1); if ($Session =~ /^IMAPS?$/) { $IMAPUserLogin{$user}++; } elsif ($Session =~ /^POPS?/) { $POPUserLogin{$user}++; } elsif ($Session =~ /^(?:citadel-TCP|LMTP)$/) { #ignore } else { chomp($ThisLine); $OtherList{$ThisLine}++; } # $Session = ""; ## this may be wrong } #TD: Expunged 0 messages from elsif ($ThisLine =~ /^Expunged (\d+) messages from <(.+)>/) { if ($1 > 0) { $IMAPexpunge{$2} += $1; } } ### Citadel internal processing ### elsif ( ($ThisLine =~ /^Selected room/) || ($ThisLine =~ /^Performing before-save hooks$/) || ($ThisLine =~ /^Skipping hooks$/) || ($ThisLine =~ /^Saving to disk$/) || ($ThisLine =~ /^Creating MetaData record$/) || ($ThisLine =~ /^Storing pointers$/) || ($ThisLine =~ /^Updating user$/) || ($ThisLine =~ /^\d+ unique messages to be merged$/) || ($ThisLine =~ /^Performing room hooks for <.+>$/) || ($ThisLine =~ /^Performing after-save hooks$/) || ($ThisLine =~ /^Wordbreaking message \d+/) || ($ThisLine =~ /^Purge use table: /) || ($ThisLine =~ /^Purge (?:euid|EUID) index: /) || ($ThisLine =~ /^dead_session_purge\(\): purging session/) || ($ThisLine =~ /^RemoveContext\([\w-]+\) session/) || ($ThisLine =~ /^---- Looking up \[[A-Z]+\] -----$/) || ($ThisLine =~ /^(?:CC\[[ \d]+\])?Changed to <.*>$/) || ($ThisLine =~ /^do_fulltext_indexing\(\)/) || ($ThisLine =~ /^Indexed \d+ of \d+ messages/) || ($ThisLine =~ /^ft_index_message\(\) (?:adding|removing) msg/) || ($ThisLine =~ /^fixed_output(?:_pre|_post)?\(\) (?:part|type)/) || ($ThisLine =~ /^Skipping part \d+/) || ($ThisLine =~ /^Indexing message \d+ \[\d+ tokens\]/) || ($ThisLine =~ /^Indexing message #\d+ <.*>/) || ($ThisLine =~ /^Flush(?:ing|ed) index cache to disk/) || ($ThisLine =~ /^Delivering to room <.*>$/) || ($ThisLine =~ /^Returning to original room/) || ($ThisLine =~ /^(?:Context: )?User \d+ maps to/) || ($ThisLine =~ /^Auto-purger: (?:starting|finished)/) || ($ThisLine =~ /^Auto purger found a user \d+ with name <.*>$/) || ($ThisLine =~ /^Delivering private local mail to <.*>$/) || ($ThisLine =~ /^(?:CC\[[ \d]+\])?Final selection: /) || ($ThisLine =~ /^Processed \d+ message reference count adjustments/) || ($ThisLine =~ /^Generating delivery instructions$/) || ($ThisLine =~ /^Initializing (?:server extensions|ipgm secret)/) || ($ThisLine =~ /^Seeding the pseudo-random number generator/) || ($ThisLine =~ /^Registered (?:server command|a new .+ function)/) || ($ThisLine =~ /^Creating base rooms/) || ($ThisLine =~ /^Floor \d{1,3}: \d+ rooms/) || ($ThisLine =~ /^Server-hosted upgrade level is/) || ### report this as status ??? ($ThisLine =~ /^(?:Sieve: )?Extensions:/) || ($ThisLine =~ /registered\.$/) || ($ThisLine =~ /^Initiali(?:s|z)e modules, /) || ($ThisLine =~ /(?:_thread|startup|databases)\(\) (?:initializing|finished|started)/) || ($ThisLine =~ /^(?:Modules: )?Service \S+ has been manually disabled, skipping/) || ($ThisLine =~ /^Checking floor reference counts$/) || ($ThisLine =~ /^Changing uid to \d+$/) || ### report these files ??? ($ThisLine =~ /^Loading (?:citadel.config|\S+\/public_clients)$/) || ($ThisLine =~ /^Checking\/re-building control record$/) || ($ThisLine =~ /^Acquiring control record$/) || ($ThisLine =~ /^Path is /) || ($ThisLine =~ /^Cleaning up fulltext noise words\.$/) || ($ThisLine =~ /^Saving calendar UID <\S+>$/) || ($ThisLine =~ /^Raw length is \d+$/) || ($ThisLine =~ /^Allocating$/) || ($ThisLine =~ /Server hosted updates need to be processed at this time/) || ($ThisLine =~ /^User (?:0|-\d+) not found$/) || ($ThisLine =~ /^Deleted \d+ other msgs of this type$/) || ($ThisLine =~ /^diff length is \d+ bytes$/) || ($ThisLine =~ /^diff cmd/) || ($ThisLine =~ /^History page not being historied$/) || ($ThisLine =~ /^UID of vNote is: [0-9a-f-]+$/) || ($ThisLine =~ /^Part \d+ contains a vNote/) || ($ThisLine =~ /^\.\.\. yes its local\.$/) || ($ThisLine =~ /^Loaded module: /) || ($ThisLine =~ /^Waiting \d+ seconds for \d+ worker threads to exit$/) || ($ThisLine =~ /^Existing database version on disk is/) || ($ThisLine =~ /^Upgrad(?:ing|e) modules/) || ($ThisLine =~ /^Modules: (?:upgrade|Upgrade modules|Destroyed service)/) || ### report this as warning ??? ($ThisLine =~ /^Modules: Initializing\. CtdlThreads not yet enabled\.$/) || ($ThisLine =~ /^libcitadel\(unnumbered\)$/) || ($ThisLine =~ /^(Modules: )?\[citadel-UDS\] Closed UNIX domain socket/) || ($ThisLine =~ /^Found\.$/) || ($ThisLine =~ /^No external notifiers configured on system\/user$/) ) { # ignore these lines } #TD: validate_recipients() #TD: local: 1 #TD: room: 0 <> #TD: inet: 0 <> #TD: ignet: 0 <> #TD: error: -1 elsif ($ThisLine =~ /^(validate_recipients)\(\)$/) { $Ctdlcmds{$1}++; } elsif ($ThisLine =~ /^\s{1,2}(local|room|inet|ignet|error): -?(\d+) <(.*)>$/) { if ($2 > 0) { $CtdlValRcpt{$1}{$3} += $2; } } #TD: Deleting message <103425> elsif ($ThisLine =~ /Deleting message <(\d+)>$/) { $CtdlMsgDeleted++; } #TD: 7 message(s) deleted. elsif ($ThisLine =~ /(\d+) message\(s\) deleted\.$/) { # This belongs to CtdlDeleteMessages if ($1 > 0) { $CtdlMsgDeleted += $1; } } #TD: Expired 147 messages. #TD: Expired 0 rooms. #TD: Purged 0 visits. elsif ($ThisLine =~ /^(Expired|Purged) (\d+) (messages|rooms|visits|users|entries from the EUID index|stale OpenID associations|entries from the use table)/) { $CtdlCleanup{$1}{$3} += $2; } #TD: Context: New user created elsif ($ThisLine =~ /^(?:Context: )?New user <(.*)> created$/) { push(@CtdlUserCreated, $1); } #TD: Deleting log: /var/lib/citadel/data/log.0000004270 elsif ($ThisLine =~ /Deleting log: (.*)$/) { push(@CtdlLogDeleted, $1); } #TD: Deleting user #TD: Context: Deleting user elsif ($ThisLine =~ /^(?:Context: )?Deleting user <(.*)>$/) { push(@CtdlUserDeleted, $1); } #TD: Deleting room <00000000033.Tasks> elsif ($ThisLine =~ /^(?:Context: )?Deleting room <(.*)>$/) { push(@CtdlRoomDeleted, $1); } #TD: PurgeMessages() called elsif ($ThisLine =~ /(Purge(?:Messages|Rooms|Users))\(\) called$/) { $Ctdlcmds{$1}++; } #TD: qp_encode_email_addrs: [postfix-users@postfix.org] elsif ($ThisLine =~ /qp_encode_email_addrs: \[(.+)\]$/) { $Ctdlqp_encode{$1}++; } #TD: Message 0 appears to be corrupted elsif ($ThisLine =~ /Message (\d+) appears to be corrupted/) { $CtdlMsgCorrupted{$1}++; } #TD: Performing replication checks in elsif ($ThisLine =~ /Performing replication checks in <(.+)>$/) { $CtdlReplChecks{$1}{$2}++; } #TD: Adding contact: "Full Name" elsif ($ThisLine =~ /Adding contact: (.*)$/) { $CtdlAddContact{$1}++; } elsif ($ThisLine =~ /^Ctdl/) { if ($ThisLine =~ /^$/) { # ignore these lines } # ToDo: This can be done better #TD: CtdlFetchMessage(108265, 1) #TD: CtdlOutputPreLoadedMsg(TheMessage=not null, 1, 0, 0, 1 #TD: CtdlDeleteMessages(SpamAssassin-user, 1 msgs, ) #TD: CtdlCreateRoom(name=Contacts, type=4, view=2) # Contacts already exists. elsif ($ThisLine =~ /^Ctdl(\w+)\(/) { $Ctdlcmds{$1}++; } } #TD: chmod(/srv/citadel/data//cdb.03, 0600) returned 0 #TD: chown(/var/lib/citadel/data//cdb.08, CTDLUID, -1) returned 0 elsif ($ThisLine =~ /^(chown|chmod)\((.*), [A-Z0-9]+(?:, -?\d+)?\) returned (\d+)/) { $CtdlFileOp{$1}{$2}++; } #TD: Generating a self-signed certificate. #TD: Generating RSA key pair. elsif ($ThisLine =~ /^Generating(?: a)? (.+)\.$/ ) { $CtdlGenerate{$1}++; } #TD: client_write(13 bytes) failed: Broken pipe (32) elsif ($ThisLine =~ /^client_write\((\d+) bytes\) failed: (.+)$/) { $CtdlWriteFail{$2} += $1; } ### IGnet Networking ### elsif ( ($ThisLine =~ /^network: (?:running|loading) outbound queue$/) || ($ThisLine =~ /^network: (?:nothing in|processing) inbound queue/) || ($ThisLine =~ /^network: queue run completed/) || ($ThisLine =~ /^network: polling/) || ($ThisLine =~ /^NW\[\w*\]\[\d+\]: polling/) || ($ThisLine =~ /^>[0-9]{3} \w* (?:Citadel|as network|talking to)/) || ($ThisLine =~ /^nttlist= to <\S+>$/) || ($ThisLine =~ /^network_process_buffer\(\) processing \d+ bytes$/) || ($ThisLine =~ /^Expecting to transfer \d+ bytes$/) || ($ThisLine =~ /^network_usetable\(\) : /) || ($ThisLine =~ /^(?:CC\[[ \d]+\])?(?:Not )?(?:s|S)ending to \S+$/) || ($ThisLine =~ /^(?:Appending to|Consolidate) \//) || ($ThisLine =~ /^(?:CC\[[ \d]+\])?Invalid node (?:name )?<\S+>$/) || ($ThisLine =~ /^(?:CC\[[ \d]+\])?skipping Spoolcleanup because of \d+ files unprocessed\.$/) ) { # ignore these lines } #TD: Networking started for <0000000007.Mail> elsif ($ThisLine =~ /^Networking started for <(.+)>$/) { $NetStarts{$1}++; } #TD: Network full processing in 1021 seconds. elsif ($ThisLine =~ /^Network full processing in (\d+) seconds/) { $NetProcessingCount++; $NetProcessingTime += $1; } #TD: Network node logged in from example.com [10.0.0.1] elsif ($ThisLine =~ /^Network node <(.+)> logged in from (.*)/) { $NetNodes{"Logins from"}{$1}{$2}++; } #TD: Connecting to at example.com:504 #TD: IO[13221]CC[13221]NW[genux][8624]Connecting to at example.com:504 elsif ($ThisLine =~ /^(?:IO\[\d+\]CC\[\d+\]NW\[\w+\]\[\d+\])?Connecting to <(.+)> at (.*)/) { $NetNodes{"Connects to"}{$1}{$2}++; $NetNode=$1; $NetHost=$2; } #TD: Sent 0 octets to #TD: IO[49977]CC[49977]NW[valaskjalf][49972]Sent 0 octets to elsif ($ThisLine =~ /^(?:IO\[\d+\]CC\[\d+\]NW\[\w+\]\[\d+\])?Sent (\d+) octets to <(.+)>/) { $NetNodes{"Bytes sent to"}{$2}{""} += $1; } #TD: Can't connect to example.com:504: Connection timed out elsif ($ThisLine =~ /^Can't connect to (.+): (.+)$/) { $NetNoConnect{"Can't connect to"}{$1}{$2}++; } #TD: connect() failed: Connection timed out elsif ($ThisLine =~ /^connect\(\) failed: Connection timed out$/) { $NetNoConnect{"Can't connect to"}{$NetNode}{$NetHost}++; } #TD: Can't get example.com host entry: Connection timed out elsif ($ThisLine =~ /^Can't get (.+) host entry: (.+)$/) { $NetNoConnect{"Can't get host entry"}{$1}{$2}++; } #TD: EVCURL:IO[4515]CC[4515] error description: Failed to connect to 2a00:1450:8005::79: Network is unreachable elsif ($ThisLine =~ /^EVCURL:IO\[[ \d]+\]CC\[\d+\] error description: (Failed (?:to )?connect to) (.*)(?::|;) (.*)/) { $NetNoConnect{"$3"}{$1}{$2}++; $NetNode=$1; $NetHost=$2; } #TD: EVCURL:IO[4515]CC[4515] error description: Recv failure: Connection reset by peer #TD: EVCURL:IO[2152]CC[2752] error description: The requested URL returned error: 404 elsif ($ThisLine =~ /^EVCURL:IO\[[ \d]+\]CC\[\d+\] error description: (Recv failure: |Couldn't resolve host |Empty reply from server|The requested URL returned error: )(.*)/) { $NetNoConnect{"$2"}{"$1"}{""}++; } #TD: EVCURL:IO[4515]CC[4515] error performing request: Couldn't connect to server elsif ($ThisLine =~ /^EVCURL:IO\[[ \d]+\]CC\[\d+\] error performing request: (.*)/) { $NetNoConnect{"$1"}{$NetNode}{$NetHost}++; # That isn't correct !!! } #TD: network: processing 0 bytes from /var/spool/citadel/network/spoolin//genux.0e73.012a #TD: CC[0]network: processing 426944 bytes from /var/spool/citadel/network/spoolin//wk.64c1.000a elsif ($ThisLine =~ /^(?:CC\[[ \d]+\])?network: processing (\d+) bytes from \/\S+\/spool\/citadel\/network\/spoolin\/+(\w+)\.[\.0-9a-f]+$/) { $NetNodes{"Bytes download from"}{$2}{""} += $1 } #TD: Duplicate session for network node elsif ($ThisLine =~ /^Duplicate session for network node <(\S+)>$/) { $NetNodes{"Duplicate session"}{$1}{""}++; } #TD: IO[50917]CC[50917]NW[wk][31235]Already talking to wk; skipping this time. elsif ($ThisLine =~ /^IO\[[ \d]+\]CC\[\d+\]NW\[(\w+)\]\[\d+\]Already talking to \w+; skipping this time\.$/) { $NetNodes{"Already talking to"}{$1}{""}++; } #TD: Removing elsif ($ThisLine =~ /^Removing <(\S+)>$/) { $NetFilesRemoved{$1}++; } #TD: >540 authentication failed elsif ($ThisLine =~ /^>5\d\d authentication failed$/) { $NetNodes{"Authentication failed to"}{$NetNode}{$NetHost}++; } #TD: An unknown Citadel server called "node" attempted to connect from name [1.1.1.1]. elsif ($ThisLine =~ /^An unknown Citadel server called "(\S*)" attempted to connect from (\S*) \[(\S+)\]/) { $NetNodes{"Attempted connects"}{$1}{"$2 [$3]"}++; } #TD: Connected to node "" but I was expecting to connect to node "node". elsif ($ThisLine =~ /^Connected to node "(\S*)" but I was expecting to connect to node "(\S*)"/) { $NetNodes{"Connects to server with wrong node name"}{"$2 (as $1)"}{""}++; } #TD: A Citadel server at example.com [10.0.0.1] failed to authenticate as network node "node". elsif ($ThisLine =~ /A Citadel server at (\S+) \[(\S+)\] failed to authenticate as network node "(\S*)"/) { $NetNodes{"Authentication failed from"}{$3}{"$1 [$2]"}++; } ### web access ### elsif ( ($ThisLine =~ /^New client socket \d+/) || ($ThisLine =~ /^Closing socket -?\d+/) || ($ThisLine =~ /^Checking whether [0-9a-fA-F:.]+ is a local or public client/) || ($ThisLine =~ /^\.\.\. yes it is/) || ($ThisLine =~ /^Looking up hostname '/) || ($ThisLine =~ /^Client \d\/\d\/[\d.]+ \(.*\)/) || ($ThisLine =~ /^(?:\[\d+\]\[.*\] )?