F5 StudioF5 Studio
Skip to main content

Debug & Logging

F5 Safezones includes three independent systems for monitoring and diagnostics: a bridge logging system for framework detection and initialization, a console debug system for development and testing, and an audit logging system for tracking admin actions in production.

Bridge Logging

The bridge logging system outputs information about framework auto-detection and initialization on both client and server. This is independent of the main debug system.

Configuration

config.lua
Config.BridgeLog = true

Set to false to suppress bridge logs. Error-level messages always print regardless of this setting, so you'll always see critical initialization failures.

Example Output

[f5_safezones:bridge:SERVER] Starting framework detection...
[f5_safezones:bridge:SERVER] Detection priority: QBox -> QBCore -> ESX
[f5_safezones:bridge:SERVER] Framework detected: qbcore (resource: qb-core) after 1 attempt(s)
[f5_safezones:bridge:SERVER] Initializing QBCore server bridge...
[f5_safezones:bridge:SERVER] QBCore server bridge initialized
[f5_safezones:bridge:SERVER] Admin detection: QBCore.Functions.HasPermission (admin, god)
[f5_safezones:bridge:SERVER] Server bridge ready

Log Levels

LevelColorDescription
errorRed (^1)Critical failures — always shown
warnYellow (^3)Non-critical warnings
infoBlue (^5)Status and progress messages
successGreen (^2)Successful initialization steps
debugBlue (^4)Detailed internal information

Failure Diagnostics

If no framework is detected after 30 seconds, the bridge logs the state of all known framework resources:

[f5_safezones:bridge:SERVER] No supported framework detected after 300 attempts (30.0s)
[f5_safezones:bridge:SERVER] Resource states:
[f5_safezones:bridge:SERVER] qbox (qbx_core): missing
[f5_safezones:bridge:SERVER] qbcore (qb-core): stopped
[f5_safezones:bridge:SERVER] esx (es_extended): missing

This helps diagnose load-order issues or missing framework resources.

Console Debug System

The console debug system outputs detailed information to the F8 console (client) and server console with color-coded categories.

Enabling Debug Mode

config.lua
Config.Debug = true

When enabled, every system component logs its activity to the console.

Debug Categories

Each category can be independently enabled or disabled:

config.lua
Config.DebugCategories = {
INIT = true, -- Startup and initialization
ZONE = true, -- Zone loading and processing
COLLISION = true, -- Collision system events
NETWORK = true, -- Network events and verification
ADMIN = true, -- Admin actions
UI = true, -- NUI panel events
PLAYER = true, -- Player enter/exit events
PERFORMANCE = true, -- Performance metrics
COMMAND = true, -- Command execution
ERROR = true, -- Error messages
SUCCESS = true, -- Success confirmations
DATA = true -- Data operations (save/load)
}

Console Colors

Each category has an assigned console color:

CategoryColorFiveM Code
INITYellow^3
ZONEGreen^2
COLLISIONBlue^4
NETWORKCyan^6
ADMINBright Red^9
UIPurple^5
PLAYERBlue^4
PERFORMANCEOrange^8
COMMANDYellow^3
ERRORRed^1
SUCCESSGreen^2
DATACyan^6

Debug Functions

Three logging functions are available globally (both client and server):

-- Simple log message
Log('ZONE', 'Processing zone: %s', zoneName)

-- Log separator line
LogSeparator('INIT', '=') -- Prints: ============...

-- Log a block of lines with header
LogBlock('UI', 'Coordinate export', {
'Position: 195.17, -933.77, 29.70',
'Heading: 45.00'
})

Visual Debug Mode

The visual debug mode renders zone boundaries directly in the game world, making it easy to verify zone placement and dimensions.

Toggling via Command

/szdebug              -- Toggle debug for all zones
/szdebug all -- Show all zones
/szdebug active -- Show only active zones
/szdebug inactive -- Show only inactive zones
/szdebug <id> -- Show a specific zone by ID

Requires admin permissions.

Render Distance Debug

The /debugrender command toggles a separate debug mode that logs zone render distance calculations to the F8 console. This helps diagnose issues with markers not appearing at expected distances.

/debugrender          -- Toggle render distance debug output

Does not require admin permissions.

Set Render Distance

Override the render distance for a specific zone at runtime:

/setrenderdist <zone_id> <distance>

Example: /setrenderdist 1 200 — set zone #1 render distance to 200 units. Use /listsafezones to find zone IDs.

Toggling via Admin Panel

The admin panel includes debug controls that allow you to:

  • Toggle global debug mode with mode selection (all/active/inactive)
  • Toggle debug visualization per individual zone
  • View zone IDs and dimensions in real-time

Debug Marker Appearance

Debug markers use the color configured in Config.DebugOptions:

config.lua
Config.DebugOptions = {
enabled = false, -- Default state
markerColor = {r = 255, g = 0, b = 255, a = 150}, -- Magenta
showCoordinates = true, -- Show coordinate labels
showZoneInfo = true -- Show zone info labels
}

Per-Zone Debug State

Each zone can have its own debug visualization state, independent of the global debug mode. States are managed through the admin panel:

StateBehavior
trueAlways show debug marker for this zone
falseNever show debug marker for this zone
nil (default)Follow global debug mode setting

Audit Logging

The audit logging system records admin actions to timestamped log files on the server. These logs are displayed in the admin panel and can be used for accountability and compliance.

Configuration

config.lua
Config.Logging = {
enabled = true, -- Enable/disable logging
directory = '/data/logs', -- Log directory (relative to resource)
filePrefix = 'safezone-audit', -- Log file name prefix
retentionDays = 30, -- Days to keep log files
maxEntries = 500, -- Maximum entries to load in admin panel
}

Logged Categories

config.lua
Config.Logging.categories = {
ZONE = true, -- Zone creation, modification, deletion
SECURITY = true -- Access denied events
}

Logged Actions

config.lua
Config.Logging.actions = {
['zone:create'] = true,
['zone:update'] = true,
['zone:delete'] = true,
['zone:toggle_marker'] = true,
['zone:toggle_activation'] = true,
['zone:toggle_activation_all'] = true,
['security:denied'] = true
}

Disable individual actions by setting them to false to reduce log volume.

Player Identifiers

Log entries can include player identifiers for accountability:

config.lua
Config.Logging.includeIdentifiers = true
Config.Logging.identifierTypes = { 'steam', 'discord', 'license' }

Log File Format

Logs are stored as newline-delimited JSON (NDJSON) files:

data/logs/safezone-audit-2026-03-05.log
{"timestamp":"2026-03-05T14:30:00Z","epoch":1772925000,"category":"ZONE","action":"zone:create","message":"Created zone 'Hospital'","context":{"admin":{"id":1,"name":"AdminName","steam":"steam:110000...","discord":"discord:123..."},"zone":{"name":"Hospital","type":"circle"}}}

Each entry contains:

FieldDescription
timestampISO 8601 UTC timestamp
epochUnix timestamp
categoryLog category (ZONE, SECURITY)
actionSpecific action performed
messageHuman-readable description
context.adminAdmin who performed the action (ID, name, identifiers)
context.zoneZone information (if applicable)

Log File Management

  • New file per day — Files are named {prefix}-{date}.log (e.g., safezone-audit-2026-03-05.log)
  • Manifest tracking — A manifest.json file tracks all log files and their creation dates
  • Automatic retention — Files older than retentionDays are automatically deleted on startup
  • Backup safety — The system creates log files only when needed

Admin Panel Display

config.lua
Config.Logging.ui = {
showAdminName = true, -- Show admin names in log viewer
showIdentifiers = true, -- Show player identifiers
dateFormat = 'DD/MM/YYYY HH:mm:ss' -- Date format in UI
}

List Safezones Command

The /listsafezones command provides a detailed console output of all zones:

/listsafezones          -- List all zones
/listsafezones config -- List only config-defined zones
/listsafezones custom -- List only custom (admin-created) zones

Output includes zone type, dimensions, marker info, active players, and their time in zone.

This command can also be run from the server console (without admin permission check).

See Also