Merge remote-tracking branch 'github/pr/2391' 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 "common.h"
30 #include "filter_chain.h"
31 #include "plugin.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) && (vl->type_instance[0] != 0))
60     return (FC_TARGET_CONTINUE);
61
62   /* Copy everything: Time, interval, host, ... */
63   memcpy(&new_vl, vl, sizeof(new_vl));
64
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;
69
70   /* Move the mount point name to the plugin instance */
71   if (new_vl.plugin_instance[0] == 0)
72     v5_swap_instances(&new_vl);
73
74   /* Change the type to "df_complex" */
75   sstrncpy(new_vl.type, "df_complex", sizeof(new_vl.type));
76
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);
81
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);
85
86   /* Abort processing */
87   return (FC_TARGET_STOP);
88 } /* }}} int v5_df */
89
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);
101
102   v5_swap_instances(vl);
103   return (FC_TARGET_CONTINUE);
104 } /* }}} int v5_interface */
105
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;
116
117   if (vl->values_len != 5)
118     return (FC_TARGET_STOP);
119
120   /* Copy everything: Time, interval, host, ... */
121   memcpy(&new_vl, vl, sizeof(new_vl));
122
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;
127
128   /* Change the type to "cache_result" */
129   sstrncpy(new_vl.type, "cache_result", sizeof(new_vl.type));
130
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);
135
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);
140
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);
145
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);
149
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);
156
157   /* Abort processing */
158   return (FC_TARGET_STOP);
159 } /* }}} int v5_mysql_qcache */
160
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;
171
172   if (vl->values_len != 4)
173     return (FC_TARGET_STOP);
174
175   /* Copy everything: Time, interval, host, ... */
176   memcpy(&new_vl, vl, sizeof(new_vl));
177
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;
182
183   /* Change the type to "threads" */
184   sstrncpy(new_vl.type, "threads", sizeof(new_vl.type));
185
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);
190
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);
194
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);
198
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);
205
206   /* Abort processing */
207   return (FC_TARGET_STOP);
208 } /* }}} int v5_mysql_threads */
209
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;
221
222   if (vl->values_len != 4)
223     return (FC_TARGET_STOP);
224
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);
231
232   /* Copy everything: Time, interval, host, ... */
233   memcpy(&new_vl, vl, sizeof(new_vl));
234
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;
239
240   /* Change the type to "cache_result" */
241   sstrncpy(new_vl.type, "cache_result", sizeof(new_vl.type));
242
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);
248
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);
253
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);
258
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);
263
264   /* Abort processing */
265   return (FC_TARGET_STOP);
266 } /* }}} int v5_zfs_arc_counts */
267
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];
277
278   if (vl->values_len != 2)
279     return (FC_TARGET_STOP);
280
281   /* Copy everything: Time, interval, host, ... */
282   memcpy(&new_vl, vl, sizeof(new_vl));
283
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;
288
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));
292
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;
296
297   /* Dispatch new value lists instead of this one */
298   plugin_dispatch_values(&new_vl);
299
300   /* Abort processing */
301   return (FC_TARGET_STOP);
302 } /* }}} int v5_zfs_arc_l2_bytes */
303
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;
314
315   if (vl->values_len != 1)
316     return (FC_TARGET_STOP);
317
318   /* Copy everything: Time, interval, host, ... */
319   memcpy(&new_vl, vl, sizeof(new_vl));
320
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;
325
326   new_vl.values[0].gauge = (gauge_t)vl->values[0].gauge;
327
328   /* Change the type to "cache_size" */
329   sstrncpy(new_vl.type, "cache_size", sizeof(new_vl.type));
330
331   /* Adapt the type instance */
332   sstrncpy(new_vl.type_instance, "L2", sizeof(new_vl.type_instance));
333
334   /* Dispatch new value lists instead of this one */
335   plugin_dispatch_values(&new_vl);
336
337   /* Abort processing */
338   return (FC_TARGET_STOP);
339 } /* }}} int v5_zfs_arc_l2_size */
340
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;
351
352   if (vl->values_len != 1)
353     return (FC_TARGET_STOP);
354
355   /* Copy everything: Time, interval, host, ... */
356   memcpy(&new_vl, vl, sizeof(new_vl));
357
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;
362
363   new_vl.values[0].gauge = (gauge_t)vl->values[0].gauge;
364
365   /* Change the type to "cache_ratio" */
366   sstrncpy(new_vl.type, "cache_ratio", sizeof(new_vl.type));
367
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));
371
372   /* Dispatch new value lists instead of this one */
373   plugin_dispatch_values(&new_vl);
374
375   /* Abort processing */
376   return (FC_TARGET_STOP);
377 } /* }}} int v5_zfs_arc_ratio */
378
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;
389
390   if (vl->values_len != 4)
391     return (FC_TARGET_STOP);
392
393   /* Copy everything: Time, interval, host, ... */
394   memcpy(&new_vl, vl, sizeof(new_vl));
395
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;
400
401   /* Change the type to "cache_size" */
402   sstrncpy(new_vl.type, "cache_size", sizeof(new_vl.type));
403
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);
408
409   /* Abort processing */
410   return (FC_TARGET_STOP);
411 } /* }}} int v5_zfs_arc_size */
412
413 static int v5_destroy(void **user_data) /* {{{ */
414 {
415   return (0);
416 } /* }}} int v5_destroy */
417
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 */
423
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);
429
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));
448
449   return (FC_TARGET_CONTINUE);
450 } /* }}} int v5_invoke */
451
452 void module_register(void) {
453   target_proc_t tproc = {0};
454
455   tproc.create = v5_create;
456   tproc.destroy = v5_destroy;
457   tproc.invoke = v5_invoke;
458   fc_register_target("v5upgrade", tproc);
459 } /* module_register */
460
461 /* vim: set sw=2 sts=2 tw=78 et fdm=marker : */