contrib/examples/myplugin.c: Use a compound literal in the example plugin, too.
[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] =
54 {
55         { "my_ds", DS_TYPE_GAUGE, 0, NAN }
56 };
57
58 /*
59  * data set definition:
60  * - name of the data set
61  * - number of data sources
62  * - list of data sources
63  *
64  * NOTE: If you're defining a custom data-set, you have to make that known to
65  * any servers as well. Else, the server is not able to store values using the
66  * type defined by that data-set.
67  * It is strongly recommended to use one of the types and data-sets
68  * pre-defined in the types.db file.
69  */
70 static data_set_t ds =
71 {
72         "myplugin", STATIC_ARRAY_SIZE (dsrc), dsrc
73 };
74
75 /*
76  * This function is called once upon startup to initialize the plugin.
77  */
78 static int my_init (void)
79 {
80         /* open sockets, initialize data structures, ... */
81
82         /* A return value != 0 indicates an error and causes the plugin to be
83            disabled. */
84     return 0;
85 } /* static int my_init (void) */
86
87 /*
88  * This is a utility function used by the read callback to populate a
89  * value_list_t and pass it to plugin_dispatch_values.
90  */
91 static int my_submit (gauge_t value)
92 {
93         value_list_t vl = VALUE_LIST_INIT;
94
95         /* Convert the gauge_t to a value_t and add it to the value_list_t. */
96         vl.values = &(value_t) { .gauge = value };
97         vl.values_len = 1;
98
99         /* Only set vl.time yourself if you update multiple metrics (i.e. you
100          * have multiple calls to plugin_dispatch_values()) and they need to all
101          * have the same timestamp. */
102         /* vl.time = cdtime(); */
103
104         sstrncpy (vl.host, hostname_g, sizeof (vl.host));
105         sstrncpy (vl.plugin, "myplugin", sizeof (vl.plugin));
106
107         /* it is strongly recommended to use a type defined in the types.db file
108          * instead of a custom type */
109         sstrncpy (vl.type, "myplugin", sizeof (vl.type));
110         /* optionally set vl.plugin_instance and vl.type_instance to reasonable
111          * values (default: "") */
112
113         /* dispatch the values to collectd which passes them on to all registered
114          * write functions */
115         return plugin_dispatch_values (&vl);
116 }
117
118 /*
119  * This function is called in regular intervalls to collect the data.
120  */
121 static int my_read (void)
122 {
123         /* do the magic to read the data */
124         gauge_t value = random ();
125
126         if (my_submit (value) != 0)
127                 WARNING ("myplugin plugin: Dispatching a random value failed.");
128
129         /* A return value != 0 indicates an error and the plugin will be skipped
130          * for an increasing amount of time. */
131         return 0;
132 } /* static int my_read (void) */
133
134 /*
135  * This function is called after values have been dispatched to collectd.
136  */
137 static int my_write (const data_set_t *ds, const value_list_t *vl,
138                 user_data_t *ud)
139 {
140         char name[1024] = "";
141         int i = 0;
142
143         if (ds->ds_num != vl->values_len) {
144                 plugin_log (LOG_WARNING, "DS number does not match values length");
145                 return -1;
146         }
147
148         /* get the default base filename for the output file - depending on the
149          * provided values this will be something like
150          * <host>/<plugin>[-<plugin_type>]/<instance>[-<instance_type>] */
151         if (0 != format_name (name, 1024, vl->host, vl->plugin,
152                         vl->plugin_instance, ds->type, vl->type_instance))
153                 return -1;
154
155         for (i = 0; i < ds->ds_num; ++i) {
156                 /* do the magic to output the data */
157                 printf ("%s (%s) at %i: ", name,
158                                 (ds->ds->type == DS_TYPE_GAUGE) ? "GAUGE" : "COUNTER",
159                                 (int)vl->time);
160
161                 if (ds->ds->type == DS_TYPE_GAUGE)
162                         printf ("%f\n", vl->values[i].gauge);
163                 else
164                         printf ("%lld\n", vl->values[i].counter);
165         }
166         return 0;
167 } /* static int my_write (data_set_t *, value_list_t *) */
168
169 /*
170  * This function is called when plugin_log () has been used.
171  */
172 static void my_log (int severity, const char *msg, user_data_t *ud)
173 {
174         printf ("LOG: %i - %s\n", severity, msg);
175         return;
176 } /* static void my_log (int, const char *) */
177
178 /*
179  * This function is called when plugin_dispatch_notification () has been used.
180  */
181 static int my_notify (const notification_t *notif, user_data_t *ud)
182 {
183         char time_str[32] = "";
184         struct tm *tm = NULL;
185
186         int n = 0;
187
188         if (NULL == (tm = localtime (&notif->time)))
189                 time_str[0] = '\0';
190
191         n = strftime (time_str, 32, "%F %T", tm);
192         if (n >= 32) n = 31;
193         time_str[n] = '\0';
194
195         printf ("NOTIF (%s): %i - ", time_str, notif->severity);
196
197         if ('\0' != *notif->host)
198                 printf ("%s: ", notif->host);
199
200         if ('\0' != *notif->plugin)
201                 printf ("%s: ", notif->plugin);
202
203         if ('\0' != *notif->plugin_instance)
204                 printf ("%s: ", notif->plugin_instance);
205
206         if ('\0' != *notif->type)
207                 printf ("%s: ", notif->type);
208
209         if ('\0' != *notif->type_instance)
210                 printf ("%s: ", notif->type_instance);
211
212         printf ("%s\n", notif->message);
213         return 0;
214 } /* static int my_notify (notification_t *) */
215
216 /*
217  * This function is called before shutting down collectd.
218  */
219 static int my_shutdown (void)
220 {
221         /* close sockets, free data structures, ... */
222         return 0;
223 } /* static int my_shutdown (void) */
224
225 /*
226  * This function is called after loading the plugin to register it with
227  * collectd.
228  */
229 void module_register (void)
230 {
231         plugin_register_log ("myplugin", my_log, /* user data */ NULL);
232         plugin_register_notification ("myplugin", my_notify,
233                         /* user data */ NULL);
234         plugin_register_data_set (&ds);
235         plugin_register_read ("myplugin", my_read);
236         plugin_register_init ("myplugin", my_init);
237         plugin_register_write ("myplugin", my_write, /* user data */ NULL);
238         plugin_register_shutdown ("myplugin", my_shutdown);
239     return;
240 } /* void module_register (void) */
241