Back to Home

Redash Bot in Mattermost: charts automation

Script automates sending charts from Redash to Mattermost: fetches data via API, builds visualizations in matplotlib with annotations, combines into dashboard with PIL and publishes to channel. Includes data freshness checks and duplicate protection. Suitable for team daily BI reports.

Automate Redash: charts in Mattermost daily
Advertisement 728x90

Automating Redash Dashboards: Sending Charts to Mattermost

A Python script solves the task of automatically delivering charts from Redash to Mattermost. It fetches data via API, recreates visualizations in matplotlib, combines them into a single dashboard, and sends it to a channel. Ideal for teams where data updates with a delay and manual dashboard review is inefficient.

The pipeline runs on a cron job: it checks data freshness, builds charts with annotations, and publishes the final report before the workday begins.

Fetching Data from Redash API

Redash provides an API to execute queries by query_id with parameters. The main function:

Google AdInline article slot
import requests

BASE_URL = 'https://your-redash-instance'
HEADERS = {'Authorization': 'Key YOUR_API_KEY'}

def fetch_query(query_id, params):
    response = requests.post(
        f'{BASE_URL}/api/queries/{query_id}/results',
        headers=HEADERS,
        json={'parameters': params, 'max_age': 0},
    )
    return response.json()

If the result isn't ready, the API returns a job — implement polling to wait for completion. For dashboards, parse parameters from the URL:

from urllib.parse import parse_qs, urlparse

def parse_dashboard_url(url):
    parsed = urlparse(url)
    params = parse_qs(parsed.query)
    return {
        key: value[0]
        for key, value in params.items()
    }

Convert dynamic dates like 'last 7 days' manually:

from datetime import datetime, timedelta

def last_7_days():
    today = datetime.utcnow()
    return {
        'start': (today - timedelta(days=7)).strftime('%Y-%m-%d'),
        'end': today.strftime('%Y-%m-%d')
    }

Building and Annotating Charts

Visualizations are built in matplotlib, mimicking Redash styles: colors, line types, sizes. A basic line chart example:

Google AdInline article slot
import matplotlib.pyplot as plt

def build_chart(df):
    fig, ax = plt.subplots(figsize=(6, 4))

    ax.plot(df['date'], df['value'], linewidth=2)
    ax.plot(df['date'], df['plan'], linewidth=2)

    ax.set_title('Metric dynamics')

    return fig

The key step is annotations for readability in static images. Add the latest value, week-over-week change, deviation from plan:

ax.annotate(
    f"value: {last_value}",
    xy=(last_date, last_value),
    xytext=(10, 10),
    textcoords='offset points'
)

This allows metrics to be understood without interactivity.

Combining Charts into a Dashboard

Multiple charts (by metrics, categories) are merged into one image using PIL for better UX:

Google AdInline article slot
from PIL import Image

def merge_images(images, output_path):
    base = Image.new('RGB', (1200, 800), 'white')

    for img, pos in images:
        base.paste(img, pos)

    base.save(output_path)

Add section headers by department or theme for navigation.

Checks and Duplicate Protection

The script checks for the target date in the data:

if df['date'].max() != target_date:
    raise Exception('Data not updated yet')

Protection against duplicate sends via a state file:

from pathlib import Path

STATE_FILE = Path('last_sent.txt')

def was_sent(date):
    return STATE_FILE.exists() and STATE_FILE.read_text() == str(date)

Sending to Mattermost

Use mattermostdriver to upload the file and post:

from mattermostdriver import Driver

mm = Driver({
    'url': 'your-mattermost',
    'token': 'BOT_TOKEN',
})

mm.login()

mm.posts.create_post({
    'channel_id': channel_id,
    'message': 'Report ready',
    'file_ids': [file_id],
})

Key Points

  • Automation reduces manual effort: charts arrive in the messenger automatically upon data updates.
  • Annotations on charts ensure full informativeness without hover interactions.
  • Combining into one dashboard improves UX in chat.
  • Freshness and duplicate checks guarantee pipeline reliability.
  • Easy to scale: add new query_ids and parameters.

— Editorial Team

Advertisement 728x90

Read Next