Skip to main content

A fast and flexible API health monitoring tool

Project description

🔍 ApiMonitor

A fast, flexible, and powerful API health monitoring tool for Python. Monitor your APIs, track response times, get alerts when things go wrong, and ensure your services stay online.

✨ Features

  • 🚀 Fast Async Monitoring: Built with aiohttp for high-performance concurrent checks
  • 📊 Comprehensive Metrics: Response times, status codes, uptime percentages, SLA tracking
  • 🚨 Multiple Alert Channels: Slack, Discord, Email, Webhooks, Console notifications
  • 🎛️ Flexible Configuration: YAML/JSON config files or programmatic setup
  • 📈 Built-in Dashboard: Web interface for real-time monitoring (optional)
  • 🐳 Docker Ready: Easy deployment with Docker support
  • 💻 CLI & Python API: Use from command line or integrate into your applications
  • 🔧 Highly Configurable: Custom headers, request bodies, health checks, retry logic

🚀 Quick Start

Installation

pip install apimonitor

Command Line Usage

# Check endpoints once
apimonitor check https://api.example.com/health https://api2.example.com/status

# Monitor continuously
apimonitor run https://api.example.com/health --interval 60

# Monitor with Slack notifications
apimonitor run https://api.example.com/health --slack-webhook YOUR_WEBHOOK_URL

# Use configuration file
apimonitor init  # Create example config
apimonitor run --config-file apimonitor_config.yaml

# Start with dashboard
apimonitor run --config-file config.yaml --dashboard --dashboard-port 8080

Python API

from apimonitor import ApiMonitor

# Quick health check
from apimonitor import quick_check
result = await quick_check("https://api.example.com/health")
print(f"Status: {result.health_status}, Response time: {result.response_time_ms}ms")

# Continuous monitoring
monitor = ApiMonitor()
monitor.add_endpoint("https://api.example.com/health", "api_health")
monitor.add_notification_channel("slack", "slack", {
    "webhook_url": "YOUR_SLACK_WEBHOOK_URL"
})

# Start monitoring
await monitor.start()

📋 Configuration

YAML Configuration Example

# Basic settings
log_level: "INFO"
max_history_days: 30
dashboard_enabled: true
dashboard_port: 8080

# Endpoints to monitor
endpoints:
  - id: "api_health"
    url: "https://api.example.com/health"
    method: "GET"
    check_interval_seconds: 60
    timeout_seconds: 10
    expected_status_codes: [200]
    headers:
      Authorization: "Bearer your-token"
    
  - id: "api_users"
    url: "https://api.example.com/users"
    method: "GET"
    check_interval_seconds: 300
    timeout_seconds: 5
    expected_status_codes: [200, 201]
    sla_response_time_ms: 1000
    response_contains: "users"

# Notification channels
notifications:
  console:
    type: "console"
    enabled: true
    on_failure: true
    on_recovery: true
    
  slack:
    type: "slack"
    enabled: true
    config:
      webhook_url: "https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK"
    on_failure: true
    on_recovery: true
    max_notifications_per_hour: 10
    cooldown_minutes: 5
    
  email:
    type: "email"
    enabled: false
    config:
      smtp_host: "smtp.gmail.com"
      smtp_port: 587
      username: "your-email@gmail.com"
      password: "your-app-password"
      from_email: "monitoring@yourcompany.com"
      to_emails: ["admin@yourcompany.com", "ops@yourcompany.com"]
      use_tls: true

Environment Variables

You can also configure ApiMonitor using environment variables:

export APIMONITOR_URL="https://api.example.com/health"
export APIMONITOR_INTERVAL=300
export APIMONITOR_TIMEOUT=10
export APIMONITOR_SLACK_WEBHOOK="https://hooks.slack.com/services/..."
export APIMONITOR_LOG_LEVEL="INFO"
export APIMONITOR_DASHBOARD=true

apimonitor run

🔧 Advanced Usage

Custom Health Checks

from apimonitor import ApiMonitor
from apimonitor.models import EndpointConfig, HttpMethod

# Advanced endpoint configuration
endpoint = EndpointConfig(
    id="api_advanced",
    url="https://api.example.com/data",
    method=HttpMethod.POST,
    headers={"Authorization": "Bearer token", "Content-Type": "application/json"},
    body='{"query": "test"}',
    expected_status_codes=[200, 201],
    expected_response_time_ms=500,
    response_contains="success",
    response_not_contains="error",
    check_interval_seconds=120,
    max_retries=3,
    sla_uptime_percentage=99.9,
    sla_response_time_ms=1000
)

monitor = ApiMonitor()
monitor.config.add_endpoint(endpoint)

Custom Notifications

# Webhook notification
monitor.add_notification_channel("webhook", "webhook", {
    "url": "https://your-webhook.com/alerts",
    "headers": {"Authorization": "Bearer webhook-token"}
})

# Discord notification
monitor.add_notification_channel("discord", "discord", {
    "webhook_url": "https://discord.com/api/webhooks/YOUR_WEBHOOK"
})

# Email notification
monitor.add_notification_channel("email", "email", {
    "smtp_host": "smtp.gmail.com",
    "smtp_port": 587,
    "username": "alerts@yourcompany.com",
    "password": "your-password",
    "from_email": "alerts@yourcompany.com",
    "to_emails": ["admin@yourcompany.com"]
})

Monitoring with Context Manager

async with ApiMonitor() as monitor:
    monitor.add_endpoint("https://api.example.com/health", "api_health")
    
    # Check once
    result = await monitor.check_endpoint("api_health")
    print(f"Health: {result.health_status}")
    
    # Get statistics
    stats = monitor.get_endpoint_stats("api_health")
    print(f"Uptime: {stats.uptime_percentage:.2f}%")

📊 Dashboard

ApiMonitor includes an optional web dashboard for real-time monitoring:

# Install dashboard dependencies
pip install apimonitor[dashboard]

# Start with dashboard
apimonitor run --config-file config.yaml --dashboard --dashboard-port 8080

Visit http://localhost:8080 to see:

  • Real-time endpoint status
  • Response time graphs
  • Uptime statistics
  • Recent alerts and events
  • SLA compliance tracking

🐳 Docker Deployment

Dockerfile

FROM python:3.11-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install -r requirements.txt

COPY config.yaml .
COPY . .

CMD ["apimonitor", "run", "--config-file", "config.yaml"]

Docker Compose

version: '3.8'
services:
  apimonitor:
    build: .
    volumes:
      - ./config.yaml:/app/config.yaml
      - ./logs:/app/logs
    ports:
      - "8080:8080"
    environment:
      - APIMONITOR_LOG_LEVEL=INFO
    restart: unless-stopped

📚 CLI Reference

Commands

  • apimonitor run - Start continuous monitoring
  • apimonitor check - Check endpoints once
  • apimonitor init - Create example configuration
  • apimonitor validate - Validate configuration file
  • apimonitor stats - Show monitoring statistics

Global Options

  • --config, -c - Configuration file path
  • --verbose, -v - Verbose output
  • --version - Show version

Run Command Options

  • --config-file, -c - Configuration file
  • --interval, -i - Check interval in seconds
  • --timeout, -t - Request timeout in seconds
  • --slack-webhook - Slack webhook URL
  • --discord-webhook - Discord webhook URL
  • --email-config - Email configuration (JSON)
  • --dashboard - Enable web dashboard
  • --dashboard-port - Dashboard port
  • --background, -b - Run in background

Check Command Options

  • --timeout, -t - Request timeout in seconds
  • --method, -m - HTTP method
  • --headers, -H - HTTP headers (key:value)
  • --expected-status - Expected status codes
  • --json-output, -j - Output as JSON
  • --quiet, -q - Quiet mode

🧪 Testing

# Install test dependencies
pip install apimonitor[dev]

# Run tests
pytest tests/ -v

# Run with coverage
pytest tests/ --cov=apimonitor --cov-report=html

🔄 Integration Examples

CI/CD Pipeline Health Check

# GitHub Actions example
- name: Check API Health
  run: |
    pip install apimonitor
    apimonitor check https://api.staging.example.com/health --expected-status 200

Kubernetes Health Check

apiVersion: batch/v1
kind: CronJob
metadata:
  name: api-health-check
spec:
  schedule: "*/5 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: apimonitor
            image: your-registry/apimonitor:latest
            command: ["apimonitor", "check", "https://api.example.com/health"]
          restartPolicy: OnFailure

Serverless Monitoring (AWS Lambda)

import json
import asyncio
from apimonitor import quick_check

def lambda_handler(event, context):
    async def check_apis():
        urls = ["https://api1.example.com/health", "https://api2.example.com/health"]
        results = []
        
        for url in urls:
            result = await quick_check(url)
            results.append({
                "url": url,
                "status": result.health_status.value,
                "response_time": result.response_time_ms,
                "success": result.success
            })
        
        return results
    
    results = asyncio.run(check_apis())
    
    return {
        'statusCode': 200,
        'body': json.dumps(results)
    }

🤝 Contributing

We welcome contributions! Please see our Contributing Guide for details.

Development Setup

# Clone repository
git clone https://github.com/abderrahimghazali/apimonitor.git
cd apimonitor

# Install in development mode
pip install -e ".[dev]"

# Run tests
pytest

# Format code
black apimonitor/ tests/
isort apimonitor/ tests/

# Lint code
flake8 apimonitor/ tests/

🐛 Troubleshooting

Common Issues

1. SSL Certificate Errors

# Disable SSL verification (not recommended for production)
endpoint_config = EndpointConfig(
    id="test",
    url="https://self-signed-cert-site.com",
    # Add custom session configuration in future versions
)

2. Timeout Issues

endpoints:
  - id: "slow_api"
    url: "https://slow-api.example.com"
    timeout_seconds: 30  # Increase timeout
    max_retries: 5       # Increase retries

3. Rate Limiting

endpoints:
  - id: "rate_limited_api"
    url: "https://api.example.com"
    check_interval_seconds: 600  # Check less frequently

4. Memory Usage

# Limit history retention
max_history_days: 7

🙏 Acknowledgments

  • Built with aiohttp for fast async HTTP requests
  • Uses pydantic for configuration validation
  • CLI powered by click
  • Dashboard built with FastAPI (optional)

Need help?


Example Configuration Files

config/basic.yaml

log_level: "INFO"
dashboard_enabled: false

endpoints:
  - id: "google"
    url: "https://www.google.com"
    check_interval_seconds: 300
    timeout_seconds: 10
    expected_status_codes: [200]

notifications:
  console:
    type: "console"
    enabled: true
    on_failure: true
    on_recovery: true

config/advanced.yaml

log_level: "INFO"
log_file: "logs/apimonitor.log"
max_history_days: 30
dashboard_enabled: true
dashboard_port: 8080

# Default settings for all endpoints
default_timeout: 10.0
default_interval: 300
default_retries: 3

endpoints:
  - id: "api_health"
    url: "https://api.example.com/health"
    method: "GET"
    check_interval_seconds: 60
    timeout_seconds: 5
    expected_status_codes: [200]
    expected_response_time_ms: 500
    headers:
      User-Agent: "ApiMonitor/1.0"
      Authorization: "Bearer token123"
    sla_uptime_percentage: 99.9
    sla_response_time_ms: 1000

  - id: "api_users_post"
    url: "https://api.example.com/users"
    method: "POST"
    check_interval_seconds: 300
    timeout_seconds: 10
    expected_status_codes: [200, 201]
    headers:
      Content-Type: "application/json"
      Authorization: "Bearer token123"
    body: '{"test": true}'
    response_contains: "success"
    max_retries: 5
    retry_delay_seconds: 2.0

  - id: "slow_api"
    url: "https://httpbin.org/delay/3"
    check_interval_seconds: 600
    timeout_seconds: 15
    expected_status_codes: [200]
    expected_response_time_ms: 5000

notifications:
  console:
    type: "console"
    enabled: true
    on_failure: true
    on_recovery: true
    on_degraded: true

  slack_critical:
    type: "slack"
    enabled: true
    config:
      webhook_url: "https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK"
    on_failure: true
    on_recovery: true
    on_degraded: false
    max_notifications_per_hour: 20
    cooldown_minutes: 2

  discord_alerts:
    type: "discord"
    enabled: true
    config:
      webhook_url: "https://discord.com/api/webhooks/YOUR_WEBHOOK"
    on_failure: true
    on_recovery: true
    max_notifications_per_hour: 10
    cooldown_minutes: 5

  email_alerts:
    type: "email"
    enabled: false
    config:
      smtp_host: "smtp.gmail.com"
      smtp_port: 587
      username: "alerts@yourcompany.com"
      password: "your-app-password"
      from_email: "apimonitor@yourcompany.com"
      to_emails: 
        - "admin@yourcompany.com"
        - "ops@yourcompany.com"
      use_tls: true
    on_failure: true
    on_recovery: true
    max_notifications_per_hour: 5
    cooldown_minutes: 10

  webhook_integration:
    type: "webhook"
    enabled: false
    config:
      url: "https://your-webhook-service.com/alerts"
      headers:
        Authorization: "Bearer webhook-token"
        Content-Type: "application/json"
    on_failure: true
    on_recovery: true
    max_notifications_per_hour: 50

config/microservices.yaml

log_level: "INFO"
dashboard_enabled: true
dashboard_port: 8080

endpoints:
  # Frontend services
  - id: "web_frontend"
    url: "https://app.example.com/health"
    check_interval_seconds: 60
    timeout_seconds: 5
    expected_status_codes: [200]
    sla_uptime_percentage: 99.9

  # API Gateway
  - id: "api_gateway"
    url: "https://api.example.com/health"
    check_interval_seconds: 30
    timeout_seconds: 5
    expected_status_codes: [200]
    sla_uptime_percentage: 99.95

  # User service
  - id: "user_service"
    url: "https://users.example.com/health"
    check_interval_seconds: 120
    timeout_seconds: 10
    expected_status_codes: [200]
    headers:
      Authorization: "Bearer service-token"

  # Payment service (critical)
  - id: "payment_service"
    url: "https://payments.example.com/health"
    check_interval_seconds: 30
    timeout_seconds: 5
    expected_status_codes: [200]
    sla_uptime_percentage: 99.99
    sla_response_time_ms: 200

  # Email service
  - id: "email_service"
    url: "https://email.example.com/health"
    check_interval_seconds: 300
    timeout_seconds: 10
    expected_status_codes: [200]

  # Database health check
  - id: "database_proxy"
    url: "https://db-proxy.example.com/health"
    check_interval_seconds: 60
    timeout_seconds: 3
    expected_status_codes: [200]
    response_contains: "database_ok"

notifications:
  console:
    type: "console"
    enabled: true
    on_failure: true
    on_recovery: true

  slack_ops:
    type: "slack"
    enabled: true
    config:
      webhook_url: "https://hooks.slack.com/services/YOUR/OPS/WEBHOOK"
    on_failure: true
    on_recovery: true
    on_degraded: true
    max_notifications_per_hour: 30

  slack_critical:
    type: "slack"
    enabled: true
    config:
      webhook_url: "https://hooks.slack.com/services/YOUR/CRITICAL/WEBHOOK"
    on_failure: true
    on_recovery: false  # Only failures for critical channel
    max_notifications_per_hour: 50

docker-compose.yaml

version: '3.8'

services:
  apimonitor:
    build: .
    container_name: apimonitor
    volumes:
      - ./config/production.yaml:/app/config.yaml:ro
      - ./logs:/app/logs
      - ./data:/app/data
    ports:
      - "8080:8080"
    environment:
      - APIMONITOR_LOG_LEVEL=INFO
      - APIMONITOR_CONFIG=/app/config.yaml
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/api/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

  # Optional: Redis for shared state (future enhancement)
  redis:
    image: redis:7-alpine
    container_name: apimonitor-redis
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data
    restart: unless-stopped

volumes:
  redis_data:

Kubernetes Deployment

k8s/configmap.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: apimonitor-config
data:
  config.yaml: |
    log_level: "INFO"
    dashboard_enabled: true
    dashboard_port: 8080
    
    endpoints:
      - id: "frontend"
        url: "http://frontend-service/health"
        check_interval_seconds: 60
        timeout_seconds: 5
        expected_status_codes: [200]
    
    notifications:
      console:
        type: "console"
        enabled: true
        on_failure: true
        on_recovery: true

k8s/deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: apimonitor
spec:
  replicas: 1
  selector:
    matchLabels:
      app: apimonitor
  template:
    metadata:
      labels:
        app: apimonitor
    spec:
      containers:
      - name: apimonitor
        image: your-registry/apimonitor:latest
        ports:
        - containerPort: 8080
        volumeMounts:
        - name: config
          mountPath: /app/config.yaml
          subPath: config.yaml
        env:
        - name: APIMONITOR_CONFIG
          value: "/app/config.yaml"
        livenessProbe:
          httpGet:
            path: /api/health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 30
        readinessProbe:
          httpGet:
            path: /api/health
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 10
      volumes:
      - name: config
        configMap:
          name: apimonitor-config

k8s/service.yaml

apiVersion: v1
kind: Service
metadata:
  name: apimonitor-service
spec:
  selector:
    app: apimonitor
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080
  type: LoadBalancer

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

apimonitor-1.0.0.tar.gz (35.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

apimonitor-1.0.0-py3-none-any.whl (30.2 kB view details)

Uploaded Python 3

File details

Details for the file apimonitor-1.0.0.tar.gz.

File metadata

  • Download URL: apimonitor-1.0.0.tar.gz
  • Upload date:
  • Size: 35.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.0

File hashes

Hashes for apimonitor-1.0.0.tar.gz
Algorithm Hash digest
SHA256 835526edabcd664a142c5f406119b092f9c3ec7c67db8af8205717a7dc1344e0
MD5 1164c17ee42a58617e73179d1c2a3499
BLAKE2b-256 0ea21a74d43b7d9d933bb1018820ee3fe5007d52868657469dbf17716dd25b8a

See more details on using hashes here.

File details

Details for the file apimonitor-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: apimonitor-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 30.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.0

File hashes

Hashes for apimonitor-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e02b0e04e03206aeb998c8e85ef556f25a2ce44ecc6505768944a9ee48db134f
MD5 4d0fe408ba36534d0fb4bc63b0f488d0
BLAKE2b-256 d0e2de3ee7bb687f2b063e5ea6f7155cfff41c372403a38a20a5ea0ec39debdb

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page