Package: mrtgutils
Version: 0.8.1
Severity: wishlist
Tags: patch

Dear Maintainer,

For my box I'd like to do the following:
1) Monitor both the 5 and 15 minutes load averages.
   Unfortunately mrtg-load only returns the 5 minutes one.
   (a workaround is to use snmp but that's a more involved solution)

2) I'd also like to be able to pick whether the load average should be the in 
or out data.
   (also doable with snmp)

3) And I'd like to be able to graph the machine and idle uptimes.
   This one is not doable with snmp because 
HOST-RESOURCES-MIB::hrSystemUptime.0 returns it in the following format 
'Timeticks: (1708307) 4:44:43.07' which is not a plain integer and thus cause 
MRTG to choke on it.

4) Finally the idle uptime is the cumulated idle time of all cores/processors. 
So I'd like to be able to scale it to it matches the machine uptime.
   As far as I know MRTG does not make it possible to scale each data sample 
independently so this must be done by the script.


The first attached patch is a slight optimization to avoid parsing the /proc 
files more than once.
The second patch renames mrtg-load to mrtg-system and generalizes it to make 
all of the above possible:

1) Use 'mrtg-system -m 100 -l 5 -l 15'.
2) Use either 'mrtg-system -l 5' or 'mrtg-system -z -l 5'.
3) Use 'mrtg-system -u sys -u idle'.
4) Use 'mrtg-system -u sys -m 0.25 -u idle' for a quad-core processor.

For backward compatibility one can create a symbolic link called 'mrtg-load' 
preserving the old behavior.

-- System Information:
Debian Release: jessie/sid
  APT prefers testing
  APT policy: (990, 'testing'), (500, 'stable')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 3.2.0-4-amd64 (SMP w/4 CPU cores)
Locale: LANG=fr_FR.UTF-8, LC_CTYPE=fr_FR.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash

Versions of packages mrtgutils depends on:
ii  libc6  2.17-92

mrtgutils recommends no packages.

Versions of packages mrtgutils suggests:
ii  mrtg               2.17.4-2+b1
ii  mrtgutils-sensors  0.8.1

-- no debconf information
commit 38e1513c8f491ef24fc0dc35779febe077b7b2a5
Author: Francois Gouget <[email protected]>
Date:   Thu Sep 5 00:06:35 2013 +0200

    Only compute the uptime and load averages once per run.

diff --git a/uptime.c b/uptime.c
index 49fd813..710bac3 100644
--- a/uptime.c
+++ b/uptime.c
@@ -14,29 +14,38 @@ static int uptime (double *, double *);
 static char *sprint_uptime(void);
 
 int uptime(double *uptime_secs, double *idle_secs) {
-    double up=0, idle=0;
-    FILE *f;
-    f = fopen("/proc/uptime", "r");
-    if (!f) return -1;
-    if (fscanf(f, "%lf %lf", &up, &idle) < 2) {
+    static int got_uptime = 0;
+    static double up = 0, idle = 0;
+
+    if (!got_uptime) {
+      FILE *f;
+      f = fopen("/proc/uptime", "r");
+      if (!f) return -1;
+      if (fscanf(f, "%lf %lf", &up, &idle) < 2) {
         fprintf(stderr, "bad data in /proc/uptime\n");
         return 0;
+      }
+      fclose(f);
+      got_uptime = 1;
     }
-    fclose(f);
     if (uptime_secs) *uptime_secs = up;
     if (idle_secs) *idle_secs = idle;
     return up;  /* assume never be zero seconds in practice */
 }
 
 void loadavg(double *av1, double *av5, double *av15) {
-    double avg_1=0, avg_5=0, avg_15=0;
-    FILE *f;
-
-    f = fopen("/proc/loadavg", "r");
-    if (!f) return;
-    if (fscanf(f, "%lf %lf %lf", &avg_1, &avg_5, &avg_15) < 3) {
+    static int got_load = 0;
+    static double avg_1 = 0, avg_5 = 0, avg_15 = 0;
+
+    if (!got_load) {
+      FILE *f;
+      f = fopen("/proc/loadavg", "r");
+      if (!f) return;
+      if (fscanf(f, "%lf %lf %lf", &avg_1, &avg_5, &avg_15) < 3) {
         fprintf(stderr, "bad data in /proc/loadavg\n");
         exit(1);
+      }
+      got_load = 1;
     }
     if (av1) *av1 = avg_1;
     if (av5) *av5 = avg_5;
commit c3bb1d75a9be26219d549354bc2c56d392271154
Author: Francois Gouget <[email protected]>
Date:   Thu Sep 5 00:08:26 2013 +0200

    Rename mrtg-load to mrtg-system and generalize it.
    
    It can now be used to sample any of the load averages or the uptimes.
    It can also apply fractional multipliers and different multipliers for each of the two data samples.

diff --git a/Makefile b/Makefile
index 36c3d38..c65d785 100644
--- a/Makefile
+++ b/Makefile
@@ -6,8 +6,8 @@ ARCH:= $(shell dpkg-architecture -qDEB_BUILD_ARCH)
 WITH_SENSORS:=1
 
 COBJS = uptime.o util.o
-TARGETS = mrtg-load mrtg-ip-acct mrtg-apache
-MANPAGES = mrtg-load.1 mrtg-ip-acct.1 mrtg-apache.1
+TARGETS = mrtg-system mrtg-ip-acct mrtg-apache
+MANPAGES = mrtg-system.1 mrtg-ip-acct.1 mrtg-apache.1
 ifeq ($(WITH_SENSORS),1)
 TARGETS += mrtg-sensors
 MANPAGES += mrtg-sensors.1
@@ -28,8 +28,9 @@ mrtg-%: $(COBJS) mrtg-%.o
 
 install: $(TARGET) 
 	for i in $(TARGETS); do install -m 755 $$i $(DESTDIR)/usr/bin/$$i; done
+	ln -s mrtg-system $(DESTDIR)/usr/bin/mrtg-load
 	for i in $(MANPAGES); do install -m 644 $$i $(DESTDIR)/usr/share/man/man1/$$i; gzip -9 $(DESTDIR)/usr/share/man/man1/$$i; done
-	
+
 
 clean:
 	-rm -f *.o $(TARGETS) $(MANPAGES)
diff --git a/mrtg-load.c b/mrtg-load.c
deleted file mode 100644
index e2280a8..0000000
--- a/mrtg-load.c
+++ /dev/null
@@ -1,26 +0,0 @@
-#include "uptime.h"
-#include "util.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-int main(int argc, char **argv)
-{
-  double avg;
-  int c, mult = 1;
-  loadavg(0, &avg, 0);
-
-  while ((c = getopt(argc, argv, "m:")) > 0) {
-    switch (c) {
-      case 'm': mult = atoi(optarg); break;
-      default:
-	fprintf(stderr, "Usage: mrtg-load [-m multiplier]\n");
-	return(0);
-    }
-  }
-  
-  printf("0\n%.0f\n", avg*mult);
-  print_uptime();
-  print_hostname();
-  return 0;
-}
diff --git a/mrtg-load.pod b/mrtg-load.pod
deleted file mode 100644
index 8898e25..0000000
--- a/mrtg-load.pod
+++ /dev/null
@@ -1,28 +0,0 @@
-=head1 NAME 
-
-mrtg-load - Returns the current load average (5-minute average)
-
-=head1 SYNOPSIS
-
-mrtg-load [B<-m> multiplier]
-
-=head1 DESCRIPTION
-
-mrtg-load returns the 5-minute load average of the machine. The output is 
-written in a form useful as input for the mrtg utility.
-
-B<-m> is the multiplier to be used in the output. For example, with a 
-load of 1.2 and a multiplier of 100, the output load average will be 120.
-The default multiplier is 1.
-
-=head1 SEE ALSO
-
-mrtg(1)
-
-=head1 AUTHOR
-
-mrtg-apache was written by Randolph Chung E<lt>[email protected]<gt>.
-
-=head1 HISTORY 
-
-This document first appeared with mrtgutils-0.1
diff --git a/mrtg-system.c b/mrtg-system.c
new file mode 100644
index 0000000..ed51b7a
--- /dev/null
+++ b/mrtg-system.c
@@ -0,0 +1,93 @@
+#include "uptime.h"
+#include "util.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static int count = 0;
+
+static void check_count(const char* name)
+{
+  count++;
+  if (count > 2)
+  {
+      fprintf(stderr, "%s:error: only two parameters can be sampled at a time\n", name);
+    exit(2);
+  }
+}
+
+static void usage(int rc)
+{
+  fprintf(stderr, "Usage: mrtg-system [-m multiplier] [-z] [-l period] [-u sys|idle]\n");
+  exit(rc);
+}
+
+int main(int argc, char **argv)
+{
+  char* slash;
+  double avg1, avg5, avg15, sys_uptime, idle_uptime;
+  double mult = 1;
+  int c;
+
+  slash = strrchr(argv[0], '/');
+  if (slash) argv[0] = slash + 1;
+
+  while ((c = getopt(argc, argv, "zm:l:u:")) > 0) {
+    switch (c) {
+      case 'm':
+        mult = atof(optarg);
+        break;
+      case 'z':
+        check_count(argv[0]);
+        printf("0\n");
+        break;
+      case 'l':
+        check_count(argv[0]);
+        loadavg(&avg1, &avg5, &avg15);
+        if (strcmp(optarg, "1") == 0)
+          printf("%.0f\n", avg1*mult);
+        else if (strcmp(optarg, "5") == 0)
+          printf("%.0f\n", avg5*mult);
+        else if (strcmp(optarg, "15") == 0)
+          printf("%.0f\n", avg15*mult);
+        else {
+          fprintf(stderr, "%s:error: unknown load average period '%s'\n", argv[0], optarg);
+          usage(2);
+        }
+        break;
+      case 'u':
+        check_count(argv[0]);
+        uptime(&sys_uptime, &idle_uptime);
+        if (strcmp(optarg, "sys") == 0)
+          printf("%.0f\n", sys_uptime*mult);
+        else if (strcmp(optarg, "idle") == 0)
+          printf("%.0f\n", idle_uptime*mult);
+        else {
+          fprintf(stderr, "%s:error: unknown uptime type '%s'\n", argv[0], optarg);
+          usage(2);
+        }
+        break;
+      default:
+	usage(0);
+    }
+  }
+
+  switch (count) {
+  case 0:
+      if (strcmp(argv[0], "mrtg-load") == 0) {
+        /* For compatibility with the original mrtg-load tool */
+        loadavg(NULL, &avg5, NULL);
+        printf("0\n%.0f\n", avg5*mult);
+      } else {
+        fprintf(stderr, "%s:error: you must specify the data to sample\n", argv[0]);
+        usage(2);
+      }
+    break;
+  case 1:
+    printf("0\n");
+  }
+  print_uptime();
+  print_hostname();
+  return 0;
+}
diff --git a/mrtg-system.pod b/mrtg-system.pod
new file mode 100644
index 0000000..ce12095
--- /dev/null
+++ b/mrtg-system.pod
@@ -0,0 +1,40 @@
+=head1 NAME 
+
+mrtg-system - Returns the current load or uptime data
+
+=head1 SYNOPSIS
+
+mrtg-system [B<-m> multiplier] [B<-z>] [B<-l> period] [B<-u> type]
+
+=head1 DESCRIPTION
+
+mrtg-system returns up to two data samples with a customizable multiplier for
+each. The output is written in a form useful as input for the mrtg utility.
+
+B<-m> is the multiplier to be used in the output for the next data sample. 
+For example, with a load of 1.2 and a multiplier of 100, the output load
+average would be 120. Note that the option order is important.
+The default multiplier is 1.
+
+B<-z> causes mrtg-system to return zero for that data sample.
+
+B<-l> causes mrtg-system to return the 1, 5 or 15 minutes load average for that
+data sample.
+
+B<-u> causes mrtg-system to return the system or idle uptime. Note that the
+idle uptime measures the cumulative time each processor has been idle. So on a
+dual-core machine you would want to use a multiplier of 0.5 as follows
+'mrtg-system -u sys -m 0.5 -u idle'.
+
+
+=head1 SEE ALSO
+
+mrtg(1)
+
+=head1 AUTHOR
+
+mrtg-apache was written by Randolph Chung E<lt>[email protected]<gt>.
+
+=head1 HISTORY 
+
+This document first appeared with mrtgutils-0.1
diff --git a/uptime.c b/uptime.c
index 710bac3..9a169af 100644
--- a/uptime.c
+++ b/uptime.c
@@ -10,7 +10,6 @@
 
 static char buf[128];
 static double av[3];
-static int uptime (double *, double *);
 static char *sprint_uptime(void);
 
 int uptime(double *uptime_secs, double *idle_secs) {
diff --git a/uptime.h b/uptime.h
index b83a4a2..e7e9cd3 100644
--- a/uptime.h
+++ b/uptime.h
@@ -2,6 +2,7 @@
 #define UPTIME_H
 
 void loadavg (double *, double *, double *);
+int uptime(double *uptime_secs, double *idle_secs);
 void print_uptime(void);
 
 #endif

Reply via email to