1 /**
2 * collectd - src/target_set.c
3 * Copyright (C) 2008-2010 Florian Forster
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation; only version 2.1 of the License is
8 * applicable.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 * Authors:
20 * Florian Forster <octo at verplant.org>
21 **/
23 #include "collectd.h"
24 #include "plugin.h"
25 #include "common.h"
26 #include "filter_chain.h"
28 static void v5_swap_instances (value_list_t *vl) /* {{{ */
29 {
30 char tmp[DATA_MAX_NAME_LEN];
32 assert (sizeof (tmp) == sizeof (vl->plugin_instance));
33 assert (sizeof (tmp) == sizeof (vl->type_instance));
35 memcpy (tmp, vl->plugin_instance, sizeof (tmp));
36 memcpy (vl->plugin_instance, vl->type_instance, sizeof (tmp));
37 memcpy (vl->type_instance, tmp, sizeof (tmp));
38 } /* }}} void v5_swap_instances */
40 /*
41 * Df type
42 *
43 * By default, the "df" plugin of version 4.* uses the "df" type and puts the
44 * mount point in the type instance. Detect this behavior and convert the type
45 * to "df_complex". This can be selected in versions 4.9 and 4.10 by setting
46 * the "ReportReserved" option of the "df" plugin.
47 */
48 static int v5_df (const data_set_t *ds, value_list_t *vl) /* {{{ */
49 {
50 value_list_t new_vl;
51 value_t new_value;
53 /* Can't upgrade if both instances have been set. */
54 if ((vl->plugin_instance[0] != 0)
55 && (vl->type_instance[0] != 0))
56 return (FC_TARGET_CONTINUE);
58 /* Copy everything: Time, interval, host, ... */
59 memcpy (&new_vl, vl, sizeof (new_vl));
61 /* Reset data we can't simply copy */
62 new_vl.values = &new_value;
63 new_vl.values_len = 1;
64 new_vl.meta = NULL;
66 /* Move the mount point name to the plugin instance */
67 if (new_vl.plugin_instance[0] == 0)
68 v5_swap_instances (&new_vl);
70 /* Change the type to "df_complex" */
71 sstrncpy (new_vl.type, "df_complex", sizeof (new_vl.type));
73 /* Dispatch two new value lists instead of this one */
74 new_vl.values[0].gauge = vl->values[0].gauge;
75 sstrncpy (new_vl.type_instance, "used", sizeof (new_vl.type_instance));
76 plugin_dispatch_values (&new_vl);
78 new_vl.values[0].gauge = vl->values[1].gauge;
79 sstrncpy (new_vl.type_instance, "free", sizeof (new_vl.type_instance));
80 plugin_dispatch_values (&new_vl);
82 /* Abort processing */
83 return (FC_TARGET_STOP);
84 } /* }}} int v5_df */
86 /*
87 * Interface plugin
88 *
89 * 4.* stores the interface in the type instance and leaves the plugin
90 * instance empty. If this is the case, put the interface name into the plugin
91 * instance and clear the type instance.
92 */
93 static int v5_interface (const data_set_t *ds, value_list_t *vl) /* {{{ */
94 {
95 if ((vl->plugin_instance[0] != 0) || (vl->type_instance[0] == 0))
96 return (FC_TARGET_CONTINUE);
98 v5_swap_instances (vl);
99 return (FC_TARGET_CONTINUE);
100 } /* }}} int v5_interface */
102 /*
103 * MySQL query cache
104 *
105 * 4.* uses the "mysql_qcache" type which mixes different types of
106 * information. In 5.* this has been broken up.
107 */
108 static int v5_mysql_qcache (const data_set_t *ds, value_list_t *vl) /* {{{ */
109 {
110 value_list_t new_vl;
111 value_t new_value;
113 if (vl->values_len != 5)
114 return (FC_TARGET_STOP);
116 /* Copy everything: Time, interval, host, ... */
117 memcpy (&new_vl, vl, sizeof (new_vl));
119 /* Reset data we can't simply copy */
120 new_vl.values = &new_value;
121 new_vl.values_len = 1;
122 new_vl.meta = NULL;
124 /* Change the type to "cache_result" */
125 sstrncpy (new_vl.type, "cache_result", sizeof (new_vl.type));
127 /* Dispatch new value lists instead of this one */
128 new_vl.values[0].derive = (derive_t) vl->values[0].counter;
129 sstrncpy (new_vl.type_instance, "qcache-hits",
130 sizeof (new_vl.type_instance));
131 plugin_dispatch_values (&new_vl);
133 new_vl.values[0].derive = (derive_t) vl->values[1].counter;
134 sstrncpy (new_vl.type_instance, "qcache-inserts",
135 sizeof (new_vl.type_instance));
136 plugin_dispatch_values (&new_vl);
138 new_vl.values[0].derive = (derive_t) vl->values[2].counter;
139 sstrncpy (new_vl.type_instance, "qcache-not_cached",
140 sizeof (new_vl.type_instance));
141 plugin_dispatch_values (&new_vl);
143 new_vl.values[0].derive = (derive_t) vl->values[3].counter;
144 sstrncpy (new_vl.type_instance, "qcache-prunes",
145 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
149 * here. */
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",
153 sizeof (new_vl.type_instance));
154 plugin_dispatch_values (&new_vl);
156 /* Abort processing */
157 return (FC_TARGET_STOP);
158 } /* }}} int v5_mysql_qcache */
160 /*
161 * MySQL thread count
162 *
163 * 4.* uses the "mysql_threads" type which mixes different types of
164 * information. In 5.* this has been broken up.
165 */
166 static int v5_mysql_threads (const data_set_t *ds, value_list_t *vl) /* {{{ */
167 {
168 value_list_t new_vl;
169 value_t new_value;
171 if (vl->values_len != 4)
172 return (FC_TARGET_STOP);
174 /* Copy everything: Time, interval, host, ... */
175 memcpy (&new_vl, vl, sizeof (new_vl));
177 /* Reset data we can't simply copy */
178 new_vl.values = &new_value;
179 new_vl.values_len = 1;
180 new_vl.meta = NULL;
182 /* Change the type to "threads" */
183 sstrncpy (new_vl.type, "threads", sizeof (new_vl.type));
185 /* Dispatch new value lists instead of this one */
186 new_vl.values[0].gauge = vl->values[0].gauge;
187 sstrncpy (new_vl.type_instance, "running",
188 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",
193 sizeof (new_vl.type_instance));
194 plugin_dispatch_values (&new_vl);
196 new_vl.values[0].gauge = vl->values[2].gauge;
197 sstrncpy (new_vl.type_instance, "cached",
198 sizeof (new_vl.type_instance));
199 plugin_dispatch_values (&new_vl);
201 /* The last data source is a counter value, so we have to use a different
202 * type here. */
203 new_vl.values[0].derive = (derive_t) vl->values[3].counter;
204 sstrncpy (new_vl.type, "total_threads", sizeof (new_vl.type));
205 sstrncpy (new_vl.type_instance, "created",
206 sizeof (new_vl.type_instance));
207 plugin_dispatch_values (&new_vl);
209 /* Abort processing */
210 return (FC_TARGET_STOP);
211 } /* }}} int v5_mysql_threads */
213 /*
214 * ZFS ARC hit and miss counters
215 *
216 * 4.* uses the flawed "arc_counts" type. In 5.* this has been replaced by the
217 * more generic "cache_result" type.
218 */
219 static int v5_zfs_arc_counts (const data_set_t *ds, value_list_t *vl) /* {{{ */
220 {
221 value_list_t new_vl;
222 value_t new_value;
223 _Bool is_hits;
225 if (vl->values_len != 4)
226 return (FC_TARGET_STOP);
228 if (strcmp ("hits", vl->type_instance) == 0)
229 is_hits = 1;
230 else if (strcmp ("misses", vl->type_instance) == 0)
231 is_hits = 0;
232 else
233 return (FC_TARGET_STOP);
235 /* Copy everything: Time, interval, host, ... */
236 memcpy (&new_vl, vl, sizeof (new_vl));
238 /* Reset data we can't simply copy */
239 new_vl.values = &new_value;
240 new_vl.values_len = 1;
241 new_vl.meta = NULL;
243 /* Change the type to "cache_result" */
244 sstrncpy (new_vl.type, "cache_result", sizeof (new_vl.type));
246 /* Dispatch new value lists instead of this one */
247 new_vl.values[0].derive = (derive_t) vl->values[0].counter;
248 ssnprintf (new_vl.type_instance, sizeof (new_vl.type_instance),
249 "demand_data-%s",
250 is_hits ? "hit" : "miss");
251 plugin_dispatch_values (&new_vl);
253 new_vl.values[0].derive = (derive_t) vl->values[1].counter;
254 ssnprintf (new_vl.type_instance, sizeof (new_vl.type_instance),
255 "demand_metadata-%s",
256 is_hits ? "hit" : "miss");
257 plugin_dispatch_values (&new_vl);
259 new_vl.values[0].derive = (derive_t) vl->values[2].counter;
260 ssnprintf (new_vl.type_instance, sizeof (new_vl.type_instance),
261 "prefetch_data-%s",
262 is_hits ? "hit" : "miss");
263 plugin_dispatch_values (&new_vl);
265 new_vl.values[0].derive = (derive_t) vl->values[3].counter;
266 ssnprintf (new_vl.type_instance, sizeof (new_vl.type_instance),
267 "prefetch_metadata-%s",
268 is_hits ? "hit" : "miss");
269 plugin_dispatch_values (&new_vl);
271 /* Abort processing */
272 return (FC_TARGET_STOP);
273 } /* }}} int v5_zfs_arc_counts */
275 /*
276 * ZFS ARC L2 bytes
277 *
278 * "arc_l2_bytes" -> "io_octets-L2".
279 */
280 static int v5_zfs_arc_l2_bytes (const data_set_t *ds, value_list_t *vl) /* {{{ */
281 {
282 value_list_t new_vl;
283 value_t new_values[2];
285 if (vl->values_len != 2)
286 return (FC_TARGET_STOP);
288 /* Copy everything: Time, interval, host, ... */
289 memcpy (&new_vl, vl, sizeof (new_vl));
291 /* Reset data we can't simply copy */
292 new_vl.values = new_values;
293 new_vl.values_len = 2;
294 new_vl.meta = NULL;
296 /* Change the type/-instance to "io_octets-L2" */
297 sstrncpy (new_vl.type, "io_octets", sizeof (new_vl.type));
298 sstrncpy (new_vl.type_instance, "L2", sizeof (new_vl.type_instance));
300 /* Copy the actual values. */
301 new_vl.values[0].derive = (derive_t) vl->values[0].counter;
302 new_vl.values[1].derive = (derive_t) vl->values[1].counter;
304 /* Dispatch new value lists instead of this one */
305 plugin_dispatch_values (&new_vl);
307 /* Abort processing */
308 return (FC_TARGET_STOP);
309 } /* }}} int v5_zfs_arc_l2_bytes */
311 /*
312 * ZFS ARC L2 cache size
313 *
314 * 4.* uses a separate type for this. 5.* uses the generic "cache_size" type
315 * instead.
316 */
317 static int v5_zfs_arc_l2_size (const data_set_t *ds, value_list_t *vl) /* {{{ */
318 {
319 value_list_t new_vl;
320 value_t new_value;
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 = &new_value;
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;
357 value_t new_value;
359 if (vl->values_len != 1)
360 return (FC_TARGET_STOP);
362 /* Copy everything: Time, interval, host, ... */
363 memcpy (&new_vl, vl, sizeof (new_vl));
365 /* Reset data we can't simply copy */
366 new_vl.values = &new_value;
367 new_vl.values_len = 1;
368 new_vl.meta = NULL;
370 new_vl.values[0].gauge = (gauge_t) vl->values[0].gauge;
372 /* Change the type to "cache_ratio" */
373 sstrncpy (new_vl.type, "cache_ratio", sizeof (new_vl.type));
375 /* Adapt the type instance */
376 if (strcmp ("L1", vl->type_instance) == 0)
377 sstrncpy (new_vl.type_instance, "arc", sizeof (new_vl.type_instance));
379 /* Dispatch new value lists instead of this one */
380 plugin_dispatch_values (&new_vl);
382 /* Abort processing */
383 return (FC_TARGET_STOP);
384 } /* }}} int v5_zfs_arc_ratio */
386 /*
387 * ZFS ARC size
388 *
389 * 4.* uses the "arc_size" type with four data sources. In 5.* this has been
390 * replaces with the "cache_size" type and static data has been removed.
391 */
392 static int v5_zfs_arc_size (const data_set_t *ds, value_list_t *vl) /* {{{ */
393 {
394 value_list_t new_vl;
395 value_t new_value;
397 if (vl->values_len != 4)
398 return (FC_TARGET_STOP);
400 /* Copy everything: Time, interval, host, ... */
401 memcpy (&new_vl, vl, sizeof (new_vl));
403 /* Reset data we can't simply copy */
404 new_vl.values = &new_value;
405 new_vl.values_len = 1;
406 new_vl.meta = NULL;
408 /* Change the type to "cache_size" */
409 sstrncpy (new_vl.type, "cache_size", sizeof (new_vl.type));
411 /* Dispatch new value lists instead of this one */
412 new_vl.values[0].derive = (derive_t) vl->values[0].counter;
413 sstrncpy (new_vl.type_instance, "arc", sizeof (new_vl.type_instance));
414 plugin_dispatch_values (&new_vl);
416 /* Abort processing */
417 return (FC_TARGET_STOP);
418 } /* }}} int v5_zfs_arc_size */
420 static int v5_destroy (void **user_data) /* {{{ */
421 {
422 return (0);
423 } /* }}} int v5_destroy */
425 static int v5_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
426 {
427 *user_data = NULL;
428 return (0);
429 } /* }}} int v5_create */
431 static int v5_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */
432 notification_meta_t __attribute__((unused)) **meta,
433 void __attribute__((unused)) **user_data)
434 {
435 if ((ds == NULL) || (vl == NULL) || (user_data == NULL))
436 return (-EINVAL);
438 if (strcmp ("df", vl->type) == 0)
439 return (v5_df (ds, vl));
440 else if (strcmp ("interface", vl->plugin) == 0)
441 return (v5_interface (ds, vl));
442 else if (strcmp ("mysql_qcache", vl->type) == 0)
443 return (v5_mysql_qcache (ds, vl));
444 else if (strcmp ("mysql_threads", vl->type) == 0)
445 return (v5_mysql_threads (ds, vl));
446 else if (strcmp ("arc_counts", vl->type) == 0)
447 return (v5_zfs_arc_counts (ds, vl));
448 else if (strcmp ("arc_l2_bytes", vl->type) == 0)
449 return (v5_zfs_arc_l2_bytes (ds, vl));
450 else if (strcmp ("arc_l2_size", vl->type) == 0)
451 return (v5_zfs_arc_l2_size (ds, vl));
452 else if (strcmp ("arc_ratio", vl->type) == 0)
453 return (v5_zfs_arc_ratio (ds, vl));
454 else if (strcmp ("arc_size", vl->type) == 0)
455 return (v5_zfs_arc_size (ds, vl));
457 return (FC_TARGET_CONTINUE);
458 } /* }}} int v5_invoke */
460 void module_register (void)
461 {
462 target_proc_t tproc;
464 memset (&tproc, 0, sizeof (tproc));
465 tproc.create = v5_create;
466 tproc.destroy = v5_destroy;
467 tproc.invoke = v5_invoke;
468 fc_register_target ("v5upgrade", tproc);
469 } /* module_register */
471 /* vim: set sw=2 sts=2 tw=78 et fdm=marker : */