]> git.itanic.dy.fi Git - rrdd/blob - parser.c
bffe3377b3d2083af3727a691814a9fb548454d0
[rrdd] / parser.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4
5 #include "parser.h"
6 #include "process.h"
7 #include "string.h"
8 #include "debug.h"
9
10 #define STATFILE "/proc/stat"
11
12 int cpu_parser(char *data, const char **p)
13 {
14         char buf[1024];
15         char *str = buf;
16         FILE *file = fopen(STATFILE, "r");
17         long long user, nice, sys, idle, wait, irq, softirq;
18
19         if (file == NULL) {
20                 pr_err("Failed to open file %s\n", STATFILE);
21                 return -1;
22         }
23
24         if (!fgets(buf, 1024, file)) {
25                 pr_err("Failed to read file %s\n", STATFILE);
26                 fclose(file);
27                 return -1;
28         }
29
30         user    = dec_to_longlong(str, &str);
31         nice    = dec_to_longlong(str, &str);
32         sys     = dec_to_longlong(str, &str);
33         idle    = dec_to_longlong(str, &str);
34         wait    = dec_to_longlong(str, &str);
35         irq     = dec_to_longlong(str, &str);
36         softirq = dec_to_longlong(str, &str);
37
38         snprintf(data, RRD_DATA_MAX_LEN, "%lld:%lld:%lld:%lld:%lld:%lld:%lld",
39                 user, nice, sys, idle, wait, irq, softirq);
40
41         fclose(file);
42         return 0;
43 }
44
45 #define MEMFILE "/proc/meminfo"
46
47 int mem_parser(char *data, const char **p)
48 {
49         char buf[1024], word[1024];
50         int free = 0, buffered = 0, cache = 0, active = 0, inactive = 0,
51                 swapfree = 0, anon = 0, slab = 0, tables = 0, other = 0,
52                 swaptotal = 0, total = 0;
53         FILE *file = fopen(MEMFILE, "r");
54
55         if (file == NULL) {
56                 pr_err("Failed to open file %s\n", MEMFILE);
57                 return -1;
58         }
59
60         while (fgets(buf, 1024, file)) {
61                 get_word(buf, 0, word, 1024);
62                 
63                 if (!strcmp(word, "MemFree:")) {
64                         free = dec_to_int(buf, NULL);
65                 } else if (!strcmp(word, "MemTotal:")) {
66                         total = dec_to_int(buf, NULL);
67                 } else if (!strcmp(word, "Buffers:")) {
68                         buffered = dec_to_int(buf, NULL);
69                 } else if (!strcmp(word, "Cached:")) {
70                         cache = dec_to_int(buf, NULL);
71                 } else if (!strcmp(word, "Active:")) {
72                         active = dec_to_int(buf, NULL);
73                 } else if (!strcmp(word, "Inactive:")) {
74                         inactive = dec_to_int(buf, NULL);
75                 } else if (!strcmp(word, "SwapFree:")) {
76                         swapfree = dec_to_int(buf, NULL);
77                 } else if (!strcmp(word, "AnonPages:")) {
78                         anon = dec_to_int(buf, NULL);
79                 } else if (!strcmp(word, "Slab:")) {
80                         slab = dec_to_int(buf, NULL);
81                 } else if (!strcmp(word, "PageTables:")) {
82                         tables = dec_to_int(buf, NULL);
83                 } else if (!strcmp(word, "SwapTotal:")) {
84                         swaptotal = dec_to_int(buf, NULL);
85                 }
86         }
87         fclose(file);
88
89         other = total - free - buffered - cache - anon - slab - tables;
90
91         snprintf(data, RRD_DATA_MAX_LEN, "%f:%f:%f:%f:%f:%f:%f:%f:%f:%f:%f",
92                 free / 1024.0,
93                 buffered / 1024.0,
94                 cache / 1024.0,
95                 active / 1024.0,
96                 inactive / 1024.0,
97                 swapfree / 1024.0,
98                 anon / 1024.0,
99                 slab / 1024.0,
100                 tables / 1024.0,
101                 other / 1024.0,
102                 (swaptotal - swapfree) / 1024.0);
103
104         return 0;
105 }
106
107 int cpu_mem_parser(char *data, const char **p)
108 {
109         char cpu[1024], mem[1024];
110
111         cpu_parser(cpu, p);
112         mem_parser(mem, p);
113         snprintf(data, RRD_DATA_MAX_LEN, "%s:%s", cpu, mem);
114
115         return 0;
116 }
117
118 int digitemp_parser(char *data, const char **p)
119 {
120         const char digitemp_cmd[] = "/usr/bin/digitemp";
121         char *const digitemp_args[] = { "", "-o2", "-a", "-q", 0 };
122         FILE *readf;
123         int pid, ret;
124         float t1 = 0, t2 = 0, t3 = 0;
125         char buf[1024];
126
127         pid = run_piped_stream(digitemp_cmd, digitemp_args, 0, &readf, 0);
128         if (pid < 0) {
129                 pr_err("Failed to parse digitemp\n");
130                 sprintf(data, "U:U");
131                 return -1;
132         }
133
134         ret = fscanf(readf, "%f %f %f", &t1, &t2, &t3);
135
136         if (ret != 3) {
137                 pr_err("Failed to parse digitemp output: %m\n");
138                 sprintf(data, "U:U");
139                 return 1;
140         }
141
142         t2 += 2.16;
143         t3 += -0.44;
144
145         /* Read whatever the process might be still printing out */
146         while (fgets(buf, 1024, readf));
147
148         harvest_zombies(pid);
149         snprintf(data, RRD_DATA_MAX_LEN, "%.2f:%.2f", t3, t2);
150         return 0;
151 }
152
153 int digitemp_parser_mod(char *data, const char **p)
154 {
155         char buf[1024];
156         int ret;
157
158         ret = digitemp_parser(buf, p);
159         snprintf(data, RRD_DATA_MAX_LEN, "U:%s", buf);
160
161         return ret;
162 }
163
164 /* Run a command and feed the output from stdout directly to rrdtool */
165 int script_parser(char *rrd_data, const char **parser_data)
166 {
167         FILE *readf;
168         int pid, ret;
169         void *tmp = parser_data;
170         char **cmd = tmp;
171
172         pid = run_piped_stream(cmd[0], &cmd[1], NULL, &readf, NULL);
173         ret = fread(rrd_data, 1, RRD_DATA_MAX_LEN, readf);
174
175         pr_info("Read %d bytes :%s\n", ret, rrd_data);
176         fclose(readf);
177
178         harvest_zombies(pid);
179
180         return 0;
181 }
182
183 struct iface_stats {
184         long long rx_bytes;
185         long long rx_packets;
186         long long tx_bytes;
187         long long tx_packets;
188 };
189
190 #define PROC_NETDEV     "/proc/net/dev"
191
192 static int get_iface_stats(const char *iface, struct iface_stats *stat)
193 {
194         FILE *netdev;
195         char buf[1024];
196         char if_name[16];
197         char *str;
198         int error;
199
200         netdev = fopen(PROC_NETDEV, "r");
201
202         if (netdev == NULL) {
203                 error = errno;
204                 pr_err("Failed to open file %s: %d (%m)\n",
205                         PROC_NETDEV, error);
206                 return error;
207         }
208
209         while (fgets(buf, sizeof(buf), netdev)) {
210                 get_word(buf, &str, if_name, sizeof(if_name));
211
212                 /* Remove the ':' at the end of the if_name */
213                 if_name[strlen(if_name) - 1] = 0;
214                 if (strncmp(iface, if_name, sizeof(if_name)))
215                         continue;
216
217                 stat->rx_bytes          = dec_to_longlong(str, &str);
218                 stat->rx_packets        = dec_to_longlong(str, &str);
219                 /* errs */                dec_to_longlong(str, &str);
220                 /* drop */                dec_to_longlong(str, &str);
221                 /* fifo */                dec_to_longlong(str, &str);
222                 /* frame */               dec_to_longlong(str, &str);
223                 /* compressed */          dec_to_longlong(str, &str);
224                 /* multicast */           dec_to_longlong(str, &str);
225                 stat->tx_bytes          = dec_to_longlong(str, &str);
226                 stat->tx_packets        = dec_to_longlong(str, &str);
227
228                 pr_info("rx_b %lld rx_p %lld tx_b %lld tx_p %lld\n",
229                         stat->rx_bytes, stat->rx_packets,
230                         stat->tx_bytes, stat->tx_packets);
231
232                 return 0;
233         }
234
235         pr_err("Interface %s not found\n", iface);
236         return -ENODEV;
237 }
238
239 int netstats_parser(char *rrd_data, const char **parser_data)
240 {
241         struct iface_stats stat;
242         const char **iface_name = parser_data;
243         int max_str = RRD_DATA_MAX_LEN;
244         int ret;
245
246         if (!parser_data) {
247                 pr_err("No device names specified\n");
248                 return -1;
249         }
250
251         while(*iface_name) {
252                 pr_info("getting data for iface %s\n", *iface_name);
253                 ret = get_iface_stats(*iface_name, &stat);
254
255                 if (!ret) {
256                         ret = snprintf(rrd_data, max_str, "%lld:%lld:%lld:%lld",
257                                 stat.rx_bytes, stat.rx_packets,
258                                 stat.tx_bytes, stat.tx_packets);
259                 } else {
260                         ret = snprintf(rrd_data, max_str, "U:U:U:U");
261                 }
262
263                 max_str -= ret;
264                 rrd_data += ret;
265
266                 iface_name++;
267                 if (!*iface_name)
268                         break;
269
270                 ret = snprintf(rrd_data, max_str, ":");
271                 max_str -= ret;
272                 rrd_data += ret;
273         }
274
275         return 0;
276 }