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 LogServiceAppender::~LogServiceAppender()
50 {
51 #if defined(PION_USE_LOG4CPLUS)
52  destructorImpl();
53 #endif
54 }
55 
56 
57 #if defined(PION_USE_LOG4CXX)
58 void LogServiceAppender::append(const log4cxx::spi::LoggingEventPtr& event)
59 {
60  // custom layouts is not supported for log4cxx library
61  std::string formatted_string(boost::lexical_cast<std::string>(event->getTimeStamp()));
62  formatted_string += ' ';
63  formatted_string += event->getLevel()->toString();
64  formatted_string += ' ';
65  formatted_string += event->getLoggerName();
66  formatted_string += " - ";
67  formatted_string += event->getRenderedMessage();
68  formatted_string += '\n';
69  addLogString(formatted_string);
70 }
71 #elif defined(PION_USE_LOG4CPLUS)
72 void LogServiceAppender::append(const log4cplus::spi::InternalLoggingEvent& event)
73 {
74  // custom layouts is not supported for log4cplus library
75  std::string formatted_string(boost::lexical_cast<std::string>(event.getTimestamp().sec()));
76  formatted_string += ' ';
77  formatted_string += m_log_level_manager.toString(event.getLogLevel());
78  formatted_string += ' ';
79  formatted_string += event.getLoggerName();
80  formatted_string += " - ";
81  formatted_string += event.getMessage();
82  formatted_string += '\n';
83  addLogString(formatted_string);
84 }
85 #elif defined(PION_USE_LOG4CPP)
86 void LogServiceAppender::_append(const log4cpp::LoggingEvent& event)
87 {
88  std::string formatted_string(m_layout_ptr->format(event));
89  addLogString(formatted_string);
90 }
91 #endif
92 
93 void LogServiceAppender::addLogString(const std::string& log_string)
94 {
95  boost::mutex::scoped_lock log_lock(m_log_mutex);
96  m_log_events.push_back(log_string);
97  ++m_num_events;
98  while (m_num_events > m_max_events) {
99  m_log_events.erase(m_log_events.begin());
100  --m_num_events;
101  }
102 }
103 
104 void LogServiceAppender::writeLogEvents(const pion::http::response_writer_ptr& writer)
105 {
106 #if defined(PION_USE_LOG4CXX) || defined(PION_USE_LOG4CPLUS) || defined(PION_USE_LOG4CPP)
107  boost::mutex::scoped_lock log_lock(m_log_mutex);
108  for (std::list<std::string>::const_iterator i = m_log_events.begin();
109  i != m_log_events.end(); ++i)
110  {
111  writer << *i;
112  }
113 #elif defined(PION_DISABLE_LOGGING)
114  writer << "Logging is disabled." << http::types::STRING_CRLF;
115 #else
116  writer << "Using ostream logging." << http::types::STRING_CRLF;
117 #endif
118 }
119 
120 
121 // LogService member functions
122 
123 LogService::LogService(void)
124  : m_log_appender_ptr(new LogServiceAppender())
125 {
126 #if defined(PION_USE_LOG4CXX)
127  m_log_appender_ptr->setName("LogServiceAppender");
128  log4cxx::Logger::getRootLogger()->addAppender(m_log_appender_ptr);
129 #elif defined(PION_USE_LOG4CPLUS)
130  m_log_appender_ptr->setName("LogServiceAppender");
131  log4cplus::Logger::getRoot().addAppender(m_log_appender_ptr);
132 #elif defined(PION_USE_LOG4CPP)
133  log4cpp::Category::getRoot().addAppender(m_log_appender_ptr);
134 #endif
135 }
136 
137 LogService::~LogService()
138 {
139 #if defined(PION_USE_LOG4CXX)
140  // removeAppender() also deletes the object
141  log4cxx::Logger::getRootLogger()->removeAppender(m_log_appender_ptr);
142 #elif defined(PION_USE_LOG4CPLUS)
143  // removeAppender() also deletes the object
144  log4cplus::Logger::getRoot().removeAppender("LogServiceAppender");
145 #elif defined(PION_USE_LOG4CPP)
146  // removeAppender() also deletes the object
147  log4cpp::Category::getRoot().removeAppender(m_log_appender_ptr);
148 #else
149  delete m_log_appender_ptr;
150 #endif
151 }
152 
154 void LogService::operator()(const http::request_ptr& http_request_ptr, const tcp::connection_ptr& tcp_conn)
155 {
156  // Set Content-type to "text/plain" (plain ascii text)
157  http::response_writer_ptr writer(http::response_writer::create(tcp_conn, *http_request_ptr,
158  boost::bind(&tcp::connection::finish, tcp_conn)));
159  writer->get_response().set_content_type(http::types::CONTENT_TYPE_TEXT);
160  getLogAppender().writeLogEvents(writer);
161  writer->send();
162 }
163 
164 
165 } // end namespace plugins
166 } // end namespace pion
167 
168 
170 extern "C" PION_PLUGIN pion::plugins::LogService *pion_create_LogService(void)
171 {
172  return new pion::plugins::LogService();
173 }
174 
176 extern "C" PION_PLUGIN void pion_destroy_LogService(pion::plugins::LogService *service_ptr)
177 {
178  delete service_ptr;
179 }
static boost::shared_ptr< response_writer > create(const tcp::connection_ptr &tcp_conn, const http::response_ptr &http_response_ptr, finished_handler_t handler=finished_handler_t())
void writeLogEvents(const pion::http::response_writer_ptr &writer)
writes the events cached in memory to a response stream
Definition: LogService.cpp:104
virtual void operator()(const pion::http::request_ptr &http_request_ptr, const pion::tcp::connection_ptr &tcp_conn)
handles a new HTTP request
Definition: LogService.cpp:154
void addLogString(const std::string &log_string)
adds a formatted log message to the memory cache
Definition: LogService.cpp:93