libwinpr-utils: start implementing ConsoleAppender
authorMarc-André Moreau <marcandre.moreau@gmail.com>
Mon, 16 Sep 2013 16:05:08 +0000 (12:05 -0400)
committerMarc-André Moreau <marcandre.moreau@gmail.com>
Mon, 16 Sep 2013 16:05:08 +0000 (12:05 -0400)
winpr/include/winpr/wlog.h
winpr/libwinpr/utils/test/TestWLog.c
winpr/libwinpr/utils/wlog.c

index 70da16f..73f4a23 100644 (file)
 #include <winpr/winpr.h>
 #include <winpr/wtypes.h>
 
-#define WLOG_TRACE     0
-#define WLOG_DEBUG     1
-#define WLOG_INFO      2
-#define WLOG_WARN      3
-#define WLOG_ERROR     4
-#define WLOG_FATAL     5
-#define WLOG_OFF       6
+typedef struct _wLog wLog;
+typedef struct _wLogMessage wLogMessage;
+typedef struct _wLogAppender wLogAppender;
+
+/**
+ * Log Levels
+ */
+
+#define WLOG_TRACE             0
+#define WLOG_DEBUG             1
+#define WLOG_INFO              2
+#define WLOG_WARN              3
+#define WLOG_ERROR             4
+#define WLOG_FATAL             5
+#define WLOG_OFF               6
+
+/**
+ * Log Message
+ */
+
+#define WLOG_MESSAGE_STRING    0
+
+struct _wLogMessage
+{
+       DWORD Type;
+
+       LPSTR TextString;
+};
+
+/**
+ * Log Appenders
+ */
+
+#define WLOG_APPENDER_CONSOLE  0
+#define WLOG_APPENDER_FILE     1
+
+typedef int (*WLOG_APPENDER_WRITE_MESSAGE_FN)(wLog* log, wLogAppender* appender, DWORD logLevel, wLogMessage* logMessage);
+
+struct _wLogAppender
+{
+       DWORD Type;
+       WLOG_APPENDER_WRITE_MESSAGE_FN WriteMessage;
+};
+
+#define WLOG_CONSOLE_STDOUT    1
+#define WLOG_CONSOLE_STDERR    2
+
+struct _wLogConsoleAppender
+{
+       DWORD Type;
+       WLOG_APPENDER_WRITE_MESSAGE_FN WriteMessage;
+
+       int outputStream;
+};
+typedef struct _wLogConsoleAppender wLogConsoleAppender;
+
+struct _wLogFileAppender
+{
+       DWORD Type;
+       WLOG_APPENDER_WRITE_MESSAGE_FN WriteMessage;
+
+
+};
+typedef struct _wLogFileAppender wLogFileAppender;
+
+/**
+ * Logger
+ */
 
 struct _wLog
 {
        LPSTR Name;
        DWORD Level;
+
+       wLogAppender* Appender;
 };
-typedef struct _wLog wLog;
 
 WINPR_API void WLog_Print(wLog* log, DWORD logLevel, LPCSTR logMessage, ...);
 
 WINPR_API DWORD WLog_GetLogLevel(wLog* log);
 WINPR_API void WLog_SetLogLevel(wLog* log, DWORD logLevel);
 
+WINPR_API wLogAppender* WLog_GetLogAppender(wLog* log);
+WINPR_API void WLog_SetLogAppenderType(wLog* log, DWORD logAppenderType);
+
+WINPR_API void WLog_ConsoleAppender_SetOutputStream(wLog* log, wLogConsoleAppender* consoleAppender, int outputStream);
+
 WINPR_API wLog* WLog_New(LPCSTR name);
 WINPR_API void WLog_Free(wLog* log);
 
index 5ded941..b26001e 100644 (file)
@@ -6,10 +6,17 @@
 int TestWLog(int argc, char* argv[])
 {
        wLog* log;
+       wLogConsoleAppender* appender;
 
        log = WLog_New("TEST");
 
        WLog_SetLogLevel(log, WLOG_INFO);
+
+       WLog_SetLogAppenderType(log, WLOG_APPENDER_CONSOLE);
+       appender = (wLogConsoleAppender*) WLog_GetLogAppender(log);
+
+       WLog_ConsoleAppender_SetOutputStream(log, appender, WLOG_CONSOLE_STDERR);
+
        WLog_Print(log, WLOG_INFO, "this is a test");
        WLog_Print(log, WLOG_WARN, "this is a %dnd %s", 2, "test");
        WLog_Print(log, WLOG_ERROR, "this is an error");
index 3b0650f..9a776ec 100644 (file)
 
 #include <winpr/wlog.h>
 
+/**
+ * References for general logging concepts:
+ *
+ * Short introduction to log4j:
+ * http://logging.apache.org/log4j/1.2/manual.html
+ *
+ * logging - Logging facility for Python:
+ * http://docs.python.org/2/library/logging.html
+ */
+
 #define WLOG_BUFFER_SIZE       8192
 
 const char* WLOG_LEVELS[7] =
@@ -43,29 +53,35 @@ const char* WLOG_LEVELS[7] =
        "Off"
 };
 
-void WLog_WriteA(wLog* log, DWORD logLevel, LPCSTR logMessage)
+int WLog_Write(wLog* log, DWORD logLevel, wLogMessage* logMessage)
 {
-       char* logLevelStr;
+       if (!log->Appender)
+               return -1;
 
-       if (logLevel > log->Level)
-               return;
-
-       logLevelStr = (char*) WLOG_LEVELS[logLevel];
+       if (!log->Appender->WriteMessage)
+               return -1;
 
-       printf("[%s] [%s]: %s\n", logLevelStr, log->Name, logMessage);
+       return log->Appender->WriteMessage(log, log->Appender, logLevel, logMessage);
 }
 
 void WLog_LogVA(wLog* log, DWORD logLevel, LPCSTR logMessage, va_list args)
 {
+       wLogMessage message;
+
+       message.Type = WLOG_MESSAGE_STRING;
+
        if (!strchr(logMessage, '%'))
        {
-               WLog_WriteA(log, logLevel, logMessage);
+               message.TextString = (LPSTR) logMessage;
+               WLog_Write(log, logLevel, &message);
        }
        else
        {
                char formattedLogMessage[8192];
                wvsnprintfx(formattedLogMessage, WLOG_BUFFER_SIZE - 1, logMessage, args);
-               WLog_WriteA(log, logLevel, formattedLogMessage);
+
+               message.TextString = formattedLogMessage;
+               WLog_Write(log, logLevel, &message);
        }
 }
 
@@ -90,6 +106,156 @@ void WLog_SetLogLevel(wLog* log, DWORD logLevel)
        log->Level = logLevel;
 }
 
+wLogAppender* WLog_GetLogAppender(wLog* log)
+{
+       return log->Appender;
+}
+
+/**
+ * Console Appender
+ */
+
+void WLog_ConsoleAppender_SetOutputStream(wLog* log, wLogConsoleAppender* consoleAppender, int outputStream)
+{
+       if (!consoleAppender)
+               return;
+
+       if (outputStream < 0)
+               outputStream = WLOG_CONSOLE_STDOUT;
+
+       if (outputStream == WLOG_CONSOLE_STDOUT)
+               consoleAppender->outputStream = WLOG_CONSOLE_STDOUT;
+       else if (outputStream == WLOG_CONSOLE_STDERR)
+               consoleAppender->outputStream = WLOG_CONSOLE_STDERR;
+       else
+               consoleAppender->outputStream = WLOG_CONSOLE_STDOUT;
+}
+
+int WLog_ConsoleAppender_WriteMessage(wLog* log, wLogConsoleAppender* appender, DWORD logLevel, wLogMessage* logMessage)
+{
+       char* logLevelStr;
+
+       if (logLevel > log->Level)
+               return 0;
+
+       logLevelStr = (char*) WLOG_LEVELS[logLevel];
+
+       if (appender->outputStream == WLOG_CONSOLE_STDERR)
+               fprintf(stderr, "[%s] [%s]: %s\n", logLevelStr, log->Name, logMessage->TextString);
+       else
+               printf("[%s] [%s]: %s\n", logLevelStr, log->Name, logMessage->TextString);
+
+       return 1;
+}
+
+wLogConsoleAppender* WLog_ConsoleAppender_New(wLog* log)
+{
+       wLogConsoleAppender* ConsoleAppender;
+
+       ConsoleAppender = (wLogConsoleAppender*) malloc(sizeof(wLogConsoleAppender));
+
+       if (ConsoleAppender)
+       {
+               ZeroMemory(ConsoleAppender, sizeof(wLogConsoleAppender));
+
+               ConsoleAppender->WriteMessage = (WLOG_APPENDER_WRITE_MESSAGE_FN) WLog_ConsoleAppender_WriteMessage;
+
+               ConsoleAppender->outputStream = WLOG_CONSOLE_STDOUT;
+       }
+
+       return ConsoleAppender;
+}
+
+void WLog_ConsoleAppender_Free(wLog* log, wLogConsoleAppender* consoleAppender)
+{
+       if (consoleAppender)
+       {
+               free(consoleAppender);
+       }
+}
+
+/**
+ * File Appender
+ */
+
+int WLog_FileAppender_WriteMessage(wLog* log, wLogFileAppender* appender, DWORD logLevel, wLogMessage* logMessage)
+{
+       char* logLevelStr;
+
+       if (logLevel > log->Level)
+               return 0;
+
+       logLevelStr = (char*) WLOG_LEVELS[logLevel];
+
+       printf("[%s] [%s]: %s\n", logLevelStr, log->Name, logMessage->TextString);
+
+       return 1;
+}
+
+wLogFileAppender* WLog_FileAppender_New(wLog* log)
+{
+       wLogFileAppender* FileAppender;
+
+       FileAppender = (wLogFileAppender*) malloc(sizeof(wLogFileAppender));
+
+       if (FileAppender)
+       {
+               ZeroMemory(FileAppender, sizeof(wLogFileAppender));
+
+               FileAppender->WriteMessage = (WLOG_APPENDER_WRITE_MESSAGE_FN) WLog_FileAppender_WriteMessage;
+       }
+
+       return FileAppender;
+}
+
+void WLog_FileAppender_Free(wLog* log, wLogFileAppender* fileAppender)
+{
+       if (fileAppender)
+       {
+               free(fileAppender);
+       }
+}
+
+wLogAppender* WLog_Appender_New(wLog* log, DWORD logAppenderType)
+{
+       if (logAppenderType == WLOG_APPENDER_CONSOLE)
+       {
+               return (wLogAppender*) WLog_ConsoleAppender_New(log);
+       }
+       else if (logAppenderType == WLOG_APPENDER_FILE)
+       {
+               return (wLogAppender*) WLog_FileAppender_New(log);
+       }
+
+       return (wLogAppender*) WLog_ConsoleAppender_New(log);
+}
+
+void WLog_Appender_Free(wLog* log, wLogAppender* appender)
+{
+       if (appender)
+       {
+               if (appender->Type == WLOG_APPENDER_CONSOLE)
+               {
+                       WLog_ConsoleAppender_Free(log, (wLogConsoleAppender*) appender);
+               }
+               else if (appender->Type == WLOG_APPENDER_FILE)
+               {
+                       WLog_FileAppender_Free(log, (wLogFileAppender*) appender);
+               }
+       }
+}
+
+void WLog_SetLogAppenderType(wLog* log, DWORD logAppenderType)
+{
+       if (log->Appender)
+       {
+               WLog_Appender_Free(log, log->Appender);
+               log->Appender = NULL;
+       }
+
+       log->Appender = WLog_Appender_New(log, logAppenderType);
+}
+
 wLog* WLog_New(LPCSTR name)
 {
        wLog* log;
@@ -102,6 +268,8 @@ wLog* WLog_New(LPCSTR name)
 
                log->Name = _strdup(name);
                log->Level = WLOG_TRACE;
+
+               WLog_SetLogAppenderType(log, WLOG_APPENDER_CONSOLE);
        }
 
        return log;
@@ -111,6 +279,12 @@ void WLog_Free(wLog* log)
 {
        if (log)
        {
+               if (log->Appender)
+               {
+                       WLog_Appender_Free(log, log->Appender);
+                       log->Appender = NULL;
+               }
+
                free(log->Name);
                free(log);
        }