#include "Logging.h" #include #include "Datei.h" #include "Globals.h" #include "Zeit.h" using namespace Framework; using namespace Framework::Logging; FlushingOStream Framework::Logging::trace(std::source_location location) { DynamicBuffer* buff = new DynamicBuffer([&location]( std::stringbuf& buffer) { zLoggingHandler()->log(LogLevel::Trace, location, buffer.str().c_str()); return 0; }); return FlushingOStream(buff, [buff]() { delete buff; }); } FlushingOStream Framework::Logging::debug(std::source_location location) { DynamicBuffer* buff = new DynamicBuffer([&location]( std::stringbuf& buffer) { zLoggingHandler()->log(LogLevel::Debug, location, buffer.str().c_str()); return 0; }); return FlushingOStream(buff, [buff]() { delete buff; }); } FlushingOStream Framework::Logging::info(std::source_location location) { DynamicBuffer* buff = new DynamicBuffer([&location]( std::stringbuf& buffer) { zLoggingHandler()->log(LogLevel::Info, location, buffer.str().c_str()); return 0; }); return FlushingOStream(buff, [buff]() { delete buff; }); } FlushingOStream Framework::Logging::warning(std::source_location location) { DynamicBuffer* buff = new DynamicBuffer([&location](std::stringbuf& buffer) { zLoggingHandler()->log( LogLevel::Warning, location, buffer.str().c_str()); return 0; }); return FlushingOStream(buff, [buff]() { delete buff; }); } FlushingOStream Framework::Logging::error(std::source_location location) { DynamicBuffer* buff = new DynamicBuffer([&location]( std::stringbuf& buffer) { zLoggingHandler()->log(LogLevel::Error, location, buffer.str().c_str()); return 0; }); return FlushingOStream(buff, [buff]() { delete buff; }); } LoggingHandler* Framework::Logging::zLoggingHandler() { return Framework::loggingHandler; } class BaseLoggingFormat : public LoggingFormat { public: BaseLoggingFormat() : LoggingFormat() {} virtual Framework::Text formatMessage(const Framework::Text& msg, LogLevel level, const std::source_location& location) const override { return msg; } }; Framework::Logging::LoggingFormat::LoggingFormat() : ReferenceCounter() {} Framework::Logging::LoggingFormat::~LoggingFormat() {} LoggingFormatBuilder::LoggingFormatBuilder( std::function formatTransformer) : formatTransformer(formatTransformer) {} Framework::Logging::LoggingFormatBuilder::LoggingFormatBuilder() { formatTransformer = [](LoggingFormat* format) { return format; }; } class DateTimeLoggingFormat : public LoggingFormat { private: LoggingFormat* after; Text format; bool postBlank; public: DateTimeLoggingFormat(LoggingFormat* after, Text format, bool postBlank) : LoggingFormat(), after(after), format(format), postBlank(postBlank) {} ~DateTimeLoggingFormat() { after->release(); } virtual Framework::Text formatMessage(const Framework::Text& msg, LogLevel level, const std::source_location& location) const override { Zeit* z = getZeit(); Text* time = z->getZeit(format); Text result; if (postBlank) { result = *time + " " + after->formatMessage(msg, level, location); } else { result = *time + after->formatMessage(msg, level, location); } time->release(); z->release(); return result; } }; LoggingFormatBuilder Framework::Logging::LoggingFormatBuilder::datetime( Framework::Text format, bool postBlank) const { std::function formatTransformer = this->formatTransformer; return LoggingFormatBuilder( [format, postBlank, formatTransformer](LoggingFormat* f) { return formatTransformer( new DateTimeLoggingFormat(f, format, postBlank)); }); } class FileNameLoggingFormat : public LoggingFormat { LoggingFormat* after; bool postBlank; public: FileNameLoggingFormat(LoggingFormat* after, bool postBlank) : LoggingFormat(), after(after), postBlank(postBlank) {} ~FileNameLoggingFormat() { after->release(); } virtual Framework::Text formatMessage(const Framework::Text& msg, LogLevel level, const std::source_location& location) const override { if (postBlank) { return Text(location.file_name()) + " " + after->formatMessage(msg, level, location); } else { return Text(location.file_name()) + after->formatMessage(msg, level, location); } } }; LoggingFormatBuilder Framework::Logging::LoggingFormatBuilder::fileName( bool postBlank) const { std::function formatTransformer = this->formatTransformer; return LoggingFormatBuilder( [postBlank, formatTransformer](LoggingFormat* f) { return formatTransformer(new FileNameLoggingFormat(f, postBlank)); }); } class FileLineLoggingFormat : public LoggingFormat { LoggingFormat* after; bool postBlank; public: FileLineLoggingFormat(LoggingFormat* after, bool postBlank) : LoggingFormat(), after(after), postBlank(postBlank) {} ~FileLineLoggingFormat() { after->release(); } virtual Framework::Text formatMessage(const Framework::Text& msg, LogLevel level, const std::source_location& location) const override { if (postBlank) { return Text((int)location.line()) + ":" + Text((int)location.column()) + " " + after->formatMessage(msg, level, location); } else { return Text((int)location.line()) + ":" + Text((int)location.column()) + after->formatMessage(msg, level, location); } } }; LoggingFormatBuilder Framework::Logging::LoggingFormatBuilder::fileLine( bool postBlank) const { std::function formatTransformer = this->formatTransformer; return LoggingFormatBuilder( [postBlank, formatTransformer](LoggingFormat* f) { return formatTransformer(new FileLineLoggingFormat(f, postBlank)); }); } class FunctionLoggingFormat : public LoggingFormat { LoggingFormat* after; bool postBlank; public: FunctionLoggingFormat(LoggingFormat* after, bool postBlank) : LoggingFormat(), after(after), postBlank(postBlank) {} ~FunctionLoggingFormat() { after->release(); } virtual Framework::Text formatMessage(const Framework::Text& msg, LogLevel level, const std::source_location& location) const override { if (postBlank) { return Text(location.function_name()) + " " + after->formatMessage(msg, level, location); } else { return Text(location.function_name()) + after->formatMessage(msg, level, location); } } }; LoggingFormatBuilder Framework::Logging::LoggingFormatBuilder::functionName( bool postBlank) const { std::function formatTransformer = this->formatTransformer; return LoggingFormatBuilder( [postBlank, formatTransformer](LoggingFormat* f) { return formatTransformer(new FunctionLoggingFormat(f, postBlank)); }); } class LevelLoggingFormat : public LoggingFormat { LoggingFormat* after; bool postBlank; public: LevelLoggingFormat(LoggingFormat* after, bool postBlank) : LoggingFormat(), after(after), postBlank(postBlank) {} ~LevelLoggingFormat() { after->release(); } virtual Framework::Text formatMessage(const Framework::Text& msg, LogLevel level, const std::source_location& location) const override { Text levelStr; switch (level) { case LogLevel::Trace: levelStr = "TRACE"; break; case LogLevel::Debug: levelStr = "DEBUG"; break; case LogLevel::Info: levelStr = "INFO"; break; case LogLevel::Warning: levelStr = "WARNING"; break; case LogLevel::Error: levelStr = "ERROR"; break; } if (postBlank) { return levelStr + " " + after->formatMessage(msg, level, location); } else { return levelStr + after->formatMessage(msg, level, location); } } }; LoggingFormatBuilder Framework::Logging::LoggingFormatBuilder::level( bool postBlank) const { std::function formatTransformer = this->formatTransformer; return LoggingFormatBuilder( [postBlank, formatTransformer](LoggingFormat* f) { return formatTransformer(new LevelLoggingFormat(f, postBlank)); }); } class ColorLoggingFormat : public LoggingFormat { std::function enabled; Color color; LoggingFormat* after; public: ColorLoggingFormat(LoggingFormat* after, std::function enabled, Color color) : LoggingFormat(), enabled(enabled), color(color), after(after) {} ~ColorLoggingFormat() { after->release(); } virtual Framework::Text formatMessage(const Framework::Text& msg, LogLevel level, const std::source_location& location) const override { bool active = enabled(level); if (active) { if (color < Color::LIGHT_BLACK) { return Text("\033[1;") + Text(30 + (int)color) + "m" + after->formatMessage(msg, level, location) + "\033[0m"; } else { return Text("\033[1;") + Text(90 + (int)color - 8) + "m" + after->formatMessage(msg, level, location) + "\033[0m"; } } return after->formatMessage(msg, level, location); } }; LoggingFormatBuilder Framework::Logging::LoggingFormatBuilder::color( Color color) const { std::function formatTransformer = this->formatTransformer; return LoggingFormatBuilder([color, formatTransformer](LoggingFormat* f) { return formatTransformer(new ColorLoggingFormat( f, [](LogLevel level) { return true; }, color)); }); } LoggingFormatBuilder Framework::Logging::LoggingFormatBuilder::color( LogLevel level, Color color) const { std::function formatTransformer = this->formatTransformer; return LoggingFormatBuilder( [level, color, formatTransformer](LoggingFormat* f) { return formatTransformer(new ColorLoggingFormat( f, [level](LogLevel l) { return level == l; }, color)); }); } class BackgroundColorLoggingFormat : public LoggingFormat { std::function enabled; Color color; LoggingFormat* after; public: BackgroundColorLoggingFormat(LoggingFormat* after, std::function enabled, Color color) : LoggingFormat(), enabled(enabled), color(color), after(after) {} ~BackgroundColorLoggingFormat() { after->release(); } virtual Framework::Text formatMessage(const Framework::Text& msg, LogLevel level, const std::source_location& location) const override { bool active = enabled(level); if (active) { if (color < Color::LIGHT_BLACK) { return Text("\033[1;") + Text(40 + (int)color) + "m" + after->formatMessage(msg, level, location) + "\033[0m"; } else { return Text("\033[1;") + Text(100 + (int)color - 8) + "m" + after->formatMessage(msg, level, location) + "\033[0m"; } } return after->formatMessage(msg, level, location); } }; LoggingFormatBuilder Framework::Logging::LoggingFormatBuilder::backgroundColor( Color color) const { std::function formatTransformer = this->formatTransformer; return LoggingFormatBuilder([color, formatTransformer](LoggingFormat* f) { return formatTransformer(new BackgroundColorLoggingFormat( f, [](LogLevel level) { return true; }, color)); }); } LoggingFormatBuilder Framework::Logging::LoggingFormatBuilder::backgroundColor( LogLevel level, Color color) const { std::function formatTransformer = this->formatTransformer; return LoggingFormatBuilder( [level, color, formatTransformer](LoggingFormat* f) { return formatTransformer(new BackgroundColorLoggingFormat( f, [level](LogLevel l) { return level == l; }, color)); }); } class TextLoggingFormat : public LoggingFormat { Text text; LoggingFormat* after; public: TextLoggingFormat(LoggingFormat* after, Text text) : LoggingFormat(), text(text), after(after) {} ~TextLoggingFormat() { after->release(); } virtual Framework::Text formatMessage(const Framework::Text& msg, LogLevel level, const std::source_location& location) const override { return text + after->formatMessage(msg, level, location); } }; LoggingFormatBuilder Framework::Logging::LoggingFormatBuilder::text( Framework::Text text) const { std::function formatTransformer = this->formatTransformer; return LoggingFormatBuilder([text, formatTransformer](LoggingFormat* f) { return formatTransformer(new TextLoggingFormat(f, text)); }); } LoggingFormat* Framework::Logging::LoggingFormatBuilder::build() const { return formatTransformer(new BaseLoggingFormat()); } Framework::Logging::LoggingChannel::LoggingChannel() : ReferenceCounter(), format(0) {} Framework::Logging::LoggingChannel::~LoggingChannel() { if (this->format) { this->format->release(); } } void Framework::Logging::LoggingChannel::setFormat(LoggingFormat* format) { if (this->format) { this->format->release(); } this->format = format; } void Framework::Logging::LoggingChannel::writeMessage( const Text& msg, LogLevel level, const std::source_location& location) const { if (this->format) { Text formatted = this->format->formatMessage(msg, level, location); this->writeMessage(formatted); } else { this->writeMessage(msg); } } Framework::Logging::CoutLoggingChannel::CoutLoggingChannel() : LoggingChannel() {} void Framework::Logging::CoutLoggingChannel::writeMessage(const Text& msg) const { std::cout << msg.getText(); } Framework::Logging::ConsoleHandlerLoggingChannel::ConsoleHandlerLoggingChannel( ConsoleHandler* consolehandler) : LoggingChannel(), consolehandler(consolehandler) {} Framework::Logging::ConsoleHandlerLoggingChannel:: ~ConsoleHandlerLoggingChannel() { consolehandler->release(); } void Framework::Logging::ConsoleHandlerLoggingChannel::writeMessage( const Text& msg) const { consolehandler->print(msg); } Framework::Logging::FileLoggingChannel::FileLoggingChannel(Text filePath) : FileLoggingChannel(new Datei(filePath)) {} Framework::Logging::FileLoggingChannel::FileLoggingChannel(Datei* file) : LoggingChannel(), file(file) { if (!file->existiert()) { file->erstellen(); } if (!file->istOffen()) { file->open( Datei::Style::schreiben | Datei::Style::ende | Datei::Style::lesen); } } Framework::Logging::FileLoggingChannel::~FileLoggingChannel() { if (file->istOffen()) { file->close(); } file->release(); } void Framework::Logging::FileLoggingChannel::writeMessage(const Text& msg) const { file->schreibe(msg.getText(), msg.getLength()); file->schreibe("\n", 1); file->flush(); } Framework::Logging::LoggingHandler::LoggingHandler() : ReferenceCounter(), channels(new RCArray*[5]) { for (int i = 0; i < 5; i++) { channels[i] = new RCArray(); } } Framework::Logging::LoggingHandler::~LoggingHandler() { for (int i = 0; i < 5; i++) { channels[i]->release(); } delete[] channels; } void Framework::Logging::LoggingHandler::addChannel( LogLevel level, LoggingChannel* channel) { channels[(int)level]->add(channel); } void Framework::Logging::LoggingHandler::removeLoggingChannel( LogLevel level, LoggingChannel* zChannel) { for (auto i = channels[(int)level]->begin(); i;) { if (*i == zChannel) { i.remove(); } else { i++; } } } void Framework::Logging::LoggingHandler::addChannel(LoggingChannel* channel) { for (int i = 0; i < 5; i++) { channels[i]->add(dynamic_cast(channel->getThis())); } channel->release(); } void Framework::Logging::LoggingHandler::removeLoggingChannel( LoggingChannel* zChannel) { for (int j = 0; j < 5; j++) { for (auto i = channels[j]->begin(); i;) { if (*i == zChannel) { i.remove(); } else { i++; } } } } void Framework::Logging::LoggingHandler::log( LogLevel level, std::source_location& location, const Text message) const { for (const LoggingChannel* channel : *channels[(int)level]) { channel->writeMessage(message, level, location); } }