summaryrefslogtreecommitdiffstats
path: root/src/lib/log/buffer_appender_impl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/log/buffer_appender_impl.cc')
-rw-r--r--src/lib/log/buffer_appender_impl.cc96
1 files changed, 96 insertions, 0 deletions
diff --git a/src/lib/log/buffer_appender_impl.cc b/src/lib/log/buffer_appender_impl.cc
new file mode 100644
index 0000000..6ce8d40
--- /dev/null
+++ b/src/lib/log/buffer_appender_impl.cc
@@ -0,0 +1,96 @@
+// Copyright (C) 2012-2016 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <log/buffer_appender_impl.h>
+
+#include <log4cplus/loglevel.h>
+#include <log4cplus/version.h>
+#include <boost/scoped_ptr.hpp>
+#include <cstdio>
+
+namespace isc {
+namespace log {
+namespace internal {
+
+BufferAppender::~BufferAppender() {
+ // If there is anything left in the buffer,
+ // it means no reconfig has been done, and
+ // we can assume the logging system was either
+ // never setup, or broke while doing so.
+ // So dump all that is left to stdout
+ try {
+ flushStdout();
+ destructorImpl();
+ } catch (...) {
+ // Ok if we can't even seem to dump to stdout, never mind.
+ }
+}
+
+void
+BufferAppender::flushStdout() {
+ // This does not show a bit of information normal log messages
+ // do, so perhaps we should try and setup a new logger here
+ // However, as this is called from a destructor, it may not
+ // be a good idea; as we can't reliably know whether in what
+ // state the logger instance is now (or what the specific logger's
+ // settings were).
+ LogEventList::const_iterator it;
+ for (it = stored_.begin(); it != stored_.end(); ++it) {
+ const std::string level(it->first);
+ LogEventPtr event(it->second);
+ std::printf("%s [%s]: %s\n", level.c_str(),
+ event->getLoggerName().c_str(),
+ event->getMessage().c_str());
+ }
+ stored_.clear();
+}
+
+void
+BufferAppender::flush() {
+ LogEventList stored_copy;
+ stored_.swap(stored_copy);
+
+ LogEventList::const_iterator it;
+ for (it = stored_copy.begin(); it != stored_copy.end(); ++it) {
+ LogEventPtr event(it->second);
+ log4cplus::Logger logger =
+ log4cplus::Logger::getInstance(event->getLoggerName());
+
+ logger.log(event->getLogLevel(), event->getMessage());
+ }
+ flushed_ = true;
+}
+
+size_t
+BufferAppender::getBufferSize() const {
+ return (stored_.size());
+}
+
+void
+BufferAppender::append(const log4cplus::spi::InternalLoggingEvent& event) {
+ if (flushed_) {
+ isc_throw(LogBufferAddAfterFlush,
+ "Internal log buffer has been flushed already");
+ }
+ // get a clone, and put the pointer in a shared_ptr in the list
+#if LOG4CPLUS_VERSION < LOG4CPLUS_MAKE_VERSION(2, 0, 0)
+ std::auto_ptr<log4cplus::spi::InternalLoggingEvent>
+#else
+ std::unique_ptr<log4cplus::spi::InternalLoggingEvent>
+#endif
+ event_aptr = event.clone();
+ // Also store the string representation of the log level, to be
+ // used in flushStdout if necessary
+ stored_.push_back(LevelAndEvent(
+ log4cplus::LogLevelManager().toString(event.getLogLevel()),
+ LogEventPtr(event_aptr.release())));
+}
+
+} // end namespace internal
+} // end namespace log
+} // end namespace isc