]> arthur.barton.de Git - netdata.git/blob - src/proc_diskstats.c
added config options for all /proc and /sys filenames monitored required for #10
[netdata.git] / src / proc_diskstats.c
1 #include <inttypes.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5
6 #include "common.h"
7 #include "log.h"
8 #include "config.h"
9 #include "procfile.h"
10 #include "rrd.h"
11 #include "plugin_proc.h"
12
13 #define RRD_TYPE_DISK                           "disk"
14 #define RRD_TYPE_DISK_LEN                       strlen(RRD_TYPE_DISK)
15
16 #define MAX_PROC_DISKSTATS_LINE 4096
17
18 int do_proc_diskstats(int update_every, unsigned long long dt) {
19         static procfile *ff = NULL;
20         static char *path_to_get_hw_sector_size = NULL;
21         static int enable_new_disks = -1;
22         static int do_io = -1, do_ops = -1, do_merged_ops = -1, do_iotime = -1, do_cur_ops = -1;
23
24         if(enable_new_disks == -1)      enable_new_disks = config_get_boolean("plugin:proc:/proc/diskstats", "enable new disks detected at runtime", 1);
25
26         if(do_io == -1)                 do_io                   = config_get_boolean("plugin:proc:/proc/diskstats", "bandwidth for all disks", 1);
27         if(do_ops == -1)                do_ops                  = config_get_boolean("plugin:proc:/proc/diskstats", "operations for all disks", 1);
28         if(do_merged_ops == -1) do_merged_ops   = config_get_boolean("plugin:proc:/proc/diskstats", "merged operations for all disks", 1);
29         if(do_iotime == -1)             do_iotime               = config_get_boolean("plugin:proc:/proc/diskstats", "i/o time for all disks", 1);
30         if(do_cur_ops == -1)    do_cur_ops              = config_get_boolean("plugin:proc:/proc/diskstats", "current operations for all disks", 1);
31
32         if(dt) {};
33
34         if(!ff) ff = procfile_open(config_get("plugin:proc:/proc/diskstats", "filename to monitor", "/proc/diskstats"), " \t", PROCFILE_FLAG_DEFAULT);
35         if(!ff) return 1;
36
37         if(!path_to_get_hw_sector_size) path_to_get_hw_sector_size = config_get("plugin:proc:/proc/diskstats", "path to get h/w sector size", "/sys/block/%s/queue/hw_sector_size");
38
39         ff = procfile_readall(ff);
40         if(!ff) return 0; // we return 0, so that we will retry to open it next time
41
42         uint32_t lines = procfile_lines(ff), l;
43         uint32_t words;
44
45         for(l = 0; l < lines ;l++) {
46                 char *disk;
47                 unsigned long long      major = 0, minor = 0,
48                                                         reads = 0,  reads_merged = 0,  readsectors = 0,  readms = 0,
49                                                         writes = 0, writes_merged = 0, writesectors = 0, writems = 0,
50                                                         currentios = 0, iosms = 0, wiosms = 0;
51
52                 words = procfile_linewords(ff, l);
53                 if(words < 14) continue;
54
55                 major                   = strtoull(procfile_lineword(ff, l, 0), NULL, 10);
56                 minor                   = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
57                 disk                    = procfile_lineword(ff, l, 2);
58                 reads                   = strtoull(procfile_lineword(ff, l, 3), NULL, 10);
59                 reads_merged    = strtoull(procfile_lineword(ff, l, 4), NULL, 10);
60                 readsectors     = strtoull(procfile_lineword(ff, l, 5), NULL, 10);
61                 readms                  = strtoull(procfile_lineword(ff, l, 6), NULL, 10);
62                 writes                  = strtoull(procfile_lineword(ff, l, 7), NULL, 10);
63                 writes_merged   = strtoull(procfile_lineword(ff, l, 8), NULL, 10);
64                 writesectors    = strtoull(procfile_lineword(ff, l, 9), NULL, 10);
65                 writems                 = strtoull(procfile_lineword(ff, l, 10), NULL, 10);
66                 currentios              = strtoull(procfile_lineword(ff, l, 11), NULL, 10);
67                 iosms                   = strtoull(procfile_lineword(ff, l, 12), NULL, 10);
68                 wiosms                  = strtoull(procfile_lineword(ff, l, 13), NULL, 10);
69
70                 int def_enabled = 0;
71
72                 // remove slashes from disk names
73                 char *s;
74                 for(s = disk; *s ;s++) if(*s == '/') *s = '_';
75
76                 switch(major) {
77                         case 9: // MDs
78                         case 43: // network block
79                         case 144: // nfs
80                         case 145: // nfs
81                         case 146: // nfs
82                         case 199: // veritas
83                         case 201: // veritas
84                         case 251: // dm
85                                 def_enabled = enable_new_disks;
86                                 break;
87
88                         case 48: // RAID
89                         case 49: // RAID
90                         case 50: // RAID
91                         case 51: // RAID
92                         case 52: // RAID
93                         case 53: // RAID
94                         case 54: // RAID
95                         case 55: // RAID
96                         case 112: // RAID
97                         case 136: // RAID
98                         case 137: // RAID
99                         case 138: // RAID
100                         case 139: // RAID
101                         case 140: // RAID
102                         case 141: // RAID
103                         case 142: // RAID
104                         case 143: // RAID
105                         case 179: // MMC
106                         case 180: // USB
107                                 if(minor % 8) def_enabled = 0; // partitions
108                                 else def_enabled = enable_new_disks;
109                                 break;
110
111                         case 8: // scsi disks
112                         case 65: // scsi disks
113                         case 66: // scsi disks
114                         case 67: // scsi disks
115                         case 68: // scsi disks
116                         case 69: // scsi disks
117                         case 70: // scsi disks
118                         case 71: // scsi disks
119                         case 72: // scsi disks
120                         case 73: // scsi disks
121                         case 74: // scsi disks
122                         case 75: // scsi disks
123                         case 76: // scsi disks
124                         case 77: // scsi disks
125                         case 78: // scsi disks
126                         case 79: // scsi disks
127                         case 80: // i2o
128                         case 81: // i2o
129                         case 82: // i2o
130                         case 83: // i2o
131                         case 84: // i2o
132                         case 85: // i2o
133                         case 86: // i2o
134                         case 87: // i2o
135                         case 101: // hyperdisk
136                         case 102: // compressed
137                         case 104: // scsi
138                         case 105: // scsi
139                         case 106: // scsi
140                         case 107: // scsi
141                         case 108: // scsi
142                         case 109: // scsi
143                         case 110: // scsi
144                         case 111: // scsi
145                         case 114: // bios raid
146                         case 116: // ram board
147                         case 128: // scsi
148                         case 129: // scsi
149                         case 130: // scsi
150                         case 131: // scsi
151                         case 132: // scsi
152                         case 133: // scsi
153                         case 134: // scsi
154                         case 135: // scsi
155                         case 153: // raid
156                         case 202: // xen
157                         case 256: // flash
158                         case 257: // flash
159                                 if(minor % 16) def_enabled = 0; // partitions
160                                 else def_enabled = enable_new_disks;
161                                 break;
162
163                         case 160: // raid
164                         case 161: // raid
165                                 if(minor % 32) def_enabled = 0; // partitions
166                                 else def_enabled = enable_new_disks;
167                                 break;
168
169                         case 3: // ide
170                         case 13: // 8bit ide
171                         case 22: // ide
172                         case 33: // ide
173                         case 34: // ide
174                         case 56: // ide
175                         case 57: // ide
176                         case 88: // ide
177                         case 89: // ide
178                         case 90: // ide
179                         case 91: // ide
180                                 if(minor % 64) def_enabled = 0; // partitions
181                                 else def_enabled = enable_new_disks;
182                                 break;
183
184                         default:
185                                 def_enabled = 0;
186                                 break;
187                 }
188
189                 // check if it is enabled
190                 {
191                         char var_name[4096 + 1];
192                         snprintf(var_name, 4096, "disk %s", disk);
193                         if(!config_get_boolean("plugin:proc:/proc/diskstats", var_name, def_enabled)) continue;
194                 }
195
196                 RRDSET *st;
197
198                 // --------------------------------------------------------------------
199
200                 if(do_io) {
201                         st = rrdset_find_bytype(RRD_TYPE_DISK, disk);
202                         if(!st) {
203                                 char tf[FILENAME_MAX + 1], *t;
204                                 char ssfilename[FILENAME_MAX + 1];
205                                 int sector_size = 512;
206
207                                 strncpy(tf, disk, FILENAME_MAX);
208                                 tf[FILENAME_MAX] = '\0';
209
210                                 // replace all / with !
211                                 while((t = strchr(tf, '/'))) *t = '!';
212
213                                 snprintf(ssfilename, FILENAME_MAX, path_to_get_hw_sector_size, tf);
214                                 FILE *fpss = fopen(ssfilename, "r");
215                                 if(fpss) {
216                                         char ssbuffer[1025];
217                                         char *tmp = fgets(ssbuffer, 1024, fpss);
218
219                                         if(tmp) {
220                                                 sector_size = atoi(tmp);
221                                                 if(sector_size <= 0) {
222                                                         error("Invalid sector size %d for device %s in %s. Assuming 512.", sector_size, disk, ssfilename);
223                                                         sector_size = 512;
224                                                 }
225                                         }
226                                         else error("Cannot read data for sector size for device %s from %s. Assuming 512.", disk, ssfilename);
227
228                                         fclose(fpss);
229                                 }
230                                 else error("Cannot read sector size for device %s from %s. Assuming 512.", disk, ssfilename);
231
232                                 st = rrdset_create(RRD_TYPE_DISK, disk, NULL, disk, "Disk I/O", "kilobytes/s", 2000, update_every, RRDSET_TYPE_AREA);
233
234                                 rrddim_add(st, "reads", NULL, sector_size, 1024 * update_every, RRDDIM_INCREMENTAL);
235                                 rrddim_add(st, "writes", NULL, sector_size * -1, 1024 * update_every, RRDDIM_INCREMENTAL);
236                         }
237                         else rrdset_next(st);
238
239                         rrddim_set(st, "reads", readsectors);
240                         rrddim_set(st, "writes", writesectors);
241                         rrdset_done(st);
242                 }
243
244                 // --------------------------------------------------------------------
245
246                 if(do_ops) {
247                         st = rrdset_find_bytype("disk_ops", disk);
248                         if(!st) {
249                                 st = rrdset_create("disk_ops", disk, NULL, disk, "Disk Operations", "operations/s", 2001, update_every, RRDSET_TYPE_LINE);
250                                 st->isdetail = 1;
251
252                                 rrddim_add(st, "reads", NULL, 1, 1 * update_every, RRDDIM_INCREMENTAL);
253                                 rrddim_add(st, "writes", NULL, -1, 1 * update_every, RRDDIM_INCREMENTAL);
254                         }
255                         else rrdset_next(st);
256
257                         rrddim_set(st, "reads", reads);
258                         rrddim_set(st, "writes", writes);
259                         rrdset_done(st);
260                 }
261                 
262                 // --------------------------------------------------------------------
263
264                 if(do_merged_ops) {
265                         st = rrdset_find_bytype("disk_merged_ops", disk);
266                         if(!st) {
267                                 st = rrdset_create("disk_merged_ops", disk, NULL, disk, "Merged Disk Operations", "operations/s", 2010, update_every, RRDSET_TYPE_LINE);
268                                 st->isdetail = 1;
269
270                                 rrddim_add(st, "reads", NULL, 1, 1 * update_every, RRDDIM_INCREMENTAL);
271                                 rrddim_add(st, "writes", NULL, -1, 1 * update_every, RRDDIM_INCREMENTAL);
272                         }
273                         else rrdset_next(st);
274
275                         rrddim_set(st, "reads", reads_merged);
276                         rrddim_set(st, "writes", writes_merged);
277                         rrdset_done(st);
278                 }
279
280                 // --------------------------------------------------------------------
281
282                 if(do_iotime) {
283                         st = rrdset_find_bytype("disk_iotime", disk);
284                         if(!st) {
285                                 st = rrdset_create("disk_iotime", disk, NULL, disk, "Disk I/O Time", "milliseconds/s", 2005, update_every, RRDSET_TYPE_LINE);
286                                 st->isdetail = 1;
287
288                                 rrddim_add(st, "reads", NULL, 1, 1 * update_every, RRDDIM_INCREMENTAL);
289                                 rrddim_add(st, "writes", NULL, -1, 1 * update_every, RRDDIM_INCREMENTAL);
290                                 rrddim_add(st, "latency", NULL, 1, 1 * update_every, RRDDIM_INCREMENTAL);
291                                 rrddim_add(st, "weighted", NULL, 1, 1 * update_every, RRDDIM_INCREMENTAL);
292                         }
293                         else rrdset_next(st);
294
295                         rrddim_set(st, "reads", readms);
296                         rrddim_set(st, "writes", writems);
297                         rrddim_set(st, "latency", iosms);
298                         rrddim_set(st, "weighted", wiosms);
299                         rrdset_done(st);
300                 }
301
302                 // --------------------------------------------------------------------
303
304                 if(do_cur_ops) {
305                         st = rrdset_find_bytype("disk_cur_ops", disk);
306                         if(!st) {
307                                 st = rrdset_create("disk_cur_ops", disk, NULL, disk, "Current Disk I/O operations", "operations", 2004, update_every, RRDSET_TYPE_LINE);
308                                 st->isdetail = 1;
309
310                                 rrddim_add(st, "operations", NULL, 1, 1, RRDDIM_ABSOLUTE);
311                         }
312                         else rrdset_next(st);
313
314                         rrddim_set(st, "operations", currentios);
315                         rrdset_done(st);
316                 }
317         }
318         
319         return 0;
320 }