Skip to content

Febreeze-sys/Watcher

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Watcher

Error reporting for Roblox games. Captures unhandled errors on the server and the client and posts them to a Discord webhook as formatted embeds.

There is no backend service to run. The SDK ships as a single Luau module. Client errors are forwarded to the server through an internal RemoteEvent because Roblox only allows outbound HTTP from the server.

What you get

Unhandled errors via ScriptContext.Error on both sides, manual captureException and captureMessage, a wrap helper for risky callbacks, per-minute rate limiting, and fingerprint based dedupe so the same error firing every frame does not flood your channel.

Each Discord embed includes the message, stack trace, the script path that raised it, PlaceId, PlaceVersion, JobId, the side (server or client), the environment, the release string, your tags, and the player when the error came from the client.

Install

This is a Rojo project. Build it once:

rojo build -o Watcher.rbxm

Drop Watcher.rbxm into ReplicatedStorage, or use rojo serve to sync live.

The project file mounts the module at ReplicatedStorage.Watcher.

HttpService.HttpEnabled must be on (Game Settings, Security).

Usage

You need to call Watcher.init on both sides. The server call needs the webhook URL. The client call sets up the RemoteEvent bridge.

Server script in ServerScriptService:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Watcher = require(ReplicatedStorage.Watcher)

Watcher.init({
    webhookUrl = "https://discord.com/api/webhooks/...",
    environment = "production",
    release = "v0.1.0",
    tags = { service = "main-game" },
})

LocalScript in StarterPlayer.StarterPlayerScripts:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Watcher = require(ReplicatedStorage.Watcher)

Watcher.init({
    environment = "production",
    release = "v0.1.0",
})

The webhookUrl is ignored on the client. Do not put your webhook URL in client code.

Manual capture

local ok, err = pcall(doThing)
if not ok then
    Watcher.captureException(err, { tags = { area = "shop" } })
end

Wrap a callback

Errors raised inside the wrapped function are reported and then re-raised, so existing error handling keeps working.

Players.PlayerAdded:Connect(Watcher.wrap(function(player)
    -- ...
end))

Attach player context

Watcher.captureException(err, Watcher.addPlayerContext(player))

Config

Field Default Notes
webhookUrl required on server Discord webhook URL. Ignored on client.
environment "unknown" e.g. production, staging
release "unknown" game version string
tags {} merged into every event
rateLimitPerMinute 30 hard cap before events are dropped
dedupeWindowSeconds 60 suppress same fingerprint within window
captureUnhandled true hook ScriptContext.Error
username "Watcher" webhook display name

A fingerprint is built from the first line of the error and the originating script. Line numbers and memory addresses are normalized so a flickering error groups as one.

Examples

examples/basic_usage.server.lua shows a typical server setup. examples/error_tests.server.lua and examples/error_tests.client.lua fire a handful of different error shapes on a timer, useful for verifying that the webhook actually receives events.

License

MIT

About

Error reporting for Roblox games. Luau SDK that posts unhandled errors to a Discord webhook.

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages