Eventum Logo

Eventum

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>/getUpdates to find it)

Project structure

eventum.yml
startup.yml
generator.yml
alert.jinja

Build it

Create the project directory

mkdir -p eventum/generators/alerts/templates
cd eventum

Write 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.

generators/alerts/templates/alert.jinja
{% 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-primary

CPU usage: 95% Host: srv-db-01.example.com Time: 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.

generators/alerts/generator.yml
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: plain

The 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

eventum.yml
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.cfg

All path.* values must be absolute paths. Adjust to match your actual project location.

The startup file passes the chat ID as a parameter:

startup.yml
- 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_token

Enter your bot token when prompted (e.g., 110201543:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw).

Run it

eventum run -c eventum.yml

Every 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/end fields to suppress alerts during maintenance windows.

What's next

On this page