1 /**
2 * collectd - src/target_v5upgrade.c
3 * Copyright (C) 2008-2010 Florian Forster
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 * Florian Forster <octo at collectd.org>
25 **/
27 #include "collectd.h"
29 #include "common.h"
30 #include "filter_chain.h"
31 #include "plugin.h"
33 static void v5_swap_instances(value_list_t *vl) /* {{{ */
34 {
35 char tmp[DATA_MAX_NAME_LEN];
37 assert(sizeof(tmp) == sizeof(vl->plugin_instance));
38 assert(sizeof(tmp) == sizeof(vl->type_instance));
40 memcpy(tmp, vl->plugin_instance, sizeof(tmp));
41 memcpy(vl->plugin_instance, vl->type_instance, sizeof(tmp));
42 memcpy(vl->type_instance, tmp, sizeof(tmp));
43 } /* }}} void v5_swap_instances */
45 /*
46 * Df type
47 *
48 * By default, the "df" plugin of version 4.* uses the "df" type and puts the
49 * mount point in the type instance. Detect this behavior and convert the type
50 * to "df_complex". This can be selected in versions 4.9 and 4.10 by setting
51 * the "ReportReserved" option of the "df" plugin.
52 */
53 static int v5_df(const data_set_t *ds, value_list_t *vl) /* {{{ */
54 {
55 value_list_t new_vl;
57 /* Can't upgrade if both instances have been set. */
58 if ((vl->plugin_instance[0] != 0) && (vl->type_instance[0] != 0))
59 return (FC_TARGET_CONTINUE);
61 /* Copy everything: Time, interval, host, ... */
62 memcpy(&new_vl, vl, sizeof(new_vl));
64 /* Reset data we can't simply copy */
65 new_vl.values = &(value_t){.gauge = NAN};
66 new_vl.values_len = 1;
67 new_vl.meta = NULL;
69 /* Move the mount point name to the plugin instance */
70 if (new_vl.plugin_instance[0] == 0)
71 v5_swap_instances(&new_vl);
73 /* Change the type to "df_complex" */
74 sstrncpy(new_vl.type, "df_complex", sizeof(new_vl.type));
76 /* Dispatch two new value lists instead of this one */
77 new_vl.values[0].gauge = vl->values[0].gauge;
78 sstrncpy(new_vl.type_instance, "used", sizeof(new_vl.type_instance));
79 plugin_dispatch_values(&new_vl);
81 new_vl.values[0].gauge = vl->values[1].gauge;
82 sstrncpy(new_vl.type_instance, "free", sizeof(new_vl.type_instance));
83 plugin_dispatch_values(&new_vl);
85 /* Abort processing */
86 return (FC_TARGET_STOP);
87 } /* }}} int v5_df */
89 /*
90 * Interface plugin
91 *
92 * 4.* stores the interface in the type instance and leaves the plugin
93 * instance empty. If this is the case, put the interface name into the plugin
94 * instance and clear the type instance.
95 */
96 static int v5_interface(const data_set_t *ds, value_list_t *vl) /* {{{ */
97 {
98 if ((vl->plugin_instance[0] != 0) || (vl->type_instance[0] == 0))
99 return (FC_TARGET_CONTINUE);
101 v5_swap_instances(vl);
102 return (FC_TARGET_CONTINUE);
103 } /* }}} int v5_interface */
105 /*
106 * MySQL query cache
107 *
108 * 4.* uses the "mysql_qcache" type which mixes different types of
109 * information. In 5.* this has been broken up.
110 */
111 static int v5_mysql_qcache(const data_set_t *ds, value_list_t *vl) /* {{{ */
112 {
113 value_list_t new_vl;
115 if (vl->values_len != 5)
116 return (FC_TARGET_STOP);
118 /* Copy everything: Time, interval, host, ... */
119 memcpy(&new_vl, vl, sizeof(new_vl));
121 /* Reset data we can't simply copy */
122 new_vl.values = &(value_t){.gauge = NAN};
123 new_vl.values_len = 1;
124 new_vl.meta = NULL;
126 /* Change the type to "cache_result" */
127 sstrncpy(new_vl.type, "cache_result", sizeof(new_vl.type));
129 /* Dispatch new value lists instead of this one */
130 new_vl.values[0].derive = (derive_t)vl->values[0].counter;
131 sstrncpy(new_vl.type_instance, "qcache-hits", sizeof(new_vl.type_instance));
132 plugin_dispatch_values(&new_vl);
134 new_vl.values[0].derive = (derive_t)vl->values[1].counter;
135 sstrncpy(new_vl.type_instance, "qcache-inserts",
136 sizeof(new_vl.type_instance));
137 plugin_dispatch_values(&new_vl);
139 new_vl.values[0].derive = (derive_t)vl->values[2].counter;
140 sstrncpy(new_vl.type_instance, "qcache-not_cached",
141 sizeof(new_vl.type_instance));
142 plugin_dispatch_values(&new_vl);
144 new_vl.values[0].derive = (derive_t)vl->values[3].counter;
145 sstrncpy(new_vl.type_instance, "qcache-prunes", sizeof(new_vl.type_instance));
146 plugin_dispatch_values(&new_vl);
148 /* The last data source is a gauge value, so we have to use a different type
149 * here. */
150 new_vl.values[0].gauge = vl->values[4].gauge;
151 sstrncpy(new_vl.type, "cache_size", sizeof(new_vl.type));
152 sstrncpy(new_vl.type_instance, "qcache", sizeof(new_vl.type_instance));
153 plugin_dispatch_values(&new_vl);
155 /* Abort processing */
156 return (FC_TARGET_STOP);
157 } /* }}} int v5_mysql_qcache */
159 /*
160 * MySQL thread count
161 *
162 * 4.* uses the "mysql_threads" type which mixes different types of
163 * information. In 5.* this has been broken up.
164 */
165 static int v5_mysql_threads(const data_set_t *ds, value_list_t *vl) /* {{{ */
166 {
167 value_list_t new_vl;
169 if (vl->values_len != 4)
170 return (FC_TARGET_STOP);
172 /* Copy everything: Time, interval, host, ... */
173 memcpy(&new_vl, vl, sizeof(new_vl));
175 /* Reset data we can't simply copy */
176 new_vl.values = &(value_t){.gauge = NAN};
177 new_vl.values_len = 1;
178 new_vl.meta = NULL;
180 /* Change the type to "threads" */
181 sstrncpy(new_vl.type, "threads", sizeof(new_vl.type));
183 /* Dispatch new value lists instead of this one */
184 new_vl.values[0].gauge = vl->values[0].gauge;
185 sstrncpy(new_vl.type_instance, "running", sizeof(new_vl.type_instance));
186 plugin_dispatch_values(&new_vl);
188 new_vl.values[0].gauge = vl->values[1].gauge;
189 sstrncpy(new_vl.type_instance, "connected", sizeof(new_vl.type_instance));
190 plugin_dispatch_values(&new_vl);
192 new_vl.values[0].gauge = vl->values[2].gauge;
193 sstrncpy(new_vl.type_instance, "cached", sizeof(new_vl.type_instance));
194 plugin_dispatch_values(&new_vl);
196 /* The last data source is a counter value, so we have to use a different
197 * type here. */
198 new_vl.values[0].derive = (derive_t)vl->values[3].counter;
199 sstrncpy(new_vl.type, "total_threads", sizeof(new_vl.type));
200 sstrncpy(new_vl.type_instance, "created", sizeof(new_vl.type_instance));
201 plugin_dispatch_values(&new_vl);
203 /* Abort processing */
204 return (FC_TARGET_STOP);
205 } /* }}} int v5_mysql_threads */
207 /*
208 * ZFS ARC hit and miss counters
209 *
210 * 4.* uses the flawed "arc_counts" type. In 5.* this has been replaced by the
211 * more generic "cache_result" type.
212 */
213 static int v5_zfs_arc_counts(const data_set_t *ds, value_list_t *vl) /* {{{ */
214 {
215 value_list_t new_vl;
216 _Bool is_hits;
218 if (vl->values_len != 4)
219 return (FC_TARGET_STOP);
221 if (strcmp("hits", vl->type_instance) == 0)
222 is_hits = 1;
223 else if (strcmp("misses", vl->type_instance) == 0)
224 is_hits = 0;
225 else
226 return (FC_TARGET_STOP);
228 /* Copy everything: Time, interval, host, ... */
229 memcpy(&new_vl, vl, sizeof(new_vl));
231 /* Reset data we can't simply copy */
232 new_vl.values = &(value_t){.gauge = NAN};
233 new_vl.values_len = 1;
234 new_vl.meta = NULL;
236 /* Change the type to "cache_result" */
237 sstrncpy(new_vl.type, "cache_result", sizeof(new_vl.type));
239 /* Dispatch new value lists instead of this one */
240 new_vl.values[0].derive = (derive_t)vl->values[0].counter;
241 ssnprintf(new_vl.type_instance, sizeof(new_vl.type_instance),
242 "demand_data-%s", is_hits ? "hit" : "miss");
243 plugin_dispatch_values(&new_vl);
245 new_vl.values[0].derive = (derive_t)vl->values[1].counter;
246 ssnprintf(new_vl.type_instance, sizeof(new_vl.type_instance),
247 "demand_metadata-%s", is_hits ? "hit" : "miss");
248 plugin_dispatch_values(&new_vl);
250 new_vl.values[0].derive = (derive_t)vl->values[2].counter;
251 ssnprintf(new_vl.type_instance, sizeof(new_vl.type_instance),
252 "prefetch_data-%s", is_hits ? "hit" : "miss");
253 plugin_dispatch_values(&new_vl);
255 new_vl.values[0].derive = (derive_t)vl->values[3].counter;
256 ssnprintf(new_vl.type_instance, sizeof(new_vl.type_instance),
257 "prefetch_metadata-%s", is_hits ? "hit" : "miss");
258 plugin_dispatch_values(&new_vl);
260 /* Abort processing */
261 return (FC_TARGET_STOP);
262 } /* }}} int v5_zfs_arc_counts */
264 /*
265 * ZFS ARC L2 bytes
266 *
267 * "arc_l2_bytes" -> "io_octets-L2".
268 */
269 static int v5_zfs_arc_l2_bytes(const data_set_t *ds, value_list_t *vl) /* {{{ */
270 {
271 value_list_t new_vl;
273 if (vl->values_len != 2)
274 return (FC_TARGET_STOP);
276 /* Copy everything: Time, interval, host, ... */
277 memcpy(&new_vl, vl, sizeof(new_vl));
279 /* Reset data we can't simply copy */
280 new_vl.meta = NULL;
282 /* Change the type/-instance to "io_octets-L2" */
283 sstrncpy(new_vl.type, "io_octets", sizeof(new_vl.type));
284 sstrncpy(new_vl.type_instance, "L2", sizeof(new_vl.type_instance));
286 /* Copy the actual values. */
287 value_t values[] = {
288 {.derive = (derive_t)vl->values[0].counter},
289 {.derive = (derive_t)vl->values[1].counter},
290 };
291 new_vl.values = values;
292 new_vl.values_len = STATIC_ARRAY_SIZE(values);
294 /* Dispatch new value lists instead of this one */
295 plugin_dispatch_values(&new_vl);
297 /* Abort processing */
298 return (FC_TARGET_STOP);
299 } /* }}} int v5_zfs_arc_l2_bytes */
301 /*
302 * ZFS ARC L2 cache size
303 *
304 * 4.* uses a separate type for this. 5.* uses the generic "cache_size" type
305 * instead.
306 */
307 static int v5_zfs_arc_l2_size(const data_set_t *ds, value_list_t *vl) /* {{{ */
308 {
309 value_list_t new_vl;
311 if (vl->values_len != 1)
312 return (FC_TARGET_STOP);
314 /* Copy everything: Time, interval, host, ... */
315 memcpy(&new_vl, vl, sizeof(new_vl));
317 /* Reset data we can't simply copy */
318 new_vl.values = &(value_t){.gauge = NAN};
319 new_vl.values_len = 1;
320 new_vl.meta = NULL;
322 new_vl.values[0].gauge = (gauge_t)vl->values[0].gauge;
324 /* Change the type to "cache_size" */
325 sstrncpy(new_vl.type, "cache_size", sizeof(new_vl.type));
327 /* Adapt the type instance */
328 sstrncpy(new_vl.type_instance, "L2", sizeof(new_vl.type_instance));
330 /* Dispatch new value lists instead of this one */
331 plugin_dispatch_values(&new_vl);
333 /* Abort processing */
334 return (FC_TARGET_STOP);
335 } /* }}} int v5_zfs_arc_l2_size */
337 /*
338 * ZFS ARC ratio
339 *
340 * "arc_ratio-L1" -> "cache_ratio-arc"
341 * "arc_ratio-L2" -> "cache_ratio-L2"
342 */
343 static int v5_zfs_arc_ratio(const data_set_t *ds, value_list_t *vl) /* {{{ */
344 {
345 value_list_t new_vl;
347 if (vl->values_len != 1)
348 return (FC_TARGET_STOP);
350 /* Copy everything: Time, interval, host, ... */
351 memcpy(&new_vl, vl, sizeof(new_vl));
353 /* Reset data we can't simply copy */
354 new_vl.values = &(value_t){.gauge = NAN};
355 new_vl.values_len = 1;
356 new_vl.meta = NULL;
358 new_vl.values[0].gauge = (gauge_t)vl->values[0].gauge;
360 /* Change the type to "cache_ratio" */
361 sstrncpy(new_vl.type, "cache_ratio", sizeof(new_vl.type));
363 /* Adapt the type instance */
364 if (strcmp("L1", vl->type_instance) == 0)
365 sstrncpy(new_vl.type_instance, "arc", sizeof(new_vl.type_instance));
367 /* Dispatch new value lists instead of this one */
368 plugin_dispatch_values(&new_vl);
370 /* Abort processing */
371 return (FC_TARGET_STOP);
372 } /* }}} int v5_zfs_arc_ratio */
374 /*
375 * ZFS ARC size
376 *
377 * 4.* uses the "arc_size" type with four data sources. In 5.* this has been
378 * replaces with the "cache_size" type and static data has been removed.
379 */
380 static int v5_zfs_arc_size(const data_set_t *ds, value_list_t *vl) /* {{{ */
381 {
382 value_list_t new_vl;
384 if (vl->values_len != 4)
385 return (FC_TARGET_STOP);
387 /* Copy everything: Time, interval, host, ... */
388 memcpy(&new_vl, vl, sizeof(new_vl));
390 /* Reset data we can't simply copy */
391 new_vl.values = &(value_t){.gauge = NAN};
392 new_vl.values_len = 1;
393 new_vl.meta = NULL;
395 /* Change the type to "cache_size" */
396 sstrncpy(new_vl.type, "cache_size", sizeof(new_vl.type));
398 /* Dispatch new value lists instead of this one */
399 new_vl.values[0].derive = (derive_t)vl->values[0].counter;
400 sstrncpy(new_vl.type_instance, "arc", sizeof(new_vl.type_instance));
401 plugin_dispatch_values(&new_vl);
403 /* Abort processing */
404 return (FC_TARGET_STOP);
405 } /* }}} int v5_zfs_arc_size */
407 static int v5_destroy(void **user_data) /* {{{ */
408 {
409 return (0);
410 } /* }}} int v5_destroy */
412 static int v5_create(const oconfig_item_t *ci, void **user_data) /* {{{ */
413 {
414 *user_data = NULL;
415 return (0);
416 } /* }}} int v5_create */
418 static int v5_invoke(const data_set_t *ds, value_list_t *vl, /* {{{ */
419 notification_meta_t __attribute__((unused)) * *meta,
420 void __attribute__((unused)) * *user_data) {
421 if ((ds == NULL) || (vl == NULL) || (user_data == NULL))
422 return (-EINVAL);
424 if (strcmp("df", vl->type) == 0)
425 return (v5_df(ds, vl));
426 else if (strcmp("interface", vl->plugin) == 0)
427 return (v5_interface(ds, vl));
428 else if (strcmp("mysql_qcache", vl->type) == 0)
429 return (v5_mysql_qcache(ds, vl));
430 else if (strcmp("mysql_threads", vl->type) == 0)
431 return (v5_mysql_threads(ds, vl));
432 else if (strcmp("arc_counts", vl->type) == 0)
433 return (v5_zfs_arc_counts(ds, vl));
434 else if (strcmp("arc_l2_bytes", vl->type) == 0)
435 return (v5_zfs_arc_l2_bytes(ds, vl));
436 else if (strcmp("arc_l2_size", vl->type) == 0)
437 return (v5_zfs_arc_l2_size(ds, vl));
438 else if (strcmp("arc_ratio", vl->type) == 0)
439 return (v5_zfs_arc_ratio(ds, vl));
440 else if (strcmp("arc_size", vl->type) == 0)
441 return (v5_zfs_arc_size(ds, vl));
443 return (FC_TARGET_CONTINUE);
444 } /* }}} int v5_invoke */
446 void module_register(void) {
447 target_proc_t tproc = {0};
449 tproc.create = v5_create;
450 tproc.destroy = v5_destroy;
451 tproc.invoke = v5_invoke;
452 fc_register_target("v5upgrade", tproc);
453 } /* module_register */
455 /* vim: set sw=2 sts=2 tw=78 et fdm=marker : */