Logging
Overview
Almost every connection or matchmaking issue shows up in the client log first, so raising the log level is the cheapest first diagnosis step. Realtime v5 logs through its own static Photon.Realtime.Log class and separates two independent levels: one for the Realtime layer (client state, servers, operations) and one for the networking layer (PhotonPeer, sockets, serialization).
On top of the text log, the peer keeps live connection counters in RealtimePeer.Stats (a Photon.Client.TrafficStats), which the client can log periodically for you.
Default Logging in Realtime
Out of the box the RealtimeClient logs at LogLevel.Warning and the peer at LogLevel.Error, so a healthy session is nearly silent: you only see warnings such as a rejected Connect call, an operation sent in the wrong state, or a disconnect cause.
Output goes to UnityEngine.Debug in Unity builds and to Console.WriteLine elsewhere. Messages are unprefixed by default; Log.LogPrefix can add a timestamp and/or the level, and RealtimeClient.LogPrefix adds a per-client string (useful when several clients run in one process).
At LogLevel.Info the client additionally logs:
- a connect summary line (
ConnectUsingSettings()with the used AppSettings, region, protocol, ports), - workflow steps: server switches, authentication results, room join/leave,
- a traffic summary every
RealtimeClient.LogStatsIntervalmilliseconds (default5000), which isRealtimePeer.VitalStatsToString(false).
LogLevel.Debug adds low-level workflow detail and is mostly interesting with LogLevelPeer raised as well.
Log.Warn, Log.Info and Log.Debug are [Conditional] on DEBUG. In a release build without those defines, those calls are compiled out entirely — only errors and exceptions remain.
Define the matching symbol (PHOTON_LOG_WARNING / PHOTON_LOG_INFO / PHOTON_LOG_DEBUG) if you need warnings or info in a release build.
Configuration
LogLevel (from Photon.Client) is a simple ascending scale: Off, Error, Warning, Info, Debug. A message is logged when the level of the logging instance is equal to or higher than the message's level.
Set the levels via AppSettings — ConnectUsingSettings() applies them to the client on connect:
AppSettings field |
applied to | default |
|---|---|---|
ClientLogging |
RealtimeClient.LogLevel — client state, matchmaking, operations |
Warning |
NetworkLogging |
RealtimeClient.LogLevelPeer (i.e. RealtimePeer.LogLevel) — connection, sockets, protocol |
Error |
Both can also be set directly on the client at any time (client.LogLevel, client.LogLevelPeer), but note that ConnectUsingSettings() overwrites them from the AppSettings.
C#
using Photon.Client;
using Photon.Realtime;
// Prefix every line with elapsed time and level. Do this once, before connecting.
Log.LogPrefix = Log.PrefixOptions.TimeAndLevel;
AppSettings appSettings = new AppSettings();
appSettings.AppIdRealtime = "<your appid>";
appSettings.ClientLogging = LogLevel.Info; // client workflow: servers, rooms, operations
appSettings.NetworkLogging = LogLevel.Warning; // connection issues only
RealtimeClient client = new RealtimeClient();
client.LogPrefix = "P1"; // identifies this client if you run several
client.LogStatsInterval = 1000; // traffic summary once per second (needs LogLevel.Info)
client.ConnectUsingSettings(appSettings);
Custom Output
Log initializes itself: in Unity via [RuntimeInitializeOnLoadMethod] to UnityEngine.Debug, elsewhere via a static constructor to Console. Call Log.Init() only to change that. One overload picks a built-in stream (Auto, Console, Debug, UnityDebug), the other takes your own delegates — use it to route into an existing logging framework or a file.
C#
Log.Init(
error: msg => MyLogger.Error(msg),
warn: msg => MyLogger.Warn(msg),
info: msg => MyLogger.Info(msg),
debug: msg => MyLogger.Trace(msg),
exception: (ex, msg) => MyLogger.Error(msg, ex));
Log.Init() resets Log.LogPrefix to PrefixOptions.None in the stream-selecting overloads, so set the prefix after initializing.
For your own messages, client.DebugReturn(LogLevel.Info, "...") is an option: it applies the client's LogPrefix, so app messages line up with the SDK's. Mind that DebugReturn is the peer's log callback, so it filters against LogLevelPeer (AppSettings.NetworkLogging), not against the client's LogLevel. To tie your messages to ClientLogging instead, call Log.Info(msg, client.LogLevel, client.LogPrefix) directly.