123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- /*
- * Logging.h
- * ---------
- * Purpose: General logging
- * Notes : (currently none)
- * Authors: OpenMPT Devs
- * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
- */
- #pragma once
- #include "openmpt/all/BuildSettings.hpp"
- #include "openmpt/logging/Logger.hpp"
- #include "mptPathString.h"
- #include "mptString.h"
- #if defined(MODPLUG_TRACKER) && MPT_OS_WINDOWS
- #include <atomic>
- #endif
- OPENMPT_NAMESPACE_BEGIN
- /*
- Build time logging configuration:
- * #define MPT_LOG_GLOBAL_LEVEL_STATIC
- #define MPT_LOG_GLOBAL_LEVEL #
- Define the former (to anything) and the latter (to one of the log levels
- below) in order to statically select the verbosity of logging at build time.
- MPT_LOG calls that exceed the specified logging level will get dead-code
- eliminated at compile time.
- This especially means that, when setting MPT_LOG_GLOBAL_LEVEL to 0, no
- MPT_LOG call (with a constant level parameter) remains in the resulting
- binary, however, they still do get parsed and properly type checked by the
- compiler.
- Logging:
- If the context is related to a particular CSoundfile instance, use
- CSoundfile::AddToLog.
- Logging a simple message:
- MPT_LOG_GLOBAL(LogWarning, "sounddev", "some message");
- MPT_LOG_GLOBAL(LogWarning, "sounddev", U_("some message"));
- Facility is some course grained code section identifier (more coarse grained
- than the current file name probably), useful to do some selective logging.
- Logging a more complex message:
- MPT_LOG_GLOBAL(LogWarning, "sounddev", MPT_UFORMAT("Some message: foo={}, bar=0x{}")(foo, mpt::ufmt::hex0<8>(bar)));
- Note that even with full enabled logging and a runtime configurable logging
- level, the runtime overhead of a MPT_LOG_GLOBAL(level, facility, text) call is just a
- single conditional in case the verbosity does not require logging the respective
- message. Even the expression "text" is not evaluated.
- */
- inline mpt::ustring LogLevelToString(LogLevel level)
- {
- switch(level)
- {
- case LogError: return U_("error"); break;
- case LogWarning: return U_("warning"); break;
- case LogNotification: return U_("notify"); break;
- case LogInformation: return U_("info"); break;
- case LogDebug: return U_("debug"); break;
- }
- return U_("unknown");
- }
- class ILog
- {
- protected:
- virtual ~ILog() { }
- public:
- virtual void AddToLog(LogLevel level, const mpt::ustring &text) const = 0;
- };
- namespace mpt
- {
- namespace log
- {
- #if defined(MPT_LOG_GLOBAL_LEVEL_STATIC)
- #if (MPT_LOG_GLOBAL_LEVEL <= 0)
- // All logging has beeen statically disabled.
- // All logging code gets compiled and immediately dead-code eliminated.
- #define MPT_LOG_IS_DISABLED
- #endif
- inline constexpr int GlobalLogLevel = MPT_LOG_GLOBAL_LEVEL ;
- #else
- extern int GlobalLogLevel;
- #endif
- #if defined(MODPLUG_TRACKER) && !defined(MPT_LOG_IS_DISABLED)
- extern bool FileEnabled;
- extern bool DebuggerEnabled;
- extern bool ConsoleEnabled;
- void SetFacilities(const std::string &solo, const std::string &blocked);
- bool IsFacilityActive(const char *facility) noexcept;
- #else
- MPT_FORCEINLINE bool IsFacilityActive(const char * /*facility*/ ) noexcept { return true; }
- #endif
- class GlobalLogger final
- : public ILogger
- {
- public:
- GlobalLogger() = default;
- ~GlobalLogger() final = default;
- public:
- bool IsLevelActive(LogLevel level) const noexcept override
- {
- return (mpt::log::GlobalLogLevel >= level);
- }
- bool IsFacilityActive(const char *facility) const noexcept override
- {
- return mpt::log::IsFacilityActive(facility);
- }
- void SendLogMessage(const mpt::source_location &loc, LogLevel level, const char *facility, const mpt::ustring &message) const override;
- };
- #define MPT_LOG_GLOBAL(level, facility, text) MPT_LOG(mpt::log::GlobalLogger{}, (level), (facility), (text))
- #if defined(MODPLUG_TRACKER) && MPT_OS_WINDOWS
- namespace Trace {
- // This is not strictly thread safe in all corner cases because of missing barriers.
- // We do not care in order to not harm the fast path with additional barriers.
- // Enabled tracing incurs a runtime overhead with multiple threads as a global atomic variable
- // gets modified.
- // This cacheline bouncing does not matter at all
- // if there are not multiple thread adding trace points at high frequency (way greater than 1000Hz),
- // which, in OpenMPT, is only ever the case for just a single thread (the audio thread), if at all.
- extern std::atomic<bool> g_Enabled;
- inline bool IsEnabled() { return g_Enabled; }
- enum class Direction : int8
- {
- Unknown = 0,
- Enter = 1,
- Leave = -1,
- };
- MPT_NOINLINE void Trace(const mpt::source_location & loc, Direction direction = Direction::Unknown) noexcept;
- enum ThreadKind {
- ThreadKindGUI,
- ThreadKindAudio,
- ThreadKindNotify,
- ThreadKindWatchdir,
- };
- void Enable(std::size_t numEntries);
- void Disable();
- void SetThreadId(mpt::log::Trace::ThreadKind kind, uint32 id);
- uint32 GetThreadId(mpt::log::Trace::ThreadKind kind);
- void Seal();
- bool Dump(const mpt::PathString &filename);
- class Scope
- {
- private:
- const mpt::source_location loc;
- public:
- MPT_FORCEINLINE Scope(mpt::source_location loc) noexcept
- : loc(loc)
- {
- if(mpt::log::Trace::g_Enabled)
- {
- mpt::log::Trace::Trace(loc, mpt::log::Trace::Direction::Enter);
- }
- }
- MPT_FORCEINLINE ~Scope() noexcept
- {
- if(mpt::log::Trace::g_Enabled)
- {
- mpt::log::Trace::Trace(loc, mpt::log::Trace::Direction::Leave);
- }
- }
- };
- #define MPT_TRACE_CONCAT_HELPER(x, y) x ## y
- #define MPT_TRACE_CONCAT(x, y) MPT_TRACE_CONCAT_HELPER(x, y)
- #define MPT_TRACE_SCOPE() mpt::log::Trace::Scope MPT_TRACE_CONCAT(MPT_TRACE_VAR, __LINE__)(MPT_SOURCE_LOCATION_CURRENT())
- #define MPT_TRACE() do { if(mpt::log::Trace::g_Enabled) { mpt::log::Trace::Trace(MPT_SOURCE_LOCATION_CURRENT()); } } while(0)
- } // namespace Trace
- #else // !MODPLUG_TRACKER
- #define MPT_TRACE_SCOPE() do { } while(0)
- #define MPT_TRACE() do { } while(0)
- #endif // MODPLUG_TRACKER
- } // namespace log
- } // namespace mpt
- OPENMPT_NAMESPACE_END
|