pion  5.0.6
services/LogService.cpp
00001 // ---------------------------------------------------------------------
00002 // pion:  a Boost C++ framework for building lightweight HTTP interfaces
00003 // ---------------------------------------------------------------------
00004 // Copyright (C) 2007-2014 Splunk Inc.  (https://github.com/splunk/pion)
00005 //
00006 // Distributed under the Boost Software License, Version 1.0.
00007 // See http://www.boost.org/LICENSE_1_0.txt
00008 //
00009 
00010 #include "LogService.hpp"
00011 
00012 #if defined(PION_USE_LOG4CXX)
00013     #include <log4cxx/spi/loggingevent.h>
00014     #include <boost/lexical_cast.hpp>
00015 #elif defined(PION_USE_LOG4CPLUS)
00016     #include <log4cplus/spi/loggingevent.h>
00017     #include <boost/lexical_cast.hpp>
00018 #elif defined(PION_USE_LOG4CPP)
00019     #include <log4cpp/BasicLayout.hh>
00020 #endif
00021 
00022 #include <pion/http/response_writer.hpp>
00023 
00024 using namespace pion;
00025 using namespace log4cplus::helpers;
00026 
00027 namespace pion {        // begin namespace pion
00028 namespace plugins {     // begin namespace plugins
00029 
00030 
00031 // static members of LogServiceAppender
00032 
00033 const unsigned int      LogServiceAppender::DEFAULT_MAX_EVENTS = 25;
00034 
00035 
00036 // LogServiceAppender member functions
00037 
00038 #if defined(PION_USE_LOG4CPP)
00039 LogServiceAppender::LogServiceAppender(void)
00040     : log4cpp::AppenderSkeleton("LogServiceAppender"),
00041     m_max_events(DEFAULT_MAX_EVENTS), m_num_events(0),
00042     m_layout_ptr(new log4cpp::BasicLayout())
00043     {}
00044 #else
00045 LogServiceAppender::LogServiceAppender(void)
00046     : m_max_events(DEFAULT_MAX_EVENTS), m_num_events(0)
00047     {}
00048 #endif
00049 
00050 LogServiceAppender::~LogServiceAppender()
00051 {
00052 #if defined(PION_USE_LOG4CPLUS)
00053     destructorImpl();
00054 #endif
00055 }
00056 
00057 
00058 #if defined(PION_USE_LOG4CXX)
00059 void LogServiceAppender::append(const log4cxx::spi::LoggingEventPtr& event)
00060 {
00061     // custom layouts is not supported for log4cxx library
00062     std::string formatted_string(boost::lexical_cast<std::string>(event->getTimeStamp()));
00063     formatted_string += ' ';
00064     formatted_string += event->getLevel()->toString();
00065     formatted_string += ' ';
00066     formatted_string += event->getLoggerName();
00067     formatted_string += " - ";
00068     formatted_string += event->getRenderedMessage();
00069     formatted_string += '\n';
00070     addLogString(formatted_string);
00071 }
00072 #elif defined(PION_USE_LOG4CPLUS)
00073 void LogServiceAppender::append(const log4cplus::spi::InternalLoggingEvent& event)
00074 {
00075     // custom layouts is not supported for log4cplus library
00076     //std::string formatted_string(boost::lexical_cast<std::string>(event.getTimestamp().sec()));
00077         time_t tt = log4cplus::helpers::to_time_t(event.getTimestamp());
00078         tm* tmm = gmtime(&tt);
00079         std::string formatted_string(boost::lexical_cast<std::string>(tmm->tm_sec));
00080     formatted_string += ' ';
00081     formatted_string += m_log_level_manager.toString(event.getLogLevel());
00082     formatted_string += ' ';
00083     formatted_string += event.getLoggerName();
00084     formatted_string += " - ";
00085     formatted_string += event.getMessage();
00086     formatted_string += '\n';
00087     addLogString(formatted_string);
00088 }
00089 #elif defined(PION_USE_LOG4CPP)
00090 void LogServiceAppender::_append(const log4cpp::LoggingEvent& event)
00091 {
00092     std::string formatted_string(m_layout_ptr->format(event));
00093     addLogString(formatted_string);
00094 }
00095 #endif
00096 
00097 void LogServiceAppender::addLogString(const std::string& log_string)
00098 {
00099     boost::mutex::scoped_lock log_lock(m_log_mutex);
00100     m_log_events.push_back(log_string);
00101     ++m_num_events;
00102     while (m_num_events > m_max_events) {
00103         m_log_events.erase(m_log_events.begin());
00104         --m_num_events;
00105     }
00106 }
00107 
00108 void LogServiceAppender::writeLogEvents(pion::http::response_writer_ptr& writer)
00109 {
00110 #if defined(PION_USE_LOG4CXX) || defined(PION_USE_LOG4CPLUS) || defined(PION_USE_LOG4CPP)
00111     boost::mutex::scoped_lock log_lock(m_log_mutex);
00112     for (std::list<std::string>::const_iterator i = m_log_events.begin();
00113          i != m_log_events.end(); ++i)
00114     {
00115         writer << *i;
00116     }
00117 #elif defined(PION_DISABLE_LOGGING)
00118     writer << "Logging is disabled." << http::types::STRING_CRLF;
00119 #else
00120     writer << "Using ostream logging." << http::types::STRING_CRLF;
00121 #endif
00122 }
00123 
00124 
00125 // LogService member functions
00126 
00127 LogService::LogService(void)
00128     : m_log_appender_ptr(new LogServiceAppender())
00129 {
00130 #if defined(PION_USE_LOG4CXX)
00131     m_log_appender_ptr->setName("LogServiceAppender");
00132     log4cxx::Logger::getRootLogger()->addAppender(m_log_appender_ptr);
00133 #elif defined(PION_USE_LOG4CPLUS)
00134     m_log_appender_ptr->setName("LogServiceAppender");
00135     log4cplus::Logger::getRoot().addAppender(m_log_appender_ptr);
00136 #elif defined(PION_USE_LOG4CPP)
00137     log4cpp::Category::getRoot().addAppender(m_log_appender_ptr);
00138 #endif
00139 }
00140 
00141 LogService::~LogService()
00142 {
00143 #if defined(PION_USE_LOG4CXX)
00144     // removeAppender() also deletes the object
00145     log4cxx::Logger::getRootLogger()->removeAppender(m_log_appender_ptr);
00146 #elif defined(PION_USE_LOG4CPLUS)
00147     // removeAppender() also deletes the object
00148     log4cplus::Logger::getRoot().removeAppender("LogServiceAppender");
00149 #elif defined(PION_USE_LOG4CPP)
00150     // removeAppender() also deletes the object
00151     log4cpp::Category::getRoot().removeAppender(m_log_appender_ptr);
00152 #else
00153     delete m_log_appender_ptr;
00154 #endif
00155 }
00156 
00158 void LogService::operator()(http::request_ptr& http_request_ptr, tcp::connection_ptr& tcp_conn)
00159 {
00160     // Set Content-type to "text/plain" (plain ascii text)
00161     http::response_writer_ptr writer(http::response_writer::create(tcp_conn, *http_request_ptr,
00162                                                                    boost::bind(&tcp::connection::finish, tcp_conn)));
00163     writer->get_response().set_content_type(http::types::CONTENT_TYPE_TEXT);
00164     getLogAppender().writeLogEvents(writer);
00165     writer->send();
00166 }
00167 
00168 
00169 }   // end namespace plugins
00170 }   // end namespace pion
00171 
00172 
00174 extern "C" PION_PLUGIN pion::plugins::LogService *pion_create_LogService(void)
00175 {
00176     return new pion::plugins::LogService();
00177 }
00178 
00180 extern "C" PION_PLUGIN void pion_destroy_LogService(pion::plugins::LogService *service_ptr)
00181 {
00182     delete service_ptr;
00183 }