3485c0bbb874ca84adb9f0aecd0f04fb7656b0c9
[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 {
45         "network_send",  /* ns (network send) */
46         "network_recv",  /* nr (network receive) */
47         "disk_write",      /* dw (disk write) */
48         "disk_read",            /* dr (disk read) */
49         "activity_log",  /* al (activity log) */
50         "bitmap",                  /* bm (bit map) */
51         "local_count",    /* lo (local count) */
52         "pending",                /* pe (pending) */
53         "unacknowledged",   /* ua (unacknowledged) */
54         "app pending",    /* ap (application pending) */
55         "epochs",                  /* ep (epochs) */
56         NULL,                      /* wo (write order) */
57         "oos"                      /* oos (out of sync) */
58 };
59 static size_t drbd_names_num = STATIC_ARRAY_SIZE (drbd_names);
60
61 static int drbd_init (void)
62 {
63         return (0);
64 }
65
66
67 static int drbd_submit_fields (long int resource,
68                 char **fields, size_t fields_num)
69 {
70         char plugin_instance[DATA_MAX_NAME_LEN];
71         value_t values[fields_num];
72         value_list_t vl = VALUE_LIST_INIT;
73         size_t i;
74
75         if (resource < 0)
76         {
77                 WARNING ("drbd plugin: Unable to parse resource");
78                 return (EINVAL);
79         }
80
81         if (fields_num != drbd_names_num)
82         {
83                 WARNING ("drbd plugin: Wrong number of fields for "
84                                  "r%ld statistics. Expected %zu, got %zu.",
85                                  resource, drbd_names_num, fields_num);
86                 return (EINVAL);
87         }
88
89         ssnprintf (plugin_instance, sizeof (plugin_instance), "r%ld",
90                         resource);
91
92         for (i = 0; i < drbd_names_num; i++)
93         {
94                 char *data;
95                 /* skip non numeric wo */
96                 if (strncmp(fields[i], "wo", 2) == 0)
97                         continue;
98                 data = strchr(fields[i], ':');
99                 if (data == NULL)
100                         return (EINVAL);
101                 (void) parse_value (++data, &values[i], DS_TYPE_DERIVE);
102         }
103
104         vl.values_len = 1;
105         sstrncpy (vl.host, hostname_g, sizeof (vl.host));
106         sstrncpy (vl.plugin, "drbd", sizeof (vl.plugin));
107         sstrncpy (vl.plugin_instance, plugin_instance,
108                         sizeof (vl.plugin_instance));
109         sstrncpy (vl.type, "drbd_resource", sizeof (vl.type));
110
111         for (i = 0; i < fields_num; i++)
112         {
113                 if (drbd_names[i] == NULL)
114                         continue;
115                 vl.values = values + i;
116                 sstrncpy (vl.type_instance, drbd_names[i],
117                                 sizeof (vl.type_instance));
118                 plugin_dispatch_values (&vl);
119         }
120
121         return (0);
122 } /* drbd_submit_fields */
123
124 static int drbd_read (void)
125 {
126         FILE *fh;
127         char buffer[256];
128
129         long int resource = -1;
130         char *fields[16];
131         int fields_num = 0;
132
133         fh = fopen (drbd_stats, "r");
134         if (fh == NULL)
135         {
136                 WARNING ("drbd plugin: Unable to open %s", drbd_stats);
137                 return (EINVAL);
138         }
139
140         while (fgets (buffer, sizeof (buffer), fh) != NULL)
141         {
142                 fields_num = strsplit (buffer,
143                                 fields, STATIC_ARRAY_SIZE (fields));
144
145                 /* ignore headers (first two iterations) */
146                 if ((strcmp(fields[0], "version:") == 0) ||
147                                 (strcmp(fields[0], "srcversion:") == 0) ||
148                                 (strcmp(fields[0], "GIT-hash:") == 0))
149                 {
150                         continue;
151                 }
152
153                 if (isdigit(fields[0][0]))
154                 {
155                         /* parse the resource line, next loop iteration
156                            will submit values for this resource */
157                         resource = strtol(fields[0], NULL, 10);
158                 }
159                 else
160                 {
161                         /* handle stats data for the resource defined in the
162                            previous iteration */
163                         drbd_submit_fields(resource, fields, fields_num);
164                 }
165         } /* while (fgets) */
166
167         fclose (fh);
168         return (0);
169 } /* void drbd_read */
170
171 void module_register (void)
172 {
173         plugin_register_init ("drbd", drbd_init);
174         plugin_register_read ("drbd", drbd_read);
175 } /* void module_register */