logproviderimpl.cpp
Go to the documentation of this file.
1 /*
2 ** Author(s):
3 ** - Herve Cuche <hcuche@aldebaran-robotics.com>
4 ** - Matthieu Nottale <mnottale@aldebaran-robotics.com>
5 **
6 ** Copyright (C) 2013 Aldebaran Robotics
7 */
8 
9 // VS2015 fix atomic alignment and require an acknowledgement from developer
10 #include <boost/predef.h>
11 #if BOOST_COMP_MSVC
12 # if (BOOST_COMP_MSVC >= BOOST_VERSION_NUMBER(14, 0, 0))
13 # define _ENABLE_ATOMIC_ALIGNMENT_FIX
14 # endif
15 #endif
16 
17 #include <iostream>
18 
19 #include <boost/lexical_cast.hpp>
20 #include <boost/lockfree/queue.hpp>
21 #include <boost/lambda/algorithm.hpp>
22 
23 #include <qi/application.hpp>
24 #include <qi/anymodule.hpp>
25 #include <qi/anyobject.hpp>
26 #include <qi/type/objecttypebuilder.hpp>
27 #include <qi/os.hpp>
28 #include <qi/getenv.hpp>
29 
30 #include "src/logproviderimpl.hpp"
31 
32 QI_TYPE_INTERFACE(LogProvider);
33 
34 qiLogCategory("log.provider");
35 
36 namespace
37 {
38 const bool debug = (!qi::os::getenv("LOG_DEBUG").empty());
39 #define DEBUG(a) \
40  do \
41  { \
42  if (debug) \
43  std::cerr << a << std::endl; \
44  } while (0)
45 }
46 
47 namespace qi
48 {
49 
50 boost::lockfree::queue<qi::LogMessage*> _pendingMessages(qi::os::getEnvDefault("QI_LOG_MAX_MSGS_BUFFERS", 500));
51 
53 {
54  return boost::shared_ptr<qi::LogProviderImpl>(new LogProviderImpl());
55 }
56 
58 {
59  return boost::shared_ptr<qi::LogProviderImpl>(new LogProviderImpl(logger));
60 }
61 
62 static void removeProviderAtStop(SessionPtr session, int id)
63 {
64  DEBUG("LP removeProviderAtStop " << id);
65  LogManagerPtr lm = session->service("LogManager").value();
66  lm->removeProvider(id);
67 }
68 
69 static bool initialized = false;
70 qi::FutureSync<qi::LogProviderPtr> initializeLogging(SessionPtr session, const std::string& categoryPrefix)
71 {
72  DEBUG("registering new provider");
73  if (initialized)
74  throw std::runtime_error("Provider already registered for this process");
75 
76  LogManagerPtr lm = session->service("LogManager");
77  LogProviderPtr instance = makeLogProvider(lm);
78  if (!categoryPrefix.empty())
79  instance->setCategoryPrefix(categoryPrefix);
80 
81  qi::Future<int> id = lm.async<int>("addProvider", instance);
82  DEBUG("LP registerToLogger " << instance.uid());
83 
84  initialized = true;
85 
86  qi::Application::atStop(boost::bind(removeProviderAtStop, session, id.value()));
87  return id.then(boost::lambda::constant(instance));
88 }
89 
90 
91 static void silenceQiCategories(qi::log::SubscriberId subscriber)
92 {
93  // Safety: avoid infinite loop
94  ::qi::log::addFilter("qitype.*", qi::LogLevel_Silent, subscriber);
95  ::qi::log::addFilter("qimessaging.*", qi::LogLevel_Silent, subscriber);
96  ::qi::log::addFilter("qi.*", qi::LogLevel_Silent, subscriber);
97 }
98 
100  : _logger()
101 {
102  DEBUG("LP subscribed this " << this);
103  _subscriber =
104  qi::log::addHandler("remoteLogger", boost::bind(&LogProviderImpl::log, this, _1, _2, _3, _4, _5, _6, _7, _8));
105 
106  DEBUG("LP subscribed " << _subscriber);
108  ++_ready;
109  sendTask.setName("LogProvider");
110  sendTask.setUsPeriod(100 * 1000); // 100ms
111  sendTask.setCallback(&LogProviderImpl::sendLogs, this);
112  sendTask.start();
113 }
114 
116  : _logger(std::move(logger))
117 {
118  DEBUG("LP subscribed this " << this);
119  _subscriber =
120  qi::log::addHandler("remoteLogger", boost::bind(&LogProviderImpl::log, this, _1, _2, _3, _4, _5, _6, _7, _8));
121 
122  DEBUG("LP subscribed " << _subscriber);
124  ++_ready;
125  sendTask.setName("LogProvider");
126  sendTask.setUsPeriod(100 * 1000); // 100ms
127  sendTask.setCallback(&LogProviderImpl::sendLogs, this);
128  sendTask.start();
129 }
130 
132 {
133  DEBUG("LP ~LogProviderImpl");
134  sendTask.stop();
135  sendLogs();
136  qi::log::removeHandler("remoteLogger");
137 }
138 
140 {
141  _logger = logger;
142 }
143 
145 {
146  if (!_pendingMessages.empty() && _logger)
147  {
148  DEBUG("LP sendLogs");
149  std::vector<qi::LogMessage> msgs;
150  qi::LogMessage* msg;
151  while (_pendingMessages.pop(msg))
152  {
153  msgs.push_back(*msg);
154  delete msg;
155  }
156  try
157  {
158  _logger->log(msgs);
159  }
160  catch (const std::exception& e)
161  {
162  DEBUG(e.what());
163  }
164  }
165 }
166 
167 void LogProviderImpl::log(qi::LogLevel level,
168  const Clock::time_point date,
169  const SystemClock::time_point systemDate,
170  const char* category,
171  const char* message,
172  const char* file,
173  const char* function,
174  int line)
175 {
176  DEBUG("LP log callback: " << message << " " << file << " " << function);
177  if (!_ready.load())
178  return;
179 
180  LogMessage* msg = new LogMessage();
181  std::string source(file);
182  source += ':';
183  source += function;
184  source += ':';
185  source += boost::lexical_cast<std::string>(line);
186  msg->source = source;
187  msg->level = level;
188  msg->date = date;
189  msg->systemDate = systemDate;
190  if (_categoryPrefix.empty())
191  msg->category = category;
192  else
193  msg->category = _categoryPrefix + "." + category;
194  msg->location = qi::os::getMachineId() + ":" + boost::lexical_cast<std::string>(qi::os::getpid());
195  msg->message = message;
196  msg->id = -1;
197 
198  _pendingMessages.push(msg);
199 
200  DEBUG("LP:log done");
201 }
202 
203 void LogProviderImpl::setCategoryPrefix(const std::string& categoryPrefix)
204 {
205  DEBUG("LP setCategoryPrefix " << categoryPrefix);
206  _categoryPrefix = categoryPrefix;
207 }
208 
209 void LogProviderImpl::setLevel(qi::LogLevel level)
210 {
211  DEBUG("LP verb " << level);
212  ::qi::log::setLogLevel(level, _subscriber);
213 }
214 
215 void LogProviderImpl::addFilter(const std::string& filter, qi::LogLevel level)
216 {
217  DEBUG("LP addFilter level: " << level << " cat: " << filter);
218  {
219  boost::mutex::scoped_lock sl(_setCategoriesMutex);
220  _setCategories.insert(filter);
221  }
222  ::qi::log::addFilter(filter, level, _subscriber);
223 }
224 
225 void LogProviderImpl::setFilters(const std::vector<std::pair<std::string, qi::LogLevel> >& filters)
226 {
227  DEBUG("LP setFilters");
228  {
229  boost::mutex::scoped_lock sl(_setCategoriesMutex);
230  for (std::set<std::string>::iterator it = _setCategories.begin(); it != _setCategories.end(); ++it)
231  {
232  if (*it != "*")
233  ::qi::log::addFilter(*it, qi::LogLevel_Debug, _subscriber);
234  }
235 
236  _setCategories.clear();
237  }
238  qi::LogLevel wildcardLevel = qi::LogLevel_Silent;
239  bool wildcardIsSet = false;
240  for (unsigned i = 0; i < filters.size(); ++i)
241  {
242  if (filters[i].first == "*")
243  {
244  wildcardLevel = filters[i].second;
245  wildcardIsSet = true;
246  }
247  else
248  addFilter(filters[i].first, filters[i].second);
249  }
250 
252 
253  if (wildcardIsSet)
254  ::qi::log::addFilter("*", wildcardLevel, _subscriber);
255 }
256 
257 QI_REGISTER_MT_OBJECT(LogProvider, setLevel, addFilter, setFilters, setLogger, setCategoryPrefix);
259 
260 void registerLogProvider(qi::ModuleBuilder* mb)
261 {
262  mb->advertiseFactory<LogProviderImpl, LogManagerPtr>("LogProvider");
263  mb->advertiseMethod("makeLogProvider", static_cast<LogProviderPtr (*)(LogManagerPtr)>(&makeLogProvider));
264  mb->advertiseMethod("makeLogProvider", static_cast<LogProviderPtr (*)()>(&makeLogProvider));
265  mb->advertiseMethod("initializeLogging", &initializeLogging);
266  mb->advertiseMethod("initializeLogging", (boost::function<qi::FutureSync<qi::LogProviderPtr> (SessionPtr)>(boost::bind(&initializeLogging, _1, ""))));
267 }
268 
269 } // !qi
qi::LogProviderImpl::_categoryPrefix
std::string _categoryPrefix
Definition: logproviderimpl.hpp:64
qi::LogProviderImpl::sendTask
qi::PeriodicTask sendTask
Definition: logproviderimpl.hpp:66
qi::LogMessage::message
std::string message
Definition: logmessage.hpp:42
qi::LogProviderImpl::setLevel
void setLevel(qi::LogLevel level) override
Definition: logproviderimpl.cpp:209
qi::LogManagerPtr
qi::Object< LogManager > LogManagerPtr
Definition: logmanager.hpp:42
qi::LogProviderImpl::_logger
LogManagerPtr _logger
Definition: logproviderimpl.hpp:61
qi::LogMessage
Definition: logmessage.hpp:36
qi::removeProviderAtStop
static void removeProviderAtStop(SessionPtr session, int id)
Definition: logproviderimpl.cpp:62
qi::QI_REGISTER_IMPLEMENTATION
QI_REGISTER_IMPLEMENTATION(LogProvider, LogProviderImpl)
imagestore.session
session
Definition: imagestore.py:68
qi::_pendingMessages
boost::lockfree::queue< qi::LogMessage * > _pendingMessages(qi::os::getEnvDefault("QI_LOG_MAX_MSGS_BUFFERS", 500))
qi::LogProviderImpl::sendLogs
void sendLogs()
Definition: logproviderimpl.cpp:144
qi::initialized
static bool initialized
Definition: logproviderimpl.cpp:69
qi::LogMessage::id
unsigned int id
Definition: logmessage.hpp:43
qi::LogProviderImpl::_setCategoriesMutex
boost::mutex _setCategoriesMutex
Definition: logproviderimpl.hpp:60
qi::LogMessage::location
std::string location
Definition: logmessage.hpp:41
DEBUG
#define DEBUG(a)
Definition: logproviderimpl.cpp:39
qi::LogProviderImpl::setCategoryPrefix
void setCategoryPrefix(const std::string &categoryPrefix) override
Definition: logproviderimpl.cpp:203
qi::LogMessage::source
std::string source
Definition: logmessage.hpp:38
qi::QI_REGISTER_MT_OBJECT
QI_REGISTER_MT_OBJECT(LogProvider, setLevel, addFilter, setFilters, setLogger, setCategoryPrefix)
qi::silenceQiCategories
static void silenceQiCategories(qi::log::SubscriberId subscriber)
Definition: logproviderimpl.cpp:91
qi::initializeLogging
QICORE_API qi::FutureSync< qi::LogProviderPtr > initializeLogging(SessionPtr session, const std::string &categoryPrefix="")
Definition: logproviderimpl.cpp:70
qi::LogProviderImpl::_setCategories
std::set< std::string > _setCategories
Definition: logproviderimpl.hpp:59
QI_TYPE_INTERFACE
QI_TYPE_INTERFACE(LogProvider)
qi
Definition: file.hpp:21
qiLogCategory
qiLogCategory("log.provider")
qi::LogMessage::systemDate
qi::SystemClock::time_point systemDate
Definition: logmessage.hpp:45
qi::LogProvider
Definition: logprovider.hpp:34
qi::makeLogProvider
QICORE_API LogProviderPtr makeLogProvider(LogManagerPtr logger)
Definition: logproviderimpl.cpp:57
qi::LogProviderImpl::log
void log(qi::LogLevel level, const qi::Clock::time_point date, const qi::SystemClock::time_point systemDate, const char *category, const char *message, const char *file, const char *function, int line)
Definition: logproviderimpl.cpp:167
qi::LogProviderImpl::_subscriber
qi::log::SubscriberId _subscriber
Definition: logproviderimpl.hpp:62
qi::LogProviderImpl::setLogger
void setLogger(LogManagerPtr logger) override
Definition: logproviderimpl.cpp:139
logproviderimpl.hpp
qi::LogProviderImpl::LogProviderImpl
LogProviderImpl()
Definition: logproviderimpl.cpp:99
qi::LogProviderImpl::_ready
qi::Atomic< int > _ready
Definition: logproviderimpl.hpp:63
qi::LogMessage::level
qi::LogLevel level
Definition: logmessage.hpp:39
qi::LogProviderImpl::setFilters
void setFilters(const std::vector< std::pair< std::string, qi::LogLevel > > &filters) override
Definition: logproviderimpl.cpp:225
qi::LogProviderImpl::addFilter
void addFilter(const std::string &filter, qi::LogLevel level) override
Definition: logproviderimpl.cpp:215
qi::LogMessage::date
qi::Clock::time_point date
Definition: logmessage.hpp:44
qi::LogProviderImpl::~LogProviderImpl
~LogProviderImpl() override
Definition: logproviderimpl.cpp:131
qi::registerLogProvider
void registerLogProvider(qi::ModuleBuilder *mb)
Definition: logproviderimpl.cpp:260
qi::LogProviderImpl
Definition: logproviderimpl.hpp:34
qi::LogMessage::category
std::string category
Definition: logmessage.hpp:40
qi::LogProviderPtr
qi::Object< LogProvider > LogProviderPtr
Definition: logmanager.hpp:23


naoqi_libqicore
Author(s): Aldebaran
autogenerated on Wed Sep 14 2022 02:22:41