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"
28 #include "plugin.h"
29 #include "common.h"
30 #include "filter_chain.h"
32 static void v5_swap_instances (value_list_t *vl) /* {{{ */
33 {
34 char tmp[DATA_MAX_NAME_LEN];
36 assert (sizeof (tmp) == sizeof (vl->plugin_instance));
37 assert (sizeof (tmp) == sizeof (vl->type_instance));
39 memcpy (tmp, vl->plugin_instance, sizeof (tmp));
40 memcpy (vl->plugin_instance, vl->type_instance, sizeof (tmp));
41 memcpy (vl->type_instance, tmp, sizeof (tmp));
42 } /* }}} void v5_swap_instances */
44 /*
45 * Df type
46 *
47 * By default, the "df" plugin of version 4.* uses the "df" type and puts the
48 * mount point in the type instance. Detect this behavior and convert the type
49 * to "df_complex". This can be selected in versions 4.9 and 4.10 by setting
50 * the "ReportReserved" option of the "df" plugin.
51 */
52 static int v5_df (const data_set_t *ds, value_list_t *vl) /* {{{ */
53 {
54 value_list_t new_vl;
55 value_t new_value;
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 = &new_value;
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;
115 value_t new_value;
117 if (vl->values_len != 5)
118 return (FC_TARGET_STOP);
120 /* Copy everything: Time, interval, host, ... */
121 memcpy (&new_vl, vl, sizeof (new_vl));
123 /* Reset data we can't simply copy */
124 new_vl.values = &new_value;
125 new_vl.values_len = 1;
126 new_vl.meta = NULL;
128 /* Change the type to "cache_result" */
129 sstrncpy (new_vl.type, "cache_result", sizeof (new_vl.type));
131 /* Dispatch new value lists instead of this one */
132 new_vl.values[0].derive = (derive_t) vl->values[0].counter;
133 sstrncpy (new_vl.type_instance, "qcache-hits",
134 sizeof (new_vl.type_instance));
135 plugin_dispatch_values (&new_vl);
137 new_vl.values[0].derive = (derive_t) vl->values[1].counter;
138 sstrncpy (new_vl.type_instance, "qcache-inserts",
139 sizeof (new_vl.type_instance));
140 plugin_dispatch_values (&new_vl);
142 new_vl.values[0].derive = (derive_t) vl->values[2].counter;
143 sstrncpy (new_vl.type_instance, "qcache-not_cached",
144 sizeof (new_vl.type_instance));
145 plugin_dispatch_values (&new_vl);
147 new_vl.values[0].derive = (derive_t) vl->values[3].counter;
148 sstrncpy (new_vl.type_instance, "qcache-prunes",
149 sizeof (new_vl.type_instance));
150 plugin_dispatch_values (&new_vl);
152 /* The last data source is a gauge value, so we have to use a different type
153 * here. */
154 new_vl.values[0].gauge = vl->values[4].gauge;
155 sstrncpy (new_vl.type, "cache_size", sizeof (new_vl.type));
156 sstrncpy (new_vl.type_instance, "qcache",
157 sizeof (new_vl.type_instance));
158 plugin_dispatch_values (&new_vl);
160 /* Abort processing */
161 return (FC_TARGET_STOP);
162 } /* }}} int v5_mysql_qcache */
164 /*
165 * MySQL thread count
166 *
167 * 4.* uses the "mysql_threads" type which mixes different types of
168 * information. In 5.* this has been broken up.
169 */
170 static int v5_mysql_threads (const data_set_t *ds, value_list_t *vl) /* {{{ */
171 {
172 value_list_t new_vl;
173 value_t new_value;
175 if (vl->values_len != 4)
176 return (FC_TARGET_STOP);
178 /* Copy everything: Time, interval, host, ... */
179 memcpy (&new_vl, vl, sizeof (new_vl));
181 /* Reset data we can't simply copy */
182 new_vl.values = &new_value;
183 new_vl.values_len = 1;
184 new_vl.meta = NULL;
186 /* Change the type to "threads" */
187 sstrncpy (new_vl.type, "threads", sizeof (new_vl.type));
189 /* Dispatch new value lists instead of this one */
190 new_vl.values[0].gauge = vl->values[0].gauge;
191 sstrncpy (new_vl.type_instance, "running",
192 sizeof (new_vl.type_instance));
193 plugin_dispatch_values (&new_vl);
195 new_vl.values[0].gauge = vl->values[1].gauge;
196 sstrncpy (new_vl.type_instance, "connected",
197 sizeof (new_vl.type_instance));
198 plugin_dispatch_values (&new_vl);
200 new_vl.values[0].gauge = vl->values[2].gauge;
201 sstrncpy (new_vl.type_instance, "cached",
202 sizeof (new_vl.type_instance));
203 plugin_dispatch_values (&new_vl);
205 /* The last data source is a counter value, so we have to use a different
206 * type here. */
207 new_vl.values[0].derive = (derive_t) vl->values[3].counter;
208 sstrncpy (new_vl.type, "total_threads", sizeof (new_vl.type));
209 sstrncpy (new_vl.type_instance, "created",
210 sizeof (new_vl.type_instance));
211 plugin_dispatch_values (&new_vl);
213 /* Abort processing */
214 return (FC_TARGET_STOP);
215 } /* }}} int v5_mysql_threads */
217 /*
218 * ZFS ARC hit and miss counters
219 *
220 * 4.* uses the flawed "arc_counts" type. In 5.* this has been replaced by the
221 * more generic "cache_result" type.
222 */
223 static int v5_zfs_arc_counts (const data_set_t *ds, value_list_t *vl) /* {{{ */
224 {
225 value_list_t new_vl;
226 value_t new_value;
227 _Bool is_hits;
229 if (vl->values_len != 4)
230 return (FC_TARGET_STOP);
232 if (strcmp ("hits", vl->type_instance) == 0)
233 is_hits = 1;
234 else if (strcmp ("misses", vl->type_instance) == 0)
235 is_hits = 0;
236 else
237 return (FC_TARGET_STOP);
239 /* Copy everything: Time, interval, host, ... */
240 memcpy (&new_vl, vl, sizeof (new_vl));
242 /* Reset data we can't simply copy */
243 new_vl.values = &new_value;
244 new_vl.values_len = 1;
245 new_vl.meta = NULL;
247 /* Change the type to "cache_result" */
248 sstrncpy (new_vl.type, "cache_result", sizeof (new_vl.type));
250 /* Dispatch new value lists instead of this one */
251 new_vl.values[0].derive = (derive_t) vl->values[0].counter;
252 ssnprintf (new_vl.type_instance, sizeof (new_vl.type_instance),
253 "demand_data-%s",
254 is_hits ? "hit" : "miss");
255 plugin_dispatch_values (&new_vl);
257 new_vl.values[0].derive = (derive_t) vl->values[1].counter;
258 ssnprintf (new_vl.type_instance, sizeof (new_vl.type_instance),
259 "demand_metadata-%s",
260 is_hits ? "hit" : "miss");
261 plugin_dispatch_values (&new_vl);
263 new_vl.values[0].derive = (derive_t) vl->values[2].counter;
264 ssnprintf (new_vl.type_instance, sizeof (new_vl.type_instance),
265 "prefetch_data-%s",
266 is_hits ? "hit" : "miss");
267 plugin_dispatch_values (&new_vl);
269 new_vl.values[0].derive = (derive_t) vl->values[3].counter;
270 ssnprintf (new_vl.type_instance, sizeof (new_vl.type_instance),
271 "prefetch_metadata-%s",
272 is_hits ? "hit" : "miss");
273 plugin_dispatch_values (&new_vl);
275 /* Abort processing */
276 return (FC_TARGET_STOP);
277 } /* }}} int v5_zfs_arc_counts */
279 /*
280 * ZFS ARC L2 bytes
281 *
282 * "arc_l2_bytes" -> "io_octets-L2".
283 */
284 static int v5_zfs_arc_l2_bytes (const data_set_t *ds, value_list_t *vl) /* {{{ */
285 {
286 value_list_t new_vl;
287 value_t new_values[2];
289 if (vl->values_len != 2)
290 return (FC_TARGET_STOP);
292 /* Copy everything: Time, interval, host, ... */
293 memcpy (&new_vl, vl, sizeof (new_vl));
295 /* Reset data we can't simply copy */
296 new_vl.values = new_values;
297 new_vl.values_len = 2;
298 new_vl.meta = NULL;
300 /* Change the type/-instance to "io_octets-L2" */
301 sstrncpy (new_vl.type, "io_octets", sizeof (new_vl.type));
302 sstrncpy (new_vl.type_instance, "L2", sizeof (new_vl.type_instance));
304 /* Copy the actual values. */
305 new_vl.values[0].derive = (derive_t) vl->values[0].counter;
306 new_vl.values[1].derive = (derive_t) vl->values[1].counter;
308 /* Dispatch new value lists instead of this one */
309 plugin_dispatch_values (&new_vl);
311 /* Abort processing */
312 return (FC_TARGET_STOP);
313 } /* }}} int v5_zfs_arc_l2_bytes */
315 /*
316 * ZFS ARC L2 cache size
317 *
318 * 4.* uses a separate type for this. 5.* uses the generic "cache_size" type
319 * instead.
320 */
321 static int v5_zfs_arc_l2_size (const data_set_t *ds, value_list_t *vl) /* {{{ */
322 {
323 value_list_t new_vl;
324 value_t new_value;
326 if (vl->values_len != 1)
327 return (FC_TARGET_STOP);
329 /* Copy everything: Time, interval, host, ... */
330 memcpy (&new_vl, vl, sizeof (new_vl));
332 /* Reset data we can't simply copy */
333 new_vl.values = &new_value;
334 new_vl.values_len = 1;
335 new_vl.meta = NULL;
337 new_vl.values[0].gauge = (gauge_t) vl->values[0].gauge;
339 /* Change the type to "cache_size" */
340 sstrncpy (new_vl.type, "cache_size", sizeof (new_vl.type));
342 /* Adapt the type instance */
343 sstrncpy (new_vl.type_instance, "L2", sizeof (new_vl.type_instance));
345 /* Dispatch new value lists instead of this one */
346 plugin_dispatch_values (&new_vl);
348 /* Abort processing */
349 return (FC_TARGET_STOP);
350 } /* }}} int v5_zfs_arc_l2_size */
352 /*
353 * ZFS ARC ratio
354 *
355 * "arc_ratio-L1" -> "cache_ratio-arc"
356 * "arc_ratio-L2" -> "cache_ratio-L2"
357 */
358 static int v5_zfs_arc_ratio (const data_set_t *ds, value_list_t *vl) /* {{{ */
359 {
360 value_list_t new_vl;
361 value_t new_value;
363 if (vl->values_len != 1)
364 return (FC_TARGET_STOP);
366 /* Copy everything: Time, interval, host, ... */
367 memcpy (&new_vl, vl, sizeof (new_vl));
369 /* Reset data we can't simply copy */
370 new_vl.values = &new_value;
371 new_vl.values_len = 1;
372 new_vl.meta = NULL;
374 new_vl.values[0].gauge = (gauge_t) vl->values[0].gauge;
376 /* Change the type to "cache_ratio" */
377 sstrncpy (new_vl.type, "cache_ratio", sizeof (new_vl.type));
379 /* Adapt the type instance */
380 if (strcmp ("L1", vl->type_instance) == 0)
381 sstrncpy (new_vl.type_instance, "arc", sizeof (new_vl.type_instance));
383 /* Dispatch new value lists instead of this one */
384 plugin_dispatch_values (&new_vl);
386 /* Abort processing */
387 return (FC_TARGET_STOP);
388 } /* }}} int v5_zfs_arc_ratio */
390 /*
391 * ZFS ARC size
392 *
393 * 4.* uses the "arc_size" type with four data sources. In 5.* this has been
394 * replaces with the "cache_size" type and static data has been removed.
395 */
396 static int v5_zfs_arc_size (const data_set_t *ds, value_list_t *vl) /* {{{ */
397 {
398 value_list_t new_vl;
399 value_t new_value;
401 if (vl->values_len != 4)
402 return (FC_TARGET_STOP);
404 /* Copy everything: Time, interval, host, ... */
405 memcpy (&new_vl, vl, sizeof (new_vl));
407 /* Reset data we can't simply copy */
408 new_vl.values = &new_value;
409 new_vl.values_len = 1;
410 new_vl.meta = NULL;
412 /* Change the type to "cache_size" */
413 sstrncpy (new_vl.type, "cache_size", sizeof (new_vl.type));
415 /* Dispatch new value lists instead of this one */
416 new_vl.values[0].derive = (derive_t) vl->values[0].counter;
417 sstrncpy (new_vl.type_instance, "arc", sizeof (new_vl.type_instance));
418 plugin_dispatch_values (&new_vl);
420 /* Abort processing */
421 return (FC_TARGET_STOP);
422 } /* }}} int v5_zfs_arc_size */
424 static int v5_destroy (void **user_data) /* {{{ */
425 {
426 return (0);
427 } /* }}} int v5_destroy */
429 static int v5_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
430 {
431 *user_data = NULL;
432 return (0);
433 } /* }}} int v5_create */
435 static int v5_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */
436 notification_meta_t __attribute__((unused)) **meta,
437 void __attribute__((unused)) **user_data)
438 {
439 if ((ds == NULL) || (vl == NULL) || (user_data == NULL))
440 return (-EINVAL);
442 if (strcmp ("df", vl->type) == 0)
443 return (v5_df (ds, vl));
444 else if (strcmp ("interface", vl->plugin) == 0)
445 return (v5_interface (ds, vl));
446 else if (strcmp ("mysql_qcache", vl->type) == 0)
447 return (v5_mysql_qcache (ds, vl));
448 else if (strcmp ("mysql_threads", vl->type) == 0)
449 return (v5_mysql_threads (ds, vl));
450 else if (strcmp ("arc_counts", vl->type) == 0)
451 return (v5_zfs_arc_counts (ds, vl));
452 else if (strcmp ("arc_l2_bytes", vl->type) == 0)
453 return (v5_zfs_arc_l2_bytes (ds, vl));
454 else if (strcmp ("arc_l2_size", vl->type) == 0)
455 return (v5_zfs_arc_l2_size (ds, vl));
456 else if (strcmp ("arc_ratio", vl->type) == 0)
457 return (v5_zfs_arc_ratio (ds, vl));
458 else if (strcmp ("arc_size", vl->type) == 0)
459 return (v5_zfs_arc_size (ds, vl));
461 return (FC_TARGET_CONTINUE);
462 } /* }}} int v5_invoke */
464 void module_register (void)
465 {
466 target_proc_t tproc;
468 memset (&tproc, 0, sizeof (tproc));
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 : */