LogAppender.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2004 Vintela, Inc. All rights reserved.
00003 * Copyright (C) 2005 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 *
00011 *  - Redistributions in binary form must reproduce the above copyright notice,
00012 *    this list of conditions and the following disclaimer in the documentation
00013 *    and/or other materials provided with the distribution.
00014 *
00015 *  - Neither the name of Vintela, Inc., Novell, Inc., nor the names of its
00016 *    contributors may be used to endorse or promote products derived from this
00017 *    software without specific prior written permission.
00018 *
00019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
00020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00021 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00022 * ARE DISCLAIMED. IN NO EVENT SHALL Vintela, Inc., Novell, Inc., OR THE 
00023 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
00024 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
00025 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
00026 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
00027 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
00028 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
00029 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030 *******************************************************************************/
00031 
00032 
00037 #include "blocxx/BLOCXX_config.h"
00038 #include "blocxx/LogAppender.hpp"
00039 #include "blocxx/String.hpp"
00040 #include "blocxx/Array.hpp"
00041 #include "blocxx/LogMessage.hpp"
00042 #include "blocxx/Logger.hpp"
00043 #include "blocxx/Assertion.hpp"
00044 #include "blocxx/StringBuffer.hpp"
00045 #include "blocxx/NullAppender.hpp"
00046 #ifndef BLOCXX_WIN32
00047 #include "blocxx/SyslogAppender.hpp"
00048 #endif
00049 #include "blocxx/CerrAppender.hpp"
00050 #include "blocxx/FileAppender.hpp"
00051 #include "blocxx/Format.hpp"
00052 
00053 namespace BLOCXX_NAMESPACE
00054 {
00055 
00057 const StringArray LogAppender::ALL_COMPONENTS(String("*").tokenize());
00058 const StringArray LogAppender::ALL_CATEGORIES(String("*").tokenize());
00059 const String LogAppender::STR_TTCC_MESSAGE_FORMAT("%r [%t] %-5p %c - %m");
00060 const String LogAppender::TYPE_SYSLOG("syslog");
00061 const String LogAppender::TYPE_STDERR("stderr");
00062 const String LogAppender::TYPE_FILE("file");
00063 const String LogAppender::TYPE_NULL("null");
00064 
00065 
00066 // TODO these need to go away. 
00067 const char* const LogAppender::LOG_1_LOCATION_opt = "log.%1.location";
00068 const char* const LogAppender::LOG_1_MAX_FILE_SIZE_opt = "log.%1.max_file_size";
00069 const char* const LogAppender::LOG_1_MAX_BACKUP_INDEX_opt = "log.%1.max_backup_index";
00070 const char* const LogAppender::LOG_1_FLUSH_opt = "log.%1.flush";
00071 const char* const LogAppender::LOG_1_SYSLOG_IDENTITY_opt = "log.%1.identity";
00072 const char* const LogAppender::LOG_1_SYSLOG_FACILITY_opt = "log.%1.facility";
00073 
00075 LogAppender::LogAppender(const StringArray& components, const StringArray& categories, const String& pattern)
00076    : m_components(components.begin(), components.end())
00077    , m_categories(categories.begin(), categories.end())
00078    , m_formatter(pattern)
00079 {
00080    m_allComponents = m_components.count("*") > 0;
00081    m_allCategories = m_categories.count("*") > 0;
00082 }
00083 
00085 void
00086 LogAppender::logMessage(const LogMessage& message) const
00087 {
00088    if (componentAndCategoryAreEnabled(message.component, message.category))
00089    {
00090       StringBuffer buf;
00091       m_formatter.formatMessage(message, buf);
00092       doProcessLogMessage(buf.releaseString(), message);
00093    }
00094 }
00095 
00097 LogAppender::~LogAppender()
00098 {
00099 }
00100 
00102 bool
00103 LogAppender::categoryIsEnabled(const String& category) const
00104 {
00105    return m_allCategories || m_categories.count(category) > 0;
00106 }
00107 
00109 bool
00110 LogAppender::componentAndCategoryAreEnabled(const String& component, const String& category) const
00111 {
00112    return (m_allComponents || m_components.count(component) > 0) &&
00113       categoryIsEnabled(category);
00114 }
00115 
00117 ELogLevel
00118 LogAppender::getLogLevel() const
00119 {
00120    int nonLevelCategoryCount = m_categories.size() -
00121       m_categories.count(Logger::STR_DEBUG_CATEGORY) -
00122       m_categories.count(Logger::STR_INFO_CATEGORY) -
00123       m_categories.count(Logger::STR_ERROR_CATEGORY) -
00124       m_categories.count(Logger::STR_FATAL_CATEGORY);
00125 
00126    if (m_allCategories || nonLevelCategoryCount > 0 || categoryIsEnabled(Logger::STR_DEBUG_CATEGORY))
00127    {
00128       return E_DEBUG_LEVEL;
00129    }
00130    else if (categoryIsEnabled(Logger::STR_INFO_CATEGORY))
00131    {
00132       return E_INFO_LEVEL;
00133    }
00134    else if (categoryIsEnabled(Logger::STR_ERROR_CATEGORY))
00135    {
00136       return E_ERROR_LEVEL;
00137    }
00138    else if (categoryIsEnabled(Logger::STR_FATAL_CATEGORY))
00139    {
00140       return E_FATAL_ERROR_LEVEL;
00141    }
00142    BLOCXX_ASSERTMSG(0, "Internal error. LogAppender unable to determine log level!");
00143    return E_DEBUG_LEVEL;
00144 }
00145 
00147 LogAppenderRef
00148 LogAppender::createLogAppender(
00149    const String& name,
00150    const StringArray& components,
00151    const StringArray& categories,
00152    const String& messageFormat,
00153    const String& type,
00154    const LoggerConfigMap& configItems)
00155 {
00156    // name and configItems are unused for now, but are provided so if a logger needs to look up configuration, it
00157    // can use name to find the appropriate config items.
00158 
00159    LogAppenderRef appender;
00160    if (type.empty() || type.equalsIgnoreCase(TYPE_NULL))
00161    {
00162       appender = new NullAppender(components, categories, messageFormat);
00163    }
00164 #ifndef BLOCXX_WIN32
00165    else if ( type == TYPE_SYSLOG )
00166    {
00167       String identity = Logger::getConfigItem(configItems, Format(LOG_1_SYSLOG_IDENTITY_opt, name), BLOCXX_DEFAULT_LOG_1_SYSLOG_IDENTITY);
00168 
00169       String facility = Logger::getConfigItem(configItems, Format(LOG_1_SYSLOG_FACILITY_opt, name), BLOCXX_DEFAULT_LOG_1_SYSLOG_FACILITY);
00170 
00171       appender = new SyslogAppender(components, categories, messageFormat, identity, facility);
00172    }
00173 #endif
00174    else if (type == TYPE_STDERR || type == "cerr")
00175    {
00176       appender = new CerrAppender(components, categories, messageFormat);
00177    }
00178    else if (type == TYPE_FILE)
00179    {
00180       String configItem = Format(LOG_1_LOCATION_opt, name);
00181 
00182       String filename = Logger::getConfigItem(configItems, configItem);
00183       
00184       UInt64 maxFileSize(0);
00185       try
00186       {
00187          maxFileSize = Logger::getConfigItem(configItems, Format(LOG_1_MAX_FILE_SIZE_opt, name), 
00188             BLOCXX_DEFAULT_LOG_1_MAX_FILE_SIZE).toUInt64();
00189       }
00190       catch (StringConversionException& e)
00191       {
00192          BLOCXX_THROW_ERR_SUBEX(LoggerException, 
00193             Format("%1: Invalid config value: %2", LOG_1_MAX_FILE_SIZE_opt, e.getMessage()).c_str(), 
00194             Logger::E_INVALID_MAX_FILE_SIZE, e);
00195       }
00196       
00197       unsigned int maxBackupIndex(0);
00198       try
00199       {
00200          maxBackupIndex = Logger::getConfigItem(configItems, Format(LOG_1_MAX_BACKUP_INDEX_opt, name), 
00201             BLOCXX_DEFAULT_LOG_1_MAX_BACKUP_INDEX).toUnsignedInt();
00202       }
00203       catch (StringConversionException& e)
00204       {
00205          BLOCXX_THROW_ERR_SUBEX(LoggerException, 
00206             Format("%1: Invalid config value: %2", LOG_1_MAX_BACKUP_INDEX_opt, e.getMessage()).c_str(), 
00207             Logger::E_INVALID_MAX_BACKUP_INDEX, e);
00208       }
00209 
00210       bool flushLog = Logger::getConfigItem(configItems, Format(LOG_1_FLUSH_opt, name), BLOCXX_DEFAULT_LOG_1_FLUSH).equalsIgnoreCase("true");
00211       
00212       appender = new FileAppender(components, categories, filename.c_str(), messageFormat, maxFileSize, maxBackupIndex, flushLog);
00213    }
00214    else
00215    {
00216       BLOCXX_THROW_ERR(LoggerException, Format("Unknown log type: %1", type).c_str(), Logger::E_UNKNOWN_LOG_APPENDER_TYPE);
00217    }
00218 
00219    return appender;
00220 }
00221 
00222 
00223 } // end namespace BLOCXX_NAMESPACE
00224 
00225 

Generated on Fri Jun 16 15:39:08 2006 for blocxx by  doxygen 1.4.6