pion-net  4.0.9
LogService.cpp
1 // ------------------------------------------------------------------
2 // pion-net: a C++ framework for building lightweight HTTP interfaces
3 // ------------------------------------------------------------------
4 // Copyright (C) 2007-2008 Atomic Labs, Inc. (http://www.atomiclabs.com)
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/net/HTTPResponseWriter.hpp>
23 
24 using namespace pion;
25 using namespace pion::net;
26 
27 namespace pion { // begin namespace pion
28 namespace plugins { // begin namespace plugins
29 
30 
31 // static members of LogServiceAppender
32 
33 const unsigned int LogServiceAppender::DEFAULT_MAX_EVENTS = 25;
34 
35 
36 // LogServiceAppender member functions
37 
38 #if defined(PION_USE_LOG4CPP)
39 LogServiceAppender::LogServiceAppender(void)
40  : log4cpp::AppenderSkeleton("LogServiceAppender"),
41  m_max_events(DEFAULT_MAX_EVENTS), m_num_events(0),
42  m_layout_ptr(new log4cpp::BasicLayout())
43  {}
44 #else
45 LogServiceAppender::LogServiceAppender(void)
46  : m_max_events(DEFAULT_MAX_EVENTS), m_num_events(0)
47  {}
48 #endif
49 
50 
51 #if defined(PION_USE_LOG4CXX)
52 void LogServiceAppender::append(const log4cxx::spi::LoggingEventPtr& event)
53 {
54  // custom layouts is not supported for log4cxx library
55  std::string formatted_string(boost::lexical_cast<std::string>(event->getTimeStamp()));
56  formatted_string += ' ';
57  formatted_string += event->getLevel()->toString();
58  formatted_string += ' ';
59  formatted_string += event->getLoggerName();
60  formatted_string += " - ";
61  formatted_string += event->getRenderedMessage();
62  formatted_string += '\n';
63  addLogString(formatted_string);
64 }
65 #elif defined(PION_USE_LOG4CPLUS)
66 void LogServiceAppender::append(const log4cplus::spi::InternalLoggingEvent& event)
67 {
68  // custom layouts is not supported for log4cplus library
69  std::string formatted_string(boost::lexical_cast<std::string>(event.getTimestamp().sec()));
70  formatted_string += ' ';
71  formatted_string += m_log_level_manager.toString(event.getLogLevel());
72  formatted_string += ' ';
73  formatted_string += event.getLoggerName();
74  formatted_string += " - ";
75  formatted_string += event.getMessage();
76  formatted_string += '\n';
77  addLogString(formatted_string);
78 }
79 #elif defined(PION_USE_LOG4CPP)
80 void LogServiceAppender::_append(const log4cpp::LoggingEvent& event)
81 {
82  std::string formatted_string(m_layout_ptr->format(event));
83  addLogString(formatted_string);
84 }
85 #endif
86 
87 void LogServiceAppender::addLogString(const std::string& log_string)
88 {
89  boost::mutex::scoped_lock log_lock(m_log_mutex);
90  m_log_events.push_back(log_string);
91  ++m_num_events;
92  while (m_num_events > m_max_events) {
93  m_log_events.erase(m_log_events.begin());
94  --m_num_events;
95  }
96 }
97 
98 void LogServiceAppender::writeLogEvents(pion::net::HTTPResponseWriterPtr& writer)
99 {
100 #if defined(PION_USE_LOG4CXX) || defined(PION_USE_LOG4CPLUS) || defined(PION_USE_LOG4CPP)
101  boost::mutex::scoped_lock log_lock(m_log_mutex);
102  for (std::list<std::string>::const_iterator i = m_log_events.begin();
103  i != m_log_events.end(); ++i)
104  {
105  writer << *i;
106  }
107 #elif defined(PION_DISABLE_LOGGING)
108  writer << "Logging is disabled." << HTTPTypes::STRING_CRLF;
109 #else
110  writer << "Using ostream logging." << HTTPTypes::STRING_CRLF;
111 #endif
112 }
113 
114 
115 // LogService member functions
116 
117 LogService::LogService(void)
118  : m_log_appender_ptr(new LogServiceAppender())
119 {
120 #if defined(PION_USE_LOG4CXX)
121  m_log_appender_ptr->setName("LogServiceAppender");
122  log4cxx::Logger::getRootLogger()->addAppender(m_log_appender_ptr);
123 #elif defined(PION_USE_LOG4CPLUS)
124  m_log_appender_ptr->setName("LogServiceAppender");
125  log4cplus::Logger::getRoot().addAppender(m_log_appender_ptr);
126 #elif defined(PION_USE_LOG4CPP)
127  log4cpp::Category::getRoot().addAppender(m_log_appender_ptr);
128 #endif
129 }
130 
131 LogService::~LogService()
132 {
133 #if defined(PION_USE_LOG4CXX)
134  // removeAppender() also deletes the object
135  log4cxx::Logger::getRootLogger()->removeAppender(m_log_appender_ptr);
136 #elif defined(PION_USE_LOG4CPLUS)
137  // removeAppender() also deletes the object
138  log4cplus::Logger::getRoot().removeAppender("LogServiceAppender");
139 #elif defined(PION_USE_LOG4CPP)
140  // removeAppender() also deletes the object
141  log4cpp::Category::getRoot().removeAppender(m_log_appender_ptr);
142 #else
143  delete m_log_appender_ptr;
144 #endif
145 }
146 
148 void LogService::operator()(HTTPRequestPtr& request, TCPConnectionPtr& tcp_conn)
149 {
150  // Set Content-type to "text/plain" (plain ascii text)
151  HTTPResponseWriterPtr writer(HTTPResponseWriter::create(tcp_conn, *request,
152  boost::bind(&TCPConnection::finish, tcp_conn)));
153  writer->getResponse().setContentType(HTTPTypes::CONTENT_TYPE_TEXT);
154  getLogAppender().writeLogEvents(writer);
155  writer->send();
156 }
157 
158 
159 } // end namespace plugins
160 } // end namespace pion
161 
162 
164 extern "C" PION_SERVICE_API pion::plugins::LogService *pion_create_LogService(void)
165 {
166  return new pion::plugins::LogService();
167 }
168 
170 extern "C" PION_SERVICE_API void pion_destroy_LogService(pion::plugins::LogService *service_ptr)
171 {
172  delete service_ptr;
173 }
virtual void operator()(pion::net::HTTPRequestPtr &request, pion::net::TCPConnectionPtr &tcp_conn)
handles a new HTTP request
Definition: LogService.cpp:148
LogServiceAppender & getLogAppender(void)
returns the log appender used by LogService
Definition: LogService.hpp:134
the following enables use of the lock-free cache
void writeLogEvents(pion::net::HTTPResponseWriterPtr &writer)
writes the events cached in memory to a response stream
Definition: LogService.cpp:98
void addLogString(const std::string &log_string)
adds a formatted log message to the memory cache
Definition: LogService.cpp:87