blob: bf505635eac60cd7a8a1de4d9bb2072588a37798 [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <log4cxx/varia/fallbackerrorhandler.h>
#include <log4cxx/helpers/loglog.h>
#include <log4cxx/helpers/stringhelper.h>
#include <log4cxx/hierarchy.h>
#include <log4cxx/logmanager.h>
#include <list>
using namespace LOG4CXX_NS;
using namespace LOG4CXX_NS::helpers;
using namespace LOG4CXX_NS::spi;
using namespace LOG4CXX_NS::varia;
IMPLEMENT_LOG4CXX_OBJECT(FallbackErrorHandler)
struct FallbackErrorHandler::FallbackErrorHandlerPrivate
{
std::list<AppenderPtr> backup;
AppenderWeakPtr primary;
std::map<LogString, spi::AppenderAttachableWeakPtr> appenderHolders;
bool errorReported = false;
};
FallbackErrorHandler::FallbackErrorHandler()
: m_priv(std::make_unique<FallbackErrorHandlerPrivate>())
{
}
FallbackErrorHandler::~FallbackErrorHandler() {}
void FallbackErrorHandler::addAppenderHolder(const LogString& name, const spi::AppenderAttachablePtr& clx)
{
if (LogLog::isDebugEnabled())
{
LogLog::debug(((LogString) LOG4CXX_STR("FB: Adding appender holder ["))
+ name + LOG4CXX_STR("]."));
}
m_priv->appenderHolders.emplace(name, clx);
}
void FallbackErrorHandler::setLogger(const LoggerPtr& logger)
{
if (LogLog::isDebugEnabled())
{
LogLog::debug(((LogString) LOG4CXX_STR("FB: Adding logger ["))
+ logger->getName() + LOG4CXX_STR("]."));
}
m_priv->appenderHolders.emplace(logger->getName(), logger);
}
void FallbackErrorHandler::error(const LogString& message) const
{
LogLog::warn(message);
m_priv->errorReported = true;
}
void FallbackErrorHandler::error
( const LogString& message
, const std::exception& ex
, int errorCode
) const
{
error(message, ex, errorCode, 0);
}
void FallbackErrorHandler::error
( const LogString& message
, const std::exception& ex
, int errorCode
, const spi::LoggingEventPtr& event
) const
{
if (LogLog::isDebugEnabled())
{
LogString msg{ LOG4CXX_STR("FB: error code ") };
StringHelper::toString(errorCode, msg);
LogLog::debug(msg);
}
LogLog::warn(message, ex);
AppenderPtr primaryLocked = m_priv->primary.lock();
AppenderPtr backupLocked;
if (!m_priv->backup.empty())
{
backupLocked = m_priv->backup.front();
m_priv->backup.pop_front();
}
if ( !primaryLocked || !backupLocked )
{
return;
}
for (auto& item : m_priv->appenderHolders)
{
auto holderLocked = item.second.lock();
if (!holderLocked)
continue;
if (LogLog::isDebugEnabled())
{
LogLog::debug(LOG4CXX_STR("FB: Replacing [")
+ primaryLocked->getName() + LOG4CXX_STR("] with [")
+ backupLocked->getName() + LOG4CXX_STR("] in [")
+ item.first + LOG4CXX_STR("]."));
}
if (!holderLocked->replaceAppender(primaryLocked, backupLocked))
{
LogLog::debug(LOG4CXX_STR("FB: Failed to replace [")
+ primaryLocked->getName() + LOG4CXX_STR("] with [")
+ backupLocked->getName() + LOG4CXX_STR("] in [")
+ item.first + LOG4CXX_STR("]."));
}
}
m_priv->errorReported = true;
if (event)
{
backupLocked->doAppend(event);
}
m_priv->primary = backupLocked;
}
void FallbackErrorHandler::setAppender(const AppenderPtr& primary1)
{
if (LogLog::isDebugEnabled())
{
LogLog::debug(((LogString) LOG4CXX_STR("FB: Setting primary appender to ["))
+ primary1->getName() + LOG4CXX_STR("]."));
}
m_priv->primary = primary1;
}
void FallbackErrorHandler::setBackupAppender(const AppenderPtr& backup1)
{
if (LogLog::isDebugEnabled())
{
LogLog::debug(((LogString) LOG4CXX_STR("FB: Setting backup appender to ["))
+ backup1->getName() + LOG4CXX_STR("]."));
}
m_priv->backup.push_back(backup1);
}
void FallbackErrorHandler::setOption(const LogString& option, const LogString& value)
{
ErrorHandler::setOption(option, value);
}
bool FallbackErrorHandler::errorReported() const
{
return m_priv->errorReported;
}