// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once #include "LoggerBuffer.hpp" #include "LoggerWorker.hpp" #include "LoggerBufferContainer.hpp" #include "log_colors.hpp" #include "Timers/TimerFactory.hpp" #include #include #include #include #include #include namespace Log { enum class Device { DEFAULT, SEGGER_RTT }; struct Application { std::string name; std::string revision; std::string tag; std::string branch; }; std::ostream &operator<<(std::ostream &stream, const Application &application); class Logger { public: void enableColors(bool enable); [[nodiscard]] static Logger &get(); static void destroyInstance(); auto getLogs() -> std::string; void init(Application app, size_t fileSize = MAX_LOG_FILE_SIZE); void createTimer(sys::Service *parent); auto log(Device device, const char *fmt, va_list args) -> int; auto log(logger_level level, const char *file, int line, const char *function, const char *fmt, va_list args) -> int; auto logAssert(const char *fmt, va_list args) -> int; auto dumpToFile(std::filesystem::path logPath) -> int; auto diagnosticDump() -> int; auto flushLogs() -> int; static constexpr auto CRIT_STR = "CRIT"; static constexpr auto IRQ_STR = "IRQ"; private: Logger(); void addLogHeader(logger_level level, const char *file = nullptr, int line = -1, const char *function = nullptr); [[nodiscard]] bool filterLogs(logger_level level); /// Filter out not interesting logs via thread Name /// its' using fact that: /// - TRACE is level 0, for unedfined lookups it will be alvways trace /// - it will be one time init for apps which doesn't tell what level they should have /// - for others it will be o1 lookup so it's fine [[nodiscard]] auto getLogLevel(const std::string &name) -> logger_level; void logToDevice(const char *fmt, va_list args); void logToDevice(Device device, std::string_view logMsg, size_t length); auto writeLog(Device device, const char *fmt, va_list args) -> int; [[nodiscard]] size_t loggerBufferSizeLeft() const noexcept { const auto sizeLeft = LOGGER_BUFFER_SIZE - loggerBufferCurrentPos; assert(sizeLeft > 0); return sizeLeft; } void addFileHeader(std::ofstream &file) const; void checkBufferState(); cpp_freertos::MutexStandard mutex; cpp_freertos::MutexStandard logFileMutex; logger_level level{LOGTRACE}; const LogColors *logColors = &logColorsOff; char loggerBuffer[LOGGER_BUFFER_SIZE] = {0}; size_t loggerBufferCurrentPos = 0; size_t maxFileSize = MAX_LOG_FILE_SIZE; Application application; LoggerBufferContainer buffer; utils::Rotator rotator; sys::TimerHandle writeLogsTimer; static const char *levelNames[]; std::map filtered; static Logger *_logger; std::unique_ptr worker; }; const char *getTaskDesc(); } // namespace Log