π Just a reminder that there is a π button up there if you liked this project π π
DiscordLogger
is a swift-log implementation for sending your logs over to a Discord channel.
It uses DiscordBM to communicate with Discord.
Vapor community's Penny bot serves as a good example of utilizing this library.
Penny uses DiscordLogger
to send a select group of important logs to an internal channel, making it easy for maintainers to receive notifications about any potential issues.
Make sure you have Xcode 14.1 or above. Lower Xcode 14 versions have known issues that cause problems for libraries.
Make sure you've added swift-log and AsyncHTTPClient to your dependancies.
import DiscordLogger
import Logging
import AsyncHTTPClient
/// Make an `HTTPClient`.
/// If you've already made an `HTTPClient` somewhere else, you should use that instead.
let httpClient = HTTPClient(eventLoopGroupProvider: .createNew)
/// Configure the Discord Logging Manager.
DiscordGlobalConfiguration.logManager = await DiscordLogManager(httpClient: httpClient)
/// Bootstrap the `LoggingSystem`. After this, all your `Logger`s will automagically start using `DiscordLogHandler`.
/// Do not use a `Task { }` to avoid possible bugs. Wait before the `LoggingSystem` is bootstrapped.
await LoggingSystem.bootstrapWithDiscordLogger(
/// The webhook address to send the logs to.
/// You can easily create a webhook using Discord desktop app with a few clicks.
/// See https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks
/// There is a 'Making A Webhook' section there.
address: try .url(<#Your Webhook URL#>),
makeMainLogHandler: StreamLogHandler.standardOutput(label:metadataProvider:)
)
/// Make sure you haven't called `LoggingSystem.bootstrap` anywhere else, because you can only call it once.
/// For example Vapor's templates use `LoggingSystem.bootstrap` on boot, and you need to remove that.
DiscordLogManager
comes with a ton of useful configuration options.
Here is an example of a decently-configured DiscordLogManager
:
Read
DiscordLogManager.Configuration.init
documentation for full info.
DiscordGlobalConfiguration.logManager = await DiscordLogManager(
httpClient: httpClient,
configuration: .init(
aliveNotice: .init(
address: try .url(<#Your Webhook URL#>),
/// If nil, `DiscordLogManager` will only send 1 "I'm alive" notice, on boot.
/// If not nil, it will send a "I'm alive" notice every this-amount too, if there is no logging activity.
interval: nil,
message: "I'm Alive! :)",
color: .blue,
initialNoticeMention: .user("970723029262942248")
),
sendFullLogAsAttachment: .enabled,
mentions: [
.warning: .role("970723134149918800"),
.error: .role("970723101044244510"),
.critical: .role("970723029262942248"),
],
extraMetadata: [.warning, .error, .critical],
disabledLogLevels: [.debug, .trace],
disabledInDebug: false
)
)
/// After bootstrapping the `LoggingSystem`, and with the configuration above, but `extraMetadata` set to `[.critical]`
let logger = Logger(label: "LoggerLabel")
logger.warning("Warning you about something!")
logger.error("We're having an error!", metadata: [
"number": .stringConvertible(1),
"statusCode": "401 Unauthorized"
])
logger.critical("CRITICAL PROBLEM. ABOUT TO EXPLODE π₯")
Note
DiscordLogger
is not meant to replace your on-disk logging, as it can be much less consistent due to nature of logging over the network and also sending messages to Discord.- The library is meant to provide a convenience way of keeping track of your important logs, while still using the usual on-disk logs for full investigations if needed.
- With Penny, we log everything at
debug
/trace
level to stdout for AWS to pick up, while setting theDiscordLogManager
to send thewarning
/error
and a fewinfo
/notice
logs to Discord.- This way we are immediately notified of important
error
/wraning
s, while using the AWS logs for full investigations if needed.
To use the DiscordLogger
library in a SwiftPM project,
add the following line to the dependencies in your Package.swift
file:
.package(url: "https://github.com/DiscordBM/DiscordLogger", from: "1.0.0-beta.1"),
Include DiscordLogger
as a dependency for your targets:
.target(name: "<target>", dependencies: [
.product(name: "DiscordLogger", package: "DiscordLogger"),
]),
Finally, add import DiscordLogger
to your source code.
DiscordLogger
follows Semantic Versioning 2.0.0.
Any contribution is more than welcome. You can find me in Vapor's Discord server to discuss your ideas.