[collectd] Patch to apcups.c

Anthony Gialluca tonyabg at charter.net
Fri May 19 13:32:58 CEST 2006


Hi all,

>big sigh<   I already have a patch to the plugin I submitted.

1. (major) The code in apcups.c was adapted from apcupsd-3.12.3 the command
'apcaccess status'.  The code I used calls 'exit()' if it cannot connect
to the apcupsd
daemon. A reasonable action for a standalone program. Not good for a
monitoring
daemon.  This was completely an oversight on my part.  Mea Culpa...

2. (minor) Some dead code is now defined out if "APCMAIN" is not defined.

3. (minor) My units in "collection.cgi" where incorrect.

4. (minor) if the apcups plugin cannot connect to the apcupsd it will
simply not call the
submit routines allowing the rrd files to fill with NAN as expected,
rather than submitting
zeros.

Sorry for the inconvenience.  As before please use with caution till it
has been used more
extensively.

Sincerely,
Tony

<<<< Patch starts here <<<<
Index: contrib/collection.cgi
===================================================================
--- contrib/collection.cgi    (revision 733)
+++ contrib/collection.cgi    (working copy)
@@ -774,6 +774,93 @@
             'GPRINT:max:MAX:%5.1lf%sV Max,',
             'GPRINT:avg:LAST:%5.1lf%sV Last\l'
         ],
+        apcups_volt => [
+            'DEF:line_avg={file}:linev:AVERAGE',
+            'DEF:line_min={file}:linev:MIN',
+            'DEF:line_max={file}:linev:MAX',
+            'DEF:out_avg={file}:outputv:AVERAGE',
+            'DEF:out_min={file}:outputv:MIN',
+            'DEF:out_max={file}:outputv:MAX',
+            #"AREA:line_max#$HalfBlue",
+            #"AREA:line_min#$Canvas",
+            #"AREA:out_avg#$HalfGreen",
+            "LINE1:line_avg#$FullBlue:Line Volt",
+            'GPRINT:line_min:MIN:%5.1lf%sV Min,',
+            'GPRINT:line_avg:AVERAGE:%5.1lf%sV Avg,',
+            'GPRINT:line_max:MAX:%5.1lf%sV Max,',
+            'GPRINT:line_avg:LAST:%5.1lf%sV Last\l',
+            "LINE2:out_avg#$FullGreen:Out  Volt",
+            'GPRINT:out_min:MIN:%5.1lf%sV Min,',
+            'GPRINT:out_avg:AVERAGE:%5.1lf%sV Avg,',
+            'GPRINT:out_max:MAX:%5.1lf%sV Max,',
+            'GPRINT:out_avg:LAST:%5.1lf%sV Last\l'
+        ],
+        apcups_bvolt => [
+            'DEF:bvolt_avg={file}:battv:AVERAGE',
+            'DEF:bvolt_min={file}:battv:MIN',
+            'DEF:bvolt_max={file}:battv:MAX',
+            "AREA:bvolt_max#$HalfBlue",
+            "LINE1:bvolt_avg#$FullBlue:Batt Volt",
+            'GPRINT:bvolt_min:MIN:%5.1lf%sV Min,',
+            'GPRINT:bvolt_avg:AVERAGE:%5.1lf%sV Avg,',
+            'GPRINT:bvolt_max:MAX:%5.1lf%sV Max,',
+            'GPRINT:bvolt_avg:LAST:%5.1lf%sV Last\l',
+        ],
+        apcups_load => [
+            'DEF:load_avg={file}:loadpct:AVERAGE',
+            'DEF:load_min={file}:loadpct:MIN',
+            'DEF:load_max={file}:loadpct:MAX',
+            "AREA:load_max#$HalfBlue",
+            "LINE1:load_avg#$FullBlue:Batt load",
+            'GPRINT:load_min:MIN:%5.1lf%s%% Min,',
+            'GPRINT:load_avg:AVERAGE:%5.1lf%s%% Avg,',
+            'GPRINT:load_max:MAX:%5.1lf%s%% Max,',
+            'GPRINT:load_avg:LAST:%5.1lf%s%% Last\l',
+        ],
+        apcups_charge => [
+            'DEF:charge_avg={file}:bcharge:AVERAGE',
+            'DEF:charge_min={file}:bcharge:MIN',
+            'DEF:charge_max={file}:bcharge:MAX',
+            "AREA:charge_max#$HalfBlue",
+            "LINE1:charge_avg#$FullBlue:Batt Charge",
+            'GPRINT:charge_min:MIN:%5.1lf%s%% Min,',
+            'GPRINT:charge_avg:AVERAGE:%5.1lf%s%% Avg,',
+            'GPRINT:charge_max:MAX:%5.1lf%s%% Max,',
+            'GPRINT:charge_avg:LAST:%5.1lf%s%% Last\l',
+        ],
+        apcups_time => [
+            'DEF:time_avg={file}:timeleft:AVERAGE',
+            'DEF:time_min={file}:timeleft:MIN',
+            'DEF:time_max={file}:timeleft:MAX',
+            "AREA:time_max#$HalfBlue",
+            "LINE1:time_avg#$FullBlue:Time Avail",
+            'GPRINT:time_min:MIN:%5.1lf%smin Min,',
+            'GPRINT:time_avg:AVERAGE:%5.1lf%smin Avg,',
+            'GPRINT:time_max:MAX:%5.1lf%smin Max,',
+            'GPRINT:time_avg:LAST:%5.1lf%smin Last\l',
+        ],
+        apcups_temp => [
+            'DEF:temp_avg={file}:itemp:AVERAGE',
+            'DEF:temp_min={file}:itemp:MIN',
+            'DEF:temp_max={file}:itemp:MAX',
+            "AREA:temp_max#$HalfBlue",
+            "LINE1:temp_avg#$FullBlue:Temp Avail",
+            'GPRINT:temp_min:MIN:%5.1lf%s° Min,',
+            'GPRINT:temp_avg:AVERAGE:%5.1lf%s° Avg,',
+            'GPRINT:temp_max:MAX:%5.1lf%s° Max,',
+            'GPRINT:temp_avg:LAST:%5.1lf%s° Last\l',
+        ],
+        apcups_freq => [
+            'DEF:freq_avg={file}:linefreq:AVERAGE',
+            'DEF:freq_min={file}:linefreq:MIN',
+            'DEF:freq_max={file}:linefreq:MAX',
+            "AREA:freq_max#$HalfBlue",
+            "LINE1:freq_avg#$FullBlue:Line Freq",
+            'GPRINT:freq_min:MIN:%5.1lf%sHz Min,',
+            'GPRINT:freq_avg:AVERAGE:%5.1lf%sHz Avg,',
+            'GPRINT:freq_max:MAX:%5.1lf%sHz Max,',
+            'GPRINT:freq_avg:LAST:%5.1lf%sHz Last\l',
+        ],
         vs_threads => [
             "DEF:total_avg={file}:total:AVERAGE",
             "DEF:total_min={file}:total:MIN",
@@ -891,6 +978,13 @@
     traffic => ['-t', '{host} {inst} traffic', '-v', 'Bit/s'],
     users => ['-t', '{host} users', '-v', 'Users'],
     voltage => ['-t', '{host} voltage', '-v', 'Volts'],
+    apcups_volt => ['-t', '{host} APC voltage {inst}', '-v', 'Volts AC'],
+    apcups_bvolt => ['-t', '{host} APC Batt voltage {inst}', '-v',
'Volts DC'],
+    apcups_load => ['-t', '{host} APC Load {inst}', '-v', 'Percent'],
+    apcups_charge => ['-t', '{host} APC Batt Charge {inst}', '-v',
'Percent'],
+    apcups_time => ['-t', '{host} APC Time Left {inst}', '-v', 'Minutes'],
+    apcups_temp => ['-t', '{host} APC Internal Temp {inst}', '-v',
'°Celsius'],
+    apcups_freq => ['-t', '{host} APC Line Freq {inst}', '-v', 'Hz'],
     vs_threads => ['-t', '{host} threads', '-v', 'Threads'],
     vs_memory => ['-t', '{host} memory usage', '-v', 'Bytes'],
     vs_processes => ['-t', '{host} processes', '-v', 'Processes'],
@@ -902,6 +996,13 @@
     cpu    => \&output_graph_cpu,
     cpufreq => 1,
     disk    => 1,
+    apcups_volt => 1,
+    apcups_bvolt => 1,
+    apcups_load => 1,
+    apcups_charge => 1,
+    apcups_time => 1,
+    apcups_temp => 1,
+    apcups_freq => 1,
     load    => 0,
     mails    => 0,
     memory    => 0,
Index: src/apcups.c
===================================================================
--- src/apcups.c    (revision 733)
+++ src/apcups.c    (working copy)
@@ -59,12 +59,18 @@
 #define _(String) (String)
 #define N_(String) (String)
 #define MAXSTRING               256
+<<<<<<< .mine
+=======
 #define Error_abort0(fmd) generic_error_out(__FILE__, __LINE__, fmd)
+>>>>>>> .r733
 #define MODULE_NAME "apcups"
 
 
 /* Prototypes */
+<<<<<<< .mine
+=======
 static void generic_error_out(const char *, int , const char *, ...);
+>>>>>>> .r733
 
 /* Default values for contacting daemon */
 static char *host = "localhost";
@@ -75,6 +81,16 @@
 static char *net_errmsg = NULL;           /* pointer to error message */
 static char net_errbuf[256];              /* error message buffer for
messages */
 
+<<<<<<< .mine
+struct sockaddr_in tcp_serv_addr;  /* socket information */
+int net_errno = 0;                 /* error number -- not yet
implemented */
+char *net_errmsg = NULL;           /* pointer to error message */
+char net_errbuf[256];              /* error message buffer for messages */
+
+void (*error_cleanup) (void) = NULL;
+
+=======
+>>>>>>> .r733
 /*
  * The following are only if not compiled to test the module with its
own main.
 */
@@ -141,6 +157,18 @@
 
 #endif /* ifndef APCMAIN */
 
+<<<<<<< .mine
+struct apc_detail_s {
+  int connected;
+  float linev;
+  float loadpct;
+  float bcharge;
+  float timeleft;
+  float outputv;
+  float itemp;
+  float battv;
+  float linefreq;
+=======
 struct apc_detail_s
 {
     float linev;
@@ -151,11 +179,91 @@
     float itemp;
     float battv;
     float linefreq;
+>>>>>>> .r733
 };
 
 #define BIG_BUF 4096
 
+<<<<<<< .mine
+
+#define BIG_BUF 5000
+
+/* Implement snprintf */
+int asnprintf(char *str, size_t size, const char *fmt, ...)
+{
+#ifdef HAVE_VSNPRINTF
+   va_list arg_ptr;
+   int len;
+
+   va_start(arg_ptr, fmt);
+   len = vsnprintf(str, size, fmt, arg_ptr);
+   va_end(arg_ptr);
+
+   str[size - 1] = 0;
+   return len;
+
+#else
+
+   va_list arg_ptr;
+   int len;
+   char *buf;
+
+   buf = (char *)malloc(BIG_BUF);
+
+   va_start(arg_ptr, fmt);
+   len = vsprintf(buf, fmt, arg_ptr);
+   va_end(arg_ptr);
+
+   if (len >= BIG_BUF){
+     syslog(LOG_ERR, "apcups: asnprintf(): Buffer overflow");
+     return(0);
+   }
+
+   memcpy(str, buf, size);
+   str[size - 1] = 0;
+
+   free(buf);
+   return len;
+#endif
+}
+
+/* Implement vsnprintf() */
+int avsnprintf(char *str, size_t size, const char *format, va_list ap)
+{
+#ifdef HAVE_VSNPRINTF
+   int len;
+
+   len = vsnprintf(str, size, format, ap);
+   str[size - 1] = 0;
+
+   return len;
+
+#else
+
+   int len;
+   char *buf;
+
+   buf = (char *)malloc(BIG_BUF);
+
+   len = vsprintf(buf, format, ap);
+   if (len >= BIG_BUF){
+     syslog(LOG_ERR, "apcups: avsnprintf(): Buffer overflow");
+     return(0);
+   }
+
+  memcpy(str, buf, size);
+   str[size - 1] = 0;
+
+   free(buf);
+   return len;
+#endif
+}
+
+=======
+>>>>>>> .r733
 /*
+<<<<<<< .mine
+=======
  * Subroutine normally called by macro error_abort() to print
  * FATAL ERROR message and supplied error message
  */
@@ -176,6 +284,7 @@
 }
 
 /*
+>>>>>>> .r733
  * Read nbytes from the network.
  * It is possible that the total bytes require in several
  * read requests
@@ -378,6 +487,26 @@
 /* Get and print status from apcupsd NIS server */
 static int do_pthreads_status(char *host, int port, struct apc_detail_s
*apcups_detail)
 {
+<<<<<<< .mine
+  int sockfd, n;
+  char recvline[MAXSTRING + 1];
+  char *tokptr;
+
+  if ((sockfd = net_open(host, NULL, port)) < 0){
+    syslog(LOG_ERR, "apcups: Cannot open connection: %s",
+       net_errmsg);
+    net_errmsg = NULL;
+    return;
+  }
+ 
+  net_send(sockfd, "status", 6);
+ 
+  while ((n = net_recv(sockfd, recvline, sizeof(recvline))) > 0) {
+    recvline[n] = 0;
+#ifdef APCMAIN
+    fputs(recvline, stdout);
+#endif /* ifdef APCMAIN */
+=======
     int     sockfd;
     int     n;
     char    recvline[MAXSTRING + 1];
@@ -389,14 +518,93 @@
 #else
 # define PRINT_VALUE(name, val) /**/
 #endif
+>>>>>>> .r733
 
+<<<<<<< .mine
+    tokptr = strtok(recvline,":");
+    while(tokptr != NULL) {
+      /* Look for Limit_Add */
+      if(strncmp("LINEV",tokptr,5) == 0) {
+#ifdef APCMAIN
+    fprintf(stdout,"  Found LINEV.\n");
+#endif /* ifdef APCMAIN */
+    tokptr = strtok(NULL," \t");
+    if(tokptr == NULL) continue;
+    apcups_detail->linev = atof (tokptr);
+      }else if(strncmp("BATTV",tokptr,5) == 0) {
+#ifdef APCMAIN
+    fprintf(stdout,"  Found BATTV.\n");
+#endif /* ifdef APCMAIN */
+    tokptr = strtok(NULL," \t");
+    if(tokptr == NULL) continue;
+    apcups_detail->battv = atof (tokptr);
+      }else if(strncmp("ITEMP",tokptr,5) == 0) {
+#ifdef APCMAIN
+    fprintf(stdout,"  Found ITEMP.\n");
+#endif /* ifdef APCMAIN */
+    tokptr = strtok(NULL," \t");
+    if(tokptr == NULL) continue;
+    apcups_detail->itemp = atof (tokptr);
+      }else if(strncmp("LOADPCT",tokptr,7) == 0) {
+#ifdef APCMAIN
+    fprintf(stdout,"  Found LOADPCT.\n");
+#endif /* ifdef APCMAIN */
+    tokptr = strtok(NULL," \t");
+    if(tokptr == NULL) continue;
+    apcups_detail->loadpct = atof (tokptr);
+      }else if(strncmp("BCHARGE",tokptr,7) == 0) {
+#ifdef APCMAIN
+    fprintf(stdout,"  Found BCHARGE.\n");
+#endif /* ifdef APCMAIN */
+    tokptr = strtok(NULL," \t");
+    if(tokptr == NULL) continue;
+    apcups_detail->bcharge = atof (tokptr);
+      }else if(strncmp("OUTPUTV",tokptr,7) == 0) {
+#ifdef APCMAIN
+    fprintf(stdout,"  Found OUTPUTV.\n");
+#endif /* ifdef APCMAIN */
+    tokptr = strtok(NULL," \t");
+    if(tokptr == NULL) continue;
+    apcups_detail->outputv = atof (tokptr);
+      }else if(strncmp("LINEFREQ",tokptr,8) == 0) {
+#ifdef APCMAIN
+    fprintf(stdout,"  Found LINEFREQ.\n");
+#endif /* ifdef APCMAIN */
+    tokptr = strtok(NULL," \t");
+    if(tokptr == NULL) continue;
+    apcups_detail->linefreq = atof (tokptr);
+      }else if(strncmp("TIMELEFT",tokptr,8) == 0) {
+#ifdef APCMAIN
+    fprintf(stdout,"  Found TIMELEFT.\n");
+#endif /* ifdef APCMAIN */
+    tokptr = strtok(NULL," \t");
+    if(tokptr == NULL) continue;
+    apcups_detail->timeleft = atof (tokptr);
+      } /* */
+      tokptr = strtok(NULL,":");
+    }
+  }
+=======
     /* TODO: Keep the socket open, if possible */
     if ((sockfd = net_open (host, NULL, port)) < 0)
     {
         syslog (LOG_ERR, "apcups plugin: Connecting to the apcupsd
failed.");
         return (-1);
     }
+>>>>>>> .r733
 
+<<<<<<< .mine
+  if (n < 0) {
+    syslog(LOG_ERR, "apcups: Error recieving data: %s",
+       net_errmsg);
+    net_errmsg = NULL;
+    return;
+  }
+  /* signal that we did in fact connect. */
+  apcups_detail->connected = 1;
+ 
+  net_close(sockfd);
+=======
     net_send (sockfd, "status", 6);
 
     while ((n = net_recv (sockfd, recvline, sizeof (recvline))) > 0)
@@ -447,6 +655,7 @@
     net_close(sockfd);
 
     return (0);
+>>>>>>> .r733
 }
 
 #ifdef APCMAIN
@@ -455,12 +664,23 @@
     /* we are not really going to use this */
     struct apc_detail_s apcups_detail;
 
+<<<<<<< .mine
+  openlog("apcups",LOG_PID | LOG_NDELAY | LOG_LOCAL1);
+
+  if (!*host || strcmp(host, "0.0.0.0") == 0)
+    host = "localhost";
+ 
+  do_pthreads_status(host, port, &apcups_detail);
+ 
+  return 0;
+=======
     if (!*host || strcmp(host, "0.0.0.0") == 0)
         host = "localhost";
 
     do_pthreads_status(host, port, &apcups_detail);
 
     return 0;
+>>>>>>> .r733
 }
 #else
 static void apcups_init (void)
@@ -602,6 +822,7 @@
   apcups_detail.itemp = 0.0;
   apcups_detail.battv = 0.0;
   apcups_detail.linefreq = 0.0;
+  apcups_detail.connected = 0;
 
  
   if (!*host || strcmp(host, "0.0.0.0") == 0)
@@ -609,6 +830,12 @@
  
   do_pthreads_status(host, port, &apcups_detail);
 
+  /*
+   * if we did not connect then do not bother submitting
+   * zeros. We want rrd files to have NAN.
+  */
+  if(!apcups_detail.connected) return;
+
   apcups_submit (host, &apcups_detail);
   apc_bvolt_submit (host, &apcups_detail);
   apc_load_submit (host, &apcups_detail);
>>>>>> Patch ends here >>>>>>>

-- 
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Anthony B Gialluca                      tonyabg [at] charter [dot] net

"When a man sits with a pretty girl for an hour,
it seems like a minute. But let him sit on a hot stove
for a minute and it's longer than any hour.
That's relativity." - Albert Einstein

-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/x-pkcs7-signature
Size: 3245 bytes
Desc: S/MIME Cryptographic Signature
Url : http://mailman.verplant.org/pipermail/collectd/attachments/20060519/e2f75605/smime.bin


More information about the collectd mailing list