Logging

Enabling Logging

SDK logging is controlled through free functions in RealtimeCore/Common/LogUtils.h, in the RealtimeCore::Common namespace. LogEnable(level) and LogDisable(level) switch levels on and off, and IsLogEnabled(level) queries the current state. Messages are only delivered once at least one log output is registered with AddLogOutput.

A typical startup sequence registers an output and enables the levels of interest.

C++

using namespace RealtimeCore::Common;

// ConsoleLogOutput is a user-defined LogOutput implementation, shown further down this page.
static ConsoleLogOutput consoleLog;

AddLogOutput(&consoleLog);
LogEnable(LogLevel::Info | LogLevel::Warning | LogLevel::Error);

Log Levels

LogLevel is a bitmask enum with five levels: Trace, Debug, Info, Warning and Error and the usual bitwise operators, so any combination can be enabled or disabled at once. There is no implicit hierarchy: enabling Warning does not enable Error; combine exactly the levels you want.

SetLogLevelsFromBitmask(mask) applies a complete level set in one call. TryGetLogLevelFromString(name, outLevel) parses a level from text, which is handy for config files and command-line switches, and PrintLogLevels() logs the currently active set.

Level Typical Content
Trace Highest-volume detail, down to individual calls and wire activity.
Debug Internal state transitions and diagnostic detail for development builds.
Info Lifecycle milestones: connected, room joined, region selected.
Warning Unexpected but recoverable conditions worth investigating.
Error Failures; something did not work as requested.

Implementing a Log Output

A log output is a class deriving from the abstract RealtimeCore::Common::LogOutput, implementing one sink per level: LogTrace, LogDebug, LogInfo, LogWarning and LogError. Each sink receives the finished message as a UTF-8 const CharType*; route it to wherever your game's diagnostics live, a console, a file or an in-game overlay.

A minimal output writing every message to stderr.

C++

class ConsoleLogOutput : public RealtimeCore::Common::LogOutput
{
public:
    void LogTrace(const RealtimeCore::Common::CharType* message) override { Print("TRACE", message); }
    void LogDebug(const RealtimeCore::Common::CharType* message) override { Print("DEBUG", message); }
    void LogInfo(const RealtimeCore::Common::CharType* message) override { Print("INFO", message); }
    void LogWarning(const RealtimeCore::Common::CharType* message) override { Print("WARN", message); }
    void LogError(const RealtimeCore::Common::CharType* message) override { Print("ERROR", message); }

private:
    static void Print(const char* level, const RealtimeCore::Common::CharType* message)
    {
        std::fprintf(stderr, "[Photon][%s] %s\n", level, reinterpret_cast<const char*>(message));
    }
};

Registering Log Outputs

AddLogOutput(&output) registers a sink and RemoveLogOutput(&output) removes it, returning whether it was found. Several outputs can be active at the same time, LogOutputCount() reports how many, and every enabled message is delivered to all of them.

The registry stores a raw pointer, so the output object must stay alive for as long as it is registered. Give outputs static or application lifetime, or call RemoveLogOutput before destroying one.

Back to top