Skip to content

stevapple/swift-log-telegram

Repository files navigation

LoggingTelegram ✈️

Swift Release License

Welcome to LoggingTelegram – a logging backend for SwiftLog that sends log messages by a Telegram Bot.

Inspired by and forked from LoggingSlack.

Installation 📦

LoggingTelegram requires Xcode 11 or a Swift 5.2 toolchain with the Swift Package Manager.

Add the LoggingTelegram package as a dependency to your Package.swift file.

.package(url: "https://github.com/stevapple/swift-log-telegram.git", from: "0.0.1")

Add LoggingTelegram to your target's dependencies.

.target(name: "Example", dependencies: ["LoggingTelegram"])

Then start using by:

import LoggingTelegram

Usage 📝

Setup a Telegram Bot

LoggingTelegram uses Telegram Bot API to send log messages to any Telegram chat.

You can chat with BotFather to create a new bot and get its API token. The config methods are described here.

You need to pass the token to TelegramLogHandler.init to set it up.

Get a Target Chat ID

You can access a chat by its ID. There are various ways to get the ID of a chat, some are discussed in this thread.

You can create a group chat with TelegramGroup.id(_:Int), a channel with TelegramChannel.id(_:Int) and a user chat with TelegramUser.id(_:Int).

Alternatively, you can create a channel by its name: TelegramChannel.name(_:String), remember to drop @ prefix.

Bootstrap SwiftLog

LoggingTelegram is intended to be used as a secondary logging backend to send urgent log messages directly to Telegram.

You can use SwiftLog's MultiplexLogHandler to setup LoggingTelegram with another logging backend.

import Logging
import LoggingTelegram

let channel = TelegramChannel.name("test").mentioning([1, 3]).mentioning("2")

LoggingSystem.bootstrap { label in
    MultiplexLogHandler([
        // Setup TelegramLogHandler with your API Token and Chat instance
        TelegramLogHandler(label: label, token: "Your Bot Token Here", chat: channel),
        
        // Setup the standard logging backend to enable console logging
        StreamLogHandler.standardOutput(label: label),
        
        // Setup multiple TelegramLogHandlers
        // TelegramLogHandler(label: label, token: "Your (Another) Bot Token Here", chat: TelegramGroup.id(123))
    ])
}

Since SwiftLog does not support parallel logs and that network connection takes time, loggers after the TelegramLogHandler may need to wait for its HTTP request sometimes.

If you want to get the precise timestamp at the console, you may put TelegramLogHandler after StreamLogHandler:

import Logging
import LoggingTelegram

let channel = TelegramChannel.name("test").mentioning([1, 3]).mentioning("2")

LoggingSystem.bootstrap { label in
    MultiplexLogHandler([
        StreamLogHandler.standardOutput(label: label),
        TelegramLogHandler(label: label, token: "Your Bot Token Here", chat: channel),
        TelegramLogHandler(label: label, token: "Your (Another) Bot Token Here", chat: TelegramGroup.id(123))
    ])
}

Create and Use a Logger

You can now use SwiftLog as usual and critical log messages are sent directly to Telegram. Test code as below.

import Logging

let logger = Logger(label: "com.example.ExampleApp.main")

logger.critical("Oops, something went wrong!")

Check Logger Outputs

The logger will send a Telegram message as a bot (if the level matches) and a console message since both logging backends were setup. The example above gives the following outputs:

Telegram message

2020-04-07T16:05:25+0800 critical: Oops, something went wrong!

Configure Log Level

Only messages of log level critical are sent to Telegram by default.

You can adjust the minimal log level for a specific TelegramLogHandler by setting its logLevel property, or initializing with a level property.

var handler = TelegramLogHandler(label: "test", token: "Your Bot Token Here", chat: TelegramGroup.id(123), level: .error)
// Unrecommended! Low log levels may burden the server and abuse the Telegram function
handler.logLevel = .info

You can change the default for all TelegramLogHandlers by changing the value of telegramLogDefaultLevel.

telegramLogDefaultLevel = .error

Remember, the TelegramLogHandler.logLevel property has a priority to telegramLogDefaultLevel.

@Someone in a Group Chat or a Channel

You can mention someone in a group chat or a channel, simply by the various .mentioning() APIs, listed below:

import LoggingTelegram

var chat = TelegramChannel.name("test")

// By TelegramUser
let users = [1,2].map { TelegramUser.id($0) }
chat = chat.mentioning(users) // Returns a new TelegramChannel instance
// You can use his username to mention a user
let user = TelegramUser.name("testme")
chat = chat.mentioning(user)

// By TelegramRawId (A more flexible alias of the "TelegramUser" version)
chat = chat.mentioning(.id(3))
chat = chat.mentioning([.name("newtest"), .id(4)])

// By User ID
chat = chat.mentioning(5)
chat = chat.mentioning([6,7,8])

// By Username
chat = chat.mentioning("test 1")
chat = chat.mentioning(["test 2", "test 3"])

In brief, the chaining style is recommended when creating a chat:

import LoggingTelegram

TelegramChannel.name("test").mentioning([.id(1), .name("2"), .id(3)])
// or
TelegramChannel.name("test").mentioning([1, 3]).mentioning("2")

Mute the Messages

To not disturb subscribers, you may need to mute the message. You can pass a mute: Bool to the initializer to make it silent:

TelegramLogHandler(label: label, token: "Your Bot Token Here", chat: channel, mute: true)

The mentioned users won't be muted.

Attention ⚠️

You should know what you're doing though this package. Do not use it at client-side to protect the subscribers' info and your Bot Token.