Skip to content
Alita Robot
Esc
↑↓navigate↵open⌘Jpreview
On this page

Monitoring and Observability

Monitor Alita Robot health, metrics, and errors.

Monitoring and Observability

Alita Robot provides comprehensive monitoring capabilities including health checks, Prometheus metrics, and resource monitoring.

Health Endpoint

The health endpoint provides real-time status of the bot and its dependencies.

Endpoint

GET /health

Response Format

{
  "status": "healthy",
  "checks": {
    "database": true,
    "redis": true
  },
  "version": "2.21.0",
  "uptime": "24h30m15s"
}

Response Fields

Field Type Description
status string Overall health: healthy or unhealthy
checks.database boolean PostgreSQL connection status
checks.redis boolean Redis connection status
version string Bot version
uptime string Time since bot started

HTTP Status Codes

:::tip Use the HTTP status code (not the response body) in your load balancer or uptime monitoring tool. A 503 response means at least one dependency is unhealthy. :::

Code Meaning
200 All systems healthy
503 One or more checks failed

Health Check Logic

The health check performs:

  1. Database check: Pings PostgreSQL with a 2-second timeout
  2. Redis check: Sets and gets a test key with a 2-second timeout

Both checks must pass for healthy status.

Usage Examples

# Simple health check
curl http://localhost:8080/health

# Docker health check (built-in)
/app/alita_robot --health

# Kubernetes liveness probe
livenessProbe:
  httpGet:
    path: /health
    port: 8080
  initialDelaySeconds: 30
  periodSeconds: 10

Prometheus Metrics

The metrics endpoint exposes Prometheus-compatible metrics for monitoring.

Endpoint

GET /metrics

Bot Metrics

Besides the Go runtime metrics, the bot exports:

Metric Type Labels Meaning
alita_updates_processed_total counter update_type, outcome, command Telegram updates processed
alita_handler_errors_total counter module, expected Errors handlers returned; expected is true for expected Telegram API errors
alita_redis_commands_total counter command Redis commands sent (get, set, del, …)
alita_db_queries_total counter operation Database statements (query, create, update, delete, row, raw)
alita_db_query_duration_seconds histogram operation Database statement latency
alita_db_query_errors_total counter operation Failed database statements (a lookup that finds no row is not a failure)
go_sql_* gauge/counter db_name Connection pool stats: open, in-use and idle connections, waits
alita_telegram_api_request_duration_seconds histogram method Bot API request latency (sendMessage, getChatMember, …); getUpdates is left out, as it long-polls
alita_telegram_api_errors_total counter method, code Failed Bot API requests: HTTP status, or transport when no response came back
alita_webhook_queue_depth gauge none Webhook updates accepted and waiting for a dispatcher worker
alita_webhook_rejected_total counter reason Webhook updates answered with 503: queue_full or stopped
alita_job_runs_total counter job Background job ticks run (digestSchedulerTick, captchaCleanup, …)
alita_job_failures_total counter job Job ticks that returned an error or panicked
alita_cache_local_hits_total counter none Read-through cache lookups served by the in-process layer (CACHE_LOCAL_TTL)
alita_cache_local_misses_total counter none Read-through cache lookups that missed the in-process layer and fell through to Redis

outcome is the worst of ok, expected_error, error and panic any handler gave the update. panic counts panics recovered by command handlers or the dispatcher; a module’s own recover hides its panic. command is the command a new message starts with, without /, when it is a help-menu command, other for any other command, and empty otherwise. module is the help module of that command, or other, even when a different handler on the message failed.

Error rate:

sum(rate(alita_updates_processed_total{outcome=~"error|panic"}[5m])) / sum(rate(alita_updates_processed_total[5m]))

Per-update cost:

sum(rate(alita_redis_commands_total[5m])) / sum(rate(alita_updates_processed_total[5m]))
sum(rate(alita_db_queries_total[5m])) / sum(rate(alita_updates_processed_total[5m]))

Bot API rate limiting:

sum by (method) (rate(alita_telegram_api_errors_total{code="429"}[5m]))

In-process cache hit ratio:

rate(alita_cache_local_hits_total[5m]) / (rate(alita_cache_local_hits_total[5m]) + rate(alita_cache_local_misses_total[5m]))

Prometheus Scrape Configuration

Add to your prometheus.yml:

scrape_configs:
  - job_name: 'alita-robot'
    static_configs:
      - targets: ['alita:8080']
    scrape_interval: 15s
    scrape_timeout: 10s
    metrics_path: /metrics
    # Required when METRICS_AUTH_TOKEN is set
    authorization:
      type: Bearer
      credentials: <METRICS_AUTH_TOKEN value>   # or credentials_file: /etc/prometheus/alita_token

Authentication

When METRICS_AUTH_TOKEN is set, /metrics and /db_metrics return 401 Unauthorized unless the request sends Authorization: Bearer <token>. When it is empty, both endpoints are open and the bot logs a warning at startup. See METRICS_AUTH_TOKEN.

Docker Compose with Prometheus

services:
  prometheus:
    image: prom/prometheus:latest
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus_data:/prometheus
    ports:
      - "9090:9090"
    depends_on:
      - alita

volumes:
  prometheus_data:

Grafana Dashboard

For visualization, add Grafana:

services:
  grafana:
    image: grafana/grafana:latest
    volumes:
      - grafana_data:/var/lib/grafana
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
    depends_on:
      - prometheus

volumes:
  grafana_data:

Resource Monitoring

Alita Robot includes automatic resource monitoring to prevent resource exhaustion.

Configuration

# Maximum goroutines before triggering cleanup
# Default: 1000, Recommended: 1000-5000
RESOURCE_MAX_GOROUTINES=1000

# Maximum memory usage in MB before triggering cleanup
# Default: 500, Recommended: 500-2000
RESOURCE_MAX_MEMORY_MB=500

# Memory threshold for triggering garbage collection
# Default: 400, Recommended: 80% of RESOURCE_MAX_MEMORY_MB
RESOURCE_GC_THRESHOLD_MB=400

Auto-Remediation

:::note Auto-remediation runs automatically in the background. No manual intervention is required unless Tier 3 is triggered, at which point you should investigate and restart the bot. :::

The system uses a 4-tier auto-remediation approach when resource thresholds are exceeded:

  1. Tier 0 — Warning: Logs warnings at 80% goroutine threshold or 50% memory usage
  2. Tier 1 — GC Trigger: Triggers garbage collection at 60% memory usage or 50ms GC pause times
  3. Tier 2 — Aggressive Cleanup: Runs multiple GC cycles when memory exceeds the GC threshold
  4. Tier 3 — Restart Recommendation: Logs a restart recommendation at 150%+ goroutines or 160%+ memory usage

Activity Monitoring

Track group activity automatically:

# Days of inactivity before marking chat as inactive
# Default: 30, recommended 1-365 (not enforced)
INACTIVITY_THRESHOLD_DAYS=30

# Hours between automatic activity checks
# Default: 1, recommended 1-24 (not enforced)
ACTIVITY_CHECK_INTERVAL=1

# Enable automatic cleanup of inactive chats
# Default: true
ENABLE_AUTO_CLEANUP=true

Activity Metrics

The system tracks group activity:

  • DAG: Daily Active Groups
  • WAG: Weekly Active Groups
  • MAG: Monthly Active Groups

The activity monitor also tracks individual user activity, calculating Daily Active Users (DAU), Weekly Active Users (WAU), and Monthly Active Users (MAU).

Groups are automatically:

  • Marked inactive after the threshold period
  • Reactivated when they become active again

Performance Monitoring

Enable Performance Tracking

# Enable automatic performance monitoring
ENABLE_PERFORMANCE_MONITORING=true

# Enable background statistics collection
ENABLE_BACKGROUND_STATS=true

Collected Metrics

  • Message processing time
  • Database query duration
  • Cache hit/miss rates
  • API response times
  • Goroutine count
  • Memory usage

Database Metrics

The /db_metrics endpoint exposes real-time database connection pool statistics.

Endpoint

GET /db_metrics

When METRICS_AUTH_TOKEN is set, send the same bearer header: curl -H "Authorization: Bearer $METRICS_AUTH_TOKEN" http://localhost:8080/db_metrics.

Response Format

{
  "open_connections": 45,
  "idle": 38,
  "in_use": 7,
  "wait_count": 0,
  "wait_duration": 0,
  "max_idle_closed": 0,
  "max_lifetime_closed": 0
}

wait_duration is the total time spent waiting for a connection, in nanoseconds.

The endpoint is always registered. It queries the underlying *sql.DB connection pool stats via db.Stats().

Background Database Monitoring

In addition to the /db_metrics endpoint, a background monitoring goroutine periodically logs pool health metrics.

Configuration

# Enable background database monitoring (logs pool stats every minute at debug level; needs DEBUG=true to show)
# Controls the background goroutine, NOT the /db_metrics endpoint registration
ENABLE_DB_MONITORING=true

When enabled, the monitoring goroutine logs pool stats every minute at debug level, so the line appears only when DEBUG=true. With DEBUG=false the goroutine still runs, but only its start and stop messages are logged; use /db_metrics to read the stats in production.

[DBMonitoring] Connections: 12 open, 7 in-use, 5 idle | Wait: 0 calls, 0s total | Closed: 0 (max idle), 0 (max lifetime)

Debug Mode

For detailed logging during development:

DEBUG=true

:::caution Debug mode disables background performance monitoring and significantly increases log volume. Never enable in production as it degrades overall performance. :::

Debug mode:

  • Increases log verbosity
  • Disables background monitoring
  • Shows detailed error stack traces

Log Analysis

Log Fields

Structured log entries include:

Field Description
update_id Telegram update ID
error_type Error type (e.g., *TelegramError)
file Source file where error occurred
line Line number
function Function name

Example Log Entry

{
  "level": "error",
  "msg": "Handler error occurred: user blocked bot",
  "update_id": 123456789,
  "error_type": "*gotgbot.TelegramError",
  "file": "alita/modules/admin.go",
  "line": 45,
  "function": "handleAdminCommand",
  "time": "2024-03-15T10:30:00Z"
}

Log Levels

Level Description
DEBUG Verbose debugging (DEBUG=true only)
INFO Normal operation events
WARN Expected issues (e.g., user blocked bot)
ERROR Unexpected errors
FATAL Critical errors that stop the bot

Alerting

:::tip At minimum, set up alerts for AlitaUnhealthy and monitor the /health endpoint with an external HTTP check (e.g., blackbox exporter) to catch critical outages early. :::

Prometheus Alerting Rules

Create alerts.yml:

groups:
  - name: alita-alerts
    rules:
      - alert: AlitaUnhealthy
        expr: up{job="alita-robot"} == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "Alita Robot is down"

      - alert: HighMemoryUsage
        expr: process_resident_memory_bytes > 500000000
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "High memory usage detected"

      - alert: HighGoroutineCount
        expr: go_goroutines > 1000
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "High goroutine count detected"

Database Health

The /health endpoint returns a 503 status code when the database or Redis connection is unhealthy. Because the health check is a JSON API (not a Prometheus metric), monitor it with an external HTTP health check such as the Prometheus Blackbox Exporter or your uptime monitoring tool.

Was this page helpful?