Merge pull request #3072 from octo/ff/network_test
[collectd.git] / src / syslog.c
1 /**
2  * collectd - src/syslog.c
3  * Copyright (C) 2007       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 "utils/common/common.h"
31
32 #if HAVE_SYSLOG_H
33 #include <syslog.h>
34 #endif
35
36 #if COLLECT_DEBUG
37 static int log_level = LOG_DEBUG;
38 #else
39 static int log_level = LOG_INFO;
40 #endif /* COLLECT_DEBUG */
41 static int notif_severity;
42
43 static const char *config_keys[] = {
44     "LogLevel",
45     "NotifyLevel",
46 };
47 static int config_keys_num = STATIC_ARRAY_SIZE(config_keys);
48
49 static int sl_config(const char *key, const char *value) {
50   if (strcasecmp(key, "LogLevel") == 0) {
51     log_level = parse_log_severity(value);
52     if (log_level < 0) {
53       log_level = LOG_INFO;
54       ERROR("syslog: invalid loglevel [%s] defaulting to 'info'", value);
55       return 1;
56     }
57   } else if (strcasecmp(key, "NotifyLevel") == 0) {
58     notif_severity = parse_notif_severity(value);
59     if (notif_severity < 0) {
60       ERROR("syslog: invalid notification severity [%s]", value);
61       return 1;
62     }
63   }
64
65   return 0;
66 } /* int sl_config */
67
68 static void sl_log(int severity, const char *msg,
69                    user_data_t __attribute__((unused)) * user_data) {
70   if (severity > log_level)
71     return;
72
73   syslog(severity, "%s", msg);
74 } /* void sl_log */
75
76 static int sl_shutdown(void) {
77   closelog();
78
79   return 0;
80 }
81
82 static int sl_notification(const notification_t *n,
83                            user_data_t __attribute__((unused)) * user_data) {
84   char buf[1024] = "";
85   size_t offset = 0;
86   int log_severity;
87   const char *severity_string;
88   int status;
89
90   if (n->severity > notif_severity)
91     return 0;
92
93   switch (n->severity) {
94   case NOTIF_FAILURE:
95     severity_string = "FAILURE";
96     log_severity = LOG_ERR;
97     break;
98   case NOTIF_WARNING:
99     severity_string = "WARNING";
100     log_severity = LOG_WARNING;
101     break;
102   case NOTIF_OKAY:
103     severity_string = "OKAY";
104     log_severity = LOG_NOTICE;
105     break;
106   default:
107     severity_string = "UNKNOWN";
108     log_severity = LOG_ERR;
109   }
110
111 #define BUFFER_ADD(...)                                                        \
112   do {                                                                         \
113     status = snprintf(&buf[offset], sizeof(buf) - offset, __VA_ARGS__);        \
114     if (status < 1)                                                            \
115       return -1;                                                               \
116     else if (((size_t)status) >= (sizeof(buf) - offset))                       \
117       return -ENOMEM;                                                          \
118     else                                                                       \
119       offset += ((size_t)status);                                              \
120   } while (0)
121
122 #define BUFFER_ADD_FIELD(field)                                                \
123   do {                                                                         \
124     if (n->field[0])                                                           \
125       BUFFER_ADD(", " #field " = %s", n->field);                               \
126   } while (0)
127
128   BUFFER_ADD("Notification: severity = %s", severity_string);
129   BUFFER_ADD_FIELD(host);
130   BUFFER_ADD_FIELD(plugin);
131   BUFFER_ADD_FIELD(plugin_instance);
132   BUFFER_ADD_FIELD(type);
133   BUFFER_ADD_FIELD(type_instance);
134   BUFFER_ADD_FIELD(message);
135
136 #undef BUFFER_ADD_FIELD
137 #undef BUFFER_ADD
138
139   buf[sizeof(buf) - 1] = '\0';
140
141   sl_log(log_severity, buf, NULL);
142
143   return 0;
144 } /* int sl_notification */
145
146 void module_register(void) {
147   openlog("collectd", LOG_CONS | LOG_PID, LOG_DAEMON);
148
149   plugin_register_config("syslog", sl_config, config_keys, config_keys_num);
150   plugin_register_log("syslog", sl_log, /* user_data = */ NULL);
151   plugin_register_notification("syslog", sl_notification, NULL);
152   plugin_register_shutdown("syslog", sl_shutdown);
153 } /* void module_register(void) */