/* * This file is part of the Flowee project * Copyright (C) 2017-2026 Tom Zander * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef FLOWEE_LOGCHANNELS_P_H #define FLOWEE_LOGCHANNELS_P_H #include "LogChannel.h" /* * WARNING USAGE OF THIS HEADER IS RESTRICTED. * This Header file is part of the private API and is meant to be used solely by the Logger component. * * Usage of this API will likely mean your code will break in interesting ways in the future, * or even stop to compile. * * YOU HAVE BEEN WARNED!! */ #include #include #include class ConfigurableChannel : public Log::Channel { public: ConfigurableChannel(TimeStampFormat formatTimestamp); virtual void reopenLogFiles() {} bool logSection() const; void setLogSection(bool printSection); bool logLineNumber() const; void setLogLineNumber(bool printLineNumber); bool logMethodName() const; void setLogMethodName(bool printMethodName); bool logFilename() const; void setLogFilename(bool printFilename); virtual void setPath(const std::string &path) {} protected: TimeStampFormat m_timeStampFormat; bool m_logSection; bool m_logLineNumber; bool m_logMethodName; bool m_logFilename; }; class ConsoleLogChannel : public ConfigurableChannel { public: ConsoleLogChannel(); void setPrefix(const char *prefix); const char *prefix() const { return m_prefix; } virtual void pushLog(int64_t timeMillis, std::string *timestamp, const std::string &line, const char *filename, int lineNumber, const char *methodName, short logSection, short logLevel); private: const char *m_prefix = nullptr; }; class FileLogChannel : public ConfigurableChannel { public: FileLogChannel(const boost::filesystem::path &logFilename); ~FileLogChannel(); virtual void pushLog(int64_t timeMillis, std::string *timestamp, const std::string &line, const char *filename, int lineNumber, const char *methodName, short logSection, short logLevel); virtual void reopenLogFiles(); virtual void setPath(const std::string &path); private: FILE *m_fileout; boost::filesystem::path m_logFilename; }; /* * Logging in the context of multi-threading is hard because we need a mutex * and we serialize all thread's messages to one by one reach the file or console. * Files or console block on write pretty quickly under heavy load. Making bursts * of logging slow the application down to a single IO constrained mutex. * * As such the idea was born to keep the IO bound operation out of operational * threads and use lock-less operations to just push to memory log lines and have * a writer thread safe that to disk. * * Logging is generally speaking in Flowee not a firehose and thus storing it in * memory while running is perfectly adequate for testing setups and benchmarkings. */ class FastLogChannel : public Log::Channel { public: FastLogChannel(const boost::filesystem::path &logFilename); ~FastLogChannel(); public: void pushLog(int64_t timeMillis, std::string *timestamp, const std::string &line, const char *filename, int lineNumber, const char *methodName, short logSection, short logLevel) override; struct Item { Item() : next(0) {} std::atomic next; int64_t timeMillis; std::string line; const char *filename; const char *methodname; int lineNumber; short logSection; short logLevel; std::thread::id callingThread; }; private: std::unique_ptr m_writeThread; std::atomic m_writePtr; }; #endif