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 "plugin.h"
30 #include "common.h"
31 #include "filter_chain.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)
59 && (vl->type_instance[0] != 0))
60 return (FC_TARGET_CONTINUE);
62 /* Copy everything: Time, interval, host, ... */
63 memcpy (&new_vl, vl, sizeof (new_vl));
65 /* Reset data we can't simply copy */
66 new_vl.values = &(value_t) { .gauge = NAN };
67 new_vl.values_len = 1;
68 new_vl.meta = NULL;
70 /* Move the mount point name to the plugin instance */
71 if (new_vl.plugin_instance[0] == 0)
72 v5_swap_instances (&new_vl);
74 /* Change the type to "df_complex" */
75 sstrncpy (new_vl.type, "df_complex", sizeof (new_vl.type));
77 /* Dispatch two new value lists instead of this one */
78 new_vl.values[0].gauge = vl->values[0].gauge;
79 sstrncpy (new_vl.type_instance, "used", sizeof (new_vl.type_instance));
80 plugin_dispatch_values (&new_vl);
82 new_vl.values[0].gauge = vl->values[1].gauge;
83 sstrncpy (new_vl.type_instance, "free", sizeof (new_vl.type_instance));
84 plugin_dispatch_values (&new_vl);
86 /* Abort processing */
87 return (FC_TARGET_STOP);
88 } /* }}} int v5_df */
90 /*
91 * Interface plugin
92 *
93 * 4.* stores the interface in the type instance and leaves the plugin
94 * instance empty. If this is the case, put the interface name into the plugin
95 * instance and clear the type instance.
96 */
97 static int v5_interface (const data_set_t *ds, value_list_t *vl) /* {{{ */
98 {
99 if ((vl->plugin_instance[0] != 0) || (vl->type_instance[0] == 0))
100 return (FC_TARGET_CONTINUE);
102 v5_swap_instances (vl);
103 return (FC_TARGET_CONTINUE);
104 } /* }}} int v5_interface */
106 /*
107 * MySQL query cache
108 *
109 * 4.* uses the "mysql_qcache" type which mixes different types of
110 * information. In 5.* this has been broken up.
111 */
112 static int v5_mysql_qcache (const data_set_t *ds, value_list_t *vl) /* {{{ */
113 {
114 value_list_t new_vl;
116 if (vl->values_len != 5)
117 return (FC_TARGET_STOP);
119 /* Copy everything: Time, interval, host, ... */
120 memcpy (&new_vl, vl, sizeof (new_vl));
122 /* Reset data we can't simply copy */
123 new_vl.values = &(value_t) { .gauge = NAN };
124 new_vl.values_len = 1;
125 new_vl.meta = NULL;
127 /* Change the type to "cache_result" */
128 sstrncpy (new_vl.type, "cache_result", sizeof (new_vl.type));
130 /* Dispatch new value lists instead of this one */
131 new_vl.values[0].derive = (derive_t) vl->values[0].counter;
132 sstrncpy (new_vl.type_instance, "qcache-hits",
133 sizeof (new_vl.type_instance));
134 plugin_dispatch_values (&new_vl);
136 new_vl.values[0].derive = (derive_t) vl->values[1].counter;
137 sstrncpy (new_vl.type_instance, "qcache-inserts",
138 sizeof (new_vl.type_instance));
139 plugin_dispatch_values (&new_vl);
141 new_vl.values[0].derive = (derive_t) vl->values[2].counter;
142 sstrncpy (new_vl.type_instance, "qcache-not_cached",
143 sizeof (new_vl.type_instance));
144 plugin_dispatch_values (&new_vl);
146 new_vl.values[0].derive = (derive_t) vl->values[3].counter;
147 sstrncpy (new_vl.type_instance, "qcache-prunes",
148 sizeof (new_vl.type_instance));
149 plugin_dispatch_values (&new_vl);
151 /* The last data source is a gauge value, so we have to use a different type
152 * here. */
153 new_vl.values[0].gauge = vl->values[4].gauge;
154 sstrncpy (new_vl.type, "cache_size", sizeof (new_vl.type));
155 sstrncpy (new_vl.type_instance, "qcache",
156 sizeof (new_vl.type_instance));
157 plugin_dispatch_values (&new_vl);
159 /* Abort processing */
160 return (FC_TARGET_STOP);
161 } /* }}} int v5_mysql_qcache */
163 /*
164 * MySQL thread count
165 *
166 * 4.* uses the "mysql_threads" type which mixes different types of
167 * information. In 5.* this has been broken up.
168 */
169 static int v5_mysql_threads (const data_set_t *ds, value_list_t *vl) /* {{{ */
170 {
171 value_list_t new_vl;
173 if (vl->values_len != 4)
174 return (FC_TARGET_STOP);
176 /* Copy everything: Time, interval, host, ... */
177 memcpy (&new_vl, vl, sizeof (new_vl));
179 /* Reset data we can't simply copy */
180 new_vl.values = &(value_t) { .gauge = NAN };
181 new_vl.values_len = 1;
182 new_vl.meta = NULL;
184 /* Change the type to "threads" */
185 sstrncpy (new_vl.type, "threads", sizeof (new_vl.type));
187 /* Dispatch new value lists instead of this one */
188 new_vl.values[0].gauge = vl->values[0].gauge;
189 sstrncpy (new_vl.type_instance, "running",
190 sizeof (new_vl.type_instance));
191 plugin_dispatch_values (&new_vl);
193 new_vl.values[0].gauge = vl->values[1].gauge;
194 sstrncpy (new_vl.type_instance, "connected",
195 sizeof (new_vl.type_instance));
196 plugin_dispatch_values (&new_vl);
198 new_vl.values[0].gauge = vl->values[2].gauge;
199 sstrncpy (new_vl.type_instance, "cached",
200 sizeof (new_vl.type_instance));
201 plugin_dispatch_values (&new_vl);
203 /* The last data source is a counter value, so we have to use a different
204 * type here. */
205 new_vl.values[0].derive = (derive_t) vl->values[3].counter;
206 sstrncpy (new_vl.type, "total_threads", sizeof (new_vl.type));
207 sstrncpy (new_vl.type_instance, "created",
208 sizeof (new_vl.type_instance));
209 plugin_dispatch_values (&new_vl);
211 /* Abort processing */
212 return (FC_TARGET_STOP);
213 } /* }}} int v5_mysql_threads */
215 /*
216 * ZFS ARC hit and miss counters
217 *
218 * 4.* uses the flawed "arc_counts" type. In 5.* this has been replaced by the
219 * more generic "cache_result" type.
220 */
221 static int v5_zfs_arc_counts (const data_set_t *ds, value_list_t *vl) /* {{{ */
222 {
223 value_list_t new_vl;
224 _Bool is_hits;
226 if (vl->values_len != 4)
227 return (FC_TARGET_STOP);
229 if (strcmp ("hits", vl->type_instance) == 0)
230 is_hits = 1;
231 else if (strcmp ("misses", vl->type_instance) == 0)
232 is_hits = 0;
233 else
234 return (FC_TARGET_STOP);
236 /* Copy everything: Time, interval, host, ... */
237 memcpy (&new_vl, vl, sizeof (new_vl));
239 /* Reset data we can't simply copy */
240 new_vl.values = &(value_t) { .gauge = NAN };
241 new_vl.values_len = 1;
242 new_vl.meta = NULL;
244 /* Change the type to "cache_result" */
245 sstrncpy (new_vl.type, "cache_result", sizeof (new_vl.type));
247 /* Dispatch new value lists instead of this one */
248 new_vl.values[0].derive = (derive_t) vl->values[0].counter;
249 ssnprintf (new_vl.type_instance, sizeof (new_vl.type_instance),
250 "demand_data-%s",
251 is_hits ? "hit" : "miss");
252 plugin_dispatch_values (&new_vl);
254 new_vl.values[0].derive = (derive_t) vl->values[1].counter;
255 ssnprintf (new_vl.type_instance, sizeof (new_vl.type_instance),
256 "demand_metadata-%s",
257 is_hits ? "hit" : "miss");
258 plugin_dispatch_values (&new_vl);
260 new_vl.values[0].derive = (derive_t) vl->values[2].counter;
261 ssnprintf (new_vl.type_instance, sizeof (new_vl.type_instance),
262 "prefetch_data-%s",
263 is_hits ? "hit" : "miss");
264 plugin_dispatch_values (&new_vl);
266 new_vl.values[0].derive = (derive_t) vl->values[3].counter;
267 ssnprintf (new_vl.type_instance, sizeof (new_vl.type_instance),
268 "prefetch_metadata-%s",
269 is_hits ? "hit" : "miss");
270 plugin_dispatch_values (&new_vl);
272 /* Abort processing */
273 return (FC_TARGET_STOP);
274 } /* }}} int v5_zfs_arc_counts */
276 /*
277 * ZFS ARC L2 bytes
278 *
279 * "arc_l2_bytes" -> "io_octets-L2".
280 */
281 static int v5_zfs_arc_l2_bytes (const data_set_t *ds, value_list_t *vl) /* {{{ */
282 {
283 value_list_t new_vl;
284 value_t new_values[2];
286 if (vl->values_len != 2)
287 return (FC_TARGET_STOP);
289 /* Copy everything: Time, interval, host, ... */
290 memcpy (&new_vl, vl, sizeof (new_vl));
292 /* Reset data we can't simply copy */
293 new_vl.values = new_values;
294 new_vl.values_len = 2;
295 new_vl.meta = NULL;
297 /* Change the type/-instance to "io_octets-L2" */
298 sstrncpy (new_vl.type, "io_octets", sizeof (new_vl.type));
299 sstrncpy (new_vl.type_instance, "L2", sizeof (new_vl.type_instance));
301 /* Copy the actual values. */
302 new_vl.values[0].derive = (derive_t) vl->values[0].counter;
303 new_vl.values[1].derive = (derive_t) vl->values[1].counter;
305 /* Dispatch new value lists instead of this one */
306 plugin_dispatch_values (&new_vl);
308 /* Abort processing */
309 return (FC_TARGET_STOP);
310 } /* }}} int v5_zfs_arc_l2_bytes */
312 /*
313 * ZFS ARC L2 cache size
314 *
315 * 4.* uses a separate type for this. 5.* uses the generic "cache_size" type
316 * instead.
317 */
318 static int v5_zfs_arc_l2_size (const data_set_t *ds, value_list_t *vl) /* {{{ */
319 {
320 value_list_t new_vl;
322 if (vl->values_len != 1)
323 return (FC_TARGET_STOP);
325 /* Copy everything: Time, interval, host, ... */
326 memcpy (&new_vl, vl, sizeof (new_vl));
328 /* Reset data we can't simply copy */
329 new_vl.values = &(value_t) { .gauge = NAN };
330 new_vl.values_len = 1;
331 new_vl.meta = NULL;
333 new_vl.values[0].gauge = (gauge_t) vl->values[0].gauge;
335 /* Change the type to "cache_size" */
336 sstrncpy (new_vl.type, "cache_size", sizeof (new_vl.type));
338 /* Adapt the type instance */
339 sstrncpy (new_vl.type_instance, "L2", sizeof (new_vl.type_instance));
341 /* Dispatch new value lists instead of this one */
342 plugin_dispatch_values (&new_vl);
344 /* Abort processing */
345 return (FC_TARGET_STOP);
346 } /* }}} int v5_zfs_arc_l2_size */
348 /*
349 * ZFS ARC ratio
350 *
351 * "arc_ratio-L1" -> "cache_ratio-arc"
352 * "arc_ratio-L2" -> "cache_ratio-L2"
353 */
354 static int v5_zfs_arc_ratio (const data_set_t *ds, value_list_t *vl) /* {{{ */
355 {
356 value_list_t new_vl;
358 if (vl->values_len != 1)
359 return (FC_TARGET_STOP);
361 /* Copy everything: Time, interval, host, ... */
362 memcpy (&new_vl, vl, sizeof (new_vl));
364 /* Reset data we can't simply copy */
365 new_vl.values = &(value_t) { .gauge = NAN };
366 new_vl.values_len = 1;
367 new_vl.meta = NULL;
369 new_vl.values[0].gauge = (gauge_t) vl->values[0].gauge;
371 /* Change the type to "cache_ratio" */
372 sstrncpy (new_vl.type, "cache_ratio", sizeof (new_vl.type));
374 /* Adapt the type instance */
375 if (strcmp ("L1", vl->type_instance) == 0)
376 sstrncpy (new_vl.type_instance, "arc", sizeof (new_vl.type_instance));
378 /* Dispatch new value lists instead of this one */
379 plugin_dispatch_values (&new_vl);
381 /* Abort processing */
382 return (FC_TARGET_STOP);
383 } /* }}} int v5_zfs_arc_ratio */
385 /*
386 * ZFS ARC size
387 *
388 * 4.* uses the "arc_size" type with four data sources. In 5.* this has been
389 * replaces with the "cache_size" type and static data has been removed.
390 */
391 static int v5_zfs_arc_size (const data_set_t *ds, value_list_t *vl) /* {{{ */
392 {
393 value_list_t new_vl;
395 if (vl->values_len != 4)
396 return (FC_TARGET_STOP);
398 /* Copy everything: Time, interval, host, ... */
399 memcpy (&new_vl, vl, sizeof (new_vl));
401 /* Reset data we can't simply copy */
402 new_vl.values = &(value_t) { .gauge = NAN };
403 new_vl.values_len = 1;
404 new_vl.meta = NULL;
406 /* Change the type to "cache_size" */
407 sstrncpy (new_vl.type, "cache_size", sizeof (new_vl.type));
409 /* Dispatch new value lists instead of this one */
410 new_vl.values[0].derive = (derive_t) vl->values[0].counter;
411 sstrncpy (new_vl.type_instance, "arc", sizeof (new_vl.type_instance));
412 plugin_dispatch_values (&new_vl);
414 /* Abort processing */
415 return (FC_TARGET_STOP);
416 } /* }}} int v5_zfs_arc_size */
418 static int v5_destroy (void **user_data) /* {{{ */
419 {
420 return (0);
421 } /* }}} int v5_destroy */
423 static int v5_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
424 {
425 *user_data = NULL;
426 return (0);
427 } /* }}} int v5_create */
429 static int v5_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */
430 notification_meta_t __attribute__((unused)) **meta,
431 void __attribute__((unused)) **user_data)
432 {
433 if ((ds == NULL) || (vl == NULL) || (user_data == NULL))
434 return (-EINVAL);
436 if (strcmp ("df", vl->type) == 0)
437 return (v5_df (ds, vl));
438 else if (strcmp ("interface", vl->plugin) == 0)
439 return (v5_interface (ds, vl));
440 else if (strcmp ("mysql_qcache", vl->type) == 0)
441 return (v5_mysql_qcache (ds, vl));
442 else if (strcmp ("mysql_threads", vl->type) == 0)
443 return (v5_mysql_threads (ds, vl));
444 else if (strcmp ("arc_counts", vl->type) == 0)
445 return (v5_zfs_arc_counts (ds, vl));
446 else if (strcmp ("arc_l2_bytes", vl->type) == 0)
447 return (v5_zfs_arc_l2_bytes (ds, vl));
448 else if (strcmp ("arc_l2_size", vl->type) == 0)
449 return (v5_zfs_arc_l2_size (ds, vl));
450 else if (strcmp ("arc_ratio", vl->type) == 0)
451 return (v5_zfs_arc_ratio (ds, vl));
452 else if (strcmp ("arc_size", vl->type) == 0)
453 return (v5_zfs_arc_size (ds, vl));
455 return (FC_TARGET_CONTINUE);
456 } /* }}} int v5_invoke */
458 void module_register (void)
459 {
460 target_proc_t tproc = { 0 };
462 tproc.create = v5_create;
463 tproc.destroy = v5_destroy;
464 tproc.invoke = v5_invoke;
465 fc_register_target ("v5upgrade", tproc);
466 } /* module_register */
468 /* vim: set sw=2 sts=2 tw=78 et fdm=marker : */