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;
56 value_t new_value;
58 /* Can't upgrade if both instances have been set. */
59 if ((vl->plugin_instance[0] != 0) && (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", 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", sizeof(new_vl.type_instance));
148 plugin_dispatch_values(&new_vl);
150 /* The last data source is a gauge value, so we have to use a different type
151 * here. */
152 new_vl.values[0].gauge = vl->values[4].gauge;
153 sstrncpy(new_vl.type, "cache_size", sizeof(new_vl.type));
154 sstrncpy(new_vl.type_instance, "qcache", sizeof(new_vl.type_instance));
155 plugin_dispatch_values(&new_vl);
157 /* Abort processing */
158 return (FC_TARGET_STOP);
159 } /* }}} int v5_mysql_qcache */
161 /*
162 * MySQL thread count
163 *
164 * 4.* uses the "mysql_threads" type which mixes different types of
165 * information. In 5.* this has been broken up.
166 */
167 static int v5_mysql_threads(const data_set_t *ds, value_list_t *vl) /* {{{ */
168 {
169 value_list_t new_vl;
170 value_t new_value;
172 if (vl->values_len != 4)
173 return (FC_TARGET_STOP);
175 /* Copy everything: Time, interval, host, ... */
176 memcpy(&new_vl, vl, sizeof(new_vl));
178 /* Reset data we can't simply copy */
179 new_vl.values = &new_value;
180 new_vl.values_len = 1;
181 new_vl.meta = NULL;
183 /* Change the type to "threads" */
184 sstrncpy(new_vl.type, "threads", sizeof(new_vl.type));
186 /* Dispatch new value lists instead of this one */
187 new_vl.values[0].gauge = vl->values[0].gauge;
188 sstrncpy(new_vl.type_instance, "running", sizeof(new_vl.type_instance));
189 plugin_dispatch_values(&new_vl);
191 new_vl.values[0].gauge = vl->values[1].gauge;
192 sstrncpy(new_vl.type_instance, "connected", sizeof(new_vl.type_instance));
193 plugin_dispatch_values(&new_vl);
195 new_vl.values[0].gauge = vl->values[2].gauge;
196 sstrncpy(new_vl.type_instance, "cached", sizeof(new_vl.type_instance));
197 plugin_dispatch_values(&new_vl);
199 /* The last data source is a counter value, so we have to use a different
200 * type here. */
201 new_vl.values[0].derive = (derive_t)vl->values[3].counter;
202 sstrncpy(new_vl.type, "total_threads", sizeof(new_vl.type));
203 sstrncpy(new_vl.type_instance, "created", sizeof(new_vl.type_instance));
204 plugin_dispatch_values(&new_vl);
206 /* Abort processing */
207 return (FC_TARGET_STOP);
208 } /* }}} int v5_mysql_threads */
210 /*
211 * ZFS ARC hit and miss counters
212 *
213 * 4.* uses the flawed "arc_counts" type. In 5.* this has been replaced by the
214 * more generic "cache_result" type.
215 */
216 static int v5_zfs_arc_counts(const data_set_t *ds, value_list_t *vl) /* {{{ */
217 {
218 value_list_t new_vl;
219 value_t new_value;
220 _Bool is_hits;
222 if (vl->values_len != 4)
223 return (FC_TARGET_STOP);
225 if (strcmp("hits", vl->type_instance) == 0)
226 is_hits = 1;
227 else if (strcmp("misses", vl->type_instance) == 0)
228 is_hits = 0;
229 else
230 return (FC_TARGET_STOP);
232 /* Copy everything: Time, interval, host, ... */
233 memcpy(&new_vl, vl, sizeof(new_vl));
235 /* Reset data we can't simply copy */
236 new_vl.values = &new_value;
237 new_vl.values_len = 1;
238 new_vl.meta = NULL;
240 /* Change the type to "cache_result" */
241 sstrncpy(new_vl.type, "cache_result", sizeof(new_vl.type));
243 /* Dispatch new value lists instead of this one */
244 new_vl.values[0].derive = (derive_t)vl->values[0].counter;
245 ssnprintf(new_vl.type_instance, sizeof(new_vl.type_instance),
246 "demand_data-%s", is_hits ? "hit" : "miss");
247 plugin_dispatch_values(&new_vl);
249 new_vl.values[0].derive = (derive_t)vl->values[1].counter;
250 ssnprintf(new_vl.type_instance, sizeof(new_vl.type_instance),
251 "demand_metadata-%s", is_hits ? "hit" : "miss");
252 plugin_dispatch_values(&new_vl);
254 new_vl.values[0].derive = (derive_t)vl->values[2].counter;
255 ssnprintf(new_vl.type_instance, sizeof(new_vl.type_instance),
256 "prefetch_data-%s", is_hits ? "hit" : "miss");
257 plugin_dispatch_values(&new_vl);
259 new_vl.values[0].derive = (derive_t)vl->values[3].counter;
260 ssnprintf(new_vl.type_instance, sizeof(new_vl.type_instance),
261 "prefetch_metadata-%s", is_hits ? "hit" : "miss");
262 plugin_dispatch_values(&new_vl);
264 /* Abort processing */
265 return (FC_TARGET_STOP);
266 } /* }}} int v5_zfs_arc_counts */
268 /*
269 * ZFS ARC L2 bytes
270 *
271 * "arc_l2_bytes" -> "io_octets-L2".
272 */
273 static int v5_zfs_arc_l2_bytes(const data_set_t *ds, value_list_t *vl) /* {{{ */
274 {
275 value_list_t new_vl;
276 value_t new_values[2];
278 if (vl->values_len != 2)
279 return (FC_TARGET_STOP);
281 /* Copy everything: Time, interval, host, ... */
282 memcpy(&new_vl, vl, sizeof(new_vl));
284 /* Reset data we can't simply copy */
285 new_vl.values = new_values;
286 new_vl.values_len = 2;
287 new_vl.meta = NULL;
289 /* Change the type/-instance to "io_octets-L2" */
290 sstrncpy(new_vl.type, "io_octets", sizeof(new_vl.type));
291 sstrncpy(new_vl.type_instance, "L2", sizeof(new_vl.type_instance));
293 /* Copy the actual values. */
294 new_vl.values[0].derive = (derive_t)vl->values[0].counter;
295 new_vl.values[1].derive = (derive_t)vl->values[1].counter;
297 /* Dispatch new value lists instead of this one */
298 plugin_dispatch_values(&new_vl);
300 /* Abort processing */
301 return (FC_TARGET_STOP);
302 } /* }}} int v5_zfs_arc_l2_bytes */
304 /*
305 * ZFS ARC L2 cache size
306 *
307 * 4.* uses a separate type for this. 5.* uses the generic "cache_size" type
308 * instead.
309 */
310 static int v5_zfs_arc_l2_size(const data_set_t *ds, value_list_t *vl) /* {{{ */
311 {
312 value_list_t new_vl;
313 value_t new_value;
315 if (vl->values_len != 1)
316 return (FC_TARGET_STOP);
318 /* Copy everything: Time, interval, host, ... */
319 memcpy(&new_vl, vl, sizeof(new_vl));
321 /* Reset data we can't simply copy */
322 new_vl.values = &new_value;
323 new_vl.values_len = 1;
324 new_vl.meta = NULL;
326 new_vl.values[0].gauge = (gauge_t)vl->values[0].gauge;
328 /* Change the type to "cache_size" */
329 sstrncpy(new_vl.type, "cache_size", sizeof(new_vl.type));
331 /* Adapt the type instance */
332 sstrncpy(new_vl.type_instance, "L2", sizeof(new_vl.type_instance));
334 /* Dispatch new value lists instead of this one */
335 plugin_dispatch_values(&new_vl);
337 /* Abort processing */
338 return (FC_TARGET_STOP);
339 } /* }}} int v5_zfs_arc_l2_size */
341 /*
342 * ZFS ARC ratio
343 *
344 * "arc_ratio-L1" -> "cache_ratio-arc"
345 * "arc_ratio-L2" -> "cache_ratio-L2"
346 */
347 static int v5_zfs_arc_ratio(const data_set_t *ds, value_list_t *vl) /* {{{ */
348 {
349 value_list_t new_vl;
350 value_t new_value;
352 if (vl->values_len != 1)
353 return (FC_TARGET_STOP);
355 /* Copy everything: Time, interval, host, ... */
356 memcpy(&new_vl, vl, sizeof(new_vl));
358 /* Reset data we can't simply copy */
359 new_vl.values = &new_value;
360 new_vl.values_len = 1;
361 new_vl.meta = NULL;
363 new_vl.values[0].gauge = (gauge_t)vl->values[0].gauge;
365 /* Change the type to "cache_ratio" */
366 sstrncpy(new_vl.type, "cache_ratio", sizeof(new_vl.type));
368 /* Adapt the type instance */
369 if (strcmp("L1", vl->type_instance) == 0)
370 sstrncpy(new_vl.type_instance, "arc", sizeof(new_vl.type_instance));
372 /* Dispatch new value lists instead of this one */
373 plugin_dispatch_values(&new_vl);
375 /* Abort processing */
376 return (FC_TARGET_STOP);
377 } /* }}} int v5_zfs_arc_ratio */
379 /*
380 * ZFS ARC size
381 *
382 * 4.* uses the "arc_size" type with four data sources. In 5.* this has been
383 * replaces with the "cache_size" type and static data has been removed.
384 */
385 static int v5_zfs_arc_size(const data_set_t *ds, value_list_t *vl) /* {{{ */
386 {
387 value_list_t new_vl;
388 value_t new_value;
390 if (vl->values_len != 4)
391 return (FC_TARGET_STOP);
393 /* Copy everything: Time, interval, host, ... */
394 memcpy(&new_vl, vl, sizeof(new_vl));
396 /* Reset data we can't simply copy */
397 new_vl.values = &new_value;
398 new_vl.values_len = 1;
399 new_vl.meta = NULL;
401 /* Change the type to "cache_size" */
402 sstrncpy(new_vl.type, "cache_size", sizeof(new_vl.type));
404 /* Dispatch new value lists instead of this one */
405 new_vl.values[0].derive = (derive_t)vl->values[0].counter;
406 sstrncpy(new_vl.type_instance, "arc", sizeof(new_vl.type_instance));
407 plugin_dispatch_values(&new_vl);
409 /* Abort processing */
410 return (FC_TARGET_STOP);
411 } /* }}} int v5_zfs_arc_size */
413 static int v5_destroy(void **user_data) /* {{{ */
414 {
415 return (0);
416 } /* }}} int v5_destroy */
418 static int v5_create(const oconfig_item_t *ci, void **user_data) /* {{{ */
419 {
420 *user_data = NULL;
421 return (0);
422 } /* }}} int v5_create */
424 static int v5_invoke(const data_set_t *ds, value_list_t *vl, /* {{{ */
425 notification_meta_t __attribute__((unused)) * *meta,
426 void __attribute__((unused)) * *user_data) {
427 if ((ds == NULL) || (vl == NULL) || (user_data == NULL))
428 return (-EINVAL);
430 if (strcmp("df", vl->type) == 0)
431 return (v5_df(ds, vl));
432 else if (strcmp("interface", vl->plugin) == 0)
433 return (v5_interface(ds, vl));
434 else if (strcmp("mysql_qcache", vl->type) == 0)
435 return (v5_mysql_qcache(ds, vl));
436 else if (strcmp("mysql_threads", vl->type) == 0)
437 return (v5_mysql_threads(ds, vl));
438 else if (strcmp("arc_counts", vl->type) == 0)
439 return (v5_zfs_arc_counts(ds, vl));
440 else if (strcmp("arc_l2_bytes", vl->type) == 0)
441 return (v5_zfs_arc_l2_bytes(ds, vl));
442 else if (strcmp("arc_l2_size", vl->type) == 0)
443 return (v5_zfs_arc_l2_size(ds, vl));
444 else if (strcmp("arc_ratio", vl->type) == 0)
445 return (v5_zfs_arc_ratio(ds, vl));
446 else if (strcmp("arc_size", vl->type) == 0)
447 return (v5_zfs_arc_size(ds, vl));
449 return (FC_TARGET_CONTINUE);
450 } /* }}} int v5_invoke */
452 void module_register(void) {
453 target_proc_t tproc = {0};
455 tproc.create = v5_create;
456 tproc.destroy = v5_destroy;
457 tproc.invoke = v5_invoke;
458 fc_register_target("v5upgrade", tproc);
459 } /* module_register */
461 /* vim: set sw=2 sts=2 tw=78 et fdm=marker : */