diff options
Diffstat (limited to 'src/pmdas/rsyslog')
-rw-r--r-- | src/pmdas/rsyslog/GNUmakefile | 48 | ||||
-rwxr-xr-x | src/pmdas/rsyslog/Install | 44 | ||||
-rwxr-xr-x | src/pmdas/rsyslog/Remove | 25 | ||||
-rw-r--r-- | src/pmdas/rsyslog/pmdarsyslog.pl | 249 |
4 files changed, 366 insertions, 0 deletions
diff --git a/src/pmdas/rsyslog/GNUmakefile b/src/pmdas/rsyslog/GNUmakefile new file mode 100644 index 0000000..db3914a --- /dev/null +++ b/src/pmdas/rsyslog/GNUmakefile @@ -0,0 +1,48 @@ +#!gmake +# +# Copyright (c) 2011 Aconex. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# + +TOPDIR = ../../.. +include $(TOPDIR)/src/include/builddefs + +IAM = rsyslog +PMDADIR = $(PCP_PMDAS_DIR)/$(IAM) +LSRCFILES = Install Remove pmda$(IAM).pl +LDIRT = domain.h root pmns *.log $(MAN_PAGES) + +ifneq ($(POD2MAN),) +MAN_SECTION = 1 +MAN_PAGES = pmda$(IAM).$(MAN_SECTION) +MAN_DEST = $(PCP_MAN_DIR)/man$(MAN_SECTION) +endif + +default: check_domain $(MAN_PAGES) + +pmda$(IAM).1: pmda$(IAM).pl + $(POD_MAKERULE) + +include $(BUILDRULES) + +install: default + $(INSTALL) -m 755 -d $(PMDADIR) + $(INSTALL) -m 755 Install Remove $(PMDADIR) + $(INSTALL) -m 644 pmda$(IAM).pl $(PMDADIR)/pmda$(IAM).pl + @$(INSTALL_MAN) + +default_pcp : default + +install_pcp : install + +check_domain: ../../pmns/stdpmid + $(DOMAIN_PERLRULE) diff --git a/src/pmdas/rsyslog/Install b/src/pmdas/rsyslog/Install new file mode 100755 index 0000000..33d2ac8 --- /dev/null +++ b/src/pmdas/rsyslog/Install @@ -0,0 +1,44 @@ +#!/bin/sh +# +# Copyright (c) 2012 Red Hat. +# Copyright (c) 2011 Aconex. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# Install the rsyslog PMDA +# + +. $PCP_DIR/etc/pcp.env +. $PCP_SHARE_DIR/lib/pmdaproc.sh + +iam=rsyslog +perl_opt=true +daemon_opt=false +forced_restart=false + +statsfile="$PCP_LOG_DIR/rsyslog/stats" +statsdir=`dirname "$statsfile"` + +if ! test -d "$statsdir"; then + echo "Creating rsyslog statistics file directory: $statsdir" + mkdir "$statsdir" + [ $? -eq 0 ] || exit 1 +fi + +if ! test -p "$statsfile"; then + echo "Creating rsyslog statistics file: $statsfile" + mkfifo "$statsfile" + [ $? -eq 0 ] || exit 1 +fi + +pmdaSetup +pmdaInstall +exit 0 diff --git a/src/pmdas/rsyslog/Remove b/src/pmdas/rsyslog/Remove new file mode 100755 index 0000000..d460669 --- /dev/null +++ b/src/pmdas/rsyslog/Remove @@ -0,0 +1,25 @@ +#!/bin/sh +# +# Copyright (c) 2011 Aconex. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# Remove the rsyslog PMDA +# + +. $PCP_DIR/etc/pcp.env +. $PCP_SHARE_DIR/lib/pmdaproc.sh + +iam=rsyslog + +pmdaSetup +pmdaRemove +exit 0 diff --git a/src/pmdas/rsyslog/pmdarsyslog.pl b/src/pmdas/rsyslog/pmdarsyslog.pl new file mode 100644 index 0000000..e3972f9 --- /dev/null +++ b/src/pmdas/rsyslog/pmdarsyslog.pl @@ -0,0 +1,249 @@ +# +# Copyright (c) 2012-2013 Red Hat. +# Copyright (c) 2011 Aconex. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# + +use strict; +use warnings; +use PCP::PMDA; + +my $pmda = PCP::PMDA->new('rsyslog', 107); +my $statsfile = pmda_config('PCP_LOG_DIR') . '/rsyslog/stats'; +my ($es_connfail, $es_submits, $es_failed, $es_success) = (0,0,0,0); +my ($ux_submitted, $ux_discarded, $ux_ratelimiters) = (0,0,0); +my ($interval, $lasttime) = (0,0); + +my $queue_indom = 0; +my @queue_insts = (); +use vars qw(%queue_ids %queue_values); + +# .* rsyslogd-pstats: +# imuxsock: submitted=37 ratelimit.discarded=0 ratelimit.numratelimiters=22 +# elasticsearch: connfail=0 submits=0 failed=0 success=0 +# [main Q]: size=1 enqueued=1436 full=0 maxqsize=3 + +sub rsyslog_parser +{ + ( undef, $_ ) = @_; + + #$pmda->log("rsyslog_parser got line: $_"); + if (m|rsyslogd-pstats:|) { + my $timenow = time; + if ($lasttime != 0) { + if ($timenow > $lasttime) { + $interval = $timenow - $lasttime; + $lasttime = $timenow; + } + } else { + $lasttime = $timenow; + } + } + if (m|imuxsock: submitted=(\d+) ratelimit.discarded=(\d+) ratelimit.numratelimiters=(\d+)|) { + ($ux_submitted, $ux_discarded, $ux_ratelimiters) = ($1,$2,$3); + } + elsif (m|elasticsearch: connfail=(\d+) submits=(\d+) failed=(\d+) success=(\d+)|) { + ($es_connfail, $es_submits, $es_failed, $es_success) = ($1,$2,$3,$4); + } + elsif (m|stats: (.+): size=(\d+) enqueued=(\d+) full=(\d+) maxqsize=(\d+)|) { + my ($qname, $qid) = ($1, undef); + + if (!defined($queue_ids{$qname})) { + $qid = @queue_insts / 2; + $queue_ids{$qname} = $qid; + push @queue_insts, ($qid, $qname); + $pmda->replace_indom($queue_indom, \@queue_insts); + } + $queue_values{$qname} = [ $2, $3, $4, $5 ]; + } +} + +sub rsyslog_fetch_callback +{ + my ($cluster, $item, $inst) = @_; + + #$pmda->log("rsyslog_fetch_callback for PMID: $cluster.$item ($inst)"); + + return (PM_ERR_AGAIN,0) unless ($interval != 0); + + if ($cluster == 0) { + return (PM_ERR_INST, 0) unless ($inst == PM_IN_NULL); + if ($item == 0) { return ($interval, 1); } + if ($item == 1) { return ($ux_submitted, 1); } + if ($item == 2) { return ($ux_discarded, 1); } + if ($item == 3) { return ($ux_ratelimiters, 1); } + if ($item == 8) { return ($es_connfail, 1); } + if ($item == 9) { return ($es_submits, 1); } + if ($item == 10){ return ($es_failed, 1); } + if ($item == 11){ return ($es_success, 1); } + } + elsif ($cluster == 1) { # queues + return (PM_ERR_INST, 0) unless ($inst != PM_IN_NULL); + return (PM_ERR_INST, 0) unless ($inst <= @queue_insts); + my $qname = $queue_insts[$inst * 2 + 1]; + my $qvref = $queue_values{$qname}; + my @qvals; + + return (PM_ERR_INST, 0) unless defined ($qvref); + @qvals = @$qvref; + + if ($item == 0) { return ($qvals[0], 1); } + if ($item == 1) { return ($qvals[1], 1); } + if ($item == 2) { return ($qvals[2], 1); } + if ($item == 3) { return ($qvals[3], 1); } + } + return (PM_ERR_PMID, 0); +} + +die "Cannot find a valid rsyslog statistics named pipe\n" unless -p $statsfile; + +$pmda->connect_pmcd; + +$pmda->add_metric(pmda_pmid(0,0), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, + pmda_units(0,1,0,0,PM_TIME_SEC,0), 'rsyslog.interval', + 'Time interval observed between samples', ''); +$pmda->add_metric(pmda_pmid(0,1), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + pmda_units(0,0,1,0,0,PM_COUNT_ONE), 'rsyslog.imuxsock.submitted', + 'Cumulative count of unix domain socket input messages queued', + "Cumulative count of messages successfully queued to the rsyslog\n" . + "main message queueing core that arrived on unix domain sockets."); +$pmda->add_metric(pmda_pmid(0,2), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + pmda_units(0,0,1,0,0,PM_COUNT_ONE), 'rsyslog.imuxsock.discarded', + 'Count of unix domain socket messages discarded due to rate limiting', + "Cumulative count of messages that are were discarded due to their\n" . + "priority being at or below rate-limit-severity and their sending\n" . + "process being deemed to be sending messages too quickly (refer to\n" . + "parameters ratelimitburst, ratelimitinterval and ratelimitseverity"); +$pmda->add_metric(pmda_pmid(0,3), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + pmda_units(0,0,0,0,0,0), 'rsyslog.imuxsock.numratelimiters', + 'Count of messages received that could be subject to rate limiting', + "Cumulative count of messages that rsyslog received and performed a\n" . + "credentials (PID) lookup for subsequent rate limiting decisions.\n" . + "The message would have to be at rate-limit-severity or lower, with\n" . + "rate limiting enabled, in order for this count to be incremented."); +$pmda->add_metric(pmda_pmid(0,8), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + pmda_units(0,0,1,0,0,PM_COUNT_ONE), 'rsyslog.elasticsearch.connfail', + 'Count of failed connections while attempting to send events', ''); +$pmda->add_metric(pmda_pmid(0,9), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + pmda_units(0,0,1,0,0,PM_COUNT_ONE), 'rsyslog.elasticsearch.submits', + 'Count of valid submissions of events to elasticsearch indexer', ''); +$pmda->add_metric(pmda_pmid(0,10), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + pmda_units(0,0,1,0,0,PM_COUNT_ONE), 'rsyslog.elasticsearch.failed', + 'Count of failed attempts to send events to elasticsearch', + 'This count is often a good indicator of malformed JSON messages'); +$pmda->add_metric(pmda_pmid(0,11), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + pmda_units(0,0,1,0,0,PM_COUNT_ONE), 'rsyslog.elasticsearch.success', + 'Count of successfully acknowledged events from elasticsearch', ''); + +$pmda->add_metric(pmda_pmid(1,0), PM_TYPE_U64, $queue_indom, PM_SEM_INSTANT, + pmda_units(0,0,0,0,0,0), 'rsyslog.queues.size', + 'Current queue depth for each rsyslog queue', + "As messages arrive they are enqueued to the main message queue\n" . + "(for example) -this counter is incremented for each such message."); +$pmda->add_metric(pmda_pmid(1,1), PM_TYPE_U64, $queue_indom, PM_SEM_COUNTER, + pmda_units(0,0,1,0,0,PM_COUNT_ONE), 'rsyslog.queues.enqueued', + 'Cumulative count of nessages enqueued to individual queues', + "As messages arrive they are added to the main message processing\n" . + "queue, either individually or in batches in the case of messages\n" . + "arriving on the network."); +$pmda->add_metric(pmda_pmid(1,2), PM_TYPE_U64, $queue_indom, PM_SEM_COUNTER, + pmda_units(0,0,1,0,0,PM_COUNT_ONE), 'rsyslog.queues.full', + 'Cumulative count of message arrivals with a full queue', + "When messages are enqueued, a check is first made to ensure the\n" . + "queue is not full. If it is, this counter is incremented. The\n" . + "full-queue-handling logic will wait for a configurable time for\n" . + "the queue congestion to ease, failing which the message will be\n" . + "discarded. Worth keeping an eye on this metric, as it indicates\n" . + "rsyslog is not able to process messages quickly enough given the\n" . + "current arrival rate."); +$pmda->add_metric(pmda_pmid(1,3), PM_TYPE_U64, $queue_indom, PM_SEM_INSTANT, + pmda_units(0,0,1,0,0,PM_COUNT_ONE), 'rsyslog.queues.maxsize', + 'Maximum depth reached by an individual queue', + "When messages arrive (for example) they are enqueued to the main\n" . + "message queue - if the queue length on arrival is now greater than\n" . + "ever before observed, we set this value to the current queue size"); + +$pmda->add_indom($queue_indom, \@queue_insts, + 'Instance domain exporting each rsyslog queue', ''); + +$pmda->add_tail($statsfile, \&rsyslog_parser, 0); +$pmda->set_fetch_callback(\&rsyslog_fetch_callback); +$pmda->set_user('pcp'); +$pmda->run; + +=pod + +=head1 NAME + +pmdarsyslog - rsyslog (reliable and extended syslog) PMDA + +=head1 DESCRIPTION + +B<pmdarsyslog> is a Performance Metrics Domain Agent (PMDA) which +exports metric values from the rsyslogd(8) server. +Further details about rsyslog can be found at http://www.rsyslog.com/. + +=head1 INSTALLATION + +If you want access to the names and values for the rsyslog performance +metrics, do the following as root: + + # cd $PCP_PMDAS_DIR/rsyslog + # ./Install + +If you want to undo the installation, do the following as root: + + # cd $PCP_PMDAS_DIR/rsyslog + # ./Remove + +B<pmdarsyslog> is launched by pmcd(1) and should never be executed +directly. The Install and Remove scripts notify pmcd(1) when +the agent is installed or removed. + +In order to use this agent, rsyslog stats gathering must be enabled. +This is done by adding the lines: + + $ModLoad impstats + $PStatsInterval 5 # log every 5 seconds + syslog.info |/var/log/pcp/rsyslog/stats + +to your rsyslog.conf(5) configuration file after installing the PMDA. +Take care to ensure the syslog.info messages do not get logged in any +other file, as this could unexpectedly fill your filesystem. Syntax +useful for this is syslog.!=info for explicitly excluding these. + +=head1 FILES + +=over + +=item /var/log/pcp/rsyslog/stats + +named pipe containing statistics exported from rsyslog, +usually created by the PMDA Install script. + +=item $PCP_PMDAS_DIR/rsyslog/Install + +installation script for the B<pmdarsyslog> agent + +=item $PCP_PMDAS_DIR/rsyslog/Remove + +undo installation script for the B<pmdarsyslog> agent + +=item $PCP_LOG_DIR/pmcd/rsyslog.log + +default log file for error messages from B<pmdarsyslog> + +=back + +=head1 SEE ALSO + +pmcd(1), rsyslog.conf(5), rsyslogd(8). |