1+ /**
2+ * collectd - src/eventlog.c
3+ * Copyright (c) 2018 Google LLC
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+
24+ #include "collectd.h"
25+
26+ #include "common.h"
27+ #include "plugin.h"
28+
29+ #include "eventlogres.h"
30+
31+ #include <windows.h>
32+
33+ #if COLLECT_DEBUG
34+ static int log_level = LOG_DEBUG ;
35+ #else
36+ static int log_level = LOG_INFO ;
37+ #endif /* COLLECT_DEBUG */
38+ static int notif_severity = 0 ;
39+
40+ static const char * config_keys [] = {
41+ "LogLevel" , "NotifyLevel" ,
42+ };
43+ static int config_keys_num = STATIC_ARRAY_SIZE (config_keys );
44+
45+ static HANDLE event_source ;
46+ static char log_prefix [512 ];
47+
48+ int event_type_from_priority (int event_id ) {
49+ switch (event_id ) {
50+ case LOG_INFO :
51+ return EVENTLOG_INFORMATION_TYPE ;
52+ case LOG_NOTICE :
53+ return EVENTLOG_INFORMATION_TYPE ;
54+ case LOG_DEBUG :
55+ return EVENTLOG_INFORMATION_TYPE ;
56+ case LOG_ERR :
57+ return EVENTLOG_ERROR_TYPE ;
58+ default :
59+ return EVENTLOG_WARNING_TYPE ;
60+ }
61+ }
62+
63+ static void openlog (const char * ident ) {
64+ sprintf (log_prefix , "%s[%d]" , ident , getpid ());
65+ event_source = RegisterEventSource (NULL , ident );
66+ if (event_source == NULL ) {
67+ ERROR ("eventlog: failed to register '%s' as an event source" , ident );
68+ }
69+ }
70+
71+ static int closelog () {
72+ BOOL success = DeregisterEventSource (event_source );
73+ if (!success ) {
74+ ERROR ("eventlog: failed to deregister 'collectd' as an event source" );
75+ return 1 ;
76+ }
77+ return 0 ;
78+ }
79+
80+ static void veventlog (int priority , const char * format , va_list args ) {
81+ char msg [2056 ];
82+ vsprintf (msg , format , args );
83+ const char * messages [] = {log_prefix , msg };
84+
85+ BOOL success = ReportEvent (
86+ event_source ,
87+ event_type_from_priority (priority ), // wType
88+ 0 , // wCategory
89+ MSG_LOG , // dwEventID
90+ NULL , // lpUserSid
91+ 2 , // wNumStrings
92+ 0 , // dwDataSize
93+ messages , // lpStrings
94+ NULL // lpRawData
95+ );
96+ if (!success ) {
97+ ERROR ("eventlog: failed to report event to event log" );
98+ }
99+ }
100+
101+ static void eventlog (int priority , const char * format , ...) {
102+ va_list args ;
103+ va_start (args , format );
104+ veventlog (priority , format , args );
105+ va_end (args );
106+ }
107+
108+ static int el_config (const char * key , const char * value ) {
109+ if (strcasecmp (key , "LogLevel" ) == 0 ) {
110+ log_level = parse_log_severity (value );
111+ if (log_level < 0 ) {
112+ log_level = LOG_INFO ;
113+ ERROR ("eventlog: invalid loglevel [%s] defaulting to 'info'" , value );
114+ return 1 ;
115+ }
116+ } else if (strcasecmp (key , "NotifyLevel" ) == 0 ) {
117+ notif_severity = parse_notif_severity (value );
118+ if (notif_severity < 0 )
119+ return 1 ;
120+ }
121+
122+ return 0 ;
123+ } /* int el_config */
124+
125+ static void el_log (int severity , const char * msg ,
126+ user_data_t __attribute__((unused )) * user_data ) {
127+ if (severity > log_level )
128+ return ;
129+
130+ eventlog (severity , "%s" , msg );
131+ } /* void el_log */
132+
133+ static int el_shutdown (void ) {
134+ return closelog ();
135+ }
136+
137+ static int el_notification (const notification_t * n ,
138+ user_data_t __attribute__((unused )) * user_data ) {
139+ char buf [1024 ] = "" ;
140+ size_t offset = 0 ;
141+ int log_severity ;
142+ const char * severity_string ;
143+ int status ;
144+
145+ if (n -> severity > notif_severity )
146+ return 0 ;
147+
148+ switch (n -> severity ) {
149+ case NOTIF_FAILURE :
150+ severity_string = "FAILURE" ;
151+ log_severity = LOG_ERR ;
152+ break ;
153+ case NOTIF_WARNING :
154+ severity_string = "WARNING" ;
155+ log_severity = LOG_WARNING ;
156+ break ;
157+ case NOTIF_OKAY :
158+ severity_string = "OKAY" ;
159+ log_severity = LOG_NOTICE ;
160+ break ;
161+ default :
162+ severity_string = "UNKNOWN" ;
163+ log_severity = LOG_ERR ;
164+ }
165+
166+ #define BUFFER_ADD (...) \
167+ do { \
168+ status = snprintf(&buf[offset], sizeof(buf) - offset, __VA_ARGS__); \
169+ if (status < 1) \
170+ return -1; \
171+ else if (((size_t)status) >= (sizeof(buf) - offset)) \
172+ return -ENOMEM; \
173+ else \
174+ offset += ((size_t)status); \
175+ } while (0)
176+
177+ #define BUFFER_ADD_FIELD (field ) \
178+ do { \
179+ if (n->field[0]) \
180+ BUFFER_ADD(", " #field " = %s", n->field); \
181+ } while (0)
182+
183+ BUFFER_ADD ("Notification: severity = %s" , severity_string );
184+ BUFFER_ADD_FIELD (host );
185+ BUFFER_ADD_FIELD (plugin );
186+ BUFFER_ADD_FIELD (plugin_instance );
187+ BUFFER_ADD_FIELD (type );
188+ BUFFER_ADD_FIELD (type_instance );
189+ BUFFER_ADD_FIELD (message );
190+
191+ #undef BUFFER_ADD_FIELD
192+ #undef BUFFER_ADD
193+
194+ buf [sizeof (buf ) - 1 ] = '\0' ;
195+
196+ el_log (log_severity , buf , NULL );
197+
198+ return 0 ;
199+ } /* int el_notification */
200+
201+ void module_register (void ) {
202+ openlog ("collectd" );
203+
204+ plugin_register_config ("eventlog" , el_config , config_keys , config_keys_num );
205+ plugin_register_log ("eventlog" , el_log , /* user_data = */ NULL );
206+ plugin_register_notification ("eventlog" , el_notification , NULL );
207+ plugin_register_shutdown ("eventlog" , el_shutdown );
208+ } /* void module_register(void) */
0 commit comments