Sending OpenObserve Alerts to Telegram

WhatDoesKmean?WhatDoesKmean?
4 min read

A couple of days ago, I started playing around with OpenObserve, and I have to say… I'm impressed.

For those who haven't heard of it yet, OpenObserve is a modern, high-performance observability platform that lets you collect, store, and analyze logs, metrics, traces, and more, all in one place, with a sleek UI and great flexibility.

Not only can you create dashboards and take advantage of a vast collection of Apache ECharts visualizations to make your data shine, but you can also set up powerful alerting pipelines that notify you instantly, like sending messages to Telegram when something important happens.

What I love most about it:

  • Simplicity, easy to deploy and configure, even for quick experiments.

  • Speed, it handles queries on large datasets really well.

  • Flexibility, it integrates nicely with custom pipelines, alerting, and destinations like Telegram.

A special thank you to Md Mosaraf for all the support and for taking the time to meet with me!

In this article, I'm going to walk you through how I connected OpenObserve alerts directly to Telegram, so any event matching my criteria pops up on my phone instantly.

Prerequisites (one-time)

  • A Telegram bot token

  • Your Telegram chat_id (user, group, or channel)

Quick test (optional, proves token/chat_id work):

curl -X POST "https://api.telegram.org/bot<YOUR_BOT_TOKEN>/sendMessage" \
  -H "Content-Type: application/json" \
  -d '{"chat_id":"<YOUR_CHAT_ID>", "text":"OpenObserve test..."}'

If you get a message in Telegram, you're good.

1) Open the Management area

  • Click the gear icon (top-right) to open Management.

  • In the left menu, you'll use Alert Destinations and Templates.

2) Create the Telegram message template

  • Go to Management > Templates > New.

  • Name it: <YOUR_CUSTOM_NAME>.

  • Body (JSON). Paste this, replacing placeholders with your real IDs where noted:

{ 
    "chat_id": "<YOUR_CHAT_ID>", 
    "text": "{alert_name} is active \nOrganization: {org_name}\nStream: {stream_name}\nType: {alert_type}\nDetails:\n{rows}"
}
  • Note: \n makes new lines in Telegram.

  • {rows} will be replaced by one line per matching event, formatted by your Row Template in the alert (Step 4). If you leave Row Template empty, you'll see unhelpful {} lines.

Save the template.

3) Create the Alert Destination (Webhook)

Important: use POST with JSON. (Putting chat_id & text in the URL query string will cause 400 errors)

4) Build the Alert rule

Go to Alerts > New Alert (or edit an existing one) and configure:

Alert Setup

  • Name: any (i.e, Test)

  • Select Folder: for me is "default"

  • Stream Type: logs (as in your shot)

  • Stream Name: pick your stream (in my case, "leonardo")

  • Scheduled Alert (not Real-Time)

Alert Settings

  • Aggregation > Threshold: >= 1 Time

  • Period: 3 Minutes

  • Frequency: 3 Minutes (how often to evaluate)

  • Silence notification for: 1 Minutes (prevents spam)

  • Destination: choose Telegram, then Add New Destination

Conditions

  • Quick Mode example: level = warn (Use whatever field/value makes sense for your data)

Advanced Setup

Variables > Row Template (this is what populates {rows} in Telegram):

Example (adjust field names to what your stream actually has):

{@timestamp} {level} {source_ip} -> {destination_ip} {action} {protocol} {port}
  • You can include any fields from the event. Each matching event produces one line in the Telegram message.

Save the alert.

5) Verify

Trigger a log/event that matches your condition, for example:

curl -u <USER>:<ENCRYPT_PASS> -k http://127.0.0.1:5080/api/default/leonardo/_json -d '
  [
    {"level":"warn","timestamp":"'$(date -u +"%Y-%m-%dT%H:%M:%SZ")'","source_ip":"192.168.1.1","destination_ip":"8.8.8.8","action":"ACCEPT","protocol":"TCP","port":80},
    {"level":"warn","timestamp":"'$(date -u +"%Y-%m-%dT%H:%M:%SZ")'","source_ip":"10.0.0.5","destination_ip":"1.1.1.1","action":"DROP","protocol":"UDP","port":53},
    {"level":"warn","timestamp":"'$(date -u +"%Y-%m-%dT%H:%M:%SZ")'","source_ip":"172.16.2.20","destination_ip":"208.67.222.222","action":"ACCEPT","protocol":"ICMP","port":0},
    {"level":"warn","timestamp":"'$(date -u +"%Y-%m-%dT%H:%M:%SZ")'","source_ip":"203.0.113.12","destination_ip":"192.168.1.254","action":"REJECT","protocol":"TCP","port":22}
  ]
' -X POST --limit-rate 50k -H "Content-Type: application/json" --compressed -s -w 'Total: %{size_upload}B | Time: %{time_total}s | Speed: %{speed_upload}B/s\n' --trace-ascii /dev/null --connect-timeout 30 -m 60

After a couple of minutes, you should receive a Telegram message like this:

That’s it… Your OpenObserve alerts now flow to Telegram using your template and destination!!! πŸš€

Now you know!!! πŸ˜‰

0
Subscribe to my newsletter

Read articles from WhatDoesKmean? directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

WhatDoesKmean?
WhatDoesKmean?

CyberSecurity πŸ‘½ | Splunk Ninja 🦸 | DataDog Tamer 🐾 | Sumo Logic Fighter 🧌 | Wazuh Explorer πŸ§™β€β™‚οΈ | EkoParty 2021 πŸŽ‰ & SANS DFIR 2022 πŸ”‘ Speaker