diff options
Diffstat (limited to 'source/core/StarLogging.hpp')
-rw-r--r-- | source/core/StarLogging.hpp | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/source/core/StarLogging.hpp b/source/core/StarLogging.hpp new file mode 100644 index 0000000..d90e0e1 --- /dev/null +++ b/source/core/StarLogging.hpp @@ -0,0 +1,193 @@ +#ifndef STAR_LOGGING_HPP +#define STAR_LOGGING_HPP + +#include "StarThread.hpp" +#include "StarSet.hpp" +#include "StarString.hpp" +#include "StarPoly.hpp" +#include "StarBiMap.hpp" +#include "StarTime.hpp" +#include "StarFile.hpp" + +namespace Star { + +enum class LogLevel { + Debug, + Info, + Warn, + Error +}; +extern EnumMap<LogLevel> const LogLevelNames; + +STAR_CLASS(LogSink); + +// A sink for Logger messages. +class LogSink { +public: + LogSink(); + virtual ~LogSink(); + + virtual void log(char const* msg, LogLevel level) = 0; + + void setLevel(LogLevel level); + LogLevel level(); + +private: + atomic<LogLevel> m_level; +}; + +class StdoutLogSink : public LogSink { +public: + virtual void log(char const* msg, LogLevel level); + +private: + Mutex m_logMutex; +}; + +class FileLogSink : public LogSink { +public: + FileLogSink(String const& filename, LogLevel level, bool truncate); + + virtual void log(char const* msg, LogLevel level); + +private: + FilePtr m_output; + Mutex m_logMutex; +}; + +// A basic loging system that logs to multiple streams. Can log at Debug, +// Info, Warn, and Error logging levels. By default logs to stdout. +class Logger { +public: + static void addSink(LogSinkPtr s); + static void removeSink(LogSinkPtr s); + + // Default LogSink that outputs to stdout. + static LogSinkPtr stdoutSink(); + // Don't use the stdout sink. + static void removeStdoutSink(); + + static void log(LogLevel level, char const* msg); + + template <typename... Args> + static void logf(LogLevel level, char const* msg, Args const&... args); + + template <typename... Args> + static void debug(char const* msg, Args const&... args); + template <typename... Args> + static void info(char const* msg, Args const&... args); + template <typename... Args> + static void warn(char const* msg, Args const&... args); + template <typename... Args> + static void error(char const* msg, Args const&... args); + +private: + static shared_ptr<StdoutLogSink> s_stdoutSink; + static HashSet<LogSinkPtr> s_sinks; + static Mutex s_mutex; +}; + +// For logging data that is very high frequency. It is a map of debug values to +// be displayed every frame, or in a debug output window, etc. +class LogMap { +public: + static String getValue(String const& key); + static void setValue(String const& key, String const& value); + + // Shorthand, converts given type to string using std::ostream. + template <typename T> + static void set(String const& key, T const& t); + + static Map<String, String> getValues(); + static void clear(); + +private: + static HashMap<String, String> s_logMap; + static Mutex s_logMapMutex; +}; + +// Logging for spatial data. Divided into multiple named coordinate spaces. +class SpatialLogger { +public: + // Maximum count of objects stored per space + static size_t const MaximumLines = 200000; + static size_t const MaximumPoints = 200000; + static size_t const MaximumText = 10000; + + struct Line { + Vec2F begin; + Vec2F end; + Vec4B color; + }; + + struct Point { + Vec2F position; + Vec4B color; + }; + + struct LogText { + String text; + Vec2F position; + Vec4B color; + }; + + static void logPoly(char const* space, PolyF const& poly, Vec4B const& color); + static void logLine(char const* space, Line2F const& line, Vec4B const& color); + static void logLine(char const* space, Vec2F const& begin, Vec2F const& end, Vec4B const& color); + static void logPoint(char const* space, Vec2F const& position, Vec4B const& color); + static void logText(char const* space, String text, Vec2F const& position, Vec4B const& color); + + static Deque<Line> getLines(char const* space, bool andClear); + static Deque<Point> getPoints(char const* space, bool andClear); + static Deque<LogText> getText(char const* space, bool andClear); + + static void clear(); + +private: + static Mutex s_mutex; + static StringMap<Deque<Line>> s_lines; + static StringMap<Deque<Point>> s_points; + static StringMap<Deque<LogText>> s_logText; +}; + +template <typename... Args> +void Logger::logf(LogLevel level, char const* msg, Args const&... args) { + MutexLocker locker(s_mutex); + Maybe<std::string> output; + for (auto const& l : s_sinks) { + if (l->level() <= level) { + if (!output) + output = strf(msg, args...); + l->log(output->c_str(), level); + } + } +} + +template <typename... Args> +void Logger::debug(char const* msg, Args const&... args) { + logf(LogLevel::Debug, msg, args...); +} + +template <typename... Args> +void Logger::info(char const* msg, Args const&... args) { + logf(LogLevel::Info, msg, args...); +} + +template <typename... Args> +void Logger::warn(char const* msg, Args const&... args) { + logf(LogLevel::Warn, msg, args...); +} + +template <typename... Args> +void Logger::error(char const* msg, Args const&... args) { + logf(LogLevel::Error, msg, args...); +} + +template <typename T> +void LogMap::set(String const& key, T const& t) { + setValue(key, strf("%s", t)); +} + +} + +#endif |