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