1 /** 2 * collectd - src/daemon/plugin.h 3 * Copyright (C) 2005-2014 Florian octo 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 octo Forster <octo at collectd.org> 25 * Sebastian Harl <sh at tokkee.org> 26 **/ 27 28 #ifndef PLUGIN_H 29 #define PLUGIN_H 30 31 #include "collectd.h" 32 33 #include "configfile.h" 34 #include "utils/metadata/meta_data.h" 35 #include "utils_time.h" 36 37 #include <inttypes.h> 38 #include <pthread.h> 39 40 #define DS_TYPE_COUNTER 0 41 #define DS_TYPE_GAUGE 1 42 #define DS_TYPE_DERIVE 2 43 #define DS_TYPE_ABSOLUTE 3 44 45 #define DS_TYPE_TO_STRING(t) \ 46 (t == DS_TYPE_COUNTER) \ 47 ? "counter" \ 48 : (t == DS_TYPE_GAUGE) \ 49 ? "gauge" \ 50 : (t == DS_TYPE_DERIVE) \ 51 ? "derive" \ 52 : (t == DS_TYPE_ABSOLUTE) ? "absolute" : "unknown" 53 54 #ifndef LOG_ERR 55 #define LOG_ERR 3 56 #endif 57 #ifndef LOG_WARNING 58 #define LOG_WARNING 4 59 #endif 60 #ifndef LOG_NOTICE 61 #define LOG_NOTICE 5 62 #endif 63 #ifndef LOG_INFO 64 #define LOG_INFO 6 65 #endif 66 #ifndef LOG_DEBUG 67 #define LOG_DEBUG 7 68 #endif 69 70 #define NOTIF_MAX_MSG_LEN 256 71 72 #define NOTIF_FAILURE 1 73 #define NOTIF_WARNING 2 74 #define NOTIF_OKAY 4 75 76 #define plugin_interval (plugin_get_ctx().interval) 77 78 /* 79 * Public data types 80 */ 81 struct identifier_s { 82 char *host; 83 char *plugin; 84 char *plugin_instance; 85 char *type; 86 char *type_instance; 87 }; 88 typedef struct identifier_s identifier_t; 89 90 typedef unsigned long long counter_t; 91 typedef double gauge_t; 92 typedef int64_t derive_t; 93 typedef uint64_t absolute_t; 94 95 union value_u { 96 counter_t counter; 97 gauge_t gauge; 98 derive_t derive; 99 absolute_t absolute; 100 }; 101 typedef union value_u value_t; 102 103 struct value_list_s { 104 value_t *values; 105 size_t values_len; 106 cdtime_t time; 107 cdtime_t interval; 108 char host[DATA_MAX_NAME_LEN]; 109 char plugin[DATA_MAX_NAME_LEN]; 110 char plugin_instance[DATA_MAX_NAME_LEN]; 111 char type[DATA_MAX_NAME_LEN]; 112 char type_instance[DATA_MAX_NAME_LEN]; 113 meta_data_t *meta; 114 }; 115 typedef struct value_list_s value_list_t; 116 117 #define VALUE_LIST_INIT \ 118 { .values = NULL, .meta = NULL } 119 120 struct data_source_s { 121 char name[DATA_MAX_NAME_LEN]; 122 int type; 123 double min; 124 double max; 125 }; 126 typedef struct data_source_s data_source_t; 127 128 struct data_set_s { 129 char type[DATA_MAX_NAME_LEN]; 130 size_t ds_num; 131 data_source_t *ds; 132 }; 133 typedef struct data_set_s data_set_t; 134 135 enum notification_meta_type_e { 136 NM_TYPE_STRING, 137 NM_TYPE_SIGNED_INT, 138 NM_TYPE_UNSIGNED_INT, 139 NM_TYPE_DOUBLE, 140 NM_TYPE_BOOLEAN 141 }; 142 143 typedef struct notification_meta_s { 144 char name[DATA_MAX_NAME_LEN]; 145 enum notification_meta_type_e type; 146 union { 147 const char *nm_string; 148 int64_t nm_signed_int; 149 uint64_t nm_unsigned_int; 150 double nm_double; 151 bool nm_boolean; 152 } nm_value; 153 struct notification_meta_s *next; 154 } notification_meta_t; 155 156 typedef struct notification_s { 157 int severity; 158 cdtime_t time; 159 char message[NOTIF_MAX_MSG_LEN]; 160 char host[DATA_MAX_NAME_LEN]; 161 char plugin[DATA_MAX_NAME_LEN]; 162 char plugin_instance[DATA_MAX_NAME_LEN]; 163 char type[DATA_MAX_NAME_LEN]; 164 char type_instance[DATA_MAX_NAME_LEN]; 165 notification_meta_t *meta; 166 } notification_t; 167 168 struct user_data_s { 169 void *data; 170 void (*free_func)(void *); 171 }; 172 typedef struct user_data_s user_data_t; 173 174 enum cache_event_type_e { CE_VALUE_NEW, CE_VALUE_UPDATE, CE_VALUE_EXPIRED }; 175 176 typedef struct cache_event_s { 177 enum cache_event_type_e type; 178 const value_list_t *value_list; 179 const char *value_list_name; 180 int ret; 181 } cache_event_t; 182 183 struct plugin_ctx_s { 184 char *name; 185 cdtime_t interval; 186 cdtime_t flush_interval; 187 cdtime_t flush_timeout; 188 }; 189 typedef struct plugin_ctx_s plugin_ctx_t; 190 191 /* 192 * Callback types 193 */ 194 typedef int (*plugin_init_cb)(void); 195 typedef int (*plugin_read_cb)(user_data_t *); 196 typedef int (*plugin_write_cb)(const data_set_t *, const value_list_t *, 197 user_data_t *); 198 typedef int (*plugin_flush_cb)(cdtime_t timeout, const char *identifier, 199 user_data_t *); 200 /* "missing" callback. Returns less than zero on failure, zero if other 201 * callbacks should be called, greater than zero if no more callbacks should be 202 * called. */ 203 typedef int (*plugin_missing_cb)(const value_list_t *, user_data_t *); 204 /* "cache event" callback. CE_VALUE_NEW events are sent to all registered 205 * callbacks. Callback should check if it interested in further CE_VALUE_UPDATE 206 * and CE_VALUE_EXPIRED events for metric and set event->ret = 1 if so. 207 */ 208 typedef int (*plugin_cache_event_cb)(cache_event_t *, user_data_t *); 209 typedef void (*plugin_log_cb)(int severity, const char *message, user_data_t *); 210 typedef int (*plugin_shutdown_cb)(void); 211 typedef int (*plugin_notification_cb)(const notification_t *, user_data_t *); 212 /* 213 * NAME 214 * plugin_set_dir 215 * 216 * DESCRIPTION 217 * Sets the current `plugindir' 218 * 219 * ARGUMENTS 220 * `dir' Path to the plugin directory 221 * 222 * NOTES 223 * If `dir' is NULL the compiled in default `PLUGINDIR' is used. 224 */ 225 void plugin_set_dir(const char *dir); 226 227 /* 228 * NAME 229 * plugin_load 230 * 231 * DESCRIPTION 232 * Searches the current `plugindir' (see `plugin_set_dir') for the plugin 233 * named $type and loads it. Afterwards the plugin's `module_register' 234 * function is called, which then calls `plugin_register' to register callback 235 * functions. 236 * 237 * ARGUMENTS 238 * `name' Name of the plugin to load. 239 * `global' Make this plugins symbols available for other shared libraries. 240 * 241 * RETURN VALUE 242 * Returns zero upon success, a value greater than zero if no plugin was found 243 * and a value below zero if an error occurs. 244 * 245 * NOTES 246 * Re-loading an already loaded module is detected and zero is returned in 247 * this case. 248 */ 249 int plugin_load(const char *name, bool global); 250 bool plugin_is_loaded(char const *name); 251 252 int plugin_init_all(void); 253 void plugin_read_all(void); 254 int plugin_read_all_once(void); 255 int plugin_shutdown_all(void); 256 257 /* 258 * NAME 259 * plugin_write 260 * 261 * DESCRIPTION 262 * Calls the write function of the given plugin with the provided data set and 263 * value list. It differs from `plugin_dispatch_values' in that it does not 264 * update the cache, does not do threshold checking, call the chain subsystem 265 * and so on. It looks up the requested plugin and invokes the function, end 266 * of story. 267 * 268 * ARGUMENTS 269 * plugin Name of the plugin. If NULL, the value is sent to all registered 270 * write functions. 271 * ds Pointer to the data_set_t structure. If NULL, the data set is 272 * looked up according to the `type' member in the `vl' argument. 273 * vl The actual value to be processed. Must not be NULL. 274 * 275 * RETURN VALUE 276 * Returns zero upon success or non-zero if an error occurred. If `plugin' is 277 * NULL and more than one plugin is called, an error is only returned if *all* 278 * plugins fail. 279 * 280 * NOTES 281 * This is the function used by the `write' built-in target. May be used by 282 * other target plugins. 283 */ 284 int plugin_write(const char *plugin, const data_set_t *ds, 285 const value_list_t *vl); 286 287 int plugin_flush(const char *plugin, cdtime_t timeout, const char *identifier); 288 289 /* 290 * The `plugin_register_*' functions are used to make `config', `init', 291 * `read', `write' and `shutdown' functions known to the plugin 292 * infrastructure. Also, the data-formats are made public like this. 293 */ 294 int plugin_register_config(const char *name, 295 int (*callback)(const char *key, const char *val), 296 const char **keys, int keys_num); 297 int plugin_register_complex_config(const char *type, 298 int (*callback)(oconfig_item_t *)); 299 int plugin_register_init(const char *name, plugin_init_cb callback); 300 int plugin_register_read(const char *name, int (*callback)(void)); 301 /* "user_data" will be freed automatically, unless 302 * "plugin_register_complex_read" returns an error (non-zero). */ 303 int plugin_register_complex_read(const char *group, const char *name, 304 plugin_read_cb callback, cdtime_t interval, 305 user_data_t const *user_data); 306 int plugin_register_write(const char *name, plugin_write_cb callback, 307 user_data_t const *user_data); 308 int plugin_register_flush(const char *name, plugin_flush_cb callback, 309 user_data_t const *user_data); 310 int plugin_register_missing(const char *name, plugin_missing_cb callback, 311 user_data_t const *user_data); 312 int plugin_register_cache_event(const char *name, 313 plugin_cache_event_cb callback, 314 user_data_t const *ud); 315 int plugin_register_shutdown(const char *name, plugin_shutdown_cb callback); 316 int plugin_register_data_set(const data_set_t *ds); 317 int plugin_register_log(const char *name, plugin_log_cb callback, 318 user_data_t const *user_data); 319 int plugin_register_notification(const char *name, 320 plugin_notification_cb callback, 321 user_data_t const *user_data); 322 323 int plugin_unregister_config(const char *name); 324 int plugin_unregister_complex_config(const char *name); 325 int plugin_unregister_init(const char *name); 326 int plugin_unregister_read(const char *name); 327 int plugin_unregister_read_group(const char *group); 328 int plugin_unregister_write(const char *name); 329 int plugin_unregister_flush(const char *name); 330 int plugin_unregister_missing(const char *name); 331 int plugin_unregister_cache_event(const char *name); 332 int plugin_unregister_shutdown(const char *name); 333 int plugin_unregister_data_set(const char *name); 334 int plugin_unregister_log(const char *name); 335 int plugin_unregister_notification(const char *name); 336 337 /* 338 * NAME 339 * plugin_log_available_writers 340 * 341 * DESCRIPTION 342 * This function can be called to output a list of _all_ registered 343 * writers to the logfacility. 344 * Since some writers dynamically build their name it can be hard for 345 * the configuring person to know it. This function will fill this gap. 346 */ 347 void plugin_log_available_writers(void); 348 349 /* 350 * NAME 351 * plugin_dispatch_values 352 * 353 * DESCRIPTION 354 * This function is called by reading processes with the values they've 355 * aquired. The function fetches the data-set definition (that has been 356 * registered using `plugin_register_data_set') and calls _all_ registered 357 * write-functions. 358 * 359 * ARGUMENTS 360 * `vl' Value list of the values that have been read by a `read' 361 * function. 362 */ 363 int plugin_dispatch_values(value_list_t const *vl); 364 365 /* 366 * NAME 367 * plugin_dispatch_multivalue 368 * 369 * SYNOPSIS 370 * plugin_dispatch_multivalue (vl, true, DS_TYPE_GAUGE, 371 * "free", 42.0, 372 * "used", 58.0, 373 * NULL); 374 * 375 * DESCRIPTION 376 * Takes a list of type instances and values and dispatches that in a batch, 377 * making sure that all values have the same time stamp. If "store_percentage" 378 * is set to true, the "type" is set to "percent" and a percentage is 379 * calculated and dispatched, rather than the absolute values. Values that are 380 * NaN are dispatched as NaN and will not influence the total. 381 * 382 * The variadic arguments is a list of type_instance / type pairs, that are 383 * interpreted as type "char const *" and type, encoded by their corresponding 384 * "store_type": 385 * 386 * - "gauge_t" when "DS_TYPE_GAUGE" 387 * - "absolute_t" when "DS_TYPE_ABSOLUTE" 388 * - "derive_t" when "DS_TYPE_DERIVE" 389 * - "counter_t" when "DS_TYPE_COUNTER" 390 * 391 * The last argument must be 392 * a NULL pointer to signal end-of-list. 393 * 394 * RETURNS 395 * The number of values it failed to dispatch (zero on success). 396 */ 397 __attribute__((sentinel)) int plugin_dispatch_multivalue(value_list_t const *vl, 398 bool store_percentage, 399 int store_type, ...); 400 401 int plugin_dispatch_missing(const value_list_t *vl); 402 void plugin_dispatch_cache_event(enum cache_event_type_e event_type, 403 unsigned long callbacks_mask, const char *name, 404 const value_list_t *vl); 405 406 int plugin_dispatch_notification(const notification_t *notif); 407 408 void plugin_log(int level, const char *format, ...) 409 __attribute__((format(printf, 2, 3))); 410 411 /* These functions return the parsed severity or less than zero on failure. */ 412 int parse_log_severity(const char *severity); 413 int parse_notif_severity(const char *severity); 414 415 #define ERROR(...) plugin_log(LOG_ERR, __VA_ARGS__) 416 #define WARNING(...) plugin_log(LOG_WARNING, __VA_ARGS__) 417 #define NOTICE(...) plugin_log(LOG_NOTICE, __VA_ARGS__) 418 #define INFO(...) plugin_log(LOG_INFO, __VA_ARGS__) 419 #if COLLECT_DEBUG 420 #define DEBUG(...) plugin_log(LOG_DEBUG, __VA_ARGS__) 421 #else /* COLLECT_DEBUG */ 422 #define DEBUG(...) /* noop */ 423 #endif /* ! COLLECT_DEBUG */ 424 425 /* This will log messages, prefixed by plugin name */ 426 void daemon_log(int level, const char *format, ...) 427 __attribute__((format(printf, 2, 3))); 428 429 #define P_ERROR(...) daemon_log(LOG_ERR, __VA_ARGS__) 430 #define P_WARNING(...) daemon_log(LOG_WARNING, __VA_ARGS__) 431 #define P_NOTICE(...) daemon_log(LOG_NOTICE, __VA_ARGS__) 432 #define P_INFO(...) daemon_log(LOG_INFO, __VA_ARGS__) 433 434 const data_set_t *plugin_get_ds(const char *name); 435 436 int plugin_notification_meta_add_string(notification_t *n, const char *name, 437 const char *value); 438 int plugin_notification_meta_add_signed_int(notification_t *n, const char *name, 439 int64_t value); 440 int plugin_notification_meta_add_unsigned_int(notification_t *n, 441 const char *name, uint64_t value); 442 int plugin_notification_meta_add_double(notification_t *n, const char *name, 443 double value); 444 int plugin_notification_meta_add_boolean(notification_t *n, const char *name, 445 bool value); 446 447 int plugin_notification_meta_copy(notification_t *dst, 448 const notification_t *src); 449 450 int plugin_notification_meta_free(notification_meta_t *n); 451 452 /* 453 * Plugin context management. 454 */ 455 456 void plugin_init_ctx(void); 457 458 plugin_ctx_t plugin_get_ctx(void); 459 plugin_ctx_t plugin_set_ctx(plugin_ctx_t ctx); 460 461 /* 462 * NAME 463 * plugin_get_interval 464 * 465 * DESCRIPTION 466 * This function returns the current value of the plugin's interval. The 467 * return value will be strictly greater than zero in all cases. If 468 * everything else fails, it will fall back to 10 seconds. 469 */ 470 cdtime_t plugin_get_interval(void); 471 472 /* 473 * Context-aware thread management. 474 */ 475 476 int plugin_thread_create(pthread_t *thread, void *(*start_routine)(void *), 477 void *arg, char const *name); 478 479 /* 480 * Plugins need to implement this 481 */ 482 483 void module_register(void); 484 485 #endif /* PLUGIN_H */ 486