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