Logging.cpp 18 KB

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