Prometheus and Alertmanager

Alerts in, PromQL as evidence for every pack, approved silences, and fixes when your monitoring itself breaks.

Firing alerts from Alertmanager become 3AM incidents (silenced and inhibited ones don't). 3AM's packs run their checks as PromQL against your Prometheus: MySQL, Kubernetes, JVM, nginx and the rest. 3AM also watches Prometheus and Alertmanager themselves. When monitoring is broken, its own evidence is unreliable, so it treats that as an incident too.

Before you start

  • Read access to Prometheus' HTTP API, and to Alertmanager's.
  • Write access to Alertmanager silences, only if 3AM may create silences. Every silence is approved.
  • Outbound access from 3AM to both. Nothing connects to 3AM.

1. Create credentials

Your setupGive 3AM
No authenticationThe URLs
web.yml basic authA user and password (add a user for 3AM)
A reverse proxy or SSO in frontA bearer token
Alertmanager behind a different proxyIts own credentials (the alertmanager_* settings)
HTTPS with an internal CAThe CA certificate, as a PEM file

web.yml stores bcrypt hashes. Make one for 3AM's password:

htpasswd -nbBC 10 3am 'a-long-random-password' | cut -d: -f2
web.yml
basic_auth_users:
  3am: $2y$10$…          # the hash from above

2. Check your exporters

The packs' checks read standard exporter metrics. A stock exporter covers the core checks; a few need a flag:

TechnologyExporterWorks out of the boxTurn on for more
MySQL / MariaDBmysqld_exporterup, read-only, connection usage, row-lock waits--collect.info_schema.processlist for per-user connections. Replication lag is reported on replicas
Alertmanagerits own /metrics (scrape it)notification failures
Kuberneteskube-state-metricsrestarts, OOM kills

A check whose metric is missing is reported as inconclusive. It never counts as passed.

3. Add the connector

In the console: Connections → Add a connection → Prometheus / Alertmanager. Or in connectors.json:

/etc/3am/connectors.json
{ "name": "prometheus", "kind": "prometheus",
  "settings": { "url": "https://prometheus.bank.internal:9090",
                "username": "3am", "password": { "file": "/etc/3am/secrets/prometheus-password" },
                "alertmanager_url": "https://alertmanager.bank.internal:9093",
                "alertmanager_bearer_token": { "env": "AM_TOKEN" },
                "ca_file": "/etc/3am/secrets/bank-ca.pem" } }
kind: prometheusalerts inmetrics and queriesactions
SettingWhat to enterRequiredDefault
urlPrometheus base URLyes—
alertmanager_urlAlertmanager base URLno—
bearer_tokensecretBearer token, if requiredno—
usernameBasic-auth user, if requiredno—
passwordsecretBasic-auth passwordno—
alertmanager_bearer_tokensecretAlertmanager bearer token (if different)no—
alertmanager_usernameAlertmanager basic-auth user (if different)no—
alertmanager_passwordsecretAlertmanager basic-auth password (if different)no—
ca_fileCA certificate for a private CA (PEM file)no—
verify_tlsVerify TLSyestrue

4. Verify

Test connection runs a real query (not just a ping) and checks Alertmanager with its own credentials:

Test connection
Connected. Prometheus 3.15.0 + Alertmanager 0.34.1
jobs: 6 (mysql, prometheus, …)   alert rules: 95   targets: 32

To check the whole path, add a rule that always fires and reload Prometheus:

groups:
  - name: 3am-test
    rules:
      - alert: ThreeAMPipelineTest
        expr: vector(1)
        labels: { severity: critical, service: monitoring }

Within a minute the console shows an incident for ThreeAMPipelineTest. 3AM finds nothing to prove and says so. Remove the rule afterwards.

What it proves and fixes

3AM raises these from Prometheus' and Alertmanager's own status, even with no alert rule for them. If your own rule for the same thing fires, 3AM uses yours.

CauseHow 3AM knowsFix
Prometheus or Alertmanager down or hungIt doesn't answer. Raised as PrometheusComponentDown, even when Prometheus is the one downRestart its pod or workload (Kubernetes connector)
Prometheus' storage fullThe TSDB fails to write its WAL or to compactGrow its volume by half (Kubernetes connector). Two approvers
Target unreachableThe scrape error: connection refused, DNS, timeoutRestart the target's workload, if it runs in a namespace 3AM watches
Target refuses credentialsThe scrape error is a 401 or 403Advice: update the scrape job's credentials
Target answers garbageA parse or content-type errorAdvice: check the exporter
Config reload failedPrometheus' runtime statusAdvice: promtool check config, fix, reload
Rules failingRule health, with each failing rule's errorAdvice: fix the named rules
No AlertmanagerPrometheus' Alertmanager discoveryAdvice: alerts reach nobody until it's fixed
Notifications failingalertmanager_notifications_failed_total rising, per integrationAdvice: fix the receiver

Restarts and volume growth go through the Kubernetes connector, which finds the workload behind Prometheus', Alertmanager's or the target's address. Without it these causes go to a person with the evidence.

Actions

ActionParametersNotes
silencealertname, minutes, comment, matchers1–1440 minutes, createdBy: 3AM. The rehearsal lists the alerts it would silence
unsilencesilence_idExpires a silence
targets, prometheus_status, alertmanager_status, components_status, volume_usageRead-only evidence for the packs

Troubleshooting

Prometheus: authentication failed

Check the user and password, or the bearer token.

Alertmanager: authentication failed

Alertmanager has its own credentials. Fill in the alertmanager_* settings.

the certificate is not trusted: set ca_file

Set CA certificate to your internal CA, in PEM format.

Prometheus refused the query (bad_data)

A check's PromQL didn't parse on your Prometheus. The message includes Prometheus' own explanation; send it to support@3am.si.

Silenced alerts still appear

Without alertmanager_url, 3AM reads Prometheus' alerts, which know nothing about silences. Add the Alertmanager URL.

Certification

Live, on Prometheus 3.15 behind HTTPS with an internal CA and basic auth, Alertmanager 0.34 behind a bearer-token proxy, and the real mysqld_exporter 0.20 (2026-10-04):

  • 46 checks. End to end, the database was set read-only. This Prometheus fired MySQLReadOnly through Alertmanager, 3AM proved it from this Prometheus' metric and fixed it with approval, and the alert resolved.
  • Fixes, on Kubernetes. A hung Prometheus, a hung Alertmanager and a hung scrape target were each restarted and verified (details).

On this page