Sign inSign up

barnesbiz/garmin_exporter

By barnesbiz

•Updated 28 days ago

OTel-native Prometheus exporter for Garmin Connect.

Image
Internet of things
Monitoring & observability
1

1.3K

barnesbiz/garmin_exporter repository overview

⁠Garmin Exporter

GitHub Release Build Status Go Report Card GHCR Docker Hub

OTel-native Prometheus exporter for Garmin Connect⁠.

Listens on port 10045 by default. Authenticates with Garmin Connect via username and password (with MFA support), caches the OAuth2 token to disk, and refreshes it automatically. Exposes metrics at /metrics, and can additionally push metrics, traces, and logs to an OTLP endpoint.

If this project is useful to you, a star on the repo would be appreciated.

⁠Quick start

⁠Docker
  docker run -d -p 10045:10045 \
    -v garmin_data:/data \
    -e [email protected] \
    -e GARMIN_PASSWORD=yourpassword \
    ghcr.io/barnes-c/garmin_exporter:latest \
    --token-file=/data/garmin_token.json
⁠Binary

  make build
  [email protected] GARMIN_PASSWORD=yourpassword
  ./garmin_exporter

Scrape: curl localhost:10045/metrics. Probes: /healthz, /readyz.

First login: if your account has MFA enabled, the exporter prompts for a one-time code on stdin. Run it interactively once (add stdin_open: true and tty: true in Compose); once the token is cached to --token-file, subsequent restarts are unattended. Prefer the GARMIN_USERNAME / GARMIN_PASSWORD environment variables over their flags. Flag values are visible to other users on the host via ps.

⁠Examples

Checkout the examples in examples/⁠:

⁠Configuration

Key flags (full list via --help):

FlagEnv varDefaultPurpose
--cache.ttlGARMIN_CACHE_TTL1hGarmin API refresh interval; independent of scrape interval
--activity-limitGARMIN_ACTIVITY_LIMIT30Number of recent activities to fetch per refresh
--passwordGARMIN_PASSWORD(required)Garmin Connect password
--token-fileGARMIN_TOKEN_FILEgarmin_token.jsonPath to the cached OAuth2 token file
--usernameGARMIN_USERNAME(required)Garmin Connect email address
--log.levelGARMIN_LOG_LEVELinfoLog level (debug, info, warn, error)
--web.health-pathGARMIN_WEB_HEALTH_PATH/healthzLiveness probe path
--web.listen-addressGARMIN_WEB_LISTEN_ADDRESS:10045Listen address
--web.prometheusGARMIN_WEB_PROMETHEUStrueDisable for OTLP-push-only deployments
--web.ready-pathGARMIN_WEB_READY_PATH/readyzReadiness probe path
--web.telemetry-pathGARMIN_WEB_TELEMETRY_PATH/metricsPrometheus endpoint
⁠OTel pipeline

The OTel pipeline is entirely environment-driven; see the OTel SDK env var spec⁠ for the full list. /metrics is always served unless --web.prometheus=false.

VariablePurpose
OTEL_METRICS_EXPORTERComma-separated push exporters: otlp, console, none (default none)
OTEL_TRACES_EXPORTERTraces exporter: otlp, console, none (default none)
OTEL_LOGS_EXPORTERLogs exporter: otlp, console, none (default none)
OTEL_EXPORTER_OTLP_ENDPOINTCollector endpoint, e.g. localhost:4317
OTEL_EXPORTER_OTLP_PROTOCOLgrpc or http/protobuf
OTEL_METRIC_EXPORT_INTERVALOTLP metric push interval, in ms
OTEL_TRACES_SAMPLERe.g. parentbased_traceidratio
OTEL_TRACES_SAMPLER_ARGSampler argument (e.g. 0.1)
OTEL_SERVICE_NAMEResource service.name (default garmin_exporter)
OTEL_CONFIG_FILEPath to otelconf YAML; overrides all other OTEL_* vars

The three exporter selectors default to none instead of the spec default otlp. The OTel exporters stays silent until OTLP is opted in.

⁠Metrics

All instruments are observable gauges. Naming follows garmin.<area>.<name>. Attributes are noted in parentheses.

MetricCollector
garmin.activity.count (type)activities
garmin.activity.duration_seconds_total (type)activities
garmin.activity.distance_meters_total (type)activities
garmin.activity.calories_total (type)activities
garmin.activity.last_timestamp_seconds (type)activities
garmin.activity.lifetime_countactivities
garmin.blood_pressure.systolic_mmhgblood_pressure
garmin.blood_pressure.diastolic_mmhgblood_pressure
garmin.blood_pressure.pulse_bpmblood_pressure
garmin.body.weight_gramsbody
garmin.body.bmibody
garmin.body.fat_percentbody
garmin.body.water_percentbody
garmin.body.bone_mass_gramsbody
garmin.body.muscle_mass_gramsbody
garmin.body.visceral_fatbody
garmin.body.metabolic_age_yearsbody
garmin.body_composition.weight_grams_avgbody_composition
garmin.body_composition.bmi_avgbody_composition
garmin.body_composition.fat_percent_avgbody_composition
garmin.body_composition.water_percent_avgbody_composition
garmin.body_composition.bone_mass_grams_avgbody_composition
garmin.body_composition.muscle_mass_grams_avgbody_composition
garmin.body_composition.visceral_fat_avgbody_composition
garmin.body_composition.metabolic_age_years_avgbody_composition
garmin.cycling.ftp_wattscycling
garmin.device.countdevices
garmin.device.info (device_id, name, status)devices
garmin.gear.max_meters (gear_name, gear_type)gear
garmin.gear.notified_at_meters (gear_name, gear_type)gear
garmin.gear.active (gear_name, gear_type)gear
garmin.goals.active_totalgoals
garmin.goals.earned_badges_totalgoals
garmin.golf.last_round_scoregolf
garmin.golf.last_round_to_pargolf
garmin.heartrate.resting_bpmheartrate
garmin.heartrate.min_bpmheartrate
garmin.heartrate.max_bpmheartrate
garmin.heartrate.seven_day_avg_resting_bpmheartrate
garmin.hydration.intake_mlhydration
garmin.hydration.goal_mlhydration
garmin.hydration.daily_avg_mlhydration
garmin.hydration.sweat_loss_mlhydration
garmin.hydration.activity_intake_mlhydration
garmin.intensity.weekly_goal_minutesintensity
garmin.intensity.moderate_minutes_totalintensity
garmin.intensity.vigorous_minutes_totalintensity
garmin.lactatethreshold.running_speed_mpslactatethreshold
garmin.lactatethreshold.running_heart_rate_bpmlactatethreshold
garmin.lactatethreshold.cycling_heart_rate_bpmlactatethreshold
garmin.personalrecords.value (pr_type, name)personalrecords
garmin.respiration.avg_waking_bpmrespiration
garmin.respiration.highest_bpmrespiration
garmin.respiration.lowest_bpmrespiration
garmin.runningtolerance.scorerunningtolerance
garmin.runningtolerance.levelrunningtolerance
garmin.sleep.total_secondssleep
garmin.sleep.deep_secondssleep
garmin.sleep.light_secondssleep
garmin.sleep.rem_secondssleep
garmin.sleep.awake_secondssleep
garmin.sleep.nap_secondssleep
garmin.sleep.restless_moments_totalsleep
garmin.sleep.avg_respiration_bpmsleep
garmin.sleep.highest_respiration_bpmsleep
garmin.sleep.lowest_respiration_bpmsleep
garmin.sleep.avg_stresssleep
garmin.sleep.hrv_last_night_mssleep
garmin.sleep.hrv_weekly_avg_mssleep
garmin.sleep.hrv_baseline_low_upper_mssleep
garmin.sleep.hrv_baseline_balanced_low_mssleep
garmin.sleep.hrv_baseline_balanced_upper_mssleep
garmin.spo2.avg_percentspo2
garmin.spo2.lowest_percentspo2
garmin.spo2.seven_day_avg_percentspo2
garmin.stress.avg_levelstress
garmin.stress.max_levelstress
garmin.training.readiness_scoretraining
garmin.training.readiness_sleep_scoretraining
garmin.training.readiness_recovery_minutestraining
garmin.training.readiness_hrv_weekly_avg_mstraining
garmin.training.vo2max_generictraining
garmin.training.vo2max_cyclingtraining
garmin.training.fitness_age_yearstraining
garmin.training.race_prediction_5k_secondstraining
garmin.training.race_prediction_10k_secondstraining
garmin.training.race_prediction_half_marathon_secondstraining
garmin.training.race_prediction_marathon_secondstraining
garmin.training.endurance_scoretraining
garmin.training.hill_scoretraining
garmin.trainingstatus.statustrainingstatus
garmin.trainingstatus.weekly_training_loadtrainingstatus
garmin.trainingstatus.acwr_percenttrainingstatus
garmin.trainingstatus.acwr_ratiotrainingstatus
garmin.trainingstatus.aerobic_low_monthly_loadtrainingstatus
garmin.trainingstatus.aerobic_high_monthly_loadtrainingstatus
garmin.trainingstatus.anaerobic_monthly_loadtrainingstatus
garmin.wellness.total_stepswellness
garmin.wellness.step_goalwellness
garmin.wellness.total_distance_meterswellness
garmin.wellness.total_kilocalorieswellness
garmin.wellness.active_kilocalorieswellness
garmin.wellness.bmr_kilocalorieswellness
garmin.wellness.active_secondswellness
garmin.wellness.highly_active_secondswellness
garmin.wellness.sedentary_secondswellness
garmin.wellness.sleeping_secondswellness
garmin.wellness.floors_ascendedwellness
garmin.wellness.floors_descendedwellness
garmin.wellness.floors_ascended_goalwellness
garmin.wellness.resting_heart_rate_bpmwellness
garmin.wellness.min_heart_rate_bpmwellness
garmin.wellness.max_heart_rate_bpmwellness
garmin.wellness.body_battery_latestwellness
garmin.wellness.body_battery_highestwellness
garmin.wellness.body_battery_lowestwellness
garmin.wellness.body_battery_chargedwellness
garmin.wellness.body_battery_drainedwellness
garmin.wellness.avg_waking_respiration_bpmwellness
garmin.wellness.highest_respiration_bpmwellness
garmin.wellness.lowest_respiration_bpmwellness
garmin.wellness.avg_stress_duration_secondswellness
garmin.wellness.rest_stress_duration_secondswellness
garmin.wellness.low_stress_duration_secondswellness
garmin.wellness.high_stress_duration_secondswellness
garmin.wellness.moderate_intensity_minuteswellness
garmin.wellness.vigorous_intensity_minuteswellness
garmin.collector.up (collector)—

See collector/⁠ for per-collector implementation.

⁠Development

make all       # fmt, vet, lint, build, test
make test      # go test -race ./...
make snapshot  # local goreleaser build

⁠License

Apache-2.0⁠

Tag summary

Content type

Image

Digest

sha256:0da185109…

Size

9 MB

Last updated

28 days ago

docker pull barnesbiz/garmin_exporter