logger.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. /******************************************************************************
  2. *
  3. * package: Log4Qt
  4. * file: logger.cpp
  5. * created: September 2007
  6. * author: Martin Heinrich
  7. *
  8. *
  9. * changes: Sep 2008, Martin Heinrich:
  10. * - Fixed problem in Qt 4.4 where QReadWriteLock is by default
  11. * non-recursive.
  12. *
  13. *
  14. * Copyright 2007 - 2008 Martin Heinrich
  15. *
  16. * Licensed under the Apache License, Version 2.0 (the "License");
  17. * you may not use this file except in compliance with the License.
  18. * You may obtain a copy of the License at
  19. *
  20. * http://www.apache.org/licenses/LICENSE-2.0
  21. *
  22. * Unless required by applicable law or agreed to in writing, software
  23. * distributed under the License is distributed on an "AS IS" BASIS,
  24. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  25. * See the License for the specific language governing permissions and
  26. * limitations under the License.
  27. *
  28. ******************************************************************************/
  29. /******************************************************************************
  30. * Dependencies
  31. ******************************************************************************/
  32. #include "log4qt/logger.h"
  33. #include <QtCore/QDebug>
  34. #include "log4qt/appenderskeleton.h"
  35. #include "log4qt/varia/listappender.h"
  36. #include "log4qt/loggingevent.h"
  37. #include "log4qt/log4qt.h"
  38. #include "log4qt/loggerrepository.h"
  39. #include "log4qt/logmanager.h"
  40. namespace Log4Qt
  41. {
  42. /**************************************************************************
  43. * Declarations
  44. **************************************************************************/
  45. /**************************************************************************
  46. * C helper functions
  47. **************************************************************************/
  48. /**************************************************************************
  49. * Class implementation: Logger
  50. **************************************************************************/
  51. Logger::Logger(LoggerRepository* pLoggerRepository, Level level, const QString &rName, Logger *pParent) :
  52. QObject(0),
  53. #if QT_VERSION < QT_VERSION_CHECK(4, 4, 0)
  54. mObjectGuard(),
  55. #else
  56. mObjectGuard(QReadWriteLock::Recursive),
  57. #endif
  58. mName(rName),
  59. mpLoggerRepository(pLoggerRepository),
  60. mAdditivity(true),
  61. mAppenders(),
  62. mLevel(level),
  63. mpParent(pParent)
  64. {
  65. Q_ASSERT_X(pLoggerRepository, "Logger::Logger()", "Construction of Logger with null LoggerRepository");
  66. setObjectName(mName);
  67. }
  68. Logger::~Logger()
  69. {
  70. logger()->warn("Unexpected destruction of Logger");
  71. // QWriteLocker locker(&mObjectGuard);
  72. //
  73. // QMutableListIterator< LogObjectPtr<Appender> > i(mAppenders);
  74. // while (i.hasNext())
  75. // {
  76. // i.next();
  77. // i.remove();
  78. // }
  79. }
  80. QList<Appender *> Logger::appenders() const
  81. {
  82. QReadLocker locker(&mObjectGuard);
  83. QList<Appender *> result;
  84. Appender *p_appender;
  85. Q_FOREACH(p_appender, mAppenders)
  86. result << p_appender;
  87. return result;
  88. }
  89. void Logger::setLevel(Level level)
  90. {
  91. // QWriteLocker locker(&mObjectGuard); // Read/Write int is safe
  92. if ((parentLogger() == 0) && (level == Level::NULL_INT))
  93. {
  94. logger()->warn("Invalid root logger level NULL_INT. Using DEBUG_INT instead");
  95. level = Level::DEBUG_INT;
  96. }
  97. mLevel = level;
  98. }
  99. void Logger::addAppender(Appender *pAppender)
  100. {
  101. // Avoid deadlock:
  102. // - Handle warnings, before write lock is aquired
  103. // Keep objects with a 0 reference count safe
  104. LogObjectPtr<Appender> p_appender = pAppender;
  105. {
  106. QReadLocker locker(&mObjectGuard);
  107. if(!p_appender)
  108. {
  109. logger()->warn("Adding null Appender to Logger '%1'", name());
  110. return;
  111. }
  112. if(mAppenders.contains(p_appender))
  113. {
  114. logger()->warn("Adding of duplicate appender '%2' to logger '%1'", name(), p_appender->name());
  115. return;
  116. }
  117. }
  118. {
  119. QWriteLocker locker(&mObjectGuard);
  120. if(mAppenders.contains(p_appender))
  121. return;
  122. mAppenders.append(p_appender);
  123. }
  124. }
  125. Appender *Logger::appender(const QString &rName) const
  126. {
  127. QReadLocker locker(&mObjectGuard);
  128. Appender *p_appender;
  129. Q_FOREACH(p_appender, mAppenders)
  130. if (p_appender->name() == rName)
  131. return p_appender;
  132. return 0;
  133. }
  134. void Logger::callAppenders(const LoggingEvent &rEvent) const
  135. {
  136. QReadLocker locker(&mObjectGuard);
  137. Appender *p_appender;
  138. Q_FOREACH(p_appender, mAppenders)
  139. p_appender->doAppend(rEvent);
  140. if (additivity() && (parentLogger() != 0))
  141. parentLogger()->callAppenders(rEvent);
  142. }
  143. bool Logger::isAttached(Appender *pAppender) const
  144. {
  145. QReadLocker locker(&mObjectGuard);
  146. // Keep objects with a 0 reference count safe
  147. LogObjectPtr<Appender> p_appender = pAppender;
  148. return mAppenders.contains(p_appender);
  149. }
  150. void Logger::removeAllAppenders()
  151. {
  152. // Avoid deadlock:
  153. // - Only log warnings without having the write log aquired
  154. // - Hold a reference to all appenders so that the remove does not
  155. // destruct the appender over the reference count while the write
  156. // log is held. The appender may log messages.
  157. logger()->trace("Removing all appenders from logger '%1'", name());
  158. QList< LogObjectPtr<Appender> > appenders;
  159. {
  160. QWriteLocker locker(&mObjectGuard);
  161. QMutableListIterator< LogObjectPtr<Appender> > i(mAppenders);
  162. while (i.hasNext())
  163. {
  164. Appender *p_appender = i.next();
  165. ListAppender *p_listappender = qobject_cast<ListAppender*>(p_appender);
  166. if (p_listappender && p_listappender->configuratorList())
  167. continue;
  168. else
  169. {
  170. appenders << p_appender;
  171. i.remove();
  172. }
  173. }
  174. }
  175. appenders.clear();
  176. }
  177. void Logger::removeAppender(Appender *pAppender)
  178. {
  179. // Avoid deadlock:
  180. // - Only log warnings without having the write log aquired
  181. // - Hold a reference to the appender so that the remove does not
  182. // destruct the appender over the reference count while the write
  183. // log is held. The appender may log messages.
  184. LogObjectPtr<Appender> p_appender = pAppender;
  185. if(!p_appender)
  186. {
  187. logger()->warn("Request to remove null Appender from Logger '%1'", name());
  188. return;
  189. }
  190. int n;
  191. {
  192. QWriteLocker locker(&mObjectGuard);
  193. n = mAppenders.removeAll(p_appender);
  194. }
  195. if (n == 0)
  196. {
  197. logger()->warn("Request to remove Appender '%2', which is not part of Logger '%1' appenders", name(), p_appender->name());
  198. return;
  199. }
  200. }
  201. void Logger::removeAppender(const QString &rName)
  202. {
  203. Appender *p_appender = appender(rName);
  204. if (p_appender)
  205. removeAppender(p_appender);
  206. }
  207. Level Logger::effectiveLevel() const
  208. {
  209. Q_ASSERT_X(LogManager::rootLogger()->level() != Level::NULL_INT, "Logger::effectiveLevel()", "Root logger level must not be NULL_INT");
  210. QReadLocker locker(&mObjectGuard);
  211. const Logger *p_logger = this;
  212. while (p_logger->level() == Level::NULL_INT)
  213. p_logger = p_logger->parentLogger();
  214. return p_logger->level();
  215. }
  216. bool Logger::isEnabledFor(Level level) const
  217. {
  218. if (mpLoggerRepository->isDisabled(level))
  219. return false;
  220. return (effectiveLevel() <= level);
  221. }
  222. Logger *Logger::logger(const QString &rName)
  223. {
  224. return LogManager::logger(rName);
  225. }
  226. Logger *Logger::logger(const char *pName)
  227. {
  228. return LogManager::logger(QLatin1String(pName));
  229. }
  230. Logger *Logger::rootLogger()
  231. {
  232. return LogManager::rootLogger();
  233. }
  234. #ifndef QT_NO_DEBUG_STREAM
  235. QDebug Logger::debug(QDebug &rDebug) const
  236. {
  237. QReadLocker locker(&mObjectGuard);
  238. QString parent_logger;
  239. if (mpParent)
  240. parent_logger = mpParent->name();
  241. rDebug.nospace() << "Logger("
  242. << "name:" << name() << " "
  243. << "appenders:" << mAppenders.count() << " "
  244. << "additivity:" << mAdditivity << " "
  245. << mLevel
  246. << "parentLogger:" << parent_logger
  247. << ")";
  248. return rDebug.space();
  249. }
  250. #endif // QT_NO_DEBUG_STREAM
  251. void Logger::forcedLog(Level level, const QString &rMessage) const
  252. {
  253. QReadLocker locker(&mObjectGuard);
  254. LoggingEvent event(this, level, rMessage);
  255. callAppenders(event);
  256. }
  257. /**************************************************************************
  258. * Implementation: Operators, Helper
  259. **************************************************************************/
  260. #ifndef QT_NO_DEBUG_STREAM
  261. QDebug operator<<(QDebug debug, const Logger &rLogger)
  262. {
  263. return rLogger.debug(debug);
  264. }
  265. #endif // QT_NO_DEBUG_STREAM
  266. } // namespace Log4Qt