Scheduled Telegram Alerts
Simulate a monitoring system that sends alert notifications to a Telegram chat on a cron schedule.
Build a generator that simulates infrastructure monitoring alerts and delivers them to a Telegram chat via the Bot API. Alerts fire on a cron schedule with randomized severity and service names — a miniature alerting pipeline in a few files.
What you'll build
The generator uses:
- cron input — fires every 2 minutes.
- Template with conditional Jinja2 logic — different message format per severity level.
- HTTP output — sends POST requests to the Telegram Bot API.
- Secrets — bot token stored securely in the keyring.
- Parameters — chat ID passed through
startup.yml.
Prerequisites
- Eventum installed
- A Telegram bot token (create one via @BotFather)
- The chat ID of the target chat (send a message to your bot, then query
https://api.telegram.org/bot<TOKEN>/getUpdatesto find it)
Project structure
Build it
Create the project directory
mkdir -p eventum/generators/alerts/templates
cd eventumWrite the alert template
The template produces a JSON body for the Telegram sendMessage API. It uses module.rand to pick a random severity and service, then builds a Markdown-formatted message with an emoji indicator.
{% set severity = module.rand.weighted_choice(["info", "warning", "critical", "resolved"], [0.4, 0.35, 0.2, 0.05]) %}
{% set service = module.rand.choice(["api-gateway", "auth-service", "db-primary", "cache-redis", "worker-queue", "nginx-lb"]) %}
{% set icons = {"info": "\u2139\ufe0f", "warning": "\u26a0\ufe0f", "critical": "\ud83d\udd34", "resolved": "\u2705"} %}
{% set metric = module.rand.choice(["CPU usage", "memory usage", "request latency", "error rate", "disk I/O", "connection pool"]) %}
{% if severity == "critical" %}
{% set value = module.rand.number.integer(90, 100) %}
{% elif severity == "warning" %}
{% set value = module.rand.number.integer(70, 89) %}
{% else %}
{% set value = module.rand.number.integer(10, 69) %}
{% endif %}
{
"chat_id": {{ params.chat_id }},
"parse_mode": "Markdown",
"text": "{{ icons[severity] }} *{{ severity | upper }}* | `{{ service }}`\n\n{{ metric }}: *{{ value }}%*\nHost: `{{ module.faker.locale.en.hostname() }}`\nTime: {{ timestamp.strftime('%H:%M:%S UTC') }}"
}The message looks like this in Telegram:
🔴 CRITICAL |
db-primaryCPU usage: 95% Host:
srv-db-01.example.comTime: 14:30:00 UTC
Configure the generator
The cron expression 0 */2 * * * * fires at second 0 of every 2nd minute. The HTTP output posts to the Telegram API endpoint.
input:
- cron:
expression: "0 */2 * * * *"
count: 1
event:
template:
mode: all
params:
chat_id: ${params.chat_id}
templates:
- alert:
template: templates/alert.jinja
output:
- stdout: {}
- http:
url: "https://api.telegram.org/bot${secrets.telegram_token}/sendMessage"
method: POST
success_code: 200
headers:
Content-Type: "application/json"
formatter:
format: plainThe plain formatter passes the template output as-is — the template already produces a valid JSON request body. The stdout output is included for local debugging; remove it in production.
Configure the application
server:
host: "0.0.0.0"
port: 9474
path:
startup: /home/user/eventum/startup.yml
generators_dir: /home/user/eventum/generators
logs: /home/user/eventum/logs
keyring_cryptfile: /home/user/eventum/cryptfile.cfgAll path.* values must be absolute paths. Adjust to match your actual project location.
The startup file passes the chat ID as a parameter:
- id: alerts
path: alerts/generator.yml
params:
chat_id: "123456789"Replace 123456789 with your actual Telegram chat ID.
Store the bot token
The bot token is sensitive — store it in the keyring:
eventum-keyring set telegram_tokenEnter your bot token when prompted (e.g., 110201543:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw).
Run it
eventum run -c eventum.ymlEvery 2 minutes, an alert message appears in your Telegram chat. The terminal shows the raw JSON body on stdout:
{
"chat_id": 123456789,
"parse_mode": "Markdown",
"text": "\u26a0\ufe0f *WARNING* | `cache-redis`\n\nmemory usage: *78%*\nHost: `srv-cache-02.example.com`\nTime: 14:32:00 UTC"
}Going further
- Escalation schedule — use multiple inputs with different cron expressions: check every 2 minutes during business hours, every 10 minutes overnight.
- Incident sequences — switch to FSM mode to model alert → acknowledged → investigating → resolved workflows.
- Slack or Discord — swap the Telegram API URL for a Slack Incoming Webhook or Discord Webhook URL and adjust the JSON payload accordingly.
- Silence window — use the cron
start/endfields to suppress alerts during maintenance windows.