Skip to main content

Logging

This page describes FigNet's logging model: how to emit and configure logs from your own code, and the tag/format conventions used for FigNet low-level runtime logs and Entangle app-level logs.

Basic Usage

FigNet logs through a pluggable ILogger interface, exposed as the static FN.Logger property.

FN.Logger.Info("Hello FigNet");

To use your own logger, implement ILogger and assign it to FN.Logger. Prefer FN.EnsureLogger(...) over assigning FN.Logger directly - it only takes effect if no logger is set yet, which avoids re-subscribing to FN.LogMessageReceived and producing duplicate log lines.

The shipped default logger writes to the console, or to a file, depending on the LoggingMethod server config field (see Configuration):

  • CONSOLE - logs to standard output.
  • FILE - logs to a rolling daily file under logs/<name>.txt at the root of the application.
  • NONE - disables logging (no-op logger).

In Unity, the default logger wraps Unity's Debug.Log (Debug.Log / Debug.LogWarning / Debug.LogError / Debug.LogException depending on level).

Goals

  • Keep logs compact and easy to scan.
  • Use one predictable tag format on native and Unity.
  • Separate low-level transport/framework logs from app-level gameplay logs.
  • Keep the source argument of FN.LogMessageReceived as a real source only.
  • Avoid pushing stack traces or exception metadata into the source slot.

Ownership

Two log families exist:

  • FigNet low-level logs: framework, provider, socket, packet, security, dispatch.
  • Entangle app-level logs: room, entity, ownership, gameplay payload, state changes.

Use the correct family for the correct layer:

  • Use [Fn][...] for transport/framework concerns.
  • Use [En][...] for Entangle behavior and game-facing flows.

Tag Format

Logs use compact segmented tags.

FigNet

Format:

[Fn][<Provider|Core>][<Area>] Message...

Examples:

[Fn][Core][Mod] Built-in module loaded.
[Fn][Enet][Life] Listening side=server port=5559 multithreaded=true packetMagic=PlaintextDatagramOnly.
[Fn][Enet][Conn] Connected side=client remote=127.0.0.1.
[Fn][Enet][Sec] Secure session established side=server peerId=42.
[Fn][Tcp][Drop] Reserved messageId=49374 cannot be sent side=server.

Provider tags:

  • Core
  • Enet
  • Lnl for LiteNetLib
  • Tcp
  • Ws
  • Wsn

Entangle

Format:

[En][<Area>] Message...
[En][<Area>][<SubArea>] Message...

Examples:

[En][Conn] Network status changed status=Connected.
[En][Auth] RegisterAppId completed success=true.
[En][Room] JoinRoom completed status=Success selfId=4 roomId=10 roomName=Lobby.
[En][Entity] InstantiateEntity roomId=10 networkId=25 type=Agent entityId=3 ownerId=4.
[En][Payload] JoinRoom response payload was null.

Use sub-areas only when they add real value. Do not add extra tag segments just to mirror class names.

Fixed Area Vocabulary

FigNet Low-Level Areas

Use these area tags:

  • Life
  • Conn
  • Auth
  • Sec
  • Rx
  • Tx
  • Drop
  • Cfg
  • Mod
  • Int

Meaning:

  • Life: startup, shutdown, listen, connect start.
  • Conn: peer connect, disconnect, timeout, reconnect skip.
  • Auth: registration, built-in identity/auth flow.
  • Sec: handshake, packet auth failure, secure session state.
  • Rx: receive-path packet processing.
  • Tx: send-path packet processing.
  • Drop: reserved, unsupported, rejected, discarded traffic.
  • Cfg: configuration or registration issues.
  • Mod: module load/unload behavior.
  • Int: internal transport/runtime exceptions or diagnostics.

Entangle Areas

Use these area tags:

  • Conn
  • Auth
  • Lobby
  • Room
  • Entity
  • State
  • Own
  • Event
  • Payload
  • Cfg

Meaning:

  • Conn: connection availability or connectivity-dependent actions.
  • Auth: app registration or identity/auth outcomes.
  • Lobby: room creation/list queries/join entry flow.
  • Room: room membership or room-level state changes.
  • Entity: entity spawn/delete/presence behavior.
  • State: state delta/state apply/state snapshots.
  • Own: ownership requests and ownership changes.
  • Event: room/game event emission or receipt.
  • Payload: null payloads, invalid payloads, serialization problems.
  • Cfg: prefab/configuration/setup problems.

Message Style Rules

Write message bodies as short facts.

Prefer:

Peer connected peerId=42 remote=127.0.0.1.

Avoid:

SERVER::Client connected 42 || 127.0.0.1

Rules:

  • Use sentence-style facts, not shouty phrases.
  • Put classification in tags, not in the message body.
  • Prefer key=value pairs for searchable details.
  • End normal messages with a period.
  • Use the message body for exception text, never the source parameter.

Exceptions

Use Internals.FormatExceptionMessage(...) when logging exceptions through the shared helpers.

Example:

Internals.EmitCoreLog(
LogType.Error,
"Int",
Internals.FormatExceptionMessage("Server application processing failed.", ex));

Do not do this:

FN.LogMessageReceived?.Invoke(ex.Message, ex.StackTrace, LogType.Error);

Helper Usage

FigNet

Use the shared helper methods from Internals:

  • EmitCoreLog
  • EmitProviderLog
  • EmitAppLog
  • CreateCoreLogSource
  • CreateProviderLogSource
  • FormatLogLine
  • FormatExceptionMessage

Provider files should usually wrap these with local helpers such as:

private void LogServer(LogType level, string area, string message)
{
if (Internals.ShouldLog(level, LoggingLevel))
{
Internals.EmitProviderLog(level, "En", true, area, message);
}
}

Entangle

Use the shared Entangle wrapper:

  • EN_Internals.ShouldLog(...)
  • EN_Internals.Log(level, area, message, subArea = null)

Example:

EN_Internals.Log(LogType.Info, "Room", $"LeaveRoom completed.");
EN_Internals.Log(LogType.Warn, "Payload", "JoinRoom response payload was null.");

Runtime Override

  • FN.SetLogLevel(...) installs a process-wide runtime override.
  • When the override is active, it becomes the effective threshold for core logs, provider logs, and admin HTTP / ASP.NET logs.
  • When no override is active, provider logs fall back to their configured LoggingLevel and admin HTTP logs use their default category noise floors.

Runtime Guidance

  • Use Verbose for packet content dumps.
  • Use Debug for packet metadata without payload dumps.
  • Use Info for expected lifecycle and state transitions.
  • Use Warn for dropped packets or recoverable misuse.
  • Use Error for failed operations or invalid runtime states.
  • Use Fatal sparingly for unrecoverable process-level failures.

Adding New Logs

When adding a new log:

  1. Decide whether it belongs to FigNet or Entangle.
  2. Choose the smallest valid area tag from the fixed vocabulary.
  3. Use the shared helper, not a raw FN.LogMessageReceived?.Invoke(...).
  4. Keep the message body factual and compact.
  5. Put stack traces in the message, not the source.

Examples

Low-level receive/drop:

[Fn][Enet][Rx] Received side=server messageId=18 encrypted=true callbackId=0 senderId=42 channelId=0 size=96.
[Fn][Enet][Drop] Dropped side=server messageId=18 senderId=42 before secure session establishment.

Low-level security:

[Fn][Enet][Sec] Secure session established side=client.
[Fn][Enet][Sec] Secure packet authentication failed side=server senderId=42.

Entangle room/entity:

[En][Room] JoinRoom completed status=Success selfId=4 roomId=10 roomName=Lobby.
[En][Entity] DeleteEntity roomId=10 networkId=25 type=Agent entityId=3.
[En][Payload] InstantiateEntity payload was null op=InstantiateEntity.