Pacote Django para gerenciamento de bots e tarefas de RPA
Project description
botapp
botapp é um SDK + dashboard Django para observabilidade de automações RPA. Ele instrumenta seus bots com um único decorator, registra cada execução (sucesso, falha, duração, ambiente), expõe um painel web para acompanhamento e dispara alertas (Slack, Discord, e-mail) quando algo foge do esperado.
Sumário
- Visão geral
- Funcionalidades
- Arquitetura — modos de uso
- Instalação
- Início rápido
- Modelo de dados
- SDK — instrumentando bots
- Dashboard web
- Sistema de alertas
- API REST
- Comandos de gerência
- Variáveis de ambiente
- Deploy em produção
- Troubleshooting
- Desenvolvimento local
- Licença
Visão geral
Quando você mantém uma frota de bots RPA, a dor de cabeça não é escrever o bot — é saber quando ele parou de rodar, quando passou a falhar demais ou quando está mais lento do que deveria. O botapp resolve isso com três camadas acopladas:
- SDK (
from botapp import BotApp) — um decorator@app.taskque envolve suas funções e grava cada execução no banco automaticamente. - Dashboard web — painel administrativo Django com listagens, detalhes de logs, exploração filtrada, exportação CSV/PDF e gestão de alertas.
- Motor de alertas — um scheduler que varre periodicamente o banco em busca de anomalias (
silent_bot,error_spike,heartbeat_lost,duration_regression) e dispara notificações em Slack, Discord e e-mail.
Todos os três podem ser usados em conjunto ou separadamente.
Funcionalidades
Observabilidade
- Decorator único para instrumentar tarefas (
@app.task), com captura automática de:host_name,host_ip,user_login,pid,bot_diros_platform,python_version,env(dev/staging/prod)start_time,end_time,duration,status,exception_type,error_message,trigger_source.
- Denormalização
Bot.last_execution_at/Bot.last_statusviapost_savesignal para listagens rápidas. - Função
reconcile_bot_last_execution()para self-heal quando SDKs antigos escrevem logs sem disparar signals.
Dashboard
- Lista de bots com status, última execução, contadores, filtros por departamento/status.
- Detalhe do bot com histórico paginado de execuções, gráficos de taxa de erro e duração.
- Página Dashboard global com contadores agregados (bots ativos, silenciosos, alertas críticos).
- Explore — filtros combinados em TaskLog com exportação CSV.
- Manutenção — ações de limpeza de órfãos e configuração em massa de thresholds por bot.
- Tema responsivo, CSP opcional, rate limiting em rotas sensíveis.
Alertas
- 4 regras de detecção prontas, todas com severidade graduada (
low,medium,high,critical):- silent_bot — bot ativo sem execução há mais de N horas/minutos.
- error_spike — pico de falhas em janela recente.
- heartbeat_lost — log com
status='started'que nunca fechou. - duration_regression — duração média recente acima do SLA da task.
- Idempotência: não cria alerta duplicado se já existir um ativo do mesmo tipo para o mesmo bot.
- Dispatcher multi-canal com fallback tolerante (Slack, Discord, e-mail).
- Ações de
acknowledgeeresolvevia UI ou REST. - Override de threshold por bot (
silence_threshold_hours,silence_threshold_minutes).
API REST
- DRF com
ViewSetsparaBot,Task,TaskLog. - Autenticação
SessionAuthentication+BasicAuthentication. - Permissão padrão:
IsAuthenticated. - Rate limiting em endpoints sensíveis via
django-ratelimit.
Operacional
- Comandos de gerência para setup, scheduler, limpeza de órfãos e reconciliação.
- Thread in-process opcional para dev (
BOTAPP_ALERT_SCHEDULER_ENABLED). - Comando dedicado para produção multi-worker:
botapp run_alert_scheduler.
Arquitetura — modos de uso
O botapp pode ser consumido de duas formas, detectadas automaticamente em botapp/__init__.py:
Modo standalone
Quando DJANGO_SETTINGS_MODULE não está definido, o pacote usa seu próprio botapp.settings. É assim que o dashboard é servido como serviço autônomo.
from botapp import BotApp # resolve para botapp.core.BotApp
app = BotApp('meu_banco')
- Grava direto no Postgres usando os modelos Django.
- Ideal para bots que rodam no mesmo host/rede do banco.
Modo plugin (REST client)
Quando o SDK é importado dentro de outro projeto Django (DJANGO_SETTINGS_MODULE definido e ROOT_URLCONF diferente de botapp.urls), BotApp é substituído por BotAppRestful, que fala com um dashboard remoto via HTTP.
# Em outro projeto Django, com BOTAPP_API_URL apontando para o dashboard remoto
from botapp import BotApp # resolve para botapp.core_restful.BotAppRestful
app = BotApp()
- Não exige acesso direto ao banco.
- Perfeito para bots embarcados em aplicações maiores ou em redes segregadas.
- Requer
BOTAPP_API_URL,BOTAPP_API_USUARIO,BOTAPP_API_SENHA.
Instalação
Requisitos: Python 3.8+, Django 3.2+, Postgres 12+ (SQLite funciona para testes).
pip install botapp
Dependências instaladas automaticamente: Django, psycopg2-binary, djangorestframework, django-admin-rangefilter, django-ratelimit, whitenoise, python-dotenv, openpyxl, xhtml2pdf, requests.
Início rápido
1. Configure o ambiente
Crie um .env na raiz do projeto:
BOTAPP_DEBUG=True
BOTAPP_SECRET_KEY=troque-em-producao
BOTAPP_ALLOWED_HOSTS=*
# Postgres
PG_BOTAPP_SCHEMA=botapp_schema
PG_BOTAPP_DBNAME=botapp
PG_BOTAPP_USER=botapp
PG_BOTAPP_PASSWORD=senha
PG_BOTAPP_HOST=localhost
PG_BOTAPP_PORT=5432
# Superusuário inicial (criado pelo comando setup)
BOTAPP_SUPERUSER_USERNAME=admin
BOTAPP_SUPERUSER_EMAIL=admin@example.com
BOTAPP_SUPERUSER_PASSWORD=troque-em-producao
2. Inicialize o banco
botapp setup # cria schema + roda migrations + cria superusuário
3. Suba o dashboard
botapp runserver 0.0.0.0:8000
Acesse http://localhost:8000/.
4. Instrumente um bot
from botapp import BotApp
app = BotApp('botapp') # mesmo PG_BOTAPP_DBNAME
app.set_bot(
bot_name='relatorio_diario',
bot_description='Consolida vendas do dia',
bot_version='1.0.0',
bot_department='Financeiro',
)
@app.task
def gerar_relatorio():
"""Gera e envia o relatório diário."""
# seu código aqui
return 'ok'
gerar_relatorio() # será registrada como TaskLog automaticamente
Modelo de dados
Bot
├── name, description, version, department
├── is_active
├── last_execution_at (denorm) ← atualizado pelo signal em TaskLog
├── last_status (denorm)
├── silence_threshold_hours/minutes ← override por bot do limiar de silent_bot
└── tasks (1:N)
Task
├── bot (FK)
├── name (__name__ da função decorada)
├── description (docstring)
├── expected_duration_seconds ← SLA usado pelo detector de regressão
└── logs (1:N)
TaskLog
├── task (FK)
├── status ← started | completed | failed
├── start_time / end_time / duration
├── result_data (JSON) ← retorno da função serializado
├── error_message / exception_type ← traceback do erro, se houver
├── host_ip, host_name, pid, user_login, os_platform, python_version
├── bot_dir, env, trigger_source, manual_trigger
└── indexes: -start_time, task+-start_time, status+-start_time, env+-start_time
Alert
├── type ← silent_bot | error_spike | heartbeat_lost | duration_regression
├── severity ← low | medium | high | critical
├── bot (FK, nullable) ← null = alerta global
├── message, payload (JSON)
├── created_at / updated_at
├── acked_at, acked_by (FK User) ← reconhecimento manual
├── resolved_at, resolved_by ← resolução manual
└── notified_at ← última vez que o dispatcher enviou
Migrations relevantes:
0008_indexes_performance— índices de performance em TaskLog.0009_bot_last_execution_denorm— campos denormalizados em Bot.0010_alerts— tabelaAlert.0011_task_expected_duration_seconds— SLA por task.0012_bot_silence_threshold_minutes— granularidade fina por bot.
SDK — instrumentando bots
BotApp (standalone)
from botapp import BotApp
app = BotApp(db_name='botapp')
app.set_bot(
bot_name='meu_bot', # normalizado: só alfanuméricos, capitalize
bot_description='O que faz',
bot_version='1.2.3',
bot_department='TI',
)
@app.task
def minha_tarefa(arg1, arg2):
"""Docstring vira a description da Task."""
return {'ok': True}
Comportamento do decorator:
- Se o bot estiver
is_active=False, a execução é bloqueada com exceção. - Cria/recupera a
Taskpelofunc.__name__e atualiza a description se a docstring mudou. - Cria
TaskLog(status='started')com snapshot do ambiente. - Executa a função. Em caso de exceção, grava
exception_type+error_messagee re-lança. - No
finally, setaend_timee o status final.
BotAppRestful (modo plugin)
# Em outro projeto Django
from botapp import BotApp # resolve para BotAppRestful se detectar host Django
app = BotApp() # usa BOTAPP_API_URL do env
app.set_bot('meu_bot', 'desc', '1.0', 'TI')
@app.task
def tarefa():
...
O fluxo é o mesmo, mas todas as operações batem na API REST do dashboard remoto via requests. Credenciais vêm de BOTAPP_API_USUARIO / BOTAPP_API_SENHA (HTTP Basic).
Dashboard web
Rotas principais (prefixadas por / quando em modo standalone):
| Rota | Descrição |
|---|---|
/bots/ |
Lista de bots com filtros. |
/bots/<id>/ |
Detalhe do bot: execuções, métricas, gráficos. |
/bot/<id>/toggle-status/ |
Liga/desliga bot (POST). |
/log/<id>/ |
Detalhe completo de um TaskLog. |
/dashboard/ |
Painel agregado: bots ativos, silenciosos, alertas. |
/alerts/ |
Lista de alertas (filtros: status, severity, type, bot). |
/alerts/<id>/ack/ |
POST — ack um alerta. |
/alerts/<id>/resolve/ |
POST — resolve um alerta. |
/alerts/unread-count/ |
JSON para badge do menu (polling leve). |
/maintenance/cleanup-orphans/ |
UI para acionar cleanup_orphans via HTTP. |
/maintenance/silence-thresholds/ |
Edição em massa de thresholds de silent_bot. |
/bots/bulk-silence-threshold/ |
Ação em massa dos thresholds. |
/explore/ |
Filtros combinados em TaskLog. |
/explore/export.csv |
Exporta o resultado filtrado como CSV. |
/admin/ |
Django admin. |
/api/ |
API REST (ver seção API REST). |
/accounts/login/ · /accounts/logout/ |
Autenticação. |
/accounts/password_reset/… |
Fluxo completo de reset por e-mail. |
Sistema de alertas
Regras
| Tipo | Dispara quando | Severidade calculada em função de |
|---|---|---|
silent_bot |
Bot is_active sem execução há mais de N horas (override por bot ok). |
horas_silencio / threshold |
error_spike |
≥ X falhas em janela deslizante de M minutos. | falhas / threshold |
heartbeat_lost |
Log com status='started' mais antigo que N horas. |
Severidade fixa por idade |
duration_regression |
Média das últimas N execuções acima de expected_duration_seconds × k. |
duração_média / expected |
Dispatcher (notifiers.py)
Ao criar um alerta, check_alerts chama dispatch_alert(alert) que envia para todos os canais configurados. Cada canal é opt-in: se a env var correspondente não estiver definida, o canal é silenciosamente ignorado. Uma falha em um canal não bloqueia os outros.
- Slack: webhook com attachment colorido por severidade.
- Discord: embed com cor hex equivalente.
- E-mail: usa
settings.EMAIL_*(SMTP do Django) com lista de destinatários emBOTAPP_ALERT_EMAIL_RECIPIENTS.
Se qualquer canal teve sucesso, alert.notified_at é atualizado — assim, executar check_alerts em intervalo curto não re-dispara notificações a cada rodada.
Como rodar o detector
Desenvolvimento (thread in-process, single worker):
BOTAPP_ALERT_SCHEDULER_ENABLED=true
BOTAPP_ALERT_SCHEDULER_INTERVAL_SECONDS=60
Ao subir o Django, o AppConfig.ready() inicia uma thread daemon que loopa check_alerts a cada intervalo. Não use em produção com múltiplos workers — N workers × N schedulers gera concorrência e alertas duplicados.
Produção (processo dedicado):
botapp run_alert_scheduler --interval 60
Ou em container:
services:
botapp_scheduler:
image: meu-registry/botapp
environment:
BOTAPP_ROLE: scheduler
command: botapp run_alert_scheduler
Flags úteis:
--interval N— sobrescreveBOTAPP_ALERT_SCHEDULER_INTERVAL_SECONDS.--once— roda uma vez e sai (útil para cron externo).check_alerts --dry-run— só loga o que faria.check_alerts --no-notify— cria alertas mas não envia webhooks.
API REST
Base: /api/ · Autenticação: Session ou Basic · Permissão: IsAuthenticated.
| Método · Rota | Descrição |
|---|---|
GET /api/bots/ |
Lista bots (parametros: search). |
POST /api/bots/ |
Cria bot. |
GET /api/bots/{id}/ |
Detalhe. |
PATCH /api/bots/{id}/ |
Atualização parcial. |
DELETE /api/bots/{id}/ |
Remove. |
GET /api/tasks/ |
Lista tasks (?bot=<id>&name=<str>). |
POST /api/tasks/ |
Cria task. |
GET /api/tasklog/ |
Lista logs. |
POST /api/tasklog/ |
Cria log (usado pelo BotAppRestful). |
PATCH /api/tasklog/{id}/ |
Atualiza log (status, end_time, duration…). |
Exemplo:
curl -u admin:senha http://localhost:8000/api/bots/?search=relatorio
Comandos de gerência
Disponíveis via entry point botapp (equivalente a python manage.py):
| Comando | Uso |
|---|---|
botapp setup |
Cria schema + roda migrations + cria superusuário. |
botapp migrate [--noinput] |
Aplica migrations. |
botapp collectstatic [--noinput] |
Coleta estáticos (whitenoise em produção). |
botapp runserver [host:port] |
Servidor dev. |
botapp check_alerts [--dry-run] [--no-notify] |
Roda o motor de alertas uma vez. |
botapp run_alert_scheduler [--interval N] [--once] |
Loop blocante do motor (para processo dedicado). |
botapp cleanup_orphans [--threshold-hours N] [--bot-id ID] [--dry-run] [--batch-size N] [--sleep-ms N] |
Fecha logs travados. |
botapp reconcile_bot_denorm |
Reconcilia Bot.last_execution_at com o TaskLog real mais recente. |
Variáveis de ambiente
Essenciais
| Variável | Default | Descrição |
|---|---|---|
DJANGO_SETTINGS_MODULE |
botapp.settings (standalone) |
Aponta para seu settings em modo plugin. |
BOTAPP_DEBUG |
False |
Modo debug do Django. |
BOTAPP_SECRET_KEY |
obrigatório em prod | Secret key. Default de dev não é aceito com DEBUG=False. |
BOTAPP_ALLOWED_HOSTS |
* |
Lista separada por vírgula. |
BOTAPP_CSRF_TRUSTED_ORIGINS |
* (quando DEBUG=False) |
Lista separada por vírgula. |
BOTAPP_PORT_ADMIN |
8000 |
Porta usada por app.open_admin(). |
BOTAPP_LANGUAGE_CODE |
pt-br |
|
BOTAPP_TIME_ZONE |
America/Cuiaba |
Fuso padrão. |
BOTAPP_USE_I18N |
True |
|
BOTAPP_USE_TZ |
True |
Mantenha True para datetimes aware (exigido pelos notifiers). |
BOTAPP_DEPLOY_ENV |
dev |
Gravado em TaskLog.env. |
BOTAPP_LOGGING_LEVEL |
INFO |
Nível do logger botapp. |
BOTAPP_DJANGO_LOG_LEVEL |
WARNING |
Nível do logger django. |
Banco de dados (Postgres)
| Variável | Descrição |
|---|---|
BOTAPP_DATABASES |
(opcional) JSON com o dict DATABASES completo. Sobrescreve as demais. |
PG_BOTAPP_SCHEMA |
Schema das tabelas (default botapp_schema). |
PG_BOTAPP_DBNAME |
Nome do banco. |
PG_BOTAPP_USER |
Usuário. |
PG_BOTAPP_PASSWORD |
Senha. |
PG_BOTAPP_HOST |
Host. |
PG_BOTAPP_PORT |
Porta (default 5432). |
Superusuário inicial (usado por botapp setup)
| Variável | Default |
|---|---|
BOTAPP_SUPERUSER_USERNAME |
admin |
BOTAPP_SUPERUSER_EMAIL |
admin@example.com |
BOTAPP_SUPERUSER_PASSWORD |
admin123 (proibido em prod) |
Cache / Redis
| Variável | Default |
|---|---|
BOTAPP_CACHES |
JSON com o dict CACHES. Se ausente em prod, usa Redis. |
BOTAPP_REDIS_URL |
redis://botapp_redis:6379/1 |
E-mail (SMTP)
| Variável | Default |
|---|---|
BOTAPP_EMAIL_HOST |
— |
BOTAPP_EMAIL_PORT |
587 |
BOTAPP_EMAIL_USER |
— |
BOTAPP_EMAIL_PASSWORD |
— |
BOTAPP_EMAIL_USE_TLS |
True |
BOTAPP_DEFAULT_FROM_EMAIL |
BOTAPP_EMAIL_USER |
Modo plugin (REST client)
| Variável | Default | Descrição |
|---|---|---|
BOTAPP_API_URL |
— | URL do dashboard remoto. Obrigatório no modo plugin. |
BOTAPP_API_USUARIO |
— | HTTP Basic user. |
BOTAPP_API_SENHA |
— | HTTP Basic password. |
BOTAPP_API_TIMEOUT |
10 |
Timeout (s) das chamadas HTTP. |
Scheduler / alertas
| Variável | Default |
|---|---|
BOTAPP_ALERT_SCHEDULER_ENABLED |
false (não inicia thread in-process) |
BOTAPP_ALERT_SCHEDULER_INTERVAL_SECONDS |
60 |
BOTAPP_SILENT_BOT_THRESHOLD_HOURS |
24 |
BOTAPP_ERROR_SPIKE_WINDOW_MINUTES |
60 |
BOTAPP_ERROR_SPIKE_THRESHOLD |
5 |
BOTAPP_HEARTBEAT_LOST_THRESHOLD_HOURS |
6 |
BOTAPP_DURATION_REGRESSION_MULTIPLIER |
1.5 |
BOTAPP_DURATION_REGRESSION_WINDOW |
20 (últimas N execuções) |
Canais de notificação
| Variável | Default | Efeito |
|---|---|---|
BOTAPP_SLACK_WEBHOOK_URL |
— | Se definida, envia para Slack. |
BOTAPP_DISCORD_WEBHOOK_URL |
— | Se definida, envia para Discord. |
BOTAPP_ALERT_EMAIL_RECIPIENTS |
— | Lista separada por vírgula. Se vazia, não envia. |
BOTAPP_DASHBOARD_URL |
— | Base usada para gerar link nas notificações. |
BOTAPP_NOTIFIER_TIMEOUT |
5 |
Timeout (s) das chamadas aos webhooks. |
Limpeza de órfãos
| Variável | Default |
|---|---|
BOTAPP_ORPHAN_THRESHOLD_HOURS |
24 |
BOTAPP_ORPHAN_BATCH_SIZE |
500 |
BOTAPP_ORPHAN_SLEEP_MS |
100 |
BOTAPP_ORPHAN_HTTP_MAX |
5000 |
Export
| Variável | Default | Descrição |
|---|---|---|
BOTAPP_CSV_MAX_ROWS |
0 |
0 = ilimitado. Teto opcional para /explore/export.csv. |
Deploy em produção
Topologia recomendada:
┌──────────────┐ ┌────────────────────┐ ┌─────────────────────┐
│ Bots (SDK) │──▶│ web (gunicorn) │──▶│ Postgres + Redis │
└──────────────┘ │ BOTAPP_ROLE=web │ └─────────────────────┘
│ N workers │
└────────────────────┘
│
┌────────────────────┐
│ scheduler │ (um único processo)
│ BOTAPP_ROLE= │
│ scheduler │
└────────────────────┘
Pontos importantes:
- Nunca deixe
BOTAPP_ALERT_SCHEDULER_ENABLED=trueno containerwebcom múltiplos workers — use um containerschedulerdedicado. - Rode
botapp migrateantes do primeiro start (ou no entrypoint do serviço web). - Configure
BOTAPP_SECRET_KEY,BOTAPP_ALLOWED_HOSTS,BOTAPP_CSRF_TRUSTED_ORIGINSexplicitamente. - HTTPS reverse proxy na frente do gunicorn; o settings já ativa
SECURE_SSL_REDIRECT, HSTS e cookies seguros quandoDEBUG=False. BOTAPP_DASHBOARD_URLdeve apontar para a URL pública do dashboard — usado nos links das notificações.
Exemplo de docker-compose mínimo:
services:
web:
image: botapp:latest
environment:
BOTAPP_ROLE: web
BOTAPP_ALERT_SCHEDULER_ENABLED: "false"
env_file: .env.prod
ports: ["8000:8000"]
scheduler:
image: botapp:latest
environment:
BOTAPP_ROLE: scheduler
BOTAPP_ALERT_SCHEDULER_ENABLED: "true"
env_file: .env.prod
command: botapp run_alert_scheduler
depends_on: [web]
redis:
image: redis:alpine
Troubleshooting
Alertas não estão sendo criados.
Verifique nessa ordem: (1) a migration 0010_alerts rodou (\dt botapp_alert no psql); (2) o scheduler está rodando (botapp run_alert_scheduler em container dedicado ou BOTAPP_ALERT_SCHEDULER_ENABLED=true em dev); (3) existem bots com is_active=True e últimos logs fora do threshold. Rode botapp check_alerts --dry-run para ver o que seria criado sem tocar no banco.
Alertas criados mas sem notificação.
Nenhuma das envs de canal foi definida — o dispatcher pula canais sem configuração. Defina pelo menos uma entre BOTAPP_SLACK_WEBHOOK_URL, BOTAPP_DISCORD_WEBHOOK_URL, BOTAPP_ALERT_EMAIL_RECIPIENTS. Verifique o log do scheduler por notifier.slack: falha / notifier.discord: falha / notifier.email: falha.
Bot.last_execution_at desatualizado.
SDK antigo (sem o signal post_save) está escrevendo TaskLog direto no banco. Rode botapp reconcile_bot_denorm manualmente ou aguarde o check_alerts (ele chama a reconciliação a cada rodada).
Muitos alertas heartbeat_lost.
Crashes deixaram logs em status='started'. Rode botapp cleanup_orphans --threshold-hours 24 para fechá-los retroativamente como failed/orphan_heartbeat.
ProgrammingError: relation "botapp_alert" does not exist.
As migrations não rodaram no ambiente. Execute botapp migrate --noinput.
Unknown command: 'check_alerts'.
Você está em uma versão < 0.3.1, que foi publicada sem o diretório management/. Atualize para 0.3.1+.
Desenvolvimento local
git clone https://github.com/botlorien/botapp
cd botapp
python -m venv .venv && source .venv/bin/activate
pip install -e .
pip install build twine
# Configure .env como na seção "Início rápido"
botapp setup
botapp runserver
Para testar o SDK contra o banco local, use example.py como referência.
Publicando uma nova versão
python setup.py sdist bdist_wheel
twine upload dist/*
Antes de publicar, verifique que find_packages() detecta todos os subpacotes (em particular botapp.management e botapp.management.commands, que precisam de __init__.py):
python -c "from setuptools import find_packages; print(find_packages())"
Licença
MIT — ver LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file botapp-0.4.1.tar.gz.
File metadata
- Download URL: botapp-0.4.1.tar.gz
- Upload date:
- Size: 102.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5ea178b1d4d3c228fe4d6ca931748c835bc10c85c781cc2c6a3f7208a10e3f97
|
|
| MD5 |
f595dc228e94a58d5acd4b72dd2a931d
|
|
| BLAKE2b-256 |
521031cfb3c809cbad7d0cc69a048d8981cfe189af232e91027203fcaadc6b43
|