Introduction

Ansible Automation Controller (formerly AWX/Tower) exposes a Prometheus-compatible /api/v2/metrics endpoint that provides real-time data about job execution, host status, system performance, and more. By connecting Prometheus to scrape these metrics and Grafana to visualize them, you get a complete real-time monitoring stack for your automation platform. This article covers the full integration setup from metrics endpoint to production dashboards.

Architecture Overview

┌──────────────────────┐     scrape      ┌──────────────┐
│ Automation Controller│────/metrics────→│  Prometheus   │
│ (ac.example.com)     │   every 5s      │ (time-series │
└──────────────────────┘                  │  database)   │
                                          └──────┬───────┘
                                                 │ query
                                          ┌──────▼───────┐
                                          │   Grafana     │
                                          │ (dashboards)  │
                                          └──────────────┘

Prerequisites

ComponentVersionPurpose
Automation Controller4.x+Metrics source
Prometheus2.x+Metrics collection and storage
Grafana9.x+Visualization and alerting
Network accessHTTPS 443Controller → Prometheus

Step 1: Enable Metrics on Automation Controller

The metrics endpoint is available at https://controller.example.com/api/v2/metrics. You need an API token:

Create an API Token

# Via the API
curl -k -X POST \
  https://ac.example.com/api/v2/tokens/ \
  -H "Content-Type: application/json" \
  -u admin:password \
  -d '{"scope": "read"}'

Or create one in the UI: Settings → Tokens → Add Token (read scope only).

Verify Metrics Endpoint

curl -k -H "Authorization: Bearer YOUR_TOKEN" \
  https://ac.example.com/api/v2/metrics/

Available Metrics

MetricTypeDescription
awx_system_infogaugeController version and install info
awx_organizations_totalgaugeTotal organizations
awx_users_totalgaugeTotal users
awx_teams_totalgaugeTotal teams
awx_inventories_totalgaugeTotal inventories
awx_projects_totalgaugeTotal projects
awx_job_templates_totalgaugeTotal job templates
awx_workflows_totalgaugeTotal workflow templates
awx_hosts_totalgaugeTotal hosts (by status)
awx_schedules_totalgaugeTotal schedules
awx_running_jobs_totalgaugeCurrently running jobs
awx_pending_jobs_totalgaugeQueued jobs waiting to run
awx_status_totalgaugeJobs by status (successful, failed, error)
callback_receiver_events_*counter/gaugeEvent processing metrics
subsystem_metrics_*gaugeInternal task system metrics

Step 2: Configure Prometheus

prometheus.yml

global:
  scrape_interval: 15s
  evaluation_interval: 15s
  scrape_timeout: 10s

  external_labels:
    environment: production

rule_files:
  - /etc/prometheus/rules/*.rules

scrape_configs:
  # Prometheus self-monitoring
  - job_name: prometheus
    metrics_path: /metrics
    static_configs:
      - targets:
          - localhost:9090

  # Node exporters for system metrics
  - job_name: node
    file_sd_configs:
      - files:
          - /etc/prometheus/file_sd/node.yml

  # Automation Controller
  - job_name: automation_controller
    metrics_path: /api/v2/metrics
    scrape_interval: 5s
    scheme: https
    tls_config:
      insecure_skip_verify: true  # Use proper certs in production
    bearer_token: YOUR_API_TOKEN
    static_configs:
      - targets:
          - ac.example.com
        labels:
          instance: production-controller

Using a Token File (More Secure)

  - job_name: automation_controller
    metrics_path: /api/v2/metrics
    scrape_interval: 5s
    scheme: https
    tls_config:
      ca_file: /etc/prometheus/certs/controller-ca.crt
    bearer_token_file: /etc/prometheus/secrets/controller-token
    static_configs:
      - targets:
          - ac.example.com

Start Prometheus

# Docker
docker run -d \
  --name prometheus \
  -p 9090:9090 \
  -v /etc/prometheus:/etc/prometheus \
  prom/prometheus \
  --config.file=/etc/prometheus/prometheus.yml

# Or systemd
sudo systemctl start prometheus

Verify Scraping

Visit http://prometheus:9090/targets — the automation_controller target should show UP.

Step 3: Configure Grafana

Add Prometheus Data Source

  1. Navigate to Configuration → Data Sources → Add data source
  2. Select Prometheus
  3. Set URL: http://prometheus:9090
  4. Click Save & Test

Or via provisioning:

# /etc/grafana/provisioning/datasources/prometheus.yml
apiVersion: 1
datasources:
  - name: Prometheus
    type: prometheus
    url: http://prometheus:9090
    access: proxy
    isDefault: true

Build Dashboards

Job Success Rate Panel

# PromQL — success rate last 24h
sum(awx_status_total{status="successful"}) /
(sum(awx_status_total{status="successful"}) + sum(awx_status_total{status="failed"})) * 100

Running Jobs Gauge

# PromQL — currently running jobs
awx_running_jobs_total

Pending Jobs Queue

# PromQL — jobs waiting in queue
awx_pending_jobs_total

Host Status Breakdown

# PromQL — hosts by status
awx_hosts_total

Job Failure Rate Over Time

# PromQL — failed jobs per hour
rate(awx_status_total{status="failed"}[1h])

Dashboard Layout Recommendations

┌─────────────────────────────────────────────────┐
│ Row 1: Overview Stats                           │
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐  │
│ │ Jobs │ │ Pass │ │ Fail │ │Queue │ │ Run  │  │
│ │Total │ │ Rate │ │ Rate │ │ Depth│ │ ning │  │
│ └──────┘ └──────┘ └──────┘ └──────┘ └──────┘  │
├─────────────────────────────────────────────────┤
│ Row 2: Time Series                              │
│ ┌───────────────────────┐ ┌───────────────────┐ │
│ │ Jobs Over Time        │ │ Host Status       │ │
│ │ (stacked area)        │ │ (pie chart)       │ │
│ └───────────────────────┘ └───────────────────┘ │
├─────────────────────────────────────────────────┤
│ Row 3: Details                                  │
│ ┌───────────────────────┐ ┌───────────────────┐ │
│ │ Failure Rate Graph    │ │ Event Processing  │ │
│ │ (line chart)          │ │ (counter rate)    │ │
│ └───────────────────────┘ └───────────────────┘ │
└─────────────────────────────────────────────────┘

Step 4: Create Alerting Rules

Prometheus Alert Rules

# /etc/prometheus/rules/controller.rules
groups:
  - name: automation_controller
    rules:
      - alert: HighJobFailureRate
        expr: |
          sum(rate(awx_status_total{status="failed"}[5m])) /
          sum(rate(awx_status_total[5m])) > 0.1
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "High job failure rate on {{ $labels.instance }}"
          description: "More than 10% of jobs failing in the last 5 minutes"

      - alert: JobQueueBacklog
        expr: awx_pending_jobs_total > 20
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Job queue backlog on {{ $labels.instance }}"
          description: "{{ $value }} jobs pending in queue"

      - alert: ControllerDown
        expr: up{job="automation_controller"} == 0
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "Automation Controller unreachable"
          description: "Cannot scrape metrics from {{ $labels.instance }}"

Grafana Alert Example

Configure in Grafana UI: Alerting → Alert Rules → New Alert Rule

SettingValue
Queryawx_pending_jobs_total
ConditionWhen last() is above 20
Evaluate every1m
For5m
NotificationSlack/Email/PagerDuty

Ansible Playbook for Deployment

Automate the entire monitoring stack setup:

---
- name: Deploy monitoring stack
  hosts: monitoring
  become: true
  vars:
    controller_url: ac.example.com
    controller_token: "{{ vault_controller_token }}"
  tasks:
    - name: Install Prometheus
      ansible.builtin.package:
        name: prometheus
        state: present

    - name: Deploy Prometheus config
      ansible.builtin.template:
        src: prometheus.yml.j2
        dest: /etc/prometheus/prometheus.yml
        mode: "0644"
      notify: Restart Prometheus

    - name: Deploy alert rules
      ansible.builtin.copy:
        src: controller.rules
        dest: /etc/prometheus/rules/controller.rules
        mode: "0644"
      notify: Restart Prometheus

    - name: Install Grafana
      ansible.builtin.package:
        name: grafana
        state: present

    - name: Deploy Grafana data source
      ansible.builtin.template:
        src: grafana-datasource.yml.j2
        dest: /etc/grafana/provisioning/datasources/prometheus.yml
        mode: "0644"
      notify: Restart Grafana

    - name: Ensure services are running
      ansible.builtin.service:
        name: "{{ item }}"
        state: started
        enabled: true
      loop:
        - prometheus
        - grafana-server

  handlers:
    - name: Restart Prometheus
      ansible.builtin.service:
        name: prometheus
        state: restarted

    - name: Restart Grafana
      ansible.builtin.service:
        name: grafana-server
        state: restarted

Security Best Practices

  1. Use read-only tokens — metrics endpoint only needs read scope
  2. Enable TLS — use proper certificates, not insecure_skip_verify
  3. Restrict network access — only Prometheus should reach the metrics endpoint
  4. Rotate tokens — set token expiry and rotate regularly
  5. Use token files — bearer_token_file over inline tokens in config
  6. RBAC in Grafana — limit dashboard access to operations team

Troubleshooting

Prometheus Target Shows DOWN

# Check connectivity
curl -k https://ac.example.com/api/v2/metrics/ \
  -H "Authorization: Bearer YOUR_TOKEN"

# Check Prometheus logs
journalctl -u prometheus | tail -20

No Data in Grafana

  1. Verify Prometheus data source connection (Settings → Data Sources → Test)
  2. Check time range in dashboard (last 5 minutes vs last 24 hours)
  3. Query up{job="automation_controller"} in Prometheus to verify scraping

Metrics Stale or Delayed

# Reduce scrape interval for fresher data
scrape_interval: 5s  # default is 15s

Conclusion

Integrating Automation Controller with Prometheus and Grafana gives you real-time visibility into your automation platform — job success rates, queue depth, host status, and system health on a single dashboard. Use the /api/v2/metrics endpoint with a bearer token, configure Prometheus to scrape every 5 seconds, and build Grafana dashboards with the PromQL queries above. Add alerting rules for job failures and queue backlogs to catch issues before they impact operations.