exportarr

repository·main·Indexed 20 days ago

https://github.com/onedr0p/exportarr

An All-in-One (AIO) Prometheus Exporter for media automation applications, including Sonarr, Radarr, Lidarr, Prowlarr, Bazarr, and Sabnzbd. It provides pre-configured Grafana dashboard JSON examples and supports deployment via Docker or CLI. The tool includes features for Prowlarr historical metric backfilling and specific configuration options to optimize scrape performance and resource usage for large libraries.

Tokens
7.7K
Snippets
16
Records
20
Agent score
73%

What's inside exportarr

  1. Optimize scrape performance and resource usage

    main

    Scrape performance varies significantly by application. Use these guidelines to tune your scrape_interval and container limits:

    Scrape Timing Guidelines

    • Bazarr: Can take tens of seconds (especially with episode metrics). Set scrape_interval to 60s or more.
    • Sonarr/Lidarr: Takes a few seconds due to per-series/artist fan-out.
    • Radarr: Takes 1-2 seconds (large JSON payload).
    • SABnzbd/Prowlarr: Very fast.

    Important: If a scrape arrives while the previous one is still running, Exportarr skips it and raises an error gauge. Always set your scrape_interval longer than your slowest expected scrape.

    Resource Management

    • Memory: Expect 25–100 MB RSS. High-end usage occurs during Bazarr episode walks or large Radarr movie lists. In Kubernetes, set GOMEMLIMIT to the container memory limit to manage GC spikes.
    • Slow Scrapes: If scrapes are too slow, do not simply decrease REQUEST_TIMEOUT. Instead, use DISABLE_* flags (e.g., DISABLE_HISTORY_METRICS, DISABLE_WANTED_METRICS, DISABLE_EPISODE_METRICS) to remove the expensive endpoints entirely.
  2. Upgrade from v2 to v3

    main

    v3 is a breaking release. When upgrading, you must address several removals, changes in configuration, and metric behaviors.

    Configuration Changes

    • API Keys: The APIKEY alias is removed. Use API_KEY instead. If using Docker/Kubernetes secrets, API_KEY_FILE remains supported.
    • Config Files: CONFIG or --config (which parsed config.xml) is removed. You must now provide the target app's URL and API_KEY (or API_KEY_FILE).
    • Authentication: HTTP basic auth is removed. For form-based authentication, use AUTH_USERNAME, AUTH_PASSWORD, and set FORM_AUTH=true. Setting credentials without FORM_AUTH=true will cause a startup error.
    • Log Levels: fatal, panic, and dpanic are no longer valid. Use debug, info, warn, or error.
    • Metrics Opt-out: ENABLE_ADDITIONAL_METRICS is removed. Metrics are now enabled by default. To restore v2's behavior (turning them off), set the following environment variables to true:
      • DISABLE_QUALITY_METRICS
      • DISABLE_EPISODE_METRICS
      • DISABLE_ALBUM_METRICS

    Alerting and Scrape Behavior

    • Error Handling: A failing collector no longer causes a 500 error for the whole /metrics endpoint. Instead, the endpoint returns 200, but a per-collector error gauge (e.g., radarr_collector_error) is set to 1. Update your alerts to monitor *_collector_error > 0 instead of checking if up == 0.
    • Overlapping Scrapes: If a scrape is triggered while a previous collection for the same app is still running, Exportarr will skip the new scrape and raise the collector's error gauge to prevent overloading the target app.

    Metric Changes

    • Bazarr Scores: bazarr_subtitles_score_total (unbounded cardinality) is replaced by the bazarr_subtitles_score histogram with buckets 10..90, 95, 100. Use histogram_quantile() for analysis.
    • Queue Metrics: <app>_queue_total now emits series based on (status, download_status, download_state). An empty queue now emits a single zero series with empty labels, allowing dashboards to distinguish between an empty queue and a failed scrape.
    • Duration Metrics: Self-instrumentation duration gauges (e.g., <app>_scrape_duration_seconds) are now histograms.
    • Log Format: Logs are now structured slog. Use --log-format json for JSON output.
    | v2                                   | v3                                                                                             |
    | ------------------------------------ | ------------------------------------------------------------------------------------------ |
    | `APIKEY`                             | `API_KEY`                                                                                  |
    | `API_KEY_FILE=/path`                 | unchanged — still supported (Docker/Kubernetes secrets)                                    |
    | `CONFIG=/path/config.xml`           | `URL` + `API_KEY`                                                                          |
    | `BASIC_AUTH_USERNAME`/`..._PASSWORD` | removed — form auth uses `AUTH_USERNAME`/`AUTH_PASSWORD` + `FORM_AUTH=true`                |
    | `LOG_LEVEL=fatal`                   | `LOG_LEVEL=error`                                                                          |
    | `ENABLE_ADDITIONAL_METRICS=true`    | (default behavior — remove it)                                                               |
    | `ENABLE_ADDITIONAL_METRICS` unset    | `DISABLE_QUALITY_METRICS` + `DISABLE_EPISODE_METRICS` + `DISABLE_ALBUM_METRICS` all `true` |
  3. Enable Prowlarr historical metric backfill

    main

    The Prowlarr collector uses a stats endpoint that collects counters for small time windows. By default, metrics start from zero when Exportarr starts. To collect historical data, enable backfill using PROWLARR__BACKFILL or --backfill.

    If the backfill process times out, you can limit the scope by specifying a start date with PROWLARR__BACKFILL_SINCE_DATE or --backfill-since-date in YYYY-MM-DD format.

    # Example using environment variable
    PROWLARR__BACKFILL_SINCE_DATE=2023-03-01
    
    # Example using CLI flag
    ./exportarr prowlarr --backfill --backfill-since-date=2023-03-01
  4. Install and run Exportarr via Docker CLI

    main

    To run Exportarr as a standalone Docker container, use the docker run command. You must provide a unique port for each instance and specify the target application, its URL, and its API key.

    Note: You must run one Exportarr instance per application (e.g., one for Sonarr, one for Radarr).

    # Replace $app, $port and $apikey with your target app, port and api key
    # PORT must be unique across all Exportarr instances
    docker run --name exportarr_$app \
      -e PORT=9707 \
      -e URL="http://x.x.x.x:$port" \
      -e API_KEY="$apikey" \
      --restart unless-stopped \
      -p 9707:9707 \
      -d ghcr.io/onedr0p/exportarr:latest $app
  5. Optimize large library scrapes in v3

    main

    For users with very large Sonarr or Radarr instances, v3 provides mechanisms to prevent scrapes from hanging or causing high CPU usage on the target application.

    • Skip Heavy Endpoints: Use DISABLE_HISTORY_METRICS and DISABLE_WANTED_METRICS to skip endpoints that require full table counts.
    • Request Timeout: You can cap the time spent on each request to the target app using REQUEST_TIMEOUT or the --request-timeout flag (defaults to 60s).
    • Performance: v3 uses pageSize=1 and concurrent lookups to make large-library scrapes significantly faster and more reliable.
  6. Run Exportarr via CLI

    main

    If running the binary directly, use the following command structure. Ensure the --port is unique if running multiple instances on the same host.

    # Replace $app, $port and $apikey with your target app, port and api key
    ./exportarr $app \
      --port 9707 \
      --url "http://x.x.x.x:$port" \
      --api-key "$apikey"
  7. Use the exportarr CLI

    main

    exportarr is a Prometheus exporter for *arr applications (Radarr, Sonarr, Lidarr, Bazarr, Prowlarr, and SABnzbd). It is executed via a single binary.

    When running the command, the application loads and validates its configuration before starting the HTTP server. If the configuration is invalid, the CLI will report the error and exit.

    Note: The application supports standard Cobra commands like help and completion which do not require a valid configuration to run.

    exportarr
  8. Understand the metrics collected by Exportarr

    main

    The metrics exported depend on the specific application subcommand used.

    Standard *arr apps (Radarr, Sonarr, Lidarr)

    These applications share a common set of collectors:

    • Queue: Metrics related to the download/processing queue.
    • Root Folder: Metrics regarding the root media folders.
    • Disk Space: Metrics about available and used disk space.
    • System Status: General system status metrics.
    • System Health: Health check metrics.
    • History: Download/activity history (enabled by default, can be disabled via DisableHistoryMetrics).

    Additionally, each app has its own specific collector (e.g., RadarrCollector, SonarrCollector, or LidarrCollector) to capture application-specific data.

    Prowlarr

    In addition to standard collectors, Prowlarr includes:

    • Prowlarr-specific metrics.
    • System Status and System Health.
    • Unavailable Indexer Emitter: Specifically tracks unavailable indexers.
    • History: (Enabled by default, can be disabled via DisableHistoryMetrics).

    Bazarr

    • Bazarr-specific metrics.
  9. Run the exportarr CLI

    main

    The exportarr command is an All-In-One (AIO) Prometheus exporter designed for *arr applications. It is the main entrypoint for the tool. When executed, it initializes the application and provides access to various commands and configuration options via the CLI.

    # Example of running the binary (assuming it is in your PATH)
    exportarr
  10. Use Grafana dashboard JSON examples

    main

    Exportarr provides pre-configured Grafana dashboard JSON files to visualize service data. You can use these as templates or starting points for your own monitoring setup.

    • Dashboard 1: Focused specifically on Radarr metrics. See dashboard.json for the implementation.
    • Dashboard 2: A multi-service dashboard covering Prowlarr, Sabnzbd, Radarr, Sonarr, and Lidarr. See dashboard2.json for the implementation.

    Important Note on Kubernetes: The Dashboard 2 template is designed for Kubernetes environments. The Uptime and Network panels rely on Kubernetes Prometheus metrics. If you are running Exportarr in a non-Kubernetes environment, you must delete or edit these specific panels to prevent errors.

    // To use these, import the JSON files into your Grafana instance:
    // Dashboard 1: dashboard.json
    // Dashboard 2: dashboard2.json
  11. Reference Exportarr configuration options

    main

    Exportarr can be configured via Environment Variables or CLI flags.

    Required Variables:

    • URL / --url or -u: The full URL to the app being exported.
    • API_KEY / --api-key or -a: API Key for the app being exported.

    Common Optional Variables:

    • PORT / --port or -p: The port Exportarr listens on (default: 8081).
    • INTERFACE / --interface or -i: The interface IP to listen on (default: 0.0.0.0).
    • LOG_LEVEL / --log-level or -l: Log level (debug, info, warn, error; default: info).
    • LOG_FORMAT / --log-format: Log format (console, json; default: console).
    • DISABLE_SSL_VERIFY / --disable-ssl-verify: Disable SSL verification (default: false).
    • REQUEST_TIMEOUT / --request-timeout: HTTP timeout per request (default: 60s).
    • FORM_AUTH / --form-auth: Use form-based authentication (default: false).
    • AUTH_USERNAME / --auth-username: Username for form auth.
    • AUTH_PASSWORD / --auth-password: Password for form auth.
    |        Environment Variable        | CLI Flag                       | Description                                                                                                                                                            | Default              | Required |
    | --------------------------------: | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------- | :------: |
    |               `PORT`               | `--port` or `-p`               | The port Exportarr will listen on                                                                                                                        | `8081`               |    ❌    |
    |               `URL`                | `--url` or `-u`                | The full URL to the app being exported                                                                                                                   |                      |    ✅    |
    |             `API_KEY`              | `--api-key` or `-a`            | API Key for the app being exported                                                                                                                       |                      |    ✅    |
    |           `API_KEY_FILE`           | —                              | Path to a file containing the API key (Docker/Kubernetes secrets); overrides `API_KEY`                                                                   |                      |    ❌    |
    |            `INTERFACE`             | `--interface` or `-i`          | The interface IP Exportarr will listen on                                                                                                                | `0.0.0.0`            |    ❌    |
    |            `LOG_LEVEL`             | `--log-level` or `-l`          | Log level (`debug`, `info`, `warn`, `error`)                                                                                                              | `info`               |    ❌    |
    |            `LOG_FORMAT`             | `--log-format`                 | Log format (`console`, `json`)                                                                                                                          | `console`            |    ❌    |
    |        `DISABLE_SSL_VERIFY`        | `--disable-ssl-verify`         | Set to `true` to disable SSL verification                                                                                                                | `false`              |    ❌    |
    |         `REQUEST_TIMEOUT`          | `--request-timeout`            | HTTP timeout per request to the target app                                                                                                               | `60s`                |    ❌    |
    |          `AUTH_PASSWORD`           | `--auth-password`              | Password for form auth                                                                                                                                   |                      |    ❌    |
    |          `AUTH_USERNAME`             | `--auth-username`              | Username for form auth                                                                                                                                   |                      |    ❌    |
    |            `FORM_AUTH`             | `--form-auth`                  | Use form-based authentication                                                                                                                            | `false`              |    ❌    |
    |    `ENABLE_UNKNOWN_QUEUE_ITEMS`    | `--enable-unknown-queue-items` | Set to `true` to enable gathering unknown queue items                                                                                                    | `false`              |    ❌    |
    |     `DISABLE_QUALITY_METRICS`      | `--disable-quality-metrics`    | Skip per-item quality breakdowns (episodefile/trackfile lookups; ~1 API call per series/artist each scrape)                                               | `false`              |    ❌    |
    |     `DISABLE_EPISODE_METRICS`      | `--disable-episode-metrics`    | Skip per-episode metrics (sonarr episode monitoring, bazarr episode-subtitle walk; load scales with library size)                                           | `false`              |    ❌    |
    |     `DISABLE_ALBUM_METRICS`        | `--disable-album-metrics`      | Skip per-album metrics (lidarr album lookups; ~1 API call per artist each scrape)                                                                        | `false`              |    ❌    |
    |      `DISABLE_HISTORY_METRICS`     | `--disable-history-metrics`    | Skip the history endpoint — its total forces a full count over the unprunable history table, slow on multi-year instances                               | `false`              |    ❌    |
    |      `DISABLE_WANTED_METRICS`      | `--disable-wanted-metrics`     | Skip the wanted/missing and wanted/cutoff endpoints — their totals force full counts, slow on very large libraries                                     | `false`              |    ❌    |
    |        `PROWLARR__BACKFILL`       | `--backfill`                   | Set to `true` to enable backfill of historical metrics                                                                                                   | `false`              |    ❌    |
    |  `PROWLARR__BACKFILL_SINCE_DATE`  | `--backfill-since-date`        | Set a date (`YYYY-MM-DD`) from which to start the backfill                                                                                               | `1970-01-01` (epoch) |    ❌    |
    |    `BAZARR__SERIES_BATCH_SIZE`     | `--series-batch-size`          | Number of series per Bazarr episodes API call                                                                                                            | `300`                |    ❌    |
    | `BAZARR__SERIES_BATCH_CONCURRENCY` | `--series-batch-concurrency`   | Concurrent Bazarr episodes API calls                                                                                                                     | `10`                 |    ❌    |
  12. Perform custom requests with DoRequest

    main

    If you need more control over the request process, use DoRequest. This method handles URL joining, query parameter merging, and JSON unmarshalling.

    Parameters:

    • endpoint (string): The API endpoint path.
    • target (any): A pointer to the variable where the decoded JSON response should be stored.
    • queryParams (...QueryParams): Variadic list of url.Values to be merged into the final request URL.
    params := url.Values{}
    params.Add("term", "search")
    
    var result MyResponse
    err := c.DoRequest("/api/v3/search", &result, params)
    if err != nil {
        return err
    }