5a0eac3098a3c696c33124b55cb2ef2e93f7221c
[collectd.git] / src / drbd.c
1 /**
2  * collectd - src/drbd.c
3  * Copyright (C) 2014  Tim Laszlo
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  *
23  * Authors:
24  *   Tim Laszlo <tim.laszlo at gmail.com>
25  **/
26
27 /*
28  See: http://www.drbd.org/users-guide/ch-admin.html#s-performance-indicators
29
30  version: 8.3.11 (api:88/proto:86-96)
31  srcversion: 71955441799F513ACA6DA60
32   0: cs:Connected ro:Primary/Secondary ds:UpToDate/UpToDate B r-----
33          ns:64363752 nr:0 dw:357799284 dr:846902273 al:34987022 bm:18062 lo:0 \
34                                                 pe:0 ua:0 ap:0 ep:1 wo:f oos:0
35  */
36
37 #include "collectd.h"
38
39 #include "common.h"
40 #include "plugin.h"
41
42 static const char *drbd_stats = "/proc/drbd";
43 static const char *drbd_names[] = {
44     "network_send",   /* ns (network send) */
45     "network_recv",   /* nr (network receive) */
46     "disk_write",     /* dw (disk write) */
47     "disk_read",      /* dr (disk read) */
48     "activity_log",   /* al (activity log) */
49     "bitmap",         /* bm (bit map) */
50     "local_count",    /* lo (local count) */
51     "pending",        /* pe (pending) */
52     "unacknowledged", /* ua (unacknowledged) */
53     "app pending",    /* ap (application pending) */
54     "epochs",         /* ep (epochs) */
55     NULL,             /* wo (write order) */
56     "oos"             /* oos (out of sync) */
57 };
58 static size_t drbd_names_num = STATIC_ARRAY_SIZE(drbd_names);
59
60 static int drbd_init(void) { return 0; }
61
62 static int drbd_submit_fields(long int resource, char **fields,
63                               size_t fields_num) {
64   char plugin_instance[DATA_MAX_NAME_LEN];
65   value_t values[fields_num];
66   value_list_t vl = VALUE_LIST_INIT;
67
68   if (resource < 0) {
69     WARNING("drbd plugin: Unable to parse resource");
70     return EINVAL;
71   }
72
73   if (fields_num != drbd_names_num) {
74     WARNING("drbd plugin: Wrong number of fields for "
75             "r%ld statistics. Expected %zu, got %zu.",
76             resource, drbd_names_num, fields_num);
77     return EINVAL;
78   }
79
80   snprintf(plugin_instance, sizeof(plugin_instance), "r%ld", resource);
81
82   for (size_t i = 0; i < drbd_names_num; i++) {
83     char *data;
84     /* skip non numeric wo */
85     if (strncmp(fields[i], "wo", 2) == 0)
86       continue;
87     data = strchr(fields[i], ':');
88     if (data == NULL)
89       return EINVAL;
90     (void)parse_value(++data, &values[i], DS_TYPE_DERIVE);
91   }
92
93   vl.values_len = 1;
94   sstrncpy(vl.plugin, "drbd", sizeof(vl.plugin));
95   sstrncpy(vl.plugin_instance, plugin_instance, sizeof(vl.plugin_instance));
96   sstrncpy(vl.type, "drbd_resource", sizeof(vl.type));
97
98   for (size_t i = 0; i < fields_num; i++) {
99     if (drbd_names[i] == NULL)
100       continue;
101     vl.values = values + i;
102     sstrncpy(vl.type_instance, drbd_names[i], sizeof(vl.type_instance));
103     plugin_dispatch_values(&vl);
104   }
105
106   return 0;
107 } /* drbd_submit_fields */
108
109 static int drbd_read(void) {
110   FILE *fh;
111   char buffer[256];
112
113   long int resource = -1;
114   char *fields[16];
115   int fields_num = 0;
116
117   fh = fopen(drbd_stats, "r");
118   if (fh == NULL) {
119     WARNING("drbd plugin: Unable to open %s", drbd_stats);
120     return EINVAL;
121   }
122
123   while (fgets(buffer, sizeof(buffer), fh) != NULL) {
124     fields_num = strsplit(buffer, fields, STATIC_ARRAY_SIZE(fields));
125
126     /* ignore headers (first two iterations) */
127     if ((strcmp(fields[0], "version:") == 0) ||
128         (strcmp(fields[0], "srcversion:") == 0) ||
129         (strcmp(fields[0], "GIT-hash:") == 0)) {
130       continue;
131     }
132
133     if (isdigit(fields[0][0])) {
134       /* parse the resource line, next loop iteration
135          will submit values for this resource */
136       resource = strtol(fields[0], NULL, 10);
137     } else {
138       /* handle stats data for the resource defined in the
139          previous iteration */
140       drbd_submit_fields(resource, fields, fields_num);
141     }
142   } /* while (fgets) */
143
144   fclose(fh);
145   return 0;
146 } /* void drbd_read */
147
148 void module_register(void) {
149   plugin_register_init("drbd", drbd_init);
150   plugin_register_read("drbd", drbd_read);
151 } /* void module_register */