A Prometheus exporter for the gpsd GPS daemon that provides comprehensive GPS monitoring and visualization capabilities.
gpsd-prometheus-exporter
connects to the TCP port of the GPSD daemon and records relevant GPS statistics, formatting them as Prometheus metrics for visualization in tools like Grafana.
The exporter provides real-time monitoring of:
- GPS position accuracy and quality metrics
- Individual satellite data and signal strength
- PPS (Pulse Per Second) time synchronization accuracy
- Geographic offset tracking from a reference point
Monitor GPS accuracy and quality metrics including DOP (Dilution of Precision) values:
Track individual satellite performance and signal quality:
Monitor clock offset from PPS (Pulse Per Second) signals for precise time synchronization:
To enable PPS monitoring, start gpsd with a PPS device:
gpsd <options> [serial port path] /dev/pps[0-9]
Then add --pps-histogram
to the exporter runtime arguments.
Track position offset from a stationary reference point:
The easiest way to run the exporter is using Docker.
docker run -d --name gpsd-exporter \
--network=host \
-p 9015:9015 \
-e GPSD_HOST=localhost \
-e GPSD_PORT=2947 \
-e GEOPOINT_LON=38.897809878 \
-e GEOPOINT_LAT=-77.036551259 \
-e PPS_BUCKET_SIZE=250 \
-e PPS_BUCKET_COUNT=40 \
-e GEO_BUCKET_SIZE=0.5 \
-e GEO_BUCKET_COUNT=40 \
-e EXPORTER_PORT=9015 \
-e VERBOSE=1 \
-e DEBUG=0 \
ghcr.io/brendanbank/gpsd-prometheus-exporter:latest
Two Docker Compose files are provided:
Using Pre-built Image (docker-compose.yml
):
docker compose up -d
Building Locally (docker-compose.build.yml
):
docker compose -f docker-compose.build.yml up --build
Example configurations:
Pre-built Image (docker-compose.yml
):
services:
gpsd-exporter:
image: ghcr.io/brendanbank/gpsd-prometheus-exporter:latest
container_name: gpsd-exporter
ports:
- "${EXPORTER_PORT:-9015}:9015"
environment:
- GPSD_HOST=${GPSD_HOST:-host.docker.internal}
- GPSD_PORT=${GPSD_PORT:-2947}
- GEOPOINT_LON=${GEOPOINT_LON:-38.897809878}
- GEOPOINT_LAT=${GEOPOINT_LAT:--77.036551259}
- PPS_BUCKET_SIZE=${PPS_BUCKET_SIZE:-250}
- PPS_BUCKET_COUNT=${PPS_BUCKET_COUNT:-40}
- PPS_TIME1=${PPS_TIME1}
- GEO_BUCKET_SIZE=${GEO_BUCKET_SIZE:-0.5}
- GEO_BUCKET_COUNT=${GEO_BUCKET_COUNT:-40}
- EXPORTER_PORT=${EXPORTER_PORT:-9015}
- DEBUG=${DEBUG:-0}
- VERBOSE=${VERBOSE:-1}
extra_hosts:
- "host.docker.internal:host-gateway"
restart: unless-stopped
network_mode: host
Local Build (docker-compose.build.yml
):
services:
gpsd-exporter:
build:
context: .
dockerfile: Dockerfile
image: gpsd-prometheus-exporter:stable
container_name: gpsd-exporter
ports:
- "${EXPORTER_PORT:-9015}:9015"
environment:
- GPSD_HOST=${GPSD_HOST:-localhost}
- GPSD_PORT=${GPSD_PORT:-2947}
- GEOPOINT_LON=${GEOPOINT_LON:-38.897809878}
- GEOPOINT_LAT=${GEOPOINT_LAT:--77.036551259}
- PPS_BUCKET_SIZE=${PPS_BUCKET_SIZE:-250}
- PPS_BUCKET_COUNT=${PPS_BUCKET_COUNT:-40}
- PPS_TIME1=${PPS_TIME1}
- GEO_BUCKET_SIZE=${GEO_BUCKET_SIZE:-0.5}
- GEO_BUCKET_COUNT=${GEO_BUCKET_COUNT:-40}
- EXPORTER_PORT=${EXPORTER_PORT:-9015}
- DEBUG=${DEBUG:-0}
- VERBOSE=${VERBOSE:-1}
restart: unless-stopped
network_mode: host
- Linux (supports host networking):
docker run -d --name gpsd-exporter \
--network=host \
-e GPSD_HOST=localhost \
-e GPSD_PORT=2947 \
ghcr.io/brendanbank/gpsd-prometheus-exporter:latest
# Access metrics directly on the host
curl 127.0.0.1:9015
Docker Compose on Linux can use network_mode: host
(as shown in the examples above). When using host networking, omit any ports:
mappings as they are ignored.
- macOS (host networking is not supported):
docker run -d --name gpsd-exporter \
-p 9015:9015 \
-e GPSD_HOST=host.docker.internal \
-e GPSD_PORT=2947 \
ghcr.io/brendanbank/gpsd-prometheus-exporter:latest
# Access metrics via the published port
curl 127.0.0.1:9015
For Docker Compose on macOS, remove network_mode: host
, keep ports:
and extra_hosts
, and set GPSD_HOST=host.docker.internal
:
services:
gpsd-exporter:
ports:
- "9015:9015"
extra_hosts:
- "host.docker.internal:host-gateway"
environment:
- GPSD_HOST=host.docker.internal
- GPSD_PORT=2947
Remote gpsd (any OS): If your gpsd runs on a remote host (e.g., ntp0.bgwlan.nl
), host networking is not required. Publish the port and point GPSD_HOST
to the remote server:
docker run -d --name gpsd-exporter \
-p 9015:9015 \
-e GPSD_HOST=ntp0.bgwlan.nl \
-e GPSD_PORT=2947 \
ghcr.io/brendanbank/gpsd-prometheus-exporter:latest
The following environment variables are supported for Docker deployments:
Variable | Default | Description |
---|---|---|
GPSD_HOST |
localhost |
gpsd hostname/IP address |
GPSD_PORT |
2947 |
gpsd TCP port |
EXPORTER_PORT |
9015 |
Prometheus exporter port |
GEOPOINT_LON |
38.897809878 |
Reference longitude for offset calculation |
GEOPOINT_LAT |
-77.036551259 |
Reference latitude for offset calculation |
PPS_BUCKET_SIZE |
250 |
PPS histogram bucket size in nanoseconds |
PPS_TIME1 |
(not set) | PPS time1 offset (enables PPS histogram when set) |
VERBOSE |
1 |
Enable verbose output (any value = verbose) |
DEBUG |
0 |
Debug level (0 = no debug, 1+ = debug) |
GEO_BUCKET_SIZE |
0.5 |
Geo offset histogram bucket size in meters |
GEO_BUCKET_COUNT |
40 |
Geo offset histogram bucket count |
PPS_BUCKET_COUNT |
40 |
PPS histogram bucket count |
Create a .env
file for configuration:
# Create .env file
cat > .env << EOF
GPSD_HOST=localhost
GPSD_PORT=2947
GEOPOINT_LON=38.897809878
GEOPOINT_LAT=-77.036551259
PPS_BUCKET_SIZE=250
PPS_BUCKET_COUNT=40
PPS_TIME1=0.123
GEO_BUCKET_SIZE=0.5
GEO_BUCKET_COUNT=40
EXPORTER_PORT=9015
VERBOSE=1
DEBUG=0
EOF
For systems where Docker is not available:
Ensure gpsd, Prometheus, and Grafana are properly running. The exporter requires:
- Python 3
- prometheus_client
- gps library (version 3.18+)
# Install dependencies
apt update
apt install python3-prometheus-client python3-gps
# Clone repository
git clone https://github.com/brendanbank/gpsd-prometheus-exporter.git
cd gpsd-prometheus-exporter
# Install service files
cp gpsd_exporter.defaults /etc/default
cp gpsd_exporter.service /etc/systemd/system
cp gpsd_exporter.py /usr/local/bin
chmod +x /usr/local/bin/gpsd_exporter.py
# Enable and start service
systemctl enable gpsd_exporter.service
systemctl start gpsd_exporter.service
Some U-Blox GPS units require forced 115200 baud. See gps_setserial.service for boot-time configuration.
usage: gpsd_exporter.py [-h] [-v] [-V] [-d] [-p PORT] [-H HOSTNAME] [-E EXPORTER_PORT] [-t TIMEOUT]
[--retry-delay RETRY_DELAY] [--max-retry-delay MAX_RETRY_DELAY] [-S]
[--offset-from-geopoint] [--geopoint-lat GEO_LAT] [--geopoint-lon GEO_LON]
[--geo-bucket-size GEO_BUCKET_SIZE] [--geo-bucket-count GEO_BUCKET_COUNT]
[--pps-histogram] [--pps-bucket-size PPS_BUCKET_SIZE]
[--pps-bucket-count PPS_BUCKET_COUNT] [--pps-time1 PPS_TIME1]
gpsd_exporter -- Exporter for gpsd output
options:
-h, --help show this help message and exit
-v, --verbose set verbosity level [default: None]
-V, --version show program's version number and exit
-d, --debug set debug level [default: 0]
-p PORT, --port PORT set gpsd TCP Port number [default: 2947]
-H HOSTNAME, --hostname HOSTNAME
set gpsd TCP Hostname/IP address [default: localhost]
-E EXPORTER_PORT, --exporter-port EXPORTER_PORT
set TCP Port for the exporter server [default: 9015]
-t TIMEOUT, --timeout TIMEOUT
set connection timeout in seconds [default: 10]
--retry-delay RETRY_DELAY
initial retry delay in seconds [default: 10]
--max-retry-delay MAX_RETRY_DELAY
maximum retry delay in seconds [default: 300]
-S, --disable-monitor-satellites
Stops monitoring all satellites individually
--offset-from-geopoint
track offset (x,y offset and distance) from a stationary location.
--geopoint-lat GEO_LAT
Latitude of a fixed stationary location.
--geopoint-lon GEO_LON
Longitude of a fixed stationary location.
--geo-bucket-size GEO_BUCKET_SIZE
Bucket side of Geo histogram [default: 0.5 meter]
--geo-bucket-count GEO_BUCKET_COUNT
Bucket count of Geo histogram [default: 40]
--pps-histogram generate histogram data from pps devices.
--pps-bucket-size PPS_BUCKET_SIZE
Bucket side of PPS histogram in nanoseconds. [default: 250 ns]
--pps-bucket-count PPS_BUCKET_COUNT
Bucket count of PPS histogram [default: 40]
--pps-time1 PPS_TIME1
Local pps clock (offset) time1 (ntp.conf) [default: 0]
Test the exporter with a simple Docker run:
curl -s localhost:9015
Expected output:
# HELP gpsd_gdop Geometric (hyperspherical) dilution of precision
# TYPE gpsd_gdop gauge
gpsd_gdop 1.36
# HELP gpsd_hdop Horizontal dilution of precision
# TYPE gpsd_hdop gauge
gpsd_hdop 0.74
# HELP gpsd_lat Latitude in degrees: +/- signifies North/South.
# TYPE gpsd_lat gauge
gpsd_lat 52.4240029
# HELP gpsd_long Longitude in degrees: +/- signifies East/West.
# TYPE gpsd_long gauge
gpsd_long 4.6157675
...
Build the Docker image locally with enhanced features:
docker compose -f docker-compose.build.yml up --build
Add to your Prometheus configuration (/etc/prometheus/prometheus.yml
):
scrape_configs:
- job_name: gpsd
static_configs:
- targets: ['localhost:9015']
scrape_interval: 15s
Import the provided Grafana dashboard JSON into Grafana for comprehensive GPS monitoring visualization.
Licensed under the BSD-3-Clause License. See LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.