The logger module provides a unified logging system that supports both Discord webhooks and ox_lib logging backends (Datadog, Grafana Loki, Fivemanage).
The logger module is server-side only. Attempting to use it on the client will result in an error.
Overview
The logger provides:
Discord webhook integration with rich embeds
ox_lib logger support for professional logging services
Automatic rate limit handling for Discord webhooks
Color-coded messages
Flexible tagging system for Discord notifications
Basic Usage
local logger = require 'modules/logger'
logger . log ({
source = 'PlayerManager' ,
event = 'PlayerConnected' ,
message = 'Player John Doe connected to the server' ,
webhook = 'https://discord.com/api/webhooks/your-webhook-url' ,
color = 'green'
})
API Reference
log
Creates a log entry with optional Discord webhook and ox_lib logging.
Parameters
The log configuration object Source of the log. Usually a player ID or resource name.
The action or event being logged. Usually a verb describing what happened (e.g., “SpawnVehicle”, “TransferMoney”).
The detailed message describing what happened.
Discord webhook URL. If provided, the log will be sent to Discord.
Color for Discord embed. Available colors: default, blue, red, green, white, black, orange, yellow, pink, lightgreen.
Discord tags to mention. Example: {'<@&123456789>', '@everyone'}
Tags for ox_lib logger (used by Datadog, Grafana Loki, etc.)
Discord Integration
Discord Embed Colors
The logger supports predefined colors for Discord embeds:
-- From logger.lua:11-22
local Colors = {
default = 14423100 , -- Gray
blue = 255 ,
red = 16711680 ,
green = 65280 ,
white = 16777215 ,
black = 0 ,
orange = 16744192 ,
yellow = 16776960 ,
pink = 16761035 ,
lightgreen = 65309 ,
}
Discord Webhook Example
local logger = require 'modules/logger'
-- Log a player action to Discord
logger . log ({
source = GetPlayerName ( source ),
event = 'VehicleSpawned' ,
message = ( 'Player spawned a %s at coordinates %s' ): format ( vehicleModel , coords ),
webhook = 'https://discord.com/api/webhooks/your-webhook-url' ,
color = 'blue' ,
tags = { '<@&987654321>' } -- Mention a role
})
Discord logs are formatted as rich embeds with:
Title : The event name
Color : The specified color (or default gray)
Description : The log message
Author : The source (player name or resource)
Footer : Timestamp in HH:MM:SS MM-DD-YYYY format
Avatar : QBX duck logo
Username : “QBX Logs”
-- From logger.lua:108-120
local embedData = {
{
title = log . event ,
color = Colors [ log . color ] or Colors . default ,
footer = {
text = os.date ( '%H:%M:%S %m-%d-%Y' ),
},
description = log . message ,
author = {
name = log . source ,
},
}
}
Rate Limiting
The logger automatically handles Discord’s rate limits:
Queue System
All Discord logs are queued and processed sequentially to avoid rate limit errors:
-- Logs are added to a queue
logQueue [ # logQueue + 1 ] = {
webhook = log . webhook ,
tags = log . tags ,
embed = embedData
}
-- Queue is processed in a separate thread
if not isProcessingQueue then
isProcessingQueue = true
CreateThread ( processLogQueue )
end
Automatic Delays
The system implements smart delays:
After every 5 logs, waits 60 seconds to prevent rate limiting
Respects Discord’s rate limit headers
Automatically calculates delay based on X-RateLimit-Reset header
-- From logger.lua:91-96
if logCount % 5 == 0 then
Wait ( 60000 ) -- Wait 1 minute after every 5 logs
else
applyRequestDelay () -- Apply calculated delay
end
The rate limiting system ensures your Discord webhooks won’t get banned for exceeding rate limits, even during high-activity periods.
ox_lib Integration
Every log is automatically sent to ox_lib’s logger, which supports multiple backends:
-- From logger.lua:150
lib . logger ( log . source , log . event , log . message , log . oxLibTags )
Supported Backends
Datadog : Professional log aggregation and monitoring
Grafana Loki : Open-source log aggregation
Fivemanage : FiveM-specific logging service
Configure these in your ox_lib settings to enable professional logging.
Examples
Player Action Logging
local logger = require 'modules/logger'
RegisterNetEvent ( 'qbx_core:server:playerDied' , function ()
local src = source
local player = exports . qbx_core : GetPlayer ( src )
logger . log ({
source = GetPlayerName ( src ),
event = 'PlayerDeath' ,
message = ( 'Player %s died at %s' ): format (
player . PlayerData . charinfo . firstname .. ' ' .. player . PlayerData . charinfo . lastname ,
json . encode ( GetEntityCoords ( GetPlayerPed ( src )))
),
webhook = GetConvar ( 'discord_death_webhook' , '' ),
color = 'red'
})
end )
Admin Action Logging
local logger = require 'modules/logger'
RegisterCommand ( 'giveitem' , function ( source , args )
local src = source
local targetId = tonumber ( args [ 1 ])
local item = args [ 2 ]
local amount = tonumber ( args [ 3 ])
-- Give the item...
logger . log ({
source = GetPlayerName ( src ),
event = 'AdminGiveItem' ,
message = ( 'Admin %s gave %dx %s to player %s' ): format (
GetPlayerName ( src ),
amount ,
item ,
GetPlayerName ( targetId )
),
webhook = GetConvar ( 'discord_admin_webhook' , '' ),
color = 'orange' ,
tags = { '<@&' .. GetConvar ( 'discord_admin_role' , '' ) .. '>' }, -- Mention admin role
oxLibTags = 'admin,items'
})
end )
Economy Transaction Logging
local logger = require 'modules/logger'
function TransferMoney ( fromId , toId , amount )
-- Transfer logic...
logger . log ({
source = 'EconomySystem' ,
event = 'MoneyTransfer' ,
message = ( '$%d transferred from %s to %s' ): format (
amount ,
GetPlayerName ( fromId ),
GetPlayerName ( toId )
),
webhook = GetConvar ( 'discord_economy_webhook' , '' ),
color = 'green' ,
oxLibTags = 'economy,transaction'
})
end
Vehicle Spawn Logging
local logger = require 'modules/logger'
RegisterNetEvent ( 'qbx_core:server:spawnVehicle' , function ( model )
local src = source
local coords = GetEntityCoords ( GetPlayerPed ( src ))
logger . log ({
source = GetPlayerName ( src ),
event = 'VehicleSpawned' ,
message = ( 'Vehicle %s spawned at %s' ): format (
model ,
json . encode ( coords )
),
webhook = GetConvar ( 'discord_vehicle_webhook' , '' ),
color = 'blue'
})
end )
Best Practices
Use descriptive event names - Choose clear, action-oriented names like “PlayerConnected”, “VehicleSpawned”, “MoneyTransferred”
Include context in messages - Add relevant details like player names, amounts, locations, etc.
Use appropriate colors - Match colors to severity (red for errors, green for success, orange for warnings)
Configure webhooks via convars - Store webhook URLs in convars for easy configuration:
webhook = GetConvar ( 'discord_admin_webhook' , '' )
Use tags sparingly - Only mention roles/users for critical events to avoid notification spam
Add ox_lib tags - Include relevant tags for professional logging services:
oxLibTags = 'economy,transaction,banking'
Check webhook exists - Verify webhook URL before logging to avoid errors:
local webhook = GetConvar ( 'discord_admin_webhook' , '' )
if webhook ~= '' then
logger . log ({ ... , webhook = webhook })
end