Skip to content

Add full support for config based on environment variables #186

@hhromic

Description

@hhromic

Is your feature request related to a problem? Please describe.

We use the exporter inside a Docker container, where we dynamically generate a configuration file in an entrypoint shell script on start based on a set of environment variables passed to the container to pre-configure the SQL exporter.

The entrypoint script we made needed to address the following requirements:

  • Be able to configure database aspects from separate environment variables (host, port, dbname, etc)
  • Be able to read database secrets from an env variable or a file (i.e. to use container secrets feature)
  • Allow to configure any global configuration of the exporter without rebuilding the image
  • Be able to configure the exporter only from mounted collector files, and not need to mount a static global config.

We are aware that at the moment there is partial support for env variables in the exporter, namely:

  • SQLEXPORTER_DEBUG
  • SQLEXPORTER_CONFIG
  • SQLEXPORTER_TARGET_DSN

But we would like to be able to override any configuration in the config files, not just target.dsn.

Describe the solution you'd like

We would like for the SQL exporter to be able to be fully configured from environment variables, therefore greatly increasing usability and user experience when running in containers (not only Docker) because we can fully avoid writing entrypoint scripts.

If you are open to this feature request, I'm happy to implement it and send a PR for reviewing.

Describe alternatives you've considered

To fulfil the requirements, our current entrypoint script is as follows:

#!/usr/bin/env sh

die() { printf "fatal: %s\n" "$*" > /dev/stderr; exit 1; }
uri() { printf "%s" "$(jq -nr --arg v "$*" '$v | @uri')"; }

# define working directories and files
SHM_DIR=/dev/shm
CONFIG_FILE=$SHM_DIR/sql-exporter.yaml
COLLECTORS_DIR=  # use root directory of container

# check required environment variables
[ -z "$DB_HOST" ] && die "missing required environment variable: DB_HOST"
[ -z "$DB_USER" ] && die "missing required environment variable: DB_USER"
if [ -z "$DB_PASSWORD" ] && [ -z "$DB_PASSWORD_FILE" ]; then
  die "missing required environment variable: one of DB_PASSWORD or DB_PASSWORD_FILE"
fi
[ -z "$DB_DATABASE" ] && die "missing required environment variable: DB_DATABASE"

# prepare optional environment variables
SQLEXPORTER_GLOBAL_SCRAPE_TIMEOUT=${SQLEXPORTER_GLOBAL_SCRAPE_TIMEOUT:-10s}
SQLEXPORTER_GLOBAL_SCRAPE_TIMEOUT_OFFSET=${SQLEXPORTER_GLOBAL_SCRAPE_TIMEOUT_OFFSET:-500ms}
SQLEXPORTER_GLOBAL_MIN_INTERVAL=${SQLEXPORTER_GLOBAL_MIN_INTERVAL:-0s}
SQLEXPORTER_GLOBAL_MAX_CONNECTIONS=${SQLEXPORTER_GLOBAL_MAX_CONNECTIONS:-3}
SQLEXPORTER_GLOBAL_MAX_IDLE_CONNECTIONS=${SQLEXPORTER_GLOBAL_MAX_IDLE_CONNECTIONS:-3}
DB_PORT=${DB_PORT:-5433}

# read password from file if provided
[ -n "$DB_PASSWORD_FILE" ] && DB_PASSWORD=$(cat "$DB_PASSWORD_FILE")

# collect the names of all available collectors
COLLECTORS=
for COLL_FILE in "$COLLECTORS_DIR"/*.collector.yaml; do
  [ -e "$COLL_FILE" ] || [ -L "$COLL_FILE" ] || continue
  COLLECTOR=$(sed -rn '/^collector_name: / s/collector_name: (.+)/'"'"'\1'"'"'/g p' "$COLL_FILE")
  if [ -z "$COLLECTORS" ]; then
    COLLECTORS=$COLLECTOR
  else
    COLLECTORS="$COLLECTORS, $COLLECTOR"
  fi
done

# build the data source name (DSN) to use
DSN=driver://$(uri "$DB_USER"):$(uri "$DB_PASSWORD")
DSN=${DSN}@${DB_HOST}:${DB_PORT}/${DB_DATABASE}

# generate configuration file for the SQL exporter
cat > "$CONFIG_FILE" << __EOF__
global:
  scrape_timeout: $SQLEXPORTER_GLOBAL_SCRAPE_TIMEOUT
  scrape_timeout_offset: $SQLEXPORTER_GLOBAL_SCRAPE_TIMEOUT_OFFSET
  min_interval: $SQLEXPORTER_GLOBAL_MIN_INTERVAL
  max_connections: $SQLEXPORTER_GLOBAL_MAX_CONNECTIONS
  max_idle_connections: $SQLEXPORTER_GLOBAL_MAX_IDLE_CONNECTIONS
target:
  data_source_name: '$DSN'
  collectors: [$COLLECTORS]
collector_files: ['$COLLECTORS_DIR/*.collector.yaml']
__EOF__

# execute SQL exporter with the generated configuration file
exec sql_exporter --config.file="$CONFIG_FILE"

As it can be seen, the above script is quite a lot of boilerplate that could be instead managed natively in the SQL exporter if it had full support for environment variables, especially the global config.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions