Logging.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696
  1. #include "Logging.h"
  2. #include <iostream>
  3. #include "Datei.h"
  4. #include "Globals.h"
  5. #include "Zeit.h"
  6. using namespace Framework;
  7. using namespace Framework::Logging;
  8. FlushingOStream Framework::Logging::trace(std::source_location location)
  9. {
  10. DynamicBuffer* buff = 0;
  11. return FlushingOStream(
  12. buff = new DynamicBuffer([&location, &buff](std::stringbuf& buffer) {
  13. zLoggingHandler()->log(
  14. LogLevel::Trace, location, buffer.str().c_str());
  15. delete buff;
  16. return 0;
  17. }));
  18. }
  19. FlushingOStream Framework::Logging::debug(std::source_location location)
  20. {
  21. DynamicBuffer* buff = 0;
  22. return FlushingOStream(
  23. buff = new DynamicBuffer([&location, &buff](std::stringbuf& buffer) {
  24. zLoggingHandler()->log(
  25. LogLevel::Debug, location, buffer.str().c_str());
  26. delete buff;
  27. return 0;
  28. }));
  29. }
  30. FlushingOStream Framework::Logging::info(std::source_location location)
  31. {
  32. DynamicBuffer* buff = 0;
  33. return FlushingOStream(
  34. buff = new DynamicBuffer([&location, &buff](std::stringbuf& buffer) {
  35. zLoggingHandler()->log(
  36. LogLevel::Info, location, buffer.str().c_str());
  37. delete buff;
  38. return 0;
  39. }));
  40. }
  41. FlushingOStream Framework::Logging::warning(std::source_location location)
  42. {
  43. DynamicBuffer* buff = 0;
  44. return FlushingOStream(
  45. buff = new DynamicBuffer([&location, &buff](std::stringbuf& buffer) {
  46. zLoggingHandler()->log(
  47. LogLevel::Warning, location, buffer.str().c_str());
  48. delete buff;
  49. return 0;
  50. }));
  51. }
  52. FlushingOStream Framework::Logging::error(std::source_location location)
  53. {
  54. DynamicBuffer* buff = 0;
  55. return FlushingOStream(
  56. buff = new DynamicBuffer([&location, &buff](std::stringbuf& buffer) {
  57. zLoggingHandler()->log(
  58. LogLevel::Error, location, buffer.str().c_str());
  59. delete buff;
  60. return 0;
  61. }));
  62. }
  63. LoggingHandler* Framework::Logging::zLoggingHandler()
  64. {
  65. return Framework::loggingHandler;
  66. }
  67. class BaseLoggingFormat : public LoggingFormat
  68. {
  69. public:
  70. BaseLoggingFormat()
  71. : LoggingFormat()
  72. {}
  73. virtual Framework::Text formatMessage(const Framework::Text& msg,
  74. LogLevel level,
  75. const std::source_location& location) const override
  76. {
  77. return msg;
  78. }
  79. };
  80. Framework::Logging::LoggingFormat::LoggingFormat()
  81. : ReferenceCounter()
  82. {}
  83. Framework::Logging::LoggingFormat::~LoggingFormat() {}
  84. LoggingFormatBuilder::LoggingFormatBuilder(
  85. std::function<LoggingFormat*(LoggingFormat*)> formatTransformer)
  86. : formatTransformer(formatTransformer)
  87. {}
  88. Framework::Logging::LoggingFormatBuilder::LoggingFormatBuilder()
  89. {
  90. formatTransformer = [](LoggingFormat* format) { return format; };
  91. }
  92. class DateTimeLoggingFormat : public LoggingFormat
  93. {
  94. private:
  95. LoggingFormat* after;
  96. Text format;
  97. bool postBlank;
  98. public:
  99. DateTimeLoggingFormat(LoggingFormat* after, Text format, bool postBlank)
  100. : LoggingFormat(),
  101. after(after),
  102. format(format),
  103. postBlank(postBlank)
  104. {}
  105. ~DateTimeLoggingFormat()
  106. {
  107. after->release();
  108. }
  109. virtual Framework::Text formatMessage(const Framework::Text& msg,
  110. LogLevel level,
  111. const std::source_location& location) const override
  112. {
  113. Zeit* z = getZeit();
  114. Text* time = z->getZeit(format);
  115. Text result;
  116. if (postBlank)
  117. {
  118. result = *time + " " + after->formatMessage(msg, level, location);
  119. }
  120. else
  121. {
  122. result = *time + after->formatMessage(msg, level, location);
  123. }
  124. time->release();
  125. z->release();
  126. return result;
  127. }
  128. };
  129. LoggingFormatBuilder Framework::Logging::LoggingFormatBuilder::datetime(
  130. Framework::Text format, bool postBlank) const
  131. {
  132. std::function<LoggingFormat*(LoggingFormat*)> formatTransformer
  133. = this->formatTransformer;
  134. return LoggingFormatBuilder(
  135. [format, postBlank, formatTransformer](LoggingFormat* f) {
  136. return formatTransformer(
  137. new DateTimeLoggingFormat(f, format, postBlank));
  138. });
  139. }
  140. class FileNameLoggingFormat : public LoggingFormat
  141. {
  142. LoggingFormat* after;
  143. bool postBlank;
  144. public:
  145. FileNameLoggingFormat(LoggingFormat* after, bool postBlank)
  146. : LoggingFormat(),
  147. after(after),
  148. postBlank(postBlank)
  149. {}
  150. ~FileNameLoggingFormat()
  151. {
  152. after->release();
  153. }
  154. virtual Framework::Text formatMessage(const Framework::Text& msg,
  155. LogLevel level,
  156. const std::source_location& location) const override
  157. {
  158. if (postBlank)
  159. {
  160. return Text(location.file_name()) + " "
  161. + after->formatMessage(msg, level, location);
  162. }
  163. else
  164. {
  165. return Text(location.file_name())
  166. + after->formatMessage(msg, level, location);
  167. }
  168. }
  169. };
  170. LoggingFormatBuilder Framework::Logging::LoggingFormatBuilder::fileName(
  171. bool postBlank) const
  172. {
  173. std::function<LoggingFormat*(LoggingFormat*)> formatTransformer
  174. = this->formatTransformer;
  175. return LoggingFormatBuilder(
  176. [postBlank, formatTransformer](LoggingFormat* f) {
  177. return formatTransformer(new FileNameLoggingFormat(f, postBlank));
  178. });
  179. }
  180. class FileLineLoggingFormat : public LoggingFormat
  181. {
  182. LoggingFormat* after;
  183. bool postBlank;
  184. public:
  185. FileLineLoggingFormat(LoggingFormat* after, bool postBlank)
  186. : LoggingFormat(),
  187. after(after),
  188. postBlank(postBlank)
  189. {}
  190. ~FileLineLoggingFormat()
  191. {
  192. after->release();
  193. }
  194. virtual Framework::Text formatMessage(const Framework::Text& msg,
  195. LogLevel level,
  196. const std::source_location& location) const override
  197. {
  198. if (postBlank)
  199. {
  200. return Text((int)location.line()) + ":"
  201. + Text((int)location.column()) + " "
  202. + after->formatMessage(msg, level, location);
  203. }
  204. else
  205. {
  206. return Text((int)location.line()) + ":"
  207. + Text((int)location.column())
  208. + after->formatMessage(msg, level, location);
  209. }
  210. }
  211. };
  212. LoggingFormatBuilder Framework::Logging::LoggingFormatBuilder::fileLine(
  213. bool postBlank) const
  214. {
  215. std::function<LoggingFormat*(LoggingFormat*)> formatTransformer
  216. = this->formatTransformer;
  217. return LoggingFormatBuilder(
  218. [postBlank, formatTransformer](LoggingFormat* f) {
  219. return formatTransformer(new FileLineLoggingFormat(f, postBlank));
  220. });
  221. }
  222. class FunctionLoggingFormat : public LoggingFormat
  223. {
  224. LoggingFormat* after;
  225. bool postBlank;
  226. public:
  227. FunctionLoggingFormat(LoggingFormat* after, bool postBlank)
  228. : LoggingFormat(),
  229. after(after),
  230. postBlank(postBlank)
  231. {}
  232. ~FunctionLoggingFormat()
  233. {
  234. after->release();
  235. }
  236. virtual Framework::Text formatMessage(const Framework::Text& msg,
  237. LogLevel level,
  238. const std::source_location& location) const override
  239. {
  240. if (postBlank)
  241. {
  242. return Text(location.function_name()) + " "
  243. + after->formatMessage(msg, level, location);
  244. }
  245. else
  246. {
  247. return Text(location.function_name())
  248. + after->formatMessage(msg, level, location);
  249. }
  250. }
  251. };
  252. LoggingFormatBuilder Framework::Logging::LoggingFormatBuilder::functionName(
  253. bool postBlank) const
  254. {
  255. std::function<LoggingFormat*(LoggingFormat*)> formatTransformer
  256. = this->formatTransformer;
  257. return LoggingFormatBuilder(
  258. [postBlank, formatTransformer](LoggingFormat* f) {
  259. return formatTransformer(new FunctionLoggingFormat(f, postBlank));
  260. });
  261. }
  262. class LevelLoggingFormat : public LoggingFormat
  263. {
  264. LoggingFormat* after;
  265. bool postBlank;
  266. public:
  267. LevelLoggingFormat(LoggingFormat* after, bool postBlank)
  268. : LoggingFormat(),
  269. after(after),
  270. postBlank(postBlank)
  271. {}
  272. ~LevelLoggingFormat()
  273. {
  274. after->release();
  275. }
  276. virtual Framework::Text formatMessage(const Framework::Text& msg,
  277. LogLevel level,
  278. const std::source_location& location) const override
  279. {
  280. Text levelStr;
  281. switch (level)
  282. {
  283. case LogLevel::Trace:
  284. levelStr = "TRACE";
  285. break;
  286. case LogLevel::Debug:
  287. levelStr = "DEBUG";
  288. break;
  289. case LogLevel::Info:
  290. levelStr = "INFO";
  291. break;
  292. case LogLevel::Warning:
  293. levelStr = "WARNING";
  294. break;
  295. case LogLevel::Error:
  296. levelStr = "ERROR";
  297. break;
  298. }
  299. if (postBlank)
  300. {
  301. return levelStr + " " + after->formatMessage(msg, level, location);
  302. }
  303. else
  304. {
  305. return levelStr + after->formatMessage(msg, level, location);
  306. }
  307. }
  308. };
  309. LoggingFormatBuilder Framework::Logging::LoggingFormatBuilder::level(
  310. bool postBlank) const
  311. {
  312. std::function<LoggingFormat*(LoggingFormat*)> formatTransformer
  313. = this->formatTransformer;
  314. return LoggingFormatBuilder(
  315. [postBlank, formatTransformer](LoggingFormat* f) {
  316. return formatTransformer(new LevelLoggingFormat(f, postBlank));
  317. });
  318. }
  319. class ColorLoggingFormat : public LoggingFormat
  320. {
  321. std::function<bool(LogLevel)> enabled;
  322. Color color;
  323. LoggingFormat* after;
  324. public:
  325. ColorLoggingFormat(LoggingFormat* after,
  326. std::function<bool(LogLevel)> enabled,
  327. Color color)
  328. : LoggingFormat(),
  329. enabled(enabled),
  330. color(color),
  331. after(after)
  332. {}
  333. ~ColorLoggingFormat()
  334. {
  335. after->release();
  336. }
  337. virtual Framework::Text formatMessage(const Framework::Text& msg,
  338. LogLevel level,
  339. const std::source_location& location) const override
  340. {
  341. bool active = enabled(level);
  342. if (active)
  343. {
  344. if (color < Color::LIGHT_Black)
  345. {
  346. return Text("\033[1;") + Text(30 + (int)color) + "m"
  347. + after->formatMessage(msg, level, location) + "\033[0m";
  348. }
  349. else
  350. {
  351. return Text("\033[1;") + Text(90 + (int)color) + "m"
  352. + after->formatMessage(msg, level, location) + "\033[0m";
  353. }
  354. }
  355. return after->formatMessage(msg, level, location);
  356. }
  357. };
  358. LoggingFormatBuilder Framework::Logging::LoggingFormatBuilder::color(
  359. Color color) const
  360. {
  361. std::function<LoggingFormat*(LoggingFormat*)> formatTransformer
  362. = this->formatTransformer;
  363. return LoggingFormatBuilder([color, formatTransformer](LoggingFormat* f) {
  364. return formatTransformer(new ColorLoggingFormat(
  365. f, [](LogLevel level) { return true; }, color));
  366. });
  367. }
  368. LoggingFormatBuilder Framework::Logging::LoggingFormatBuilder::color(
  369. LogLevel level, Color color) const
  370. {
  371. std::function<LoggingFormat*(LoggingFormat*)> formatTransformer
  372. = this->formatTransformer;
  373. return LoggingFormatBuilder(
  374. [level, color, formatTransformer](LoggingFormat* f) {
  375. return formatTransformer(new ColorLoggingFormat(
  376. f, [level](LogLevel l) { return level == l; }, color));
  377. });
  378. }
  379. class BackgroundColorLoggingFormat : public LoggingFormat
  380. {
  381. std::function<bool(LogLevel)> enabled;
  382. Color color;
  383. LoggingFormat* after;
  384. public:
  385. BackgroundColorLoggingFormat(LoggingFormat* after,
  386. std::function<bool(LogLevel)> enabled,
  387. Color color)
  388. : LoggingFormat(),
  389. enabled(enabled),
  390. color(color),
  391. after(after)
  392. {}
  393. ~BackgroundColorLoggingFormat()
  394. {
  395. after->release();
  396. }
  397. virtual Framework::Text formatMessage(const Framework::Text& msg,
  398. LogLevel level,
  399. const std::source_location& location) const override
  400. {
  401. bool active = enabled(level);
  402. if (active)
  403. {
  404. if (color < Color::LIGHT_Black)
  405. {
  406. return Text("\033[1;") + Text(40 + (int)color) + "m"
  407. + after->formatMessage(msg, level, location) + "\033[0m";
  408. }
  409. else
  410. {
  411. return Text("\033[1;") + Text(100 + (int)color) + "m"
  412. + after->formatMessage(msg, level, location) + "\033[0m";
  413. }
  414. }
  415. return after->formatMessage(msg, level, location);
  416. }
  417. };
  418. LoggingFormatBuilder Framework::Logging::LoggingFormatBuilder::backgroundColor(
  419. Color color) const
  420. {
  421. std::function<LoggingFormat*(LoggingFormat*)> formatTransformer
  422. = this->formatTransformer;
  423. return LoggingFormatBuilder([color, formatTransformer](LoggingFormat* f) {
  424. return formatTransformer(new BackgroundColorLoggingFormat(
  425. f, [](LogLevel level) { return true; }, color));
  426. });
  427. }
  428. LoggingFormatBuilder Framework::Logging::LoggingFormatBuilder::backgroundColor(
  429. LogLevel level, Color color) const
  430. {
  431. std::function<LoggingFormat*(LoggingFormat*)> formatTransformer
  432. = this->formatTransformer;
  433. return LoggingFormatBuilder(
  434. [level, color, formatTransformer](LoggingFormat* f) {
  435. return formatTransformer(new BackgroundColorLoggingFormat(
  436. f, [level](LogLevel l) { return level == l; }, color));
  437. });
  438. }
  439. class TextLoggingFormat : public LoggingFormat
  440. {
  441. Text text;
  442. LoggingFormat* after;
  443. public:
  444. TextLoggingFormat(LoggingFormat* after, Text text)
  445. : LoggingFormat(),
  446. text(text),
  447. after(after)
  448. {}
  449. ~TextLoggingFormat()
  450. {
  451. after->release();
  452. }
  453. virtual Framework::Text formatMessage(const Framework::Text& msg,
  454. LogLevel level,
  455. const std::source_location& location) const override
  456. {
  457. return text + after->formatMessage(msg, level, location);
  458. }
  459. };
  460. LoggingFormatBuilder Framework::Logging::LoggingFormatBuilder::text(
  461. Framework::Text text) const
  462. {
  463. std::function<LoggingFormat*(LoggingFormat*)> formatTransformer
  464. = this->formatTransformer;
  465. return LoggingFormatBuilder([text, formatTransformer](LoggingFormat* f) {
  466. return formatTransformer(new TextLoggingFormat(f, text));
  467. });
  468. }
  469. LoggingFormat* Framework::Logging::LoggingFormatBuilder::build() const
  470. {
  471. return formatTransformer(new BaseLoggingFormat());
  472. }
  473. Framework::Logging::LoggingChannel::LoggingChannel()
  474. : ReferenceCounter(),
  475. format(0)
  476. {}
  477. Framework::Logging::LoggingChannel::~LoggingChannel()
  478. {
  479. if (this->format)
  480. {
  481. this->format->release();
  482. }
  483. }
  484. void Framework::Logging::LoggingChannel::setFormat(LoggingFormat* format)
  485. {
  486. if (this->format)
  487. {
  488. this->format->release();
  489. }
  490. this->format = format;
  491. }
  492. void Framework::Logging::LoggingChannel::writeMessage(
  493. const Text& msg, LogLevel level, const std::source_location& location) const
  494. {
  495. if (this->format)
  496. {
  497. Text formatted = this->format->formatMessage(msg, level, location);
  498. this->writeMessage(formatted);
  499. }
  500. else
  501. {
  502. this->writeMessage(msg);
  503. }
  504. }
  505. Framework::Logging::CoutLoggingChannel::CoutLoggingChannel()
  506. : LoggingChannel()
  507. {}
  508. void Framework::Logging::CoutLoggingChannel::writeMessage(const Text& msg) const
  509. {
  510. std::cout << msg.getText() << std::endl;
  511. }
  512. Framework::Logging::ConsoleHandlerLoggingChannel::ConsoleHandlerLoggingChannel(
  513. ConsoleHandler* consolehandler)
  514. : LoggingChannel(),
  515. consolehandler(consolehandler)
  516. {}
  517. Framework::Logging::ConsoleHandlerLoggingChannel::
  518. ~ConsoleHandlerLoggingChannel()
  519. {
  520. consolehandler->release();
  521. }
  522. void Framework::Logging::ConsoleHandlerLoggingChannel::writeMessage(
  523. const Text& msg) const
  524. {
  525. consolehandler->print(msg);
  526. }
  527. Framework::Logging::FileLoggingChannel::FileLoggingChannel(Text filePath)
  528. : LoggingChannel(),
  529. file(new Datei(filePath))
  530. {
  531. if (!file->existiert())
  532. {
  533. file->erstellen();
  534. }
  535. file->open(
  536. Datei::Style::schreiben | Datei::Style::ende | Datei::Style::lesen);
  537. }
  538. Framework::Logging::FileLoggingChannel::~FileLoggingChannel()
  539. {
  540. file->close();
  541. file->release();
  542. }
  543. void Framework::Logging::FileLoggingChannel::writeMessage(const Text& msg) const
  544. {
  545. file->schreibe(msg.getText(), msg.getLength());
  546. file->schreibe("\n", 1);
  547. file->flush();
  548. }
  549. Framework::Logging::LoggingHandler::LoggingHandler()
  550. : ReferenceCounter(),
  551. channels(new RCArray<LoggingChannel>*[5])
  552. {
  553. for (int i = 0; i < 5; i++)
  554. {
  555. channels[i] = new RCArray<LoggingChannel>();
  556. }
  557. }
  558. Framework::Logging::LoggingHandler::~LoggingHandler()
  559. {
  560. for (int i = 0; i < 5; i++)
  561. {
  562. channels[i]->release();
  563. }
  564. delete[] channels;
  565. }
  566. void Framework::Logging::LoggingHandler::addChannel(
  567. LogLevel level, LoggingChannel* channel)
  568. {
  569. channels[(int)level]->add(channel);
  570. }
  571. void Framework::Logging::LoggingHandler::removeLoggingChannel(
  572. LogLevel level, LoggingChannel* zChannel)
  573. {
  574. for (auto i = channels[(int)level]->begin(); i;)
  575. {
  576. if (*i == zChannel)
  577. {
  578. i.remove();
  579. }
  580. else
  581. {
  582. i++;
  583. }
  584. }
  585. }
  586. void Framework::Logging::LoggingHandler::addChannel(LoggingChannel* channel)
  587. {
  588. for (int i = 0; i < 5; i++)
  589. {
  590. channels[i]->add(dynamic_cast<LoggingChannel*>(channel->getThis()));
  591. }
  592. channel->release();
  593. }
  594. void Framework::Logging::LoggingHandler::removeLoggingChannel(
  595. LoggingChannel* zChannel)
  596. {
  597. for (int j = 0; j < 5; j++)
  598. {
  599. for (auto i = channels[j]->begin(); i;)
  600. {
  601. if (*i == zChannel)
  602. {
  603. i.remove();
  604. }
  605. else
  606. {
  607. i++;
  608. }
  609. }
  610. }
  611. }
  612. void Framework::Logging::LoggingHandler::log(
  613. LogLevel level, std::source_location& location, const Text message) const
  614. {
  615. for (const LoggingChannel* channel : *channels[(int)level])
  616. {
  617. channel->writeMessage(message, level, location);
  618. }
  619. }