This patch adds generic ETW logging on top of syslog calls.
The events are described in the message compiler file `event_logging.mc`.
Using the cross platform utility `windmc`, we will generate the header file,
`event_logging.h`, needed by the ETW implementation, and the resource file
`event_logging.rc`.
Over the generated resource file we will run another utility called `windres`.
this tool is used to compile the binary objects needed by the OS utilities
(i.e. `Event Viewer`) to view the logged events.
On usage, a registry key needs to be added/removed on the target computer.
The registry looks like the following:
[HKLM\SYSTEM\CurrentControlSet\Services\EventLog\Application\<get_process_name>]
"EventMessageFile"="<Folder_location_to>\\event_logging.dll"
I.E.:
[HKLM\SYSTEM\CurrentControlSet\Services\EventLog\Application\rbd-wnbd]
"EventMessageFile"="C:\\Program Files\\Ceph\\bin\\event_logging.dll"
Signed-off-by: Alin Gabriel Serdean <aserdean@cloudbasesolutions.com>
Signed-off-by: Lucian Petrut <lpetrut@cloudbasesolutions.com>
Co-authored-by: Lucian Petrut <lpetrut@cloudbasesolutions.com>
version.cc)
if(WIN32)
+ if(MINGW)
+ set(CMAKE_MC_COMPILER x86_64-w64-mingw32-windmc)
+ set(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres)
+ endif()
+
+ add_custom_command(
+ OUTPUT ${CMAKE_BINARY_DIR}/src/common/event_logging.h
+ COMMAND ${CMAKE_MC_COMPILER} -b -e h -h ${CMAKE_BINARY_DIR}/src/common/
+ -r ${CMAKE_BINARY_DIR}/src/common ${CMAKE_SOURCE_DIR}/src/common/win32/event_logging.mc
+ COMMAND ${CMAKE_RC_COMPILER} ${CMAKE_BINARY_DIR}/src/common/event_logging.rc
+ -o ${CMAKE_BINARY_DIR}/src/common/event_logging.o
+ COMMAND ${CMAKE_CXX_COMPILER} -o ${CMAKE_BINARY_DIR}/bin/event_logging.dll -shared
+ ${CMAKE_BINARY_DIR}/src/common/event_logging.o
+ DEPENDS ${CMAKE_SOURCE_DIR}/src/common/win32/event_logging.mc)
+
+ set_source_files_properties(${CMAKE_SOURCE_DIR}/src/common/win32/syslog.cc
+ APPEND PROPERTY OBJECT_DEPENDS ${CMAKE_BINARY_DIR}/src/common/event_logging.h)
+
+ include_directories(SYSTEM "${CMAKE_BINARY_DIR}/src/common/")
+
list(APPEND common_srcs
win32/blkdev.cc
win32/dns_resolve.cc
win32/ifaddrs.cc
win32/registry.cc
win32/service.cc
- win32/SubProcess.cc)
+ win32/SubProcess.cc
+ win32/syslog.cc)
else()
list(APPEND common_srcs
blkdev.cc
--- /dev/null
+SeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS
+ Informational=0x1:STATUS_SEVERITY_INFORMATIONAL
+ Warning=0x2:STATUS_SEVERITY_WARNING
+ Error=0x3:STATUS_SEVERITY_ERROR
+ )
+
+
+MessageId=0x0001
+Severity=Success
+SymbolicName=SUCCESS_EVENTMSG
+Language=English
+%1
+.
+
+MessageId=0x0002
+Severity=Informational
+SymbolicName=INFO_EVENTMSG
+Language=English
+%1
+.
+
+MessageId=0x0003
+Severity=Warning
+SymbolicName=WARN_EVENTMSG
+Language=English
+%1
+.
+
+MessageId=0x0004
+Severity=Error
+SymbolicName=ERROR_EVENTMSG
+Language=English
+%1
+.
+
--- /dev/null
+#include <windows.h>
+#include <syslog.h>
+#include "event_logging.h"
+#include "common/code_environment.h"
+
+static HANDLE g_event_source = NULL;
+
+bool get_event_source()
+{
+ if (!g_event_source) {
+ HANDLE temp = RegisterEventSourceA(NULL, get_process_name_cpp().c_str());
+ if (!temp)
+ return false;
+
+ if (InterlockedCompareExchangePointer(&g_event_source, temp, NULL)) {
+ // There already was an event source, let's cleanup the one that we've
+ // just created.
+ DeregisterEventSource(temp);
+ }
+ }
+
+ return true;
+}
+
+void write_event_log_entry(int level, const char* msg)
+{
+ if (!get_event_source()) {
+ return;
+ }
+
+ WORD type;
+ DWORD event_id;
+ switch (level) {
+ case LOG_DEBUG:
+ event_id = SUCCESS_EVENTMSG;
+ type = EVENTLOG_SUCCESS;
+ break;
+
+ case LOG_INFO:
+ case LOG_NOTICE:
+ event_id = INFO_EVENTMSG;
+ type = EVENTLOG_INFORMATION_TYPE;
+ break;
+
+ case LOG_WARNING:
+ event_id = WARN_EVENTMSG;
+ type = EVENTLOG_WARNING_TYPE;
+ break;
+
+ default:
+ event_id = ERROR_EVENTMSG;
+ type = EVENTLOG_ERROR_TYPE;
+ }
+
+ ReportEventA(g_event_source, type,
+ 0, event_id, NULL, 1, 0, &msg, NULL);
+}
+
+void syslog(int priority, const char* format, ...)
+{
+ va_list args;
+ va_start(args, format);
+
+ size_t length = (size_t)_vscprintf(format, args) + 1;
+
+ char* buffer = (char*) malloc(length);
+ if (NULL == buffer) {
+ va_end(args);
+ return;
+ }
+
+ vsnprintf_s(buffer, length, length - 1, format, args);
+ va_end(args);
+
+ write_event_log_entry(LOG_PRI(priority), buffer);
+ free(buffer);
+}
#define LOG_NOTICE 5 /* normal but significant condition */
#define LOG_INFO 6 /* informational */
#define LOG_DEBUG 7 /* debug-level messages */
-#define LOG_NDELAY 8 /* don't delay open */
#define LOG_KERN (0<<3) /* kernel messages */
#define LOG_USER (1<<3) /* user-level messages */
#define LOG_LOCAL6 (22<<3) /* reserved for local use */
#define LOG_LOCAL7 (23<<3) /* reserved for local use */
+#define LOG_PRIMASK 0x07 /* mask to extract priority part (internal) */
+ /* extract priority */
+#define LOG_PRI(p) ((p) & LOG_PRIMASK)
+
+
static inline void
openlog(const char *ident, int option, int facility)
{
}
-static inline void
-syslog(int priority, const char *format, ...)
-{
-}
+void
+syslog(int priority, const char *format, ...);
#endif /* syslog.h */