Skip to content
Blog

FiveM logs: where Discord webhooks fail and what to use instead

Discord webhook logs get rate-limited, can’t be searched by player and lose their attachments. How to log with ox_lib and turn the lines into evidence.

By Termi

4 min read
  • Logs
  • ox_lib
  • Discord
  • Evidence
On this page

Most FiveM servers log the same way: a Discord channel per category, such as money, deaths and admin commands, and a webhook URL in every script. It works for the first month. Then a ban appeal arrives about something three weeks old, and someone scrolls through thousands of embeds looking for one license. This guide covers where Discord logging breaks, how to send structured logs with ox_lib instead, and how to turn them into evidence you can show the player.

Where Discord logging breaks

  • Rate limits. Discord limits how fast one webhook can post. On a busy evening with every transfer, death and item move logged, requests come back 429 Too Many Requests, and a script that doesn’t retry loses that line.
  • No view per player. Finding everything about one player means searching each channel separately and putting the order back together by hand.
  • Attachments expire. Screenshots posted through a webhook get signed links that stop working outside Discord, so a link copied into a ticket breaks.
  • Anyone with the URL can post. A webhook URL works like a password. If it sits in a client script, players can read it and post whatever they like to your log channel.
  • Every reader sees everything. Channel permissions are all or nothing, so a trial moderator who can read the money channel sees every identifier logged in it.

Send structured logs with ox_lib

ox_lib, which most ESX, QBCore and Qbox servers already run, has a server-side logger. One call where the action happens replaces a webhook request:

server.lua
RegisterNetEvent('bank:transfer', function(to, amount)
    local src = source
    if not Bank.transfer(src, to, amount) then return end
    lib.logger(src, 'money.transfer', ('sent $%d to %s'):format(amount, to), 'amount:' .. amount, 'to:' .. to)
end)

The arguments are the player’s server ID, an event name, a message and any number of key:value tags. ox_lib adds the player’s name and identifiers to each line by itself, collects the lines into batches and sends them to the service named in a convar:

server.cfg
set ox:logger "fivemanage"
set fivemanage:key "fd_live_…"
set fivemanage:dataset "city"

ox_lib ships three services: Datadog, Grafana Loki and Fivemanage. Fivemanage keeps logs 15 days on its free and $8 plans, 90 days on Pro at $24 and 180 days on Network at $79.

Send them to FiveDock

FiveDock accepts the batches ox_lib’s Fivemanage logger sends, unchanged. ox_lib keeps that address in one line of imports/logger/providers/fivemanage.lua. Point it at FiveDock and use a FiveDock API token with the logs:write scope as fivemanage:key:

ox_lib/imports/logger/providers/fivemanage.lua
endpoint = 'https://api.fivedock.dev/api/logs/batch',

Updating ox_lib replaces that file, so change the line again after each update, or keep it in your own copy of ox_lib.

Each line lands in the Black Box with the player’s license, Discord ID and name. Next to it is everything the FiveDock agent records by itself: script errors, in-game reports and screenshots.

From logs to evidence

On Metro, the Black Box turns those lines into a timeline per player: every logged line about one license, from the join to the transfer to the screenshot, in order and to the second. One button turns a slice of it into an evidence package, a link you can hand to the player you just banned.

Search covers every player, for a license, a plate or a word, and you can save a search you run every night. Economy alerts watch the same lines on every plan: a transfer above a threshold, or money gained too fast, posts to Discord. On Metro the alert also takes a backup that second, and duplicate item alerts catch the same serial in two inventories.

Metro’s masking by role keeps real addresses and payment details away from trainees, which a Discord channel can’t do.

How long to keep logs

Appeals usually arrive within a few weeks of a ban. Keep at least 30 days, which FiveDock City does for €12 a month. Free keeps 7 days, and Metro keeps 90 days plus an archive.

Compared with Fivemanage

Fivemanage keeps logs longer for the money: 90 days on Pro at $24, 180 days on Network. A FiveDock plan also covers file hosting, database backups, reports and staff accounts, so compare the whole bill. Our hosting comparison puts the two side by side.

Common questions

How do I log player actions on a FiveM server?

Call lib.logger from ox_lib in the server script where the action happens, with the player’s server ID, an event name and a message. ox_lib adds the player’s identifiers and sends batches to the service set in ox:logger. FiveDock accepts ox_lib’s Fivemanage format and files each line under the player, so staff can read one player’s history in order.

Are Discord webhooks good for FiveM logs?

As a notification feed for a small server, they’re fine. As a record they fall short: webhooks are rate-limited, attachment links expire, nothing shows one player across channels, and anyone who finds a webhook URL can post to it.

How long should a FiveM server keep logs?

At least as long as your appeal window, usually two to four weeks. 30 days covers most servers. Keep 90 if you handle refund requests or long investigations.

Can I use ox_lib’s logger without Fivemanage?

Yes. Set ox:logger to datadog or loki for those services, or keep fivemanage and change its address to FiveDock’s, which accepts the same batches.

All articles