2 * collectd - src/target_v5upgrade.c
3 * Copyright (C) 2008-2010 Florian Forster
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:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
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.
24 * Florian Forster <octo at collectd.org>
29 #include "filter_chain.h"
31 #include "utils/common/common.h"
33 static void v5_swap_instances(value_list_t *vl) /* {{{ */
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 */
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.
53 static int v5_df(const data_set_t *ds, value_list_t *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;
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;
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.
96 static int v5_interface(const data_set_t *ds, value_list_t *vl) /* {{{ */
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 */
108 * 4.* uses the "mysql_qcache" type which mixes different types of
109 * information. In 5.* this has been broken up.
111 static int v5_mysql_qcache(const data_set_t *ds, value_list_t *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;
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
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 */
162 * 4.* uses the "mysql_threads" type which mixes different types of
163 * information. In 5.* this has been broken up.
165 static int v5_mysql_threads(const data_set_t *ds, value_list_t *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;
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
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 */
208 * ZFS ARC hit and miss counters
210 * 4.* uses the flawed "arc_counts" type. In 5.* this has been replaced by the
211 * more generic "cache_result" type.
213 static int v5_zfs_arc_counts(const data_set_t *ds, value_list_t *vl) /* {{{ */
218 if (vl->values_len != 4)
219 return FC_TARGET_STOP;
221 if (strcmp("hits", vl->type_instance) == 0)
223 else if (strcmp("misses", vl->type_instance) == 0)
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;
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 snprintf(new_vl.type_instance, sizeof(new_vl.type_instance), "demand_data-%s",
242 is_hits ? "hit" : "miss");
243 plugin_dispatch_values(&new_vl);
245 new_vl.values[0].derive = (derive_t)vl->values[1].counter;
246 snprintf(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 snprintf(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 snprintf(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 */
267 * "arc_l2_bytes" -> "io_octets-L2".
269 static int v5_zfs_arc_l2_bytes(const data_set_t *ds, value_list_t *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 */
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. */
288 {.derive = (derive_t)vl->values[0].counter},
289 {.derive = (derive_t)vl->values[1].counter},
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 */
302 * ZFS ARC L2 cache size
304 * 4.* uses a separate type for this. 5.* uses the generic "cache_size" type
307 static int v5_zfs_arc_l2_size(const data_set_t *ds, value_list_t *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;
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 */
340 * "arc_ratio-L1" -> "cache_ratio-arc"
341 * "arc_ratio-L2" -> "cache_ratio-L2"
343 static int v5_zfs_arc_ratio(const data_set_t *ds, value_list_t *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;
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 */
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.
380 static int v5_zfs_arc_size(const data_set_t *ds, value_list_t *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;
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) /* {{{ */
410 } /* }}} int v5_destroy */
412 static int v5_create(const oconfig_item_t *ci, void **user_data) /* {{{ */
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))
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 */