blocxx

SyslogAppender.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2004-2005, Vintela, Inc. All rights reserved.
00003 * Copyright (C) 2005-2006, Novell, Inc. All rights reserved.
00004 * 
00005 * Redistribution and use in source and binary forms, with or without
00006 * modification, are permitted provided that the following conditions are met:
00007 * 
00008 *     * Redistributions of source code must retain the above copyright notice,
00009 *       this list of conditions and the following disclaimer.
00010 *     * Redistributions in binary form must reproduce the above copyright
00011 *       notice, this list of conditions and the following disclaimer in the
00012 *       documentation and/or other materials provided with the distribution.
00013 *     * Neither the name of Vintela, Inc., nor Novell, Inc., 
00014 *       nor the names of its contributors or employees may be used to 
00015 *       endorse or promote products derived from this software without 
00016 *       specific prior written permission.
00017 * 
00018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00022 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00028 * POSSIBILITY OF SUCH DAMAGE.
00029 *******************************************************************************/
00030 
00031 
00036 #include "blocxx/BLOCXX_config.h"
00037 #include "blocxx/SyslogAppender.hpp"
00038 #include "blocxx/Logger.hpp"
00039 #include "blocxx/LogMessage.hpp"
00040 #include "blocxx/Mutex.hpp"
00041 #include "blocxx/MutexLock.hpp"
00042 #include "blocxx/Format.hpp"
00043 #include "blocxx/GlobalMutex.hpp"
00044 #include <syslog.h>
00045 
00046 #if defined(BLOCXX_WIN32)
00047 #define snprintf _snprintf // stupid windoze...
00048 #endif
00049 
00050 namespace BLOCXX_NAMESPACE
00051 {
00052 
00053 namespace // anonymous
00054 {
00055    GlobalMutex syslogGuard = BLOCXX_GLOBAL_MUTEX_INIT();
00056 
00057 #if defined(NAME_MAX)
00058    static char log_ident[NAME_MAX];
00059 #else
00060    static char log_ident[255];
00061 #endif
00062 
00063    struct Facilities
00064    {
00065       const char * const name;
00066       const int          code;
00067    };
00068 
00069    static struct Facilities facilities[] =
00070    {
00071 #ifdef LOG_AUTHPRIV
00072       { "auth",   LOG_AUTH },
00073 #endif
00074 #ifdef LOG_AUTHPRIV
00075       { "authpriv",  LOG_AUTHPRIV   },
00076 #endif
00077 #ifdef LOG_CRON
00078       { "cron",   LOG_CRON },
00079 #endif
00080 #ifdef LOG_DAEMON
00081       { "daemon", LOG_DAEMON  },
00082 #endif
00083 #ifdef LOG_FTP
00084       { "ftp", LOG_FTP     },
00085 #endif
00086 #ifdef LOG_KERN
00087       { "kern",   LOG_KERN },
00088 #endif
00089 #ifdef LOG_LPR
00090       { "lpr", LOG_LPR     },
00091 #endif
00092 #ifdef LOG_MAIL
00093       { "mail",   LOG_MAIL },
00094 #endif
00095 #ifdef LOG_NEWS
00096       { "news",   LOG_NEWS },
00097 #endif
00098 #ifdef LOG_USER
00099       { "user",   LOG_USER },
00100 #endif
00101 #ifdef LOG_UUCP
00102       { "uucp",   LOG_UUCP },
00103 #endif
00104 #ifdef LOG_LOCAL0
00105       { "local0", LOG_LOCAL0  },
00106 #endif
00107 #ifdef LOG_LOCAL1
00108       { "local1", LOG_LOCAL1  },
00109 #endif
00110 #ifdef LOG_LOCAL2
00111       { "local2", LOG_LOCAL2  },
00112 #endif
00113 #ifdef LOG_LOCAL3
00114       { "local3", LOG_LOCAL3  },
00115 #endif
00116 #ifdef LOG_LOCAL4
00117       { "local4", LOG_LOCAL4  },
00118 #endif
00119 #ifdef LOG_LOCAL5
00120       { "local5", LOG_LOCAL5  },
00121 #endif
00122 #ifdef LOG_LOCAL6
00123       { "local6", LOG_LOCAL6  },
00124 #endif
00125 #ifdef LOG_LOCAL7
00126       { "local7", LOG_LOCAL7  },
00127 #endif
00128       { NULL,     0     }
00129    };
00130 
00131 } // End of anonymous namespace
00132 
00133 
00135 SyslogAppender::SyslogAppender(const StringArray& components,
00136                                const StringArray& categories,
00137                                const String&      pattern,
00138                                const String&      identity,
00139                                const String&      facility)
00140    : LogAppender(components, categories, pattern)
00141 {
00142    if( identity.empty() || identity.isSpaces())
00143    {
00144       BLOCXX_THROW(LoggerException,
00145          "SyslogAppender: Empty syslog identity name"
00146       );
00147    }
00148    if( facility.empty())
00149    {
00150       BLOCXX_THROW(LoggerException,
00151          "SyslogAppender: Empty syslog facility name"
00152       );
00153    }
00154 
00155    struct Facilities *f = facilities;
00156    for( ; f->name != NULL; f++)
00157    {
00158       if( facility.equals(f->name))
00159          break;
00160    }
00161    if( f->name == NULL)
00162    {
00163       BLOCXX_THROW(LoggerException,
00164          Format("SyslogAppender: Unknown syslog facility name: %1",
00165             facility).c_str()
00166       );
00167    }
00168 
00169    MutexLock lock(syslogGuard);
00170    if (!calledOpenLog)
00171    {
00172       /*
00173        * Warning: openlog on linux remembers only the
00174        *          pointer to log_ident ...
00175        */
00176       ::snprintf( log_ident, sizeof(log_ident), "%s", identity.c_str());
00177       openlog( log_ident, LOG_CONS, f->code);
00178       calledOpenLog = true;
00179    }
00180 }
00181 
00183 SyslogAppender::~SyslogAppender() {}
00184 
00186 void
00187 SyslogAppender::doProcessLogMessage(const String& formattedMessage, const LogMessage& message) const
00188 {
00189    int syslogPriority;
00190    if (message.category.equalsIgnoreCase(Logger::STR_FATAL_CATEGORY))
00191    {
00192       syslogPriority = LOG_CRIT;
00193    }
00194    else if (message.category.equalsIgnoreCase(Logger::STR_ERROR_CATEGORY))
00195    {
00196       syslogPriority = LOG_ERR;
00197    }
00198    else if (message.category.equalsIgnoreCase(Logger::STR_WARNING_CATEGORY))
00199    {
00200       syslogPriority = LOG_WARNING;
00201    }
00202    else if (message.category.equalsIgnoreCase(Logger::STR_INFO_CATEGORY))
00203    {
00204       syslogPriority = LOG_INFO;
00205    }
00206    else if (message.category.equalsIgnoreCase(Logger::STR_DEBUG_CATEGORY) 
00207           || message.category.equalsIgnoreCase(Logger::STR_DEBUG2_CATEGORY) 
00208           || message.category.equalsIgnoreCase(Logger::STR_DEBUG3_CATEGORY))
00209    {
00210       syslogPriority = LOG_DEBUG;
00211    }
00212    else
00213    {
00214       syslogPriority = LOG_INFO;
00215    }
00216 
00217    StringArray a = formattedMessage.tokenize("\n");
00218    MutexLock lock(syslogGuard);
00219    for (size_t i = 0; i < a.size(); ++i)
00220    {
00221       char format[] = "%s";
00222       syslog( syslogPriority, format, a[i].c_str() );
00223    }
00224 }
00225 
00227 bool SyslogAppender::calledOpenLog = false;
00228 const GlobalString SyslogAppender::STR_DEFAULT_MESSAGE_PATTERN = BLOCXX_GLOBAL_STRING_INIT("[%t]%m");
00229 
00230 
00231 } // end namespace BLOCXX_NAMESPACE
00232 
00233 
00234 
00235