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