Prometheus exporter for Klipper to capture operational metrics. This is a very rough first implementation and subject to potentially significant changes.
Implementation is based on the Multi-Target Exporter Pattern
to enabled a single exporter to collect metrics from multiple Klipper instances.
Metrics for the exporter itself are served from the /metrics endpoint and Klipper
metrics are serviced from the /probe endpoint with a specified target.
To start the Prometheus Klipper Exporter from the command line
$ prometheus-klipper-exporter
INFO[0000] Beginning to serve on port :9101             Then add a Klipper job to the Prometheus configuration file /etc/prometheus/prometheus.yml
scrape_configs:
  - job_name: "klipper"
    scrape_interval: 5s
    metrics_path: /probe
    static_configs:
      - targets: [ 'klipper-host:7125' ]
    params:
      modules: [
        "process_stats",
        "job_queue",
        "system_info",
        "network_stats",
        "directory_info",
        "printer_objects",
        "history",
      ]
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: klipper-exporter:9101
  # optional exporter metrics
  - job_name: "klipper-exporter"
    scrape_interval: 5s
    metrics_path: /metrics
    static_configs:
      - targets: [ 'klipper-exporter:9101' ]The exporter can be run on the host running Klipper, or on a separate machine.
Replace klipper-host with the hostname or IP address of the Klipper host,
and replace klipper-exporter with the hostname or IP address of the host
runnging prometheus-klipper-exporter.
To monitor multiple Klipper instances add multiple entries to the
static_config.targets for the klipper job. e.g.
    ...
    static_configs:
      - targets: [ 'klipper-host-1:7125', 'klipper-host-2:7125 ]
    ...$ make buildYou will typically want to install the exporter binary on a host that will be constantly running, either the Klipper host iteself, or a separate server, and ensure that the process restarts on system restart.
Example installation on Raspberry Pi, using systemd to run the exporter.
$ ssh pi@klipper-host
[klipper]$ mkdir /home/pi/klipper-exporter
[klipper]$ exit
$ scp prometheus-klipper-exporter pi@klipper-host:/home/pi/klipper-exporter
$ scp klipper-exporter.service pi@klipper-host:/home/pi/
$ ssh pi@klipper-host
[klipper]$ sudo mv klipper-exporter.service /etc/systemd/system/
[klipper]$ sudo systemctl daemon-reload
[klipper]$ sudo systemctl enable klipper-exporter.service
[klipper]$ sudo systemctl start klipper-exporter.service
[klipper]$ sudo systemctl status klipper-exporter.service
[klipper]$ exitTo run the exporter as a docker container.
$ docker run -d -p 9101:9101 ghcr.io/scross01/prometheus-klipper-exporter:latestSee the example/README.md for a complete example running Prometheus, Grafana, and the klipper-exporter in Docker using docker compose.
You can configure different sets of metrics to be collected by including the
modules parameter in the prometheus.yml configuration file.
    ...
    params:
      modules: [ "process_stats", "job_queue", "system_info" ]
    ...If the modules params are omitted then only the default metrics are collected. Each group of metrics is queried from a different Moonraker API endpoint.
| module | object | default | metrics | 
|---|---|---|---|
process_stats | 
x | klipper_moonraker_cpu_usageklipper_moonraker_memory_kbklipper_moonraker_websocket_connectionsklipper_system_cpuklipper_system_cpu_tempklipper_system_memory_availableklipper_system_memory_totalklipper_system_memory_usedklipper_system_uptime | 
|
job_queue | 
x | klipper_job_queue_length | 
|
system_info | 
x | klipper_system_cpu_count | 
|
printer_objects | 
controller_fan | 
klipper_controller_fan_rpm{fan="fan"}klipper_controller_fan_speed={fan="fan"} | 
|
printer_objects | 
display_status | 
klipper_print_gcode_progress | 
|
printer_objects | 
extruder | 
klipper_extruder_powerklipper_extruder_pressure_advanceklipper_extruder_smooth_timeklipper_extruder_targetklipper_extruder_temperature | 
|
printer_objects | 
fan | 
klipper_fan_rpmklipper_fan_speed | 
|
printer_objects | 
filament_sensor | 
klipper_filament_sensor_detected{probe="probe"}klipper_filament_sensor_enabled{probe="probe"} | 
|
printer_objects | 
gcode | 
klipper_gcode_extrude_factorklipper_gcode_position_eklipper_gcode_position_xklipper_gcode_position_yklipper_gcode_position_zklipper_gcode_speed_factorklipper_gcode_speed | 
|
printer_objects | 
generic_fan | 
klipper_generic_fan_rpm{fan="fan"}klipper_generic_fan_speed{fan="fan"} | 
|
printer_objects | 
heater_bed | 
klipper_heater_bed_powerklipper_heater_bed_targetklipper_heater_bed_temperature | 
|
printer_objects | 
heater_generic | 
klipper_generic_heater_powerklipper_generic_heater_targetklipper_generic_heater_temperature | 
|
printer_objects | 
idle_timeout | 
klipper_printing_time | 
|
printer_objects | 
mcu | 
klipper_mcu_awake{mcu="mcu"}klipper_mcu_task_avg{mcu="mcu"}klipper_mcu_task_stddev{mcu="mcu"}klipper_mcu_clock_frequency{mcu="mcu"}klipper_mcu_invalid_bytes{mcu="mcu"}klipper_mcu_read_bytes{mcu="mcu"}klipper_mcu_ready_bytes{mcu="mcu"}klipper_mcu_receive_seq{mcu="mcu"}klipper_mcu_retransmit_bytes{mcu="mcu"}klipper_mcu_retransmit_seq{mcu="mcu"}klipper_mcu_rtoklipper_mcu_rttvar{mcu="mcu"}klipper_mcu_send_seq{mcu="mcu"}klipper_mcu_stalled_bytes{mcu="mcu"}klipper_mcu_srtt{mcu="mcu"}klipper_mcu_write_bytes{mcu="mcu"} | 
|
printer_objects | 
output_pin | 
klipper_output_pin_value{pin="pin"} | 
|
printer_objects | 
print_stats | 
klipper_print_filament_usedklipper_print_total_duration | 
|
printer_objects | 
temperature_fan | 
klipper_temperature_fan_speed{fan="fan"}klipper_temperature_fan_temperature{fan="fan"}klipper_temperature_fan_target{fan="fan"} | 
|
printer_objects | 
temperature_probe | 
klipper_temperature_probe_temperature{probe="probe"}klipper_temperature_probe_measured_max_temp{probe="probe"}klipper_temperature_probe_measured_min_temp{probe="probe"}klipper_temperature_probe_estimated_expansion{probe="probe"} | 
|
printer_objects | 
temperature_sensor | 
klipper_temperature_sensor_temperature{sensor="sensor"}klipper_temperature_sensor_measured_max_temp{sensor="sensor"}klipper_temperature_sensor_measured_min_temp{sensor="sensor"}klipper_temperature_sensor_estimated_expansion{sensor="sensor"} | 
|
printer_objects | 
toolhead | 
klipper_toolhead_estimated_print_timeklipper_toolhead_max_accel_to_decelklipper_toolhead_max_accelklipper_toolhead_max_velocityklipper_toolhead_print_timeklipper_toolhead_square_corner_velocity | 
|
printer_objects | 
virtual_sdcard | 
klipper_print_file_positionklipper_print_file_progress | 
|
directory_info | 
klipper_disk_usage_availableklipper_disk_usage_totalklipper_disk_usage_used | 
||
network_stats | 
klipper_network_tx_bandwidth{interface="interface"}klipper_network_rx_bytes{interface="interface"}klipper_network_tx_bytes{interface="interface"}klipper_network_rx_drop{interface="interface"}klipper_network_tx_drop{interface="interface"}klipper_network_rx_errs{interface="interface"}klipper_network_tx_errs{interface="interface"}klipper_network_rx_packets{interface="interface"}klipper_network_tx_packets{interface="interface"} | 
||
history | 
klipper_current_print_first_layer_heightklipper_current_print_layer_heightklipper_current_print_object_heightklipper_current_print_total_durationklipper_longest_jobklipper_longest_printklipper_total_filament_usedklipper_total_jobsklipper_total_print_timeklipper_total_time | 
The simplest deployment option is to run the Klipper Exporter on a host that is in
the Moonraker trusted clients configuration.  This is typically configured by default
to include all hosts in the local network. If you have a more restrictive configuration
then add the host to the moonraker.conf [authorization]
configuration section.
# moonraker.conf
[authorization]
trusted_clients:
  klipper-exporter
  ...Untrusted clients must use an API key to access Moonraker's HTTP APIs. To fetch the current API key run the following on the Klipper host:
$ cd ~/moonraker/scripts
$ ./fetch-apikey.sh
abcdef01234567890123456789012345The API key can be set in one of three ways, from the scrape job configuraion in
prometheus.yml, using the -moonraker-apikey command line argument, or
setting the MOONRAKER_APIKEY environment variable.
Set in the MOONRAKER_APIKEY environment variable.
$ export MOONRAKER_APIKEY='abcdef01234567890123456789012345'
$ prometheus-klipper-exporterSet on the klipper exporter command line using -moonraker.apikey option.
$ prometheus-klipper-exporter -moonraker.apikey='abcdef01234567890123456789012345'Add the API key to the prometheus.yml scrape config, Add authorization
configuration with the type set to APIKEY.  The key can either to set directly
in the config or referenced from file.
  - job_name: "klipper"
    ...
    authorization:
      type: APIKEY
      credentials: 'abcdef01234567890123456789012345'
      # credentials_file: /path/to/private/apikey.txt
    ...Only one API key can be set for each job. If you have multiple klipper hosts with different API keys, create a separate job for each host.
-help
Display the command line help.
-logging.level <level>
Set the logging output verbosity to one of Trace, Debug, Info,
Warning, Error, Fatal and Panic. Default level is Info which will
log anything that is info level or above (warning, error, fatal, panic).
Logging level can also be set using the LOGGING_LEVEL environment variable. The
command line option takes precedence over the environment setting.
-moonraker.apikey <string>
Set the API Key to authenticate with the Klipper APIs. See API Key Authentication
-web.listen-address [<ip_address>]:<port>
Address on which to expose metrics and web interface. Default is :9101
which will listen on port 9101 on all interfaces, which is the equiviment
of 0.0.0.0:9101.  Include the IP address to limit to listening on a specific
interface, e.g. 192.168.1.99:7070.
v0.11.0 removes the deprecated -debug and -verbose command line options.
Use the -logging.level option or LOGGING_LEVEL environment setting instead.
v0.8.0 deprecates the tempurature module option which contains a subset of
the metrics reported by the printer_objects. If you where using the
tempurature module then switch the configuration to use printer_objects instead.
The v0.7.0 release introduces several metric changes that will break any
grafana charts that have previously been defined using the old metric names from
v0.6.x or earlier.
v0.7.0 now uses labels for network interfaces, temperature sensors,
temperature fans, and output pins, rather than defining separate metrics
for each unique entity.
These changes affect the following metrics groups
klipper_network_*klipper_temperature_sensor_*klipper_temperature_fan_*klipper_output_pin_*
For example:
klipper_network_wlan0_rx_bytesbecomesklipper_network_rx_bytes{interface="wlan0"}klipper_temperature_sensor_mtu_temperaturebecomesklipper_temperature_sensor_temperature{probe="mtu"}