Code

addeded documentation for json
[rrdtool-all.git] / contrib / rrdproc / rrdproc.c
1 /*
2 ** rrdproc.c Copyright 1999 Damien Miller <djm@mindrot.org>
3 **
4 **
5 ** This program is a very lightweight collecter for rrdtool. It reads
6 ** and parses /proc/net/dev and sends a rrdtool remote control update
7 ** command to stdout.
8 **
9 ** rrdproc will sleep a user-defined amount of time between reads from
10 ** /proc/net/dev. This time should match the sample rate you created your
11 ** RRD files with.
12 **
13 ** Example:
14 **
15 ** rrdproc --interface=ppp0 \
16 **         --wait 30 \
17 **         --filename=/home/djm/traffic-ppp0.rrd | rrdtool -
18 **
19 ** This will update the RRD file /home/djm/traffic-eth0.rrd with bytes
20 ** received and sent on eth0 every 30 seconds.
21 **
22 ** rrdproc --interface=eth0 \
23 **         --wait 300 \
24 **         --frame \
25 **         --filename=/home/djm/traffic-eth0.rrd | rrdtool -
26 **
27 ** Will update /home/djm/traffic-eth0.rrd with counts of framing errors and
28 ** collisions every 5 minutes
29 **
30 ** rrdproc is licensed under the GNU GPL version 2. Please refer to
31 ** http://www.fsf.org/copyleft/gpl.html for details.
32 **
33 */
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <string.h>
38 #include <syslog.h>
39 #include <getopt.h>
40 #include <unistd.h>
41 #include <time.h>
43 #define PROC_DEV                                        "/proc/net/dev"
45 #define DEFAULT_SLEEP_TIME              3
46 #define DEFAULT_INTERFACE               "eth0"
47 #define DEFAULT_FILENAME                "traffic"
49 #define COLUMN_BYTES                            0
50 #define COLUMN_PACKETS                  1
51 #define COLUMN_ERRORS                   2
52 #define COLUMN_DROPPED                  3
53 #define COLUMN_FIFO                             4
54 #define COLUMN_FRAME                            5
56 void get_stats(FILE *devstats, const char *interface, int start_column);
57 const char *skip_columns(const char *p, int num_columns);
58 void help(void);
59 void version(void);
61 static struct option long_options[] =
62 {
63         { "wait", 1, NULL, 'w'},
64         { "interface", 1, NULL, 'i'},
65         { "filename", 1, NULL, 'f'},
66         { "help", 0, NULL, 'h'},
67         { "version", 0, NULL, 'v'},
68         { "bytes", 0, NULL, 'B'},
69         { "packets", 0, NULL, 'P'},
70         { "errors", 0, NULL, 'E'},
71         { "dropped", 0, NULL, 'D'},
72         { "fifo", 0, NULL, 'F'},
73         { "frame", 0, NULL, 'R'},
74 };
76 int main(int argc, char **argv)
77 {
78         int sleep_time = DEFAULT_SLEEP_TIME;
79         char *interface = DEFAULT_INTERFACE;
80         char *filename = DEFAULT_FILENAME;
81         int start_column = COLUMN_BYTES;
82         int c;
83         FILE *devstats;
84         
85         extern char *optarg;
86         
87         openlog("if-update", LOG_PERROR|LOG_PID, LOG_DAEMON);
88         
89         while(1)
90         {
91                 c = getopt_long(argc, argv, "w:i:f:hvBPEDFRCM", long_options, NULL);
92                 if (c == -1)
93                         break;
94                 
95                 switch(c)
96                 {
97                         case 'w':
98                                 sleep_time = atoi(optarg);
99                                 break;
100                         case 'i':
101                                 interface = strdup(optarg);
102                                 break;
103                         case 'f':
104                                 filename = strdup(optarg);
105                                 break;
106                         case 'h':
107                                 help();
108                                 exit(0);
109                         case 'v':
110                                 version();
111                                 exit(0);
112                         case 'B':
113                                 start_column = COLUMN_BYTES;
114                                 break;
115                         case 'P':
116                                 start_column = COLUMN_PACKETS;
117                                 break;
118                         case 'E':
119                                 start_column = COLUMN_ERRORS;
120                                 break;
121                         case 'D':
122                                 start_column = COLUMN_DROPPED;
123                                 break;
124                         case 'F':
125                                 start_column = COLUMN_FIFO;
126                                 break;
127                         case 'R':
128                                 start_column = COLUMN_FRAME;
129                                 break;
130                         default:
131                                 fprintf(stderr, "Invalid commandline options.\n");
132                                 help();
133                                 exit(1);
134                 }               
135         }
136         
137         setlinebuf(stdout);
138         
139         while(1)
140         {
141                 devstats = fopen(PROC_DEV, "r");
142                 if (devstats == NULL)
143                 {
144                         syslog(LOG_ERR, "Couldn't open proc file \"%s\" for reading: %m", PROC_DEV);
145                         exit(1);
146                 }
147                 printf("update %s N:", filename);
148                 get_stats(devstats, interface, start_column);
149                 sleep(sleep_time);
150                 fclose(devstats);
151         }
152         exit(0);
155 void get_stats(FILE *devstats, const char *interface, int start_column)
157         char buffer[2048];
158         const char *p;
159         int if_len;
160         unsigned long long in;
161         unsigned long long out;
162         
163         if_len = strlen(interface);
164         
165         while(fgets(buffer, sizeof(buffer), devstats) != NULL)
166         {
167                 p = buffer;
168                 
169                 /* skip space at start of line */
170                 while(*p && (*p == ' '))
171                         p++;
173                 if (strncmp(p, interface, if_len) == 0)
174                 {
175                         /* Skip to the statistic we wnt to report */
176                         p = skip_columns(p + if_len + 1, start_column);
178                         in = strtoull(p, NULL, 10);
180                         /* Skip from received column to transmit column */
181                         p = skip_columns(p, 8);
183                         out = strtoull(p, NULL, 10);
185                         printf("%Lu:%Lu\n", in, out);
187                         return;
188                 }               
189         }
191         /* Non-fatal error if interface not found */
192         syslog(LOG_WARNING, "Couldn't find statistics for interface \"%s\"", interface);
193         printf("U:U\n");
194         return;
197 void help(void)
199         fprintf(stderr, "\
200 rrdproc - Update rrd file using statistics in /proc\n\
201 \n\
202 rrdproc will periodically read /proc/net/dev and update an RRD database\n\
203 with the numbers that it finds there.\n\
204 \n\
205 Options:\n\
206     --wait, -w      [time]      Time to wait between statistics updates\n\
207     --interface, -i [name]      Name of network interface to report on\n\
208     --filename, -f  [filename]  Path of RRD file to update\n\
209     --help, -h                  Display this help\n\
210     --version, -v               Display version information\n\
211     --bytes, -B                 Report bytes in / out\n\
212     --packets, -P               Report packets in / out\n\
213     --errors, -E                Report errors in / out\n\
214     --dropped, -D               Report dropped packets in / out\n\
215     --fifo, -F                  Report fifo in / out\n\
216     --frame, -R                 Report framing errors / collisions\n\
217 ");
220 void version(void)
222         fprintf(stderr, "rrdproc v0.0\n");
225 const char *skip_columns(const char *p, int num_columns)
227         int c;
228         
229         for(c = 0; c < num_columns; c++)
230         {
231                 /* Skip numbers */
232                 while(*p && (*p != ' '))
233                         p++;
235                 /* Skip space */
236                 while(*p && (*p == ' '))
237                         p++;
239                 if (!*p)
240                 {
241                         /* Line finished early */
242                         printf("U:U\n");
243                         syslog(LOG_WARNING, "Couldn't parse interface statistics");
244                         return;
245                 }
246         }
247         
248         return(p);