pion  5.0.6
LogService.cpp
1 // ---------------------------------------------------------------------
2 // pion: a Boost C++ framework for building lightweight HTTP interfaces
3 // ---------------------------------------------------------------------
4 // Copyright (C) 2007-2014 Splunk Inc. (https://github.com/splunk/pion)
5 //
6 // Distributed under the Boost Software License, Version 1.0.
7 // See http://www.boost.org/LICENSE_1_0.txt
8 //
9 
10 #include "LogService.hpp"
11 
12 #if defined(PION_USE_LOG4CXX)
13  #include <log4cxx/spi/loggingevent.h>
14  #include <boost/lexical_cast.hpp>
15 #elif defined(PION_USE_LOG4CPLUS)
16  #include <log4cplus/spi/loggingevent.h>
17  #include <boost/lexical_cast.hpp>
18 #elif defined(PION_USE_LOG4CPP)
19  #include <log4cpp/BasicLayout.hh>
20 #endif
21 
22 #include <pion/http/response_writer.hpp>
23 
24 using namespace pion;
25 
26 namespace pion { // begin namespace pion
27 namespace plugins { // begin namespace plugins
28 
29 
30 // static members of LogServiceAppender
31 
32 const unsigned int LogServiceAppender::DEFAULT_MAX_EVENTS = 25;
33 
34 
35 // LogServiceAppender member functions
36 
37 #if defined(PION_USE_LOG4CPP)
38 LogServiceAppender::LogServiceAppender(void)
39  : log4cpp::AppenderSkeleton("LogServiceAppender"),
40  m_max_events(DEFAULT_MAX_EVENTS), m_num_events(0),
41  m_layout_ptr(new log4cpp::BasicLayout())
42  {}
43 #else
44 LogServiceAppender::LogServiceAppender(void)
45  : m_max_events(DEFAULT_MAX_EVENTS), m_num_events(0)
46  {}
47 #endif
48 
49 
50 #if defined(PION_USE_LOG4CXX)
51 void LogServiceAppender::append(const log4cxx::spi::LoggingEventPtr& event)
52 {
53  // custom layouts is not supported for log4cxx library
54  std::string formatted_string(boost::lexical_cast<std::string>(event->getTimeStamp()));
55  formatted_string += ' ';
56  formatted_string += event->getLevel()->toString();
57  formatted_string += ' ';
58  formatted_string += event->getLoggerName();
59  formatted_string += " - ";
60  formatted_string += event->getRenderedMessage();
61  formatted_string += '\n';
62  addLogString(formatted_string);
63 }
64 #elif defined(PION_USE_LOG4CPLUS)
65 void LogServiceAppender::append(const log4cplus::spi::InternalLoggingEvent& event)
66 {
67  // custom layouts is not supported for log4cplus library
68  std::string formatted_string(boost::lexical_cast<std::string>(event.getTimestamp().sec()));
69  formatted_string += ' ';
70  formatted_string += m_log_level_manager.toString(event.getLogLevel());
71  formatted_string += ' ';
72  formatted_string += event.getLoggerName();
73  formatted_string += " - ";
74  formatted_string += event.getMessage();
75  formatted_string += '\n';
76  addLogString(formatted_string);
77 }
78 #elif defined(PION_USE_LOG4CPP)
79 void LogServiceAppender::_append(const log4cpp::LoggingEvent& event)
80 {
81  std::string formatted_string(m_layout_ptr->format(event));
82  addLogString(formatted_string);
83 }
84 #endif
85 
86 void LogServiceAppender::addLogString(const std::string& log_string)
87 {
88  boost::mutex::scoped_lock log_lock(m_log_mutex);
89  m_log_events.push_back(log_string);
90  ++m_num_events;
91  while (m_num_events > m_max_events) {
92  m_log_events.erase(m_log_events.begin());
93  --m_num_events;
94  }
95 }
96 
97 void LogServiceAppender::writeLogEvents(pion::http::response_writer_ptr& writer)
98 {
99 #if defined(PION_USE_LOG4CXX) || defined(PION_USE_LOG4CPLUS) || defined(PION_USE_LOG4CPP)
100  boost::mutex::scoped_lock log_lock(m_log_mutex);
101  for (std::list<std::string>::const_iterator i = m_log_events.begin();
102  i != m_log_events.end(); ++i)
103  {
104  writer << *i;
105  }
106 #elif defined(PION_DISABLE_LOGGING)
107  writer << "Logging is disabled." << http::types::STRING_CRLF;
108 #else
109  writer << "Using ostream logging." << http::types::STRING_CRLF;
110 #endif
111 }
112 
113 
114 // LogService member functions
115 
116 LogService::LogService(void)
117  : m_log_appender_ptr(new LogServiceAppender())
118 {
119 #if defined(PION_USE_LOG4CXX)
120  m_log_appender_ptr->setName("LogServiceAppender");
121  log4cxx::Logger::getRootLogger()->addAppender(m_log_appender_ptr);
122 #elif defined(PION_USE_LOG4CPLUS)
123  m_log_appender_ptr->setName("LogServiceAppender");
124  log4cplus::Logger::getRoot().addAppender(m_log_appender_ptr);
125 #elif defined(PION_USE_LOG4CPP)
126  log4cpp::Category::getRoot().addAppender(m_log_appender_ptr);
127 #endif
128 }
129 
130 LogService::~LogService()
131 {
132 #if defined(PION_USE_LOG4CXX)
133  // removeAppender() also deletes the object
134  log4cxx::Logger::getRootLogger()->removeAppender(m_log_appender_ptr);
135 #elif defined(PION_USE_LOG4CPLUS)
136  // removeAppender() also deletes the object
137  log4cplus::Logger::getRoot().removeAppender("LogServiceAppender");
138 #elif defined(PION_USE_LOG4CPP)
139  // removeAppender() also deletes the object
140  log4cpp::Category::getRoot().removeAppender(m_log_appender_ptr);
141 #else
142  delete m_log_appender_ptr;
143 #endif
144 }
145 
147 void LogService::operator()(http::request_ptr& http_request_ptr, tcp::connection_ptr& tcp_conn)
148 {
149  // Set Content-type to "text/plain" (plain ascii text)
150  http::response_writer_ptr writer(http::response_writer::create(tcp_conn, *http_request_ptr,
151  boost::bind(&tcp::connection::finish, tcp_conn)));
152  writer->get_response().set_content_type(http::types::CONTENT_TYPE_TEXT);
153  getLogAppender().writeLogEvents(writer);
154  writer->send();
155 }
156 
157 
158 } // end namespace plugins
159 } // end namespace pion
160 
161 
163 extern "C" PION_PLUGIN pion::plugins::LogService *pion_create_LogService(void)
164 {
165  return new pion::plugins::LogService();
166 }
167 
169 extern "C" PION_PLUGIN void pion_destroy_LogService(pion::plugins::LogService *service_ptr)
170 {
171  delete service_ptr;
172 }
void writeLogEvents(pion::http::response_writer_ptr &writer)
writes the events cached in memory to a response stream
Definition: LogService.cpp:97
virtual void operator()(pion::http::request_ptr &http_request_ptr, pion::tcp::connection_ptr &tcp_conn)
handles a new HTTP request
Definition: LogService.cpp:147
LogServiceAppender & getLogAppender(void)
returns the log appender used by LogService
Definition: LogService.hpp:134
static boost::shared_ptr< response_writer > create(tcp::connection_ptr &tcp_conn, http::response_ptr &http_response_ptr, finished_handler_t handler=finished_handler_t())
void addLogString(const std::string &log_string)
adds a formatted log message to the memory cache
Definition: LogService.cpp:86