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;
56 value_t new_value;
58 /* Can't upgrade if both instances have been set. */
59 if ((vl->plugin_instance[0] != 0)
60 && (vl->type_instance[0] != 0))
61 return (FC_TARGET_CONTINUE);
63 /* Copy everything: Time, interval, host, ... */
64 memcpy (&new_vl, vl, sizeof (new_vl));
66 /* Reset data we can't simply copy */
67 new_vl.values = &new_value;
68 new_vl.values_len = 1;
69 new_vl.meta = NULL;
71 /* Move the mount point name to the plugin instance */
72 if (new_vl.plugin_instance[0] == 0)
73 v5_swap_instances (&new_vl);
75 /* Change the type to "df_complex" */
76 sstrncpy (new_vl.type, "df_complex", sizeof (new_vl.type));
78 /* Dispatch two new value lists instead of this one */
79 new_vl.values[0].gauge = vl->values[0].gauge;
80 sstrncpy (new_vl.type_instance, "used", sizeof (new_vl.type_instance));
81 plugin_dispatch_values (&new_vl);
83 new_vl.values[0].gauge = vl->values[1].gauge;
84 sstrncpy (new_vl.type_instance, "free", sizeof (new_vl.type_instance));
85 plugin_dispatch_values (&new_vl);
87 /* Abort processing */
88 return (FC_TARGET_STOP);
89 } /* }}} int v5_df */
91 /*
92 * Interface plugin
93 *
94 * 4.* stores the interface in the type instance and leaves the plugin
95 * instance empty. If this is the case, put the interface name into the plugin
96 * instance and clear the type instance.
97 */
98 static int v5_interface (const data_set_t *ds, value_list_t *vl) /* {{{ */
99 {
100 if ((vl->plugin_instance[0] != 0) || (vl->type_instance[0] == 0))
101 return (FC_TARGET_CONTINUE);
103 v5_swap_instances (vl);
104 return (FC_TARGET_CONTINUE);
105 } /* }}} int v5_interface */
107 /*
108 * MySQL query cache
109 *
110 * 4.* uses the "mysql_qcache" type which mixes different types of
111 * information. In 5.* this has been broken up.
112 */
113 static int v5_mysql_qcache (const data_set_t *ds, value_list_t *vl) /* {{{ */
114 {
115 value_list_t new_vl;
116 value_t new_value;
118 if (vl->values_len != 5)
119 return (FC_TARGET_STOP);
121 /* Copy everything: Time, interval, host, ... */
122 memcpy (&new_vl, vl, sizeof (new_vl));
124 /* Reset data we can't simply copy */
125 new_vl.values = &new_value;
126 new_vl.values_len = 1;
127 new_vl.meta = NULL;
129 /* Change the type to "cache_result" */
130 sstrncpy (new_vl.type, "cache_result", sizeof (new_vl.type));
132 /* Dispatch new value lists instead of this one */
133 new_vl.values[0].derive = (derive_t) vl->values[0].counter;
134 sstrncpy (new_vl.type_instance, "qcache-hits",
135 sizeof (new_vl.type_instance));
136 plugin_dispatch_values (&new_vl);
138 new_vl.values[0].derive = (derive_t) vl->values[1].counter;
139 sstrncpy (new_vl.type_instance, "qcache-inserts",
140 sizeof (new_vl.type_instance));
141 plugin_dispatch_values (&new_vl);
143 new_vl.values[0].derive = (derive_t) vl->values[2].counter;
144 sstrncpy (new_vl.type_instance, "qcache-not_cached",
145 sizeof (new_vl.type_instance));
146 plugin_dispatch_values (&new_vl);
148 new_vl.values[0].derive = (derive_t) vl->values[3].counter;
149 sstrncpy (new_vl.type_instance, "qcache-prunes",
150 sizeof (new_vl.type_instance));
151 plugin_dispatch_values (&new_vl);
153 /* The last data source is a gauge value, so we have to use a different type
154 * here. */
155 new_vl.values[0].gauge = vl->values[4].gauge;
156 sstrncpy (new_vl.type, "cache_size", sizeof (new_vl.type));
157 sstrncpy (new_vl.type_instance, "qcache",
158 sizeof (new_vl.type_instance));
159 plugin_dispatch_values (&new_vl);
161 /* Abort processing */
162 return (FC_TARGET_STOP);
163 } /* }}} int v5_mysql_qcache */
165 /*
166 * MySQL thread count
167 *
168 * 4.* uses the "mysql_threads" type which mixes different types of
169 * information. In 5.* this has been broken up.
170 */
171 static int v5_mysql_threads (const data_set_t *ds, value_list_t *vl) /* {{{ */
172 {
173 value_list_t new_vl;
174 value_t new_value;
176 if (vl->values_len != 4)
177 return (FC_TARGET_STOP);
179 /* Copy everything: Time, interval, host, ... */
180 memcpy (&new_vl, vl, sizeof (new_vl));
182 /* Reset data we can't simply copy */
183 new_vl.values = &new_value;
184 new_vl.values_len = 1;
185 new_vl.meta = NULL;
187 /* Change the type to "threads" */
188 sstrncpy (new_vl.type, "threads", sizeof (new_vl.type));
190 /* Dispatch new value lists instead of this one */
191 new_vl.values[0].gauge = vl->values[0].gauge;
192 sstrncpy (new_vl.type_instance, "running",
193 sizeof (new_vl.type_instance));
194 plugin_dispatch_values (&new_vl);
196 new_vl.values[0].gauge = vl->values[1].gauge;
197 sstrncpy (new_vl.type_instance, "connected",
198 sizeof (new_vl.type_instance));
199 plugin_dispatch_values (&new_vl);
201 new_vl.values[0].gauge = vl->values[2].gauge;
202 sstrncpy (new_vl.type_instance, "cached",
203 sizeof (new_vl.type_instance));
204 plugin_dispatch_values (&new_vl);
206 /* The last data source is a counter value, so we have to use a different
207 * type here. */
208 new_vl.values[0].derive = (derive_t) vl->values[3].counter;
209 sstrncpy (new_vl.type, "total_threads", sizeof (new_vl.type));
210 sstrncpy (new_vl.type_instance, "created",
211 sizeof (new_vl.type_instance));
212 plugin_dispatch_values (&new_vl);
214 /* Abort processing */
215 return (FC_TARGET_STOP);
216 } /* }}} int v5_mysql_threads */
218 /*
219 * ZFS ARC hit and miss counters
220 *
221 * 4.* uses the flawed "arc_counts" type. In 5.* this has been replaced by the
222 * more generic "cache_result" type.
223 */
224 static int v5_zfs_arc_counts (const data_set_t *ds, value_list_t *vl) /* {{{ */
225 {
226 value_list_t new_vl;
227 value_t new_value;
228 _Bool is_hits;
230 if (vl->values_len != 4)
231 return (FC_TARGET_STOP);
233 if (strcmp ("hits", vl->type_instance) == 0)
234 is_hits = 1;
235 else if (strcmp ("misses", vl->type_instance) == 0)
236 is_hits = 0;
237 else
238 return (FC_TARGET_STOP);
240 /* Copy everything: Time, interval, host, ... */
241 memcpy (&new_vl, vl, sizeof (new_vl));
243 /* Reset data we can't simply copy */
244 new_vl.values = &new_value;
245 new_vl.values_len = 1;
246 new_vl.meta = NULL;
248 /* Change the type to "cache_result" */
249 sstrncpy (new_vl.type, "cache_result", sizeof (new_vl.type));
251 /* Dispatch new value lists instead of this one */
252 new_vl.values[0].derive = (derive_t) vl->values[0].counter;
253 ssnprintf (new_vl.type_instance, sizeof (new_vl.type_instance),
254 "demand_data-%s",
255 is_hits ? "hit" : "miss");
256 plugin_dispatch_values (&new_vl);
258 new_vl.values[0].derive = (derive_t) vl->values[1].counter;
259 ssnprintf (new_vl.type_instance, sizeof (new_vl.type_instance),
260 "demand_metadata-%s",
261 is_hits ? "hit" : "miss");
262 plugin_dispatch_values (&new_vl);
264 new_vl.values[0].derive = (derive_t) vl->values[2].counter;
265 ssnprintf (new_vl.type_instance, sizeof (new_vl.type_instance),
266 "prefetch_data-%s",
267 is_hits ? "hit" : "miss");
268 plugin_dispatch_values (&new_vl);
270 new_vl.values[0].derive = (derive_t) vl->values[3].counter;
271 ssnprintf (new_vl.type_instance, sizeof (new_vl.type_instance),
272 "prefetch_metadata-%s",
273 is_hits ? "hit" : "miss");
274 plugin_dispatch_values (&new_vl);
276 /* Abort processing */
277 return (FC_TARGET_STOP);
278 } /* }}} int v5_zfs_arc_counts */
280 /*
281 * ZFS ARC L2 bytes
282 *
283 * "arc_l2_bytes" -> "io_octets-L2".
284 */
285 static int v5_zfs_arc_l2_bytes (const data_set_t *ds, value_list_t *vl) /* {{{ */
286 {
287 value_list_t new_vl;
288 value_t new_values[2];
290 if (vl->values_len != 2)
291 return (FC_TARGET_STOP);
293 /* Copy everything: Time, interval, host, ... */
294 memcpy (&new_vl, vl, sizeof (new_vl));
296 /* Reset data we can't simply copy */
297 new_vl.values = new_values;
298 new_vl.values_len = 2;
299 new_vl.meta = NULL;
301 /* Change the type/-instance to "io_octets-L2" */
302 sstrncpy (new_vl.type, "io_octets", sizeof (new_vl.type));
303 sstrncpy (new_vl.type_instance, "L2", sizeof (new_vl.type_instance));
305 /* Copy the actual values. */
306 new_vl.values[0].derive = (derive_t) vl->values[0].counter;
307 new_vl.values[1].derive = (derive_t) vl->values[1].counter;
309 /* Dispatch new value lists instead of this one */
310 plugin_dispatch_values (&new_vl);
312 /* Abort processing */
313 return (FC_TARGET_STOP);
314 } /* }}} int v5_zfs_arc_l2_bytes */
316 /*
317 * ZFS ARC L2 cache size
318 *
319 * 4.* uses a separate type for this. 5.* uses the generic "cache_size" type
320 * instead.
321 */
322 static int v5_zfs_arc_l2_size (const data_set_t *ds, value_list_t *vl) /* {{{ */
323 {
324 value_list_t new_vl;
325 value_t new_value;
327 if (vl->values_len != 1)
328 return (FC_TARGET_STOP);
330 /* Copy everything: Time, interval, host, ... */
331 memcpy (&new_vl, vl, sizeof (new_vl));
333 /* Reset data we can't simply copy */
334 new_vl.values = &new_value;
335 new_vl.values_len = 1;
336 new_vl.meta = NULL;
338 new_vl.values[0].gauge = (gauge_t) vl->values[0].gauge;
340 /* Change the type to "cache_size" */
341 sstrncpy (new_vl.type, "cache_size", sizeof (new_vl.type));
343 /* Adapt the type instance */
344 sstrncpy (new_vl.type_instance, "L2", sizeof (new_vl.type_instance));
346 /* Dispatch new value lists instead of this one */
347 plugin_dispatch_values (&new_vl);
349 /* Abort processing */
350 return (FC_TARGET_STOP);
351 } /* }}} int v5_zfs_arc_l2_size */
353 /*
354 * ZFS ARC ratio
355 *
356 * "arc_ratio-L1" -> "cache_ratio-arc"
357 * "arc_ratio-L2" -> "cache_ratio-L2"
358 */
359 static int v5_zfs_arc_ratio (const data_set_t *ds, value_list_t *vl) /* {{{ */
360 {
361 value_list_t new_vl;
362 value_t new_value;
364 if (vl->values_len != 1)
365 return (FC_TARGET_STOP);
367 /* Copy everything: Time, interval, host, ... */
368 memcpy (&new_vl, vl, sizeof (new_vl));
370 /* Reset data we can't simply copy */
371 new_vl.values = &new_value;
372 new_vl.values_len = 1;
373 new_vl.meta = NULL;
375 new_vl.values[0].gauge = (gauge_t) vl->values[0].gauge;
377 /* Change the type to "cache_ratio" */
378 sstrncpy (new_vl.type, "cache_ratio", sizeof (new_vl.type));
380 /* Adapt the type instance */
381 if (strcmp ("L1", vl->type_instance) == 0)
382 sstrncpy (new_vl.type_instance, "arc", sizeof (new_vl.type_instance));
384 /* Dispatch new value lists instead of this one */
385 plugin_dispatch_values (&new_vl);
387 /* Abort processing */
388 return (FC_TARGET_STOP);
389 } /* }}} int v5_zfs_arc_ratio */
391 /*
392 * ZFS ARC size
393 *
394 * 4.* uses the "arc_size" type with four data sources. In 5.* this has been
395 * replaces with the "cache_size" type and static data has been removed.
396 */
397 static int v5_zfs_arc_size (const data_set_t *ds, value_list_t *vl) /* {{{ */
398 {
399 value_list_t new_vl;
400 value_t new_value;
402 if (vl->values_len != 4)
403 return (FC_TARGET_STOP);
405 /* Copy everything: Time, interval, host, ... */
406 memcpy (&new_vl, vl, sizeof (new_vl));
408 /* Reset data we can't simply copy */
409 new_vl.values = &new_value;
410 new_vl.values_len = 1;
411 new_vl.meta = NULL;
413 /* Change the type to "cache_size" */
414 sstrncpy (new_vl.type, "cache_size", sizeof (new_vl.type));
416 /* Dispatch new value lists instead of this one */
417 new_vl.values[0].derive = (derive_t) vl->values[0].counter;
418 sstrncpy (new_vl.type_instance, "arc", sizeof (new_vl.type_instance));
419 plugin_dispatch_values (&new_vl);
421 /* Abort processing */
422 return (FC_TARGET_STOP);
423 } /* }}} int v5_zfs_arc_size */
425 static int v5_destroy (void **user_data) /* {{{ */
426 {
427 return (0);
428 } /* }}} int v5_destroy */
430 static int v5_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
431 {
432 *user_data = NULL;
433 return (0);
434 } /* }}} int v5_create */
436 static int v5_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */
437 notification_meta_t __attribute__((unused)) **meta,
438 void __attribute__((unused)) **user_data)
439 {
440 if ((ds == NULL) || (vl == NULL) || (user_data == NULL))
441 return (-EINVAL);
443 if (strcmp ("df", vl->type) == 0)
444 return (v5_df (ds, vl));
445 else if (strcmp ("interface", vl->plugin) == 0)
446 return (v5_interface (ds, vl));
447 else if (strcmp ("mysql_qcache", vl->type) == 0)
448 return (v5_mysql_qcache (ds, vl));
449 else if (strcmp ("mysql_threads", vl->type) == 0)
450 return (v5_mysql_threads (ds, vl));
451 else if (strcmp ("arc_counts", vl->type) == 0)
452 return (v5_zfs_arc_counts (ds, vl));
453 else if (strcmp ("arc_l2_bytes", vl->type) == 0)
454 return (v5_zfs_arc_l2_bytes (ds, vl));
455 else if (strcmp ("arc_l2_size", vl->type) == 0)
456 return (v5_zfs_arc_l2_size (ds, vl));
457 else if (strcmp ("arc_ratio", vl->type) == 0)
458 return (v5_zfs_arc_ratio (ds, vl));
459 else if (strcmp ("arc_size", vl->type) == 0)
460 return (v5_zfs_arc_size (ds, vl));
462 return (FC_TARGET_CONTINUE);
463 } /* }}} int v5_invoke */
465 void module_register (void)
466 {
467 target_proc_t tproc = { 0 };
469 tproc.create = v5_create;
470 tproc.destroy = v5_destroy;
471 tproc.invoke = v5_invoke;
472 fc_register_target ("v5upgrade", tproc);
473 } /* module_register */
475 /* vim: set sw=2 sts=2 tw=78 et fdm=marker : */