Discord
patrol.Discord sends one message per channel and per project in the batch. The body is rendered from patrol.DiscordTemplate, a text/template the package exports as a plain variable: message, type, capture time, the fields one per line, and the stacktrace frames with their editor links.
The constructor
Section titled “The constructor”patrol.NewDiscord(opts patrol.DiscordOptions) (*patrol.Discord, error)BotToken and Channels are required, and one error covers both: discord: BotToken and Channels are required. TimeZone is loaded at construction, so an invalid zone name fails here rather than at the first flush.
Options
Section titled “Options”| Field | Type | JSON | YAML and TOML | Required |
|---|---|---|---|---|
BotToken |
string |
bot_token |
BotToken |
yes |
Channels |
[]string |
channels |
Channels |
yes |
TimeZone |
string |
time_zone |
TimeZone |
no |
TimeZone is an IANA name such as Europe/Athens or UTC, used to render capture times. Empty means the local zone of the process, which on a container is usually UTC and on a laptop is not.
BotToken: ""Channels: - ""TimeZone: Europe/AthensGetting a bot token
Section titled “Getting a bot token”- User Settings, Advanced, turn on Developer Mode.
- At
discord.com/developers/applications, create an application and copy the client id from OAuth2. - Under Bot, add a bot and reset the token.
- Authorize it into your server with the
botscope. - Right click the channel, Copy ID, and add the bot to the channel’s members or roles.
What Test does
Section titled “What Test does”producer.Test(ctx) reads every channel in Channels with the bot token. It catches the two failures that look identical in production: a bad token, and a bot that is not in the channel.
A worked example
Section titled “A worked example”From _examples/basic/program:
// source: _examples/basic/program/main.go#L75-L80 // Discord. discordFlusher, err := patrol.NewDiscord(readConfig[patrol.DiscordOptions]("discord.yml")) if err != nil { log.Fatal(err) } eventFlushers = append(eventFlushers, discordFlusher)Changing the message
Section titled “Changing the message”patrol.DiscordTemplate is an exported variable. Reassign it before the first flush and every Discord message uses yours. The data it receives is one struct with an Events field, where each event has Message, Type, CapturedAt (already formatted in the configured zone), Fields, and Stacktrace, a list of frames with Function, Module, Location and Link. The same shape is handed to patrol.TwilioTemplate and patrol.EmailTemplate.
It is a package-level variable with no lock around it. Assign it at startup, not while a producer is running.
Gotchas
Section titled “Gotchas”Long batches hit Discord’s message limit. One project group becomes one message, however many events are in it, and the library does not split or truncate. A batch of a hundred events with stacktraces is far past what Discord accepts, and the rejection arrives on OnError as discord: .... Keep MaxBatchSize modest on a producer that sends to Discord, or use MergeWindow to collapse the repeats.
No files and no mentions. WithFile and WithMentions are ignored here. Files go to Slack only, and mentions are Slack user ids.
One message per channel, per project. Three channels and two project names in one batch is six messages.