LoggerTelegramBackend

Build StatusDocsHex.pm

A logger backend for Telegram.

Intended for low-volume notifications: a handful of alerts to a chat, not log shipping. See Caveats before reaching for it.

Installation

Add :logger_telegram_backend and :finch to your list of dependencies in mix.exs:

def deps do
[
{:logger_telegram_backend, "~> 4.0"},
{:finch, "~> 0.22"},
]
end

Add the backend

In your Application.start/2 callback, add the LoggerTelegramBackend:

@impl true
def start(_type, _args) do
{:ok, _pid} = LoggerTelegramBackend.attach()
# ...
end

Add the following to your configuration:

config :logger, LoggerTelegramBackend,
chat_id: "your_chat_id",
token: "your_bot_token"

Configure the Telegram bot

To create a Telegram bot, follow the instructions here and get the token for the bot.

Then send a message to the bot and get your chat_id:

TOKEN="your_bot_token"
curl https://api.telegram.org/bot$TOKEN/getUpdates

Caveats

Messages are sent synchronously from the Logger event manager, so a slow or unreachable Telegram API blocks the process that called Logger.error/1. Once Logger's :sync_threshold is crossed the stall spreads to every process that logs, and once :discard_threshold is crossed events are dropped for all backends attached to the event manager, not just this one. Telegram also rate limits to roughly one message per second per chat, and nothing here queues, retries or rate limits.

Keep :level at :warning or :error, narrow further with :metadata_filter, and set a timeout via :client_request_opts, since Finch defaults :request_timeout to :infinity on HTTP/1. For high-throughput or delivery-critical logging, use a dedicated log aggregator.

Configuration

All options live under the LoggerTelegramBackend key of the :logger application. Since the token and chat id are secrets, read them at runtime from config/runtime.exs:

# config/runtime.exs
config :logger, LoggerTelegramBackend,
chat_id: System.fetch_env!("TELEGRAM_CHAT_ID"),
token: System.fetch_env!("TELEGRAM_TOKEN"),
level: :warning
OptionDescriptionDefault
:tokenBot token. Required.
:chat_idChat to send messages to. Required.
:levelLowest level this backend sends. Events are filtered by the :logger application's own :level first.nil (everything)
:metadataMetadata keys to include, or :all for everything.[:line, :function, :module, :application, :file]
:metadata_filterKey-value pairs or bare keys that must be present for a message to be sent.[]
:clientModule implementing the LoggerTelegramBackend.HTTPClient behaviour.LoggerTelegramBackend.HTTPClient.Finch
:client_pool_optsOptions for the HTTP client pool. See Finch.start_link/1.[]
:client_request_optsOptions passed to each request. See Finch.request/3.[]

Invalid or missing options are reported as a LoggerTelegramBackend.ConfigError when the backend is attached. Options can also be changed at runtime with LoggerTelegramBackend.configure/1.

Filtering messages

:metadata_filter restricts which messages are sent. Every entry must match:

# metadata must contain application: :core
config :logger, LoggerTelegramBackend, metadata_filter: [application: :core]
# metadata must contain the key :user, set to any value
config :logger, LoggerTelegramBackend, metadata_filter: [:user]
# metadata must contain application: :core AND the key :user
config :logger, LoggerTelegramBackend, metadata_filter: [{:application, :core}, :user]

Using a proxy

An HTTP proxy is configured through :client_pool_opts:

config :logger, LoggerTelegramBackend,
client_pool_opts: [conn_opts: [proxy: {:http, "127.0.0.1", 8888, []}]]

See Finch's pool configuration options for the rest.

Using a different HTTP client

Finch is the default but not a requirement. Implement the LoggerTelegramBackend.HTTPClient behaviour and point :client at it to use something else, in which case :finch can be dropped from your dependencies. See LoggerTelegramBackend.HTTPClient for an example built on :hackney.

License

This project is Licensed under the MIT License.