Merge branch 'collectd-5.5' into collectd-5.6
[collectd.git] / src / target_v5upgrade.c
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  **/
26
27 #include "collectd.h"
28
29 #include "plugin.h"
30 #include "common.h"
31 #include "filter_chain.h"
32
33 static void v5_swap_instances (value_list_t *vl) /* {{{ */
34 {
35   char tmp[DATA_MAX_NAME_LEN];
36
37   assert (sizeof (tmp) == sizeof (vl->plugin_instance));
38   assert (sizeof (tmp) == sizeof (vl->type_instance));
39
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 */
44
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;
57
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);
62
63   /* Copy everything: Time, interval, host, ... */
64   memcpy (&new_vl, vl, sizeof (new_vl));
65
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;
70
71   /* Move the mount point name to the plugin instance */
72   if (new_vl.plugin_instance[0] == 0)
73     v5_swap_instances (&new_vl);
74
75   /* Change the type to "df_complex" */
76   sstrncpy (new_vl.type, "df_complex", sizeof (new_vl.type));
77
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);
82
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);
86
87   /* Abort processing */
88   return (FC_TARGET_STOP);
89 } /* }}} int v5_df */
90
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);
102
103   v5_swap_instances (vl);
104   return (FC_TARGET_CONTINUE);
105 } /* }}} int v5_interface */
106
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;
117
118   if (vl->values_len != 5)
119     return (FC_TARGET_STOP);
120
121   /* Copy everything: Time, interval, host, ... */
122   memcpy (&new_vl, vl, sizeof (new_vl));
123
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;
128
129   /* Change the type to "cache_result" */
130   sstrncpy (new_vl.type, "cache_result", sizeof (new_vl.type));
131
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);
137
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);
142
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);
147
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);
152
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);
160
161   /* Abort processing */
162   return (FC_TARGET_STOP);
163 } /* }}} int v5_mysql_qcache */
164
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;
175
176   if (vl->values_len != 4)
177     return (FC_TARGET_STOP);
178
179   /* Copy everything: Time, interval, host, ... */
180   memcpy (&new_vl, vl, sizeof (new_vl));
181
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;
186
187   /* Change the type to "threads" */
188   sstrncpy (new_vl.type, "threads", sizeof (new_vl.type));
189
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);
195
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);
200
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);
205
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);
213
214   /* Abort processing */
215   return (FC_TARGET_STOP);
216 } /* }}} int v5_mysql_threads */
217
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;
229
230   if (vl->values_len != 4)
231     return (FC_TARGET_STOP);
232
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);
239
240   /* Copy everything: Time, interval, host, ... */
241   memcpy (&new_vl, vl, sizeof (new_vl));
242
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;
247
248   /* Change the type to "cache_result" */
249   sstrncpy (new_vl.type, "cache_result", sizeof (new_vl.type));
250
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);
257
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);
263
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);
269
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);
275
276   /* Abort processing */
277   return (FC_TARGET_STOP);
278 } /* }}} int v5_zfs_arc_counts */
279
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];
289
290   if (vl->values_len != 2)
291     return (FC_TARGET_STOP);
292
293   /* Copy everything: Time, interval, host, ... */
294   memcpy (&new_vl, vl, sizeof (new_vl));
295
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;
300
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));
304
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;
308
309   /* Dispatch new value lists instead of this one */
310   plugin_dispatch_values (&new_vl);
311
312   /* Abort processing */
313   return (FC_TARGET_STOP);
314 } /* }}} int v5_zfs_arc_l2_bytes */
315
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;
326
327   if (vl->values_len != 1)
328     return (FC_TARGET_STOP);
329
330   /* Copy everything: Time, interval, host, ... */
331   memcpy (&new_vl, vl, sizeof (new_vl));
332
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;
337
338   new_vl.values[0].gauge = (gauge_t) vl->values[0].gauge;
339
340   /* Change the type to "cache_size" */
341   sstrncpy (new_vl.type, "cache_size", sizeof (new_vl.type));
342
343   /* Adapt the type instance */
344   sstrncpy (new_vl.type_instance, "L2", sizeof (new_vl.type_instance));
345
346   /* Dispatch new value lists instead of this one */
347   plugin_dispatch_values (&new_vl);
348
349   /* Abort processing */
350   return (FC_TARGET_STOP);
351 } /* }}} int v5_zfs_arc_l2_size */
352
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;
363
364   if (vl->values_len != 1)
365     return (FC_TARGET_STOP);
366
367   /* Copy everything: Time, interval, host, ... */
368   memcpy (&new_vl, vl, sizeof (new_vl));
369
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;
374
375   new_vl.values[0].gauge = (gauge_t) vl->values[0].gauge;
376
377   /* Change the type to "cache_ratio" */
378   sstrncpy (new_vl.type, "cache_ratio", sizeof (new_vl.type));
379
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));
383
384   /* Dispatch new value lists instead of this one */
385   plugin_dispatch_values (&new_vl);
386
387   /* Abort processing */
388   return (FC_TARGET_STOP);
389 } /* }}} int v5_zfs_arc_ratio */
390
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;
401
402   if (vl->values_len != 4)
403     return (FC_TARGET_STOP);
404
405   /* Copy everything: Time, interval, host, ... */
406   memcpy (&new_vl, vl, sizeof (new_vl));
407
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;
412
413   /* Change the type to "cache_size" */
414   sstrncpy (new_vl.type, "cache_size", sizeof (new_vl.type));
415
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);
420
421   /* Abort processing */
422   return (FC_TARGET_STOP);
423 } /* }}} int v5_zfs_arc_size */
424
425 static int v5_destroy (void **user_data) /* {{{ */
426 {
427   return (0);
428 } /* }}} int v5_destroy */
429
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 */
435
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);
442
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));
461
462   return (FC_TARGET_CONTINUE);
463 } /* }}} int v5_invoke */
464
465 void module_register (void)
466 {
467         target_proc_t tproc = { 0 };
468
469         tproc.create  = v5_create;
470         tproc.destroy = v5_destroy;
471         tproc.invoke  = v5_invoke;
472         fc_register_target ("v5upgrade", tproc);
473 } /* module_register */
474
475 /* vim: set sw=2 sts=2 tw=78 et fdm=marker : */
476