On Fri, Dec 16, 2005 at 09:22:49AM +0100, Arnaud Quette wrote:
> 2005/12/15, Alexander V. Inyukhin <[EMAIL PROTECTED]>:
>
> > I think it is a good idea to log ups variables to rrd
> > database instead of log file. So, I create standalone
> > rrd logger dervied from upslog nut client.
> > Of course, this could be easily implemented using
> > upsc or upslog clients and a cron script
> > but stanalone application is better for some reasons.
> >
> > Does anybody else need this functionality?
> > Should such a client be included in the nut
> > (with additional librrd dependency) or nut-rrd
> > package or distributed separately?
>
>
> interesting point: I'm thinking of some logging improvements, such as:
> - making upslog a real daemon, able to log data from several UPSs,
> - making log asynchronous and smart (ie log only things that have changed),
> - switching by default to a NUT specific logfile (ie upsd.log), instead of
> the syslog default,
> - adding the ability to log to other system, such as RRD...
>
> So, I'm definitly interested in your work.
Source files of upsrrd daemon and sample init.d script
are attached. Differences from upslog are minimal:
data is recorded by rrd_update using fixed log format,
log format can't be changed from command line,
so option -f and most parts of parser are removed,
invalid values are printed as 'U', and there is
no need for log rotation.
Errors while updating database will be written to syslog.
I intentionally left the rest of parser for
possible modifications of list variables in the future.
To complile daemon sources should be placed into the clients
subdirectory of nut package and appropriate Makefile rules
should be created (based on upslog rules).
Obviously, upsrrd should be linked with -lrrd and requres
librrd2-dev for building and librrd2 for execution.
Sample init.d script has hardcoded daemon command line,
which should be placed into config file.
Database could be created with following command
(I also use rrdcollect and place ups logs there):
rrdtool create /var/lib/rrdcollect/ups.rrd -s 30 \
DS:bat_charge:GAUGE:75:0:100 DS:line_voltage:GAUGE:75:0:U \
DS:ups_load:GAUGE:75:0:100 DS:ups_temp:GAUGE:75:U:U \
DS:line_freq:GAUGE:75:0:U DS:bat_voltage:GAUGE:75:0:U \
DS:bat_runtime:GAUGE:75:0:U RRA:AVERAGE:0.5:10:21
I think this daemon with some reasonable defaults
might be appropriate for most users.
/* upsrrd - log ups values to a file for later collection and analysis
Copyright (C) 1998 Russell Kroll <[EMAIL PROTECTED]>
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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* Basic theory of operation:
*
* First we go through and parse as much of the status format string as
* possible. We used to do this parsing run every time, but that's a
* waste of CPU since it can't change during the program's run.
*
* This version does the parsing pass once, and creates a linked list of
* pointers to the functions that do the work and the arg they get.
*
* That means the main loop just has to run the linked list and call
* anything it finds in there. Everything happens from there, and we
* don't have to pointlessly reparse the string every time around.
*/
#include
#include "common.h"
#include "upsclient.h"
#include "config.h"
#include "timehead.h"
#include "upsrrd.h"
static int port, exit_flag = 0;
static char *upsname, *hostname;
static UPSCONN ups;
static const char *logfn, *monhost;
static sigset_t nut_upsrrd_sigmask;
static char logbuffer[LARGEBUF];
static struct flist_t *fhead = NULL;
#define DEFAULT_LOGFORMAT "N:%VAR battery.charge%:" \
"%VAR input.voltage%:%VAR ups.load%:" \
"%VAR ups.temperature%:%VAR input.frequency%:" \
"%VAR battery.voltage%:%VAR battery.runtime%"
const char *logformat = DEFAULT_LOGFORMAT;
static void set_exit_flag(int sig)
{
exit_flag = sig;
}
/* handlers: reload on HUP, exit on INT/QUIT/TERM */
static void setup_signals(void)
{
struct sigaction sa;
sigemptyset(&nut_upsrrd_sigmask);
sigaddset(&nut_upsrrd_sigmask, SIGHUP);
sa.sa_mask = nut_upsrrd_sigmask;
sa.sa_flags = 0;
sa.sa_handler = set_exit_flag;
if (sigaction(SIGINT, &sa, NULL) < 0)
fatal("Can't install SIGINT handler");
if (sigaction(SIGQUIT, &sa, NULL) < 0)
fatal("Can't install SIGQUIT handler");
if (sigaction(SIGTERM, &sa, NULL) < 0)
fatal("Can't install SIGT