Tree wide: Reformat with clang-format.
[collectd.git] / contrib / examples / myplugin.c
1 /*
2  * /usr/share/doc/collectd/examples/myplugin.c
3  *
4  * A plugin template for collectd.
5  *
6  * Written by Sebastian Harl <sh@tokkee.org>
7  *
8  * This is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License as published by the Free
10  * Software Foundation; only version 2 of the License is applicable.
11  */
12
13 /*
14  * Notes:
15  * - plugins are executed in parallel, thus, thread-safe
16  *   functions need to be used
17  * - each of the functions below (except module_register)
18  *   is optional
19  */
20
21 #if !HAVE_CONFIG_H
22
23 #include <stdlib.h>
24
25 #include <string.h>
26
27 #ifndef __USE_ISOC99 /* required for NAN */
28 #define DISABLE_ISOC99 1
29 #define __USE_ISOC99 1
30 #endif /* !defined(__USE_ISOC99) */
31 #include <math.h>
32 #if DISABLE_ISOC99
33 #undef DISABLE_ISOC99
34 #undef __USE_ISOC99
35 #endif /* DISABLE_ISOC99 */
36
37 #include <time.h>
38
39 #endif /* ! HAVE_CONFIG */
40
41 #include <collectd/collectd.h>
42
43 #include <collectd/common.h>
44 #include <collectd/plugin.h>
45
46 /*
47  * data source definition:
48  * - name of the data source
49  * - type of the data source (DS_TYPE_GAUGE, DS_TYPE_COUNTER)
50  * - minimum allowed value
51  * - maximum allowed value
52  */
53 static data_source_t dsrc[1] = {{"my_ds", DS_TYPE_GAUGE, 0, NAN}};
54
55 /*
56  * data set definition:
57  * - name of the data set
58  * - number of data sources
59  * - list of data sources
60  *
61  * NOTE: If you're defining a custom data-set, you have to make that known to
62  * any servers as well. Else, the server is not able to store values using the
63  * type defined by that data-set.
64  * It is strongly recommended to use one of the types and data-sets
65  * pre-defined in the types.db file.
66  */
67 static data_set_t ds = {"myplugin", STATIC_ARRAY_SIZE(dsrc), dsrc};
68
69 /*
70  * This function is called once upon startup to initialize the plugin.
71  */
72 static int my_init(void) {
73   /* open sockets, initialize data structures, ... */
74
75   /* A return value != 0 indicates an error and causes the plugin to be
76      disabled. */
77   return 0;
78 } /* static int my_init (void) */
79
80 /*
81  * This is a utility function used by the read callback to populate a
82  * value_list_t and pass it to plugin_dispatch_values.
83  */
84 static int my_submit(gauge_t value) {
85   value_list_t vl = VALUE_LIST_INIT;
86
87   /* Convert the gauge_t to a value_t and add it to the value_list_t. */
88   vl.values = &(value_t){.gauge = value};
89   vl.values_len = 1;
90
91   /* Only set vl.time yourself if you update multiple metrics (i.e. you
92    * have multiple calls to plugin_dispatch_values()) and they need to all
93    * have the same timestamp. */
94   /* vl.time = cdtime(); */
95
96   sstrncpy(vl.plugin, "myplugin", sizeof(vl.plugin));
97
98   /* it is strongly recommended to use a type defined in the types.db file
99    * instead of a custom type */
100   sstrncpy(vl.type, "myplugin", sizeof(vl.type));
101   /* optionally set vl.plugin_instance and vl.type_instance to reasonable
102    * values (default: "") */
103
104   /* dispatch the values to collectd which passes them on to all registered
105    * write functions */
106   return plugin_dispatch_values(&vl);
107 }
108
109 /*
110  * This function is called in regular intervalls to collect the data.
111  */
112 static int my_read(void) {
113   /* do the magic to read the data */
114   gauge_t value = random();
115
116   if (my_submit(value) != 0)
117     WARNING("myplugin plugin: Dispatching a random value failed.");
118
119   /* A return value != 0 indicates an error and the plugin will be skipped
120    * for an increasing amount of time. */
121   return 0;
122 } /* static int my_read (void) */
123
124 /*
125  * This function is called after values have been dispatched to collectd.
126  */
127 static int my_write(const data_set_t *ds, const value_list_t *vl,
128                     user_data_t *ud) {
129   char name[1024] = "";
130   int i = 0;
131
132   if (ds->ds_num != vl->values_len) {
133     plugin_log(LOG_WARNING, "DS number does not match values length");
134     return -1;
135   }
136
137   /* get the default base filename for the output file - depending on the
138    * provided values this will be something like
139    * <host>/<plugin>[-<plugin_type>]/<instance>[-<instance_type>] */
140   if (0 != format_name(name, 1024, vl->host, vl->plugin, vl->plugin_instance,
141                        ds->type, vl->type_instance))
142     return -1;
143
144   for (i = 0; i < ds->ds_num; ++i) {
145     /* do the magic to output the data */
146     printf("%s (%s) at %i: ", name,
147            (ds->ds->type == DS_TYPE_GAUGE) ? "GAUGE" : "COUNTER",
148            (int)vl->time);
149
150     if (ds->ds->type == DS_TYPE_GAUGE)
151       printf("%f\n", vl->values[i].gauge);
152     else
153       printf("%lld\n", vl->values[i].counter);
154   }
155   return 0;
156 } /* static int my_write (data_set_t *, value_list_t *) */
157
158 /*
159  * This function is called when plugin_log () has been used.
160  */
161 static void my_log(int severity, const char *msg, user_data_t *ud) {
162   printf("LOG: %i - %s\n", severity, msg);
163   return;
164 } /* static void my_log (int, const char *) */
165
166 /*
167  * This function is called when plugin_dispatch_notification () has been used.
168  */
169 static int my_notify(const notification_t *notif, user_data_t *ud) {
170   char time_str[32] = "";
171   struct tm *tm = NULL;
172
173   int n = 0;
174
175   if (NULL == (tm = localtime(&notif->time)))
176     time_str[0] = '\0';
177
178   n = strftime(time_str, 32, "%F %T", tm);
179   if (n >= 32)
180     n = 31;
181   time_str[n] = '\0';
182
183   printf("NOTIF (%s): %i - ", time_str, notif->severity);
184
185   if ('\0' != *notif->host)
186     printf("%s: ", notif->host);
187
188   if ('\0' != *notif->plugin)
189     printf("%s: ", notif->plugin);
190
191   if ('\0' != *notif->plugin_instance)
192     printf("%s: ", notif->plugin_instance);
193
194   if ('\0' != *notif->type)
195     printf("%s: ", notif->type);
196
197   if ('\0' != *notif->type_instance)
198     printf("%s: ", notif->type_instance);
199
200   printf("%s\n", notif->message);
201   return 0;
202 } /* static int my_notify (notification_t *) */
203
204 /*
205  * This function is called before shutting down collectd.
206  */
207 static int my_shutdown(void) {
208   /* close sockets, free data structures, ... */
209   return 0;
210 } /* static int my_shutdown (void) */
211
212 /*
213  * This function is called after loading the plugin to register it with
214  * collectd.
215  */
216 void module_register(void) {
217   plugin_register_log("myplugin", my_log, /* user data */ NULL);
218   plugin_register_notification("myplugin", my_notify,
219                                /* user data */ NULL);
220   plugin_register_data_set(&ds);
221   plugin_register_read("myplugin", my_read);
222   plugin_register_init("myplugin", my_init);
223   plugin_register_write("myplugin", my_write, /* user data */ NULL);
224   plugin_register_shutdown("myplugin", my_shutdown);
225   return;
226 } /* void module_register (void) */