AI Decision System
Replayable, offline-verifiable records for AI-assisted go/no-go decisions: experiment promotions, typed model answers and human-approved actions.
Prometheus exporter and OpenTelemetry collector for the Cisco Meraki Dashboard API. Scrape-ready metrics, OTLP export and Grafana dashboards included.
Developer toolsPython · HTMLGitHub @rknightionOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Loading the full README. The saved excerpt is shown below.
Prometheus exporter and OpenTelemetry collector for the Cisco Meraki Dashboard API. Scrapes
device, network and MT sensor metrics into a /metrics endpoint and pushes native OTLP metrics.Read the full README ↗Prometheus exporter and OpenTelemetry collector for the Cisco Meraki Dashboard API. Scrapes
device, network and MT sensor metrics into a /metrics endpoint and pushes native OTLP metrics.
[!WARNING] I no longer have access to a Meraki network with anything other than MT, MR & MS devices. Changes affecting other device types (MX, MG, MV) are best-effort and driven from publicly available API documentation and SDK references rather than tested against live hardware. If you are willing to work with myself to boost support for other device types or add coverage please reach out! See the Support Matrix for exactly what is collected per product line.
A Prometheus exporter for Cisco Meraki Dashboard API metrics with OpenTelemetry tracing support.
/status health UI alongside /cardinality UI and /api/metrics/cardinality JSON API/metrics endpoint for scraping/health and /ready probes plus a /status HTML dashboard summarising collector success rates, failure streaks, and last success timestampsCopy .env.example to .env and add your Meraki API key:
cp .env.example .env
# Edit .env and set: MERAKI_EXPORTER_MERAKI__API_KEY=your_api_key_here
Run with Docker Compose:
docker compose up -d
Access metrics at http://localhost:9099/metrics
If you need to build the Docker image from source:
# Build the image
docker build -t meraki-dashboard-exporter .
# Run the container
docker run -d \
-e MERAKI_EXPORTER_MERAKI__API_KEY=your_api_key_here \
-p 9099:9099 \
meraki-dashboard-exporter
[!NOTE] A locally-built image reports its version as
0.0.0+dev(and commitunknown) on/status, the web UI, andmeraki_exporter_build_info. Real version/commit values are baked in only by CI-published images (via theAPP_VERSION/GIT_COMMITbuild-args); pass--build-arg APP_VERSION=<v> --build-arg GIT_COMMIT=<sha>todocker buildif you want them on a local build.The bundled
docker-compose.ymlhealthcheck polls/health, which includes a dead-man switch: it returns 503 (marking the container unhealthy) if no collector has completed a successful run within the staleness threshold, so a wedged exporter is restarted rather than left serving stale metrics.
A Helm chart is published to the GHCR OCI registry alongside every release, from
charts/meraki-dashboard-exporter:
helm install meraki-dashboard-exporter \
oci://ghcr.io/rknightion/charts/meraki-dashboard-exporter \
--version <exporter-version> \
--set meraki.apiKey=your_api_key_here
Replace <exporter-version> with a released version
(chart versions track exporter releases, e.g. 0.31.0), or use an existingSecret instead of
meraki.apiKey for production. See
values.yaml for all configurable settings and
the chart's CLAUDE.md for implementation notes. An
edge chart tracking main is also published on every push, versioned 0.0.0-main.*.
The exporter provides OpenTelemetry tracing when enabled:
Tracing: Distributed tracing for all operations
Logs: Structured logging with trace correlation
Benefits:
Set these environment variables:
# Enable OTEL tracing
export MERAKI_EXPORTER_OTEL__ENABLED=true
# Set the OTEL collector endpoint
export MERAKI_EXPORTER_OTEL__ENDPOINT=http://localhost:4317
# Optional: Add resource attributes
export MERAKI_EXPORTER_OTEL__RESOURCE_ATTRIBUTES='{"environment":"production","region":"us-east"}'
# Optional: Configure trace sampling rate (default: 0.1 = 10%)
export MERAKI_EXPORTER_OTEL__SAMPLING_RATE=0.1
services:
meraki-exporter:
image: meraki-dashboard-exporter
environment:
- MERAKI_EXPORTER_MERAKI__API_KEY=${MERAKI_EXPORTER_MERAKI__API_KEY}
- MERAKI_EXPORTER_OTEL__ENABLED=true
- MERAKI_EXPORTER_OTEL__ENDPOINT=http://otel-collector:4317
ports:
- "9099:9099"
otel-collector:
image: otel/opentelemetry-collector-contrib:latest
command: ["--config=/etc/otel-collector-config.yaml"]
volumes:
- ./otel-collector-config.yaml:/etc/otel-collector-config.yaml
ports:
- "4317:4317" # OTLP gRPC receiver
See docs/observability/otel.md for detailed OpenTelemetry configuration and docs/observability/tracing.md for distributed tracing documentation.
The exporter can receive webhook events from Meraki Dashboard. Webhooks accelerate device-down
detection only: a device_down/gateway_down event fast-flips meraki_device_up=0 ahead of the
next poll. Device recovery/UP and every other metric remain polled at DeviceCollector's own
solved cadence (~300s by default) — there is no whole-device "back online" webhook event to drive
a fast recovery path. See docs/data-freshness.md for the full staleness
picture and recommended alert for: durations.
# Enable webhook receiver
export MERAKI_EXPORTER_WEBHOOKS__ENABLED=true
# Set shared secret for validation (recommended)
export MERAKI_EXPORTER_WEBHOOKS__SHARED_SECRET=your_secret_here
# Optional: Require secret validation (default: true)
export MERAKI_EXPORTER_WEBHOOKS__REQUIRE_SECRET=true
# Optional: Maximum payload size in bytes (default: 1MB)
export MERAKI_EXPORTER_WEBHOOKS__MAX_PAYLOAD_SIZE=1048576
http://your-exporter:9099/api/webhooks/merakimeraki_webhook_events_received_total: Total webhook events received by org and alert typemeraki_webhook_events_processed_total: Successfully processed webhook eventsmeraki_webhook_events_failed_total: Failed webhook event processingmeraki_webhook_processing_duration_seconds: Time spent processing webhook eventsmeraki_webhook_validation_failures_total: Validation failures by error typeAll configuration is done via environment variables. See .env.example for all available options.
MERAKI_EXPORTER_MERAKI__API_KEY: Your Meraki Dashboard API keyMERAKI_EXPORTER_MERAKI__ORG_ID: Specific org ID to monitor. If unset, startup auto-selects
the only visible org, but fails fast when the API key can see multiple orgs; deploy one instance
per org. See the sharding recipe.MERAKI_EXPORTER_LOGGING__LEVEL: Logging level (default: INFO)MERAKI_EXPORTER_MERAKI__API_BASE_URL: API base URL for regional endpoints (default: https://api.meraki.com/api/v1)MERAKI_EXPORTER_API__TIMEOUT: API request timeout in seconds (default: 30)MERAKI_EXPORTER_API__MAX_RETRIES: Maximum API request retries (default: 3)MERAKI_EXPORTER_API__CONCURRENCY_LIMIT: Max parallel collector/org work (default: 5)MERAKI_EXPORTER_API__BATCH_SIZE: Default batch size for API operations (default: 20)MERAKI_EXPORTER_API__VALIDATE_KWARGS: Enable Meraki SDK kwarg validation warnings (default: false; recommended for dev/CI)MERAKI_EXPORTER_COLLECTORS__COLLECTOR_TIMEOUT: Per-run collector timeout budget in seconds (default: 240)MERAKI_EXPORTER_CLIENTS__ENABLED: Enable client collector and DNS resolution (default: false)MERAKI_EXPORTER_WEBHOOKS__ENABLED: Enable Meraki webhook receiver (default: false)MERAKI_EXPORTER_SERVER__API_TOKEN: Bearer token that enables the two state-changing control POSTs (/api/collectors/trigger, /api/clients/clear-dns-cache). When unset (default), those POSTs fail closed with HTTP 401 and their UI controls are disabled. When configured, the controls are API-only and hidden from the browser. The sensitive GET UIs remain open by default; bind the exporter to a trusted network or disable them. See security.md.meraki_org_has_beta_api (1/0 per org) plus a WARN log fire when an org is on the beta Dashboard spec, which can silently break assumed-stable collection. Alert on meraki_org_has_beta_api == 1. See .There is no fixed FAST/MEDIUM/SLOW tier system. Every API fetch is grouped into an endpoint group with its own volatility floor, and an adaptive, budget-aware scheduler solves each group's actual polling interval from organization size and the configured API budget, automatically stretching lower-priority groups when demand would exceed it. See Scheduler Architecture for the full mechanism.
MERAKI_EXPORTER_SCHEDULER__MODE: adaptive (default) or fixed (floors/pins only, no stretching)MERAKI_EXPORTER_SCHEDULER__TARGET_UTILIZATION: Fraction of the effective budget the solver plans to (default: 0.7)MERAKI_EXPORTER_SCHEDULER__MAX_STRETCH_FACTOR: Per-group interval cap as a multiple of its floor (default: 4.0)MERAKI_EXPORTER_SCHEDULER__MAX_INTERVAL_SECONDS: Absolute per-group interval cap (default: 3600)MERAKI_EXPORTER_SCHEDULER__RESOLVE_INTERVAL_SECONDS: How often the solver recomputes from org shape (default: 900)MERAKI_EXPORTER_SCHEDULER__FAILURE_RETRY_SECONDS: Minimum spacing between retries of a failing group (default: 300)MERAKI_EXPORTER_SCHEDULER__GROUP_INTERVAL_OVERRIDES: Per-group interval pins as a JSON object, e.g. {"nh_connection_stats": 900}MERAKI_EXPORTER_COLLECTORS__MAX_CONCURRENT_COLLECTORS: Max collectors whose group-clocked loops may run concurrently (default: 5)Restrict the exporter to a subset of networks. All fields are optional comma-separated lists; if every field is empty, every network in every configured organisation is scraped (the default).
# Include only networks whose name matches a glob (case-sensitive)
MERAKI_EXPORTER_NETWORK_FILTER__INCLUDE_NAMES=prod-*,staging-*
# Or by exact network ID
MERAKI_EXPORTER_NETWORK_FILTER__INCLUDE_IDS=L_123,L_456
# Or by network tag (any match wins)
MERAKI_EXPORTER_NETWORK_FILTER__INCLUDE_TAGS=production,critical
# Exclude rules (applied AFTER includes)
MERAKI_EXPORTER_NETWORK_FILTER__EXCLUDE_NAMES=*-test
MERAKI_EXPORTER_NETWORK_FILTER__EXCLUDE_IDS=L_999999
MERAKI_EXPORTER_NETWORK_FILTER__EXCLUDE_TAGS=lab
Semantics. If any INCLUDE_* field is set, a network must match at least one include rule (across name OR id OR tag) to be considered. Then any matching EXCLUDE_* rule drops it. Empty resolution at startup fails fast.
Devices in excluded networks are not scraped either. Organization-level metrics (license counts, API usage) are unaffected.
Observability. Live filter state is published as meraki_network_filter_match{org_id,network_id} (value 1 if included, 0 if excluded), meraki_network_filter_resolved{org_id}, and meraki_network_filter_total{org_id} so dashboards and alerts can verify filter scope.
For users in specific regions, use the appropriate API base URL:
https://api.meraki.com/api/v1https://api.meraki.ca/api/v1https://api.meraki.cn/api/v1https://api.meraki.in/api/v1https://api.gov-meraki.com/api/v1Example:
export MERAKI_EXPORTER_MERAKI__API_BASE_URL="https://api.meraki.ca/api/v1" # For Canada region
The exporter exposes /metrics, health/readiness probes (/health, /ready), a
/status dashboard, the client and cardinality UIs, and a few control/webhook
POSTs. See the generated HTTP Endpoints reference
for the authoritative list (method, path, and which config flag gates each one),
kept in sync via uv run python scripts/generate_endpoints_docs.py.
MERAKI_EXPORTER_CLIENTS__ENABLED=truePOST /api/webhooks/meraki/cardinality HTML report and /api/metrics/cardinality JSON API for top-k series growthSee the generated metrics reference for the authoritative metric list (kept in sync via uv run python scripts/generate_metrics_docs.py).
Metric-name, label, and unit compatibility is governed by the Metric Stability & Deprecation Policy, which defines the Stable vs Experimental tiers, the 1.0 promise, and the post-1.0 rename process.
MERAKI_EXPORTER_API__CONCURRENCY_LIMIT; MERAKI_EXPORTER_COLLECTORS__MAX_CONCURRENT_COLLECTORS separately bounds how many collectors' own loops run concurrentlyOrganizationInventory cache to suppress duplicate API callsMERAKI_EXPORTER_API__*BATCH_SIZE, MERAKI_EXPORTER_API__BATCH_DELAY)MERAKI_EXPORTER_COLLECTORS__COLLECTOR_TIMEOUT so a single collector cannot starve the run budgetuv run pytest
uv run ruff check .
uv run mypy .
MIT