Merge pull request #11 from tcivie/add-user-data-to-prometheus-metrics

Added more metrics to the prometheus exporter
This commit is contained in:
Gleb Tcivie 2024-06-30 19:21:49 +03:00 committed by GitHub
commit b84c611da9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 185 additions and 181 deletions

View file

@ -18,49 +18,49 @@ The following is a list of metrics exported by the `meshtastic-metrics-exporter`
| Metric Name | Description | Type | Labels | | Metric Name | Description | Type | Labels |
|-----------------------------------|------------------------------------------------------------------------------|-----------|--------------------------------------| |-----------------------------------|------------------------------------------------------------------------------|-----------|--------------------------------------|
| text_message_app_length | Length of text messages processed by the app | Histogram | client_id | | text_message_app_length | Length of text messages processed by the app | Histogram | node_id |
| device_latitude | Device latitude | Gauge | client_id | | device_latitude | Device latitude | Gauge | node_id |
| device_longitude | Device longitude | Gauge | client_id | | device_longitude | Device longitude | Gauge | node_id |
| device_altitude | Device altitude | Gauge | client_id | | device_altitude | Device altitude | Gauge | node_id |
| device_position_precision | Device position precision | Gauge | client_id | | device_position_precision | Device position precision | Gauge | node_id |
| telemetry_app_ch1_voltage | Voltage measured by the device on channel 1 | Gauge | client_id | | telemetry_app_ch1_voltage | Voltage measured by the device on channel 1 | Gauge | node_id |
| telemetry_app_ch1_current | Current measured by the device on channel 1 | Gauge | client_id | | telemetry_app_ch1_current | Current measured by the device on channel 1 | Gauge | node_id |
| telemetry_app_ch2_voltage | Voltage measured by the device on channel 2 | Gauge | client_id | | telemetry_app_ch2_voltage | Voltage measured by the device on channel 2 | Gauge | node_id |
| telemetry_app_ch2_current | Current measured by the device on channel 2 | Gauge | client_id | | telemetry_app_ch2_current | Current measured by the device on channel 2 | Gauge | node_id |
| telemetry_app_ch3_voltage | Voltage measured by the device on channel 3 | Gauge | client_id | | telemetry_app_ch3_voltage | Voltage measured by the device on channel 3 | Gauge | node_id |
| telemetry_app_ch3_current | Current measured by the device on channel 3 | Gauge | client_id | | telemetry_app_ch3_current | Current measured by the device on channel 3 | Gauge | node_id |
| telemetry_app_pm10_standard | Concentration Units Standard PM1.0 | Gauge | client_id | | telemetry_app_pm10_standard | Concentration Units Standard PM1.0 | Gauge | node_id |
| telemetry_app_pm25_standard | Concentration Units Standard PM2.5 | Gauge | client_id | | telemetry_app_pm25_standard | Concentration Units Standard PM2.5 | Gauge | node_id |
| telemetry_app_pm100_standard | Concentration Units Standard PM10.0 | Gauge | client_id | | telemetry_app_pm100_standard | Concentration Units Standard PM10.0 | Gauge | node_id |
| telemetry_app_pm10_environmental | Concentration Units Environmental PM1.0 | Gauge | client_id | | telemetry_app_pm10_environmental | Concentration Units Environmental PM1.0 | Gauge | node_id |
| telemetry_app_pm25_environmental | Concentration Units Environmental PM2.5 | Gauge | client_id | | telemetry_app_pm25_environmental | Concentration Units Environmental PM2.5 | Gauge | node_id |
| telemetry_app_pm100_environmental | Concentration Units Environmental PM10.0 | Gauge | client_id | | telemetry_app_pm100_environmental | Concentration Units Environmental PM10.0 | Gauge | node_id |
| telemetry_app_particles_03um | 0.3um Particle Count | Gauge | client_id | | telemetry_app_particles_03um | 0.3um Particle Count | Gauge | node_id |
| telemetry_app_particles_05um | 0.5um Particle Count | Gauge | client_id | | telemetry_app_particles_05um | 0.5um Particle Count | Gauge | node_id |
| telemetry_app_particles_10um | 1.0um Particle Count | Gauge | client_id | | telemetry_app_particles_10um | 1.0um Particle Count | Gauge | node_id |
| telemetry_app_particles_25um | 2.5um Particle Count | Gauge | client_id | | telemetry_app_particles_25um | 2.5um Particle Count | Gauge | node_id |
| telemetry_app_particles_50um | 5.0um Particle Count | Gauge | client_id | | telemetry_app_particles_50um | 5.0um Particle Count | Gauge | node_id |
| telemetry_app_particles_100um | 10.0um Particle Count | Gauge | client_id | | telemetry_app_particles_100um | 10.0um Particle Count | Gauge | node_id |
| telemetry_app_temperature | Temperature measured by the device | Gauge | client_id | | telemetry_app_temperature | Temperature measured by the device | Gauge | node_id |
| telemetry_app_relative_humidity | Relative humidity percent measured by the device | Gauge | client_id | | telemetry_app_relative_humidity | Relative humidity percent measured by the device | Gauge | node_id |
| telemetry_app_barometric_pressure | Barometric pressure in hPA measured by the device | Gauge | client_id | | telemetry_app_barometric_pressure | Barometric pressure in hPA measured by the device | Gauge | node_id |
| telemetry_app_gas_resistance | Gas resistance in MOhm measured by the device | Gauge | client_id | | telemetry_app_gas_resistance | Gas resistance in MOhm measured by the device | Gauge | node_id |
| telemetry_app_iaq | IAQ value measured by the device (0-500) | Gauge | client_id | | telemetry_app_iaq | IAQ value measured by the device (0-500) | Gauge | node_id |
| telemetry_app_distance | Distance measured by the device in mm | Gauge | client_id | | telemetry_app_distance | Distance measured by the device in mm | Gauge | node_id |
| telemetry_app_lux | Ambient light measured by the device in Lux | Gauge | client_id | | telemetry_app_lux | Ambient light measured by the device in Lux | Gauge | node_id |
| telemetry_app_white_lux | White light measured by the device in Lux | Gauge | client_id | | telemetry_app_white_lux | White light measured by the device in Lux | Gauge | node_id |
| telemetry_app_ir_lux | Infrared light measured by the device in Lux | Gauge | client_id | | telemetry_app_ir_lux | Infrared light measured by the device in Lux | Gauge | node_id |
| telemetry_app_uv_lux | Ultraviolet light measured by the device in Lux | Gauge | client_id | | telemetry_app_uv_lux | Ultraviolet light measured by the device in Lux | Gauge | node_id |
| telemetry_app_wind_direction | Wind direction in degrees measured by the device | Gauge | client_id | | telemetry_app_wind_direction | Wind direction in degrees measured by the device | Gauge | node_id |
| telemetry_app_wind_speed | Wind speed in m/s measured by the device | Gauge | client_id | | telemetry_app_wind_speed | Wind speed in m/s measured by the device | Gauge | node_id |
| telemetry_app_weight | Weight in KG measured by the device | Gauge | client_id | | telemetry_app_weight | Weight in KG measured by the device | Gauge | node_id |
| telemetry_app_battery_level | Battery level of the device (0-100, >100 means powered) | Gauge | client_id | | telemetry_app_battery_level | Battery level of the device (0-100, >100 means powered) | Gauge | node_id |
| telemetry_app_voltage | Voltage measured by the device | Gauge | client_id | | telemetry_app_voltage | Voltage measured by the device | Gauge | node_id |
| telemetry_app_channel_utilization | Utilization for the current channel, including well-formed TX, RX, and noise | Gauge | client_id | | telemetry_app_channel_utilization | Utilization for the current channel, including well-formed TX, RX, and noise | Gauge | node_id |
| telemetry_app_air_util_tx | Percent of airtime for transmission used within the last hour | Gauge | client_id | | telemetry_app_air_util_tx | Percent of airtime for transmission used within the last hour | Gauge | node_id |
| telemetry_app_uptime_seconds | How long the device has been running since the last reboot (in seconds) | Counter | client_id | | telemetry_app_uptime_seconds | How long the device has been running since the last reboot (in seconds) | Counter | node_id |
| route_length | Number of nodes in the route | Counter | client_id | | route_length | Number of nodes in the route | Counter | node_id |
| route_response | Number of responses to route discovery | Counter | client_id, response_type | | route_response | Number of responses to route discovery | Counter | node_id, response_type |
| mesh_packet_source_types | Types of mesh packets processed by source | Counter | source_id, portnum | | mesh_packet_source_types | Types of mesh packets processed by source | Counter | source_id, portnum |
| mesh_packet_destination_types | Types of mesh packets processed by destination | Counter | destination_id, portnum | | mesh_packet_destination_types | Types of mesh packets processed by destination | Counter | destination_id, portnum |
| mesh_packet_total | Total number of mesh packets processed | Counter | source_id, destination_id | | mesh_packet_total | Total number of mesh packets processed | Counter | source_id, destination_id |
@ -81,11 +81,8 @@ The project uses a `.env` file for configuration. Here is an example of the conf
```dotenv ```dotenv
# Description: Environment variables for the application # Description: Environment variables for the application
# Redis connection details # Postgres connection details
REDIS_HOST=redis DATABASE_URL=postgres://postgres:postgres@postgres:5432/meshtastic
REDIS_PORT=6379
REDIS_DB=0
REDIS_PASSWORD=
# Prometheus connection details # Prometheus connection details
PROMETHEUS_COLLECTOR_PORT=9464 PROMETHEUS_COLLECTOR_PORT=9464
@ -121,12 +118,13 @@ To run the project, simply use Docker Compose:
docker-compose up --build docker-compose up --build
``` ```
This command will build and start all the necessary services, including the MQTT server, Prometheus server, Redis This command will build and start all the necessary services, including the MQTT server, Prometheus server, Postgres
server, and Grafana. server, and Grafana.
## Grafana Dashboard ## Grafana Dashboard
The project includes a Grafana dashboard pre-configured to connect to both the Prometheus and Redis data sources. This The project includes a Grafana dashboard pre-configured to connect to both the Prometheus and Postgres data sources.
This
allows you to start creating and customizing your dashboards right away. allows you to start creating and customizing your dashboards right away.
## Contributing ## Contributing

View file

@ -31,88 +31,93 @@ class MessageProcessor:
self.processor_registry = ProcessorRegistry() self.processor_registry = ProcessorRegistry()
def init_metrics(self): def init_metrics(self):
# Source-related counters common_labels = [
'source_id', 'source_short_name', 'source_long_name', 'source_hardware_model', 'source_role',
'destination_id', 'destination_short_name', 'destination_long_name', 'destination_hardware_model',
'destination_role'
]
self.source_message_type_counter = Counter( self.source_message_type_counter = Counter(
'mesh_packet_source_types', 'mesh_packet_source_types',
'Types of mesh packets processed by source', 'Types of mesh packets processed by source',
['source_id', 'portnum'], common_labels + ['portnum'],
registry=self.registry registry=self.registry
) )
# Destination-related counters # Destination-related counters
self.destination_message_type_counter = Counter( self.destination_message_type_counter = Counter(
'mesh_packet_destination_types', 'mesh_packet_destination_types',
'Types of mesh packets processed by destination', 'Types of mesh packets processed by destination',
['destination_id', 'portnum'], common_labels + ['portnum'],
registry=self.registry registry=self.registry
) )
# Counters for the total number of packets # Counters for the total number of packets
self.total_packets_counter = Counter( self.total_packets_counter = Counter(
'mesh_packet_total', 'mesh_packet_total',
'Total number of mesh packets processed', 'Total number of mesh packets processed',
['source_id', 'destination_id'], common_labels,
registry=self.registry registry=self.registry
) )
# Histogram for the rx_time (time in seconds) # Histogram for the rx_time (time in seconds)
self.rx_time_histogram = Histogram( self.rx_time_histogram = Histogram(
'mesh_packet_rx_time', 'mesh_packet_rx_time',
'Receive time of mesh packets (seconds since 1970)', 'Receive time of mesh packets (seconds since 1970)',
['source_id', 'destination_id'], common_labels,
registry=self.registry registry=self.registry
) )
# Gauge for the rx_snr (signal-to-noise ratio) # Gauge for the rx_snr (signal-to-noise ratio)
self.rx_snr_gauge = Gauge( self.rx_snr_gauge = Gauge(
'mesh_packet_rx_snr', 'mesh_packet_rx_snr',
'Receive SNR of mesh packets', 'Receive SNR of mesh packets',
['source_id', 'destination_id'], common_labels,
registry=self.registry registry=self.registry
) )
# Counter for hop_limit # Counter for hop_limit
self.hop_limit_counter = Counter( self.hop_limit_counter = Counter(
'mesh_packet_hop_limit', 'mesh_packet_hop_limit',
'Hop limit of mesh packets', 'Hop limit of mesh packets',
['source_id', 'destination_id'], common_labels,
registry=self.registry registry=self.registry
) )
# Counter for want_ack (occurrences of want_ack set to true) # Counter for want_ack (occurrences of want_ack set to true)
self.want_ack_counter = Counter( self.want_ack_counter = Counter(
'mesh_packet_want_ack', 'mesh_packet_want_ack',
'Occurrences of want ACK for mesh packets', 'Occurrences of want ACK for mesh packets',
['source_id', 'destination_id'], common_labels,
registry=self.registry registry=self.registry
) )
# Counter for via_mqtt (occurrences of via_mqtt set to true) # Counter for via_mqtt (occurrences of via_mqtt set to true)
self.via_mqtt_counter = Counter( self.via_mqtt_counter = Counter(
'mesh_packet_via_mqtt', 'mesh_packet_via_mqtt',
'Occurrences of mesh packets sent via MQTT', 'Occurrences of mesh packets sent via MQTT',
['source_id', 'destination_id'], common_labels,
registry=self.registry registry=self.registry
) )
# Gauge for hop_start # Gauge for hop_start
self.hop_start_gauge = Gauge( self.hop_start_gauge = Gauge(
'mesh_packet_hop_start', 'mesh_packet_hop_start',
'Hop start of mesh packets', 'Hop start of mesh packets',
['source_id', 'destination_id'], common_labels,
registry=self.registry registry=self.registry
) )
# Counter for unique packet IDs # Counter for unique packet IDs
self.packet_id_counter = Counter( self.packet_id_counter = Counter(
'mesh_packet_ids', 'mesh_packet_ids',
'Unique IDs for mesh packets', 'Unique IDs for mesh packets',
['source_id', 'destination_id', 'packet_id'], common_labels + ['packet_id'],
registry=self.registry registry=self.registry
) )
# Counter for the channel used # Counter for the channel used
self.channel_counter = Counter( self.channel_counter = Counter(
'mesh_packet_channel', 'mesh_packet_channel',
'Channel used for mesh packets', 'Channel used for mesh packets',
['source_id', 'destination_id', 'channel'], common_labels + ['channel'],
registry=self.registry registry=self.registry
) )
# Gauge for the rx_rssi (received signal strength indicator) # Gauge for the rx_rssi (received signal strength indicator)
self.rx_rssi_gauge = Gauge( self.rx_rssi_gauge = Gauge(
'mesh_packet_rx_rssi', 'mesh_packet_rx_rssi',
'Receive RSSI of mesh packets', 'Receive RSSI of mesh packets',
['source_id', 'destination_id'], common_labels,
registry=self.registry registry=self.registry
) )
@ -163,78 +168,73 @@ class MessageProcessor:
return 'UNKNOWN_PORT' return 'UNKNOWN_PORT'
def process_simple_packet_details(self, destination_client_details, mesh_packet, port_num, source_client_details): def process_simple_packet_details(self, destination_client_details, mesh_packet, port_num, source_client_details):
common_labels = {
'source_id': source_client_details.node_id,
'source_short_name': source_client_details.short_name,
'source_long_name': source_client_details.long_name,
'source_hardware_model': source_client_details.hardware_model,
'source_role': source_client_details.role,
'destination_id': destination_client_details.node_id,
'destination_short_name': destination_client_details.short_name,
'destination_long_name': destination_client_details.long_name,
'destination_hardware_model': destination_client_details.hardware_model,
'destination_role': destination_client_details.role,
}
self.source_message_type_counter.labels( self.source_message_type_counter.labels(
source_id=source_client_details.node_id, **common_labels,
portnum=self.get_port_name_from_portnum(port_num) portnum=self.get_port_name_from_portnum(port_num)
).inc() ).inc()
self.destination_message_type_counter.labels( self.destination_message_type_counter.labels(
destination_id=destination_client_details.node_id, **common_labels,
portnum=self.get_port_name_from_portnum(port_num) portnum=self.get_port_name_from_portnum(port_num)
).inc() ).inc()
# Increment the total packets counter
self.total_packets_counter.labels( self.total_packets_counter.labels(
source_id=source_client_details.node_id, **common_labels
destination_id=destination_client_details.node_id
).inc() ).inc()
# Observe the rx_time in the histogram
self.rx_time_histogram.labels( self.rx_time_histogram.labels(
source_id=source_client_details.node_id, **common_labels
destination_id=destination_client_details.node_id
).observe(mesh_packet.rx_time) ).observe(mesh_packet.rx_time)
# Set the rx_snr in the gauge
self.rx_snr_gauge.labels( self.rx_snr_gauge.labels(
source_id=source_client_details.node_id, **common_labels
destination_id=destination_client_details.node_id
).set(mesh_packet.rx_snr) ).set(mesh_packet.rx_snr)
# Increment the hop_limit counter
self.hop_limit_counter.labels( self.hop_limit_counter.labels(
source_id=source_client_details.node_id, **common_labels
destination_id=destination_client_details.node_id
).inc(mesh_packet.hop_limit) ).inc(mesh_packet.hop_limit)
# Increment the want_ack counter if want_ack is true
if mesh_packet.want_ack: if mesh_packet.want_ack:
self.want_ack_counter.labels( self.want_ack_counter.labels(
source_id=source_client_details.node_id, **common_labels
destination_id=destination_client_details.node_id
).inc() ).inc()
# Increment the via_mqtt counter if via_mqtt is true
if mesh_packet.via_mqtt: if mesh_packet.via_mqtt:
self.via_mqtt_counter.labels( self.via_mqtt_counter.labels(
source_id=source_client_details.node_id, **common_labels
destination_id=destination_client_details.node_id
).inc() ).inc()
# Set the hop_start in the gauge
self.hop_start_gauge.labels( self.hop_start_gauge.labels(
source_id=source_client_details.node_id, **common_labels
destination_id=destination_client_details.node_id
).set(mesh_packet.hop_start) ).set(mesh_packet.hop_start)
# Increment the unique packet ID counter
self.packet_id_counter.labels( self.packet_id_counter.labels(
source_id=source_client_details.node_id, **common_labels,
destination_id=destination_client_details.node_id,
packet_id=mesh_packet.id packet_id=mesh_packet.id
).inc() ).inc()
# Increment the channel counter # Increment the channel counter
self.channel_counter.labels( self.channel_counter.labels(
source_id=source_client_details.node_id, **common_labels,
destination_id=destination_client_details.node_id,
channel=mesh_packet.channel channel=mesh_packet.channel
).inc() ).inc()
# Set the rx_rssi in the gauge # Set the rx_rssi in the gauge
self.rx_rssi_gauge.labels( self.rx_rssi_gauge.labels(
source_id=source_client_details.node_id, **common_labels
destination_id=destination_client_details.node_id
).set(mesh_packet.rx_rssi) ).set(mesh_packet.rx_rssi)
def _get_client_details(self, node_id: int) -> ClientDetails: def _get_client_details(self, node_id: int) -> ClientDetails:

View file

@ -31,6 +31,12 @@ class _Metrics:
self._init_metrics() self._init_metrics()
self.initialized = True # Attribute to indicate initialization self.initialized = True # Attribute to indicate initialization
@staticmethod
def _get_common_labels():
return [
'node_id', 'short_name', 'long_name', 'hardware_model', 'role'
]
def _init_metrics(self): # TODO: Go over the metrics and rethink some of them to be more like the longtitute and def _init_metrics(self): # TODO: Go over the metrics and rethink some of them to be more like the longtitute and
# latitude - The values should represent something and we shouldn't just label stuff. Also, the labels should # latitude - The values should represent something and we shouldn't just label stuff. Also, the labels should
# be less used looked upon like keys for the data # be less used looked upon like keys for the data
@ -47,7 +53,7 @@ class _Metrics:
self.message_length_histogram = Histogram( self.message_length_histogram = Histogram(
'text_message_app_length', 'text_message_app_length',
'Length of text messages processed by the app', 'Length of text messages processed by the app',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
@ -55,25 +61,25 @@ class _Metrics:
self.device_latitude_gauge = Gauge( self.device_latitude_gauge = Gauge(
'device_latitude', 'device_latitude',
'Device latitude', 'Device latitude',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.device_longitude_gauge = Gauge( self.device_longitude_gauge = Gauge(
'device_longitude', 'device_longitude',
'Device longitude', 'Device longitude',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.device_altitude_gauge = Gauge( self.device_altitude_gauge = Gauge(
'device_altitude', 'device_altitude',
'Device altitude', 'Device altitude',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.device_position_precision_gauge = Gauge( self.device_position_precision_gauge = Gauge(
'device_position_precision', 'device_position_precision',
'Device position precision', 'Device position precision',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
@ -81,42 +87,42 @@ class _Metrics:
self.ch1_voltage_gauge = Gauge( self.ch1_voltage_gauge = Gauge(
'telemetry_app_ch1_voltage', 'telemetry_app_ch1_voltage',
'Voltage measured by the device on channel 1', 'Voltage measured by the device on channel 1',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.ch1_current_gauge = Gauge( self.ch1_current_gauge = Gauge(
'telemetry_app_ch1_current', 'telemetry_app_ch1_current',
'Current measured by the device on channel 1', 'Current measured by the device on channel 1',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.ch2_voltage_gauge = Gauge( self.ch2_voltage_gauge = Gauge(
'telemetry_app_ch2_voltage', 'telemetry_app_ch2_voltage',
'Voltage measured by the device on channel 2', 'Voltage measured by the device on channel 2',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.ch2_current_gauge = Gauge( self.ch2_current_gauge = Gauge(
'telemetry_app_ch2_current', 'telemetry_app_ch2_current',
'Current measured by the device on channel 2', 'Current measured by the device on channel 2',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.ch3_voltage_gauge = Gauge( self.ch3_voltage_gauge = Gauge(
'telemetry_app_ch3_voltage', 'telemetry_app_ch3_voltage',
'Voltage measured by the device on channel 3', 'Voltage measured by the device on channel 3',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.ch3_current_gauge = Gauge( self.ch3_current_gauge = Gauge(
'telemetry_app_ch3_current', 'telemetry_app_ch3_current',
'Current measured by the device on channel 3', 'Current measured by the device on channel 3',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
@ -124,84 +130,84 @@ class _Metrics:
self.pm10_standard_gauge = Gauge( self.pm10_standard_gauge = Gauge(
'telemetry_app_pm10_standard', 'telemetry_app_pm10_standard',
'Concentration Units Standard PM1.0', 'Concentration Units Standard PM1.0',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.pm25_standard_gauge = Gauge( self.pm25_standard_gauge = Gauge(
'telemetry_app_pm25_standard', 'telemetry_app_pm25_standard',
'Concentration Units Standard PM2.5', 'Concentration Units Standard PM2.5',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.pm100_standard_gauge = Gauge( self.pm100_standard_gauge = Gauge(
'telemetry_app_pm100_standard', 'telemetry_app_pm100_standard',
'Concentration Units Standard PM10.0', 'Concentration Units Standard PM10.0',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.pm10_environmental_gauge = Gauge( self.pm10_environmental_gauge = Gauge(
'telemetry_app_pm10_environmental', 'telemetry_app_pm10_environmental',
'Concentration Units Environmental PM1.0', 'Concentration Units Environmental PM1.0',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.pm25_environmental_gauge = Gauge( self.pm25_environmental_gauge = Gauge(
'telemetry_app_pm25_environmental', 'telemetry_app_pm25_environmental',
'Concentration Units Environmental PM2.5', 'Concentration Units Environmental PM2.5',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.pm100_environmental_gauge = Gauge( self.pm100_environmental_gauge = Gauge(
'telemetry_app_pm100_environmental', 'telemetry_app_pm100_environmental',
'Concentration Units Environmental PM10.0', 'Concentration Units Environmental PM10.0',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.particles_03um_gauge = Gauge( self.particles_03um_gauge = Gauge(
'telemetry_app_particles_03um', 'telemetry_app_particles_03um',
'0.3um Particle Count', '0.3um Particle Count',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.particles_05um_gauge = Gauge( self.particles_05um_gauge = Gauge(
'telemetry_app_particles_05um', 'telemetry_app_particles_05um',
'0.5um Particle Count', '0.5um Particle Count',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.particles_10um_gauge = Gauge( self.particles_10um_gauge = Gauge(
'telemetry_app_particles_10um', 'telemetry_app_particles_10um',
'1.0um Particle Count', '1.0um Particle Count',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.particles_25um_gauge = Gauge( self.particles_25um_gauge = Gauge(
'telemetry_app_particles_25um', 'telemetry_app_particles_25um',
'2.5um Particle Count', '2.5um Particle Count',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.particles_50um_gauge = Gauge( self.particles_50um_gauge = Gauge(
'telemetry_app_particles_50um', 'telemetry_app_particles_50um',
'5.0um Particle Count', '5.0um Particle Count',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.particles_100um_gauge = Gauge( self.particles_100um_gauge = Gauge(
'telemetry_app_particles_100um', 'telemetry_app_particles_100um',
'10.0um Particle Count', '10.0um Particle Count',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
@ -210,91 +216,91 @@ class _Metrics:
self.temperature_gauge = Gauge( self.temperature_gauge = Gauge(
'telemetry_app_temperature', 'telemetry_app_temperature',
'Temperature measured by the device', 'Temperature measured by the device',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.relative_humidity_gauge = Gauge( self.relative_humidity_gauge = Gauge(
'telemetry_app_relative_humidity', 'telemetry_app_relative_humidity',
'Relative humidity percent measured by the device', 'Relative humidity percent measured by the device',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.barometric_pressure_gauge = Gauge( self.barometric_pressure_gauge = Gauge(
'telemetry_app_barometric_pressure', 'telemetry_app_barometric_pressure',
'Barometric pressure in hPA measured by the device', 'Barometric pressure in hPA measured by the device',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.gas_resistance_gauge = Gauge( self.gas_resistance_gauge = Gauge(
'telemetry_app_gas_resistance', 'telemetry_app_gas_resistance',
'Gas resistance in MOhm measured by the device', 'Gas resistance in MOhm measured by the device',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.iaq_gauge = Gauge( self.iaq_gauge = Gauge(
'telemetry_app_iaq', 'telemetry_app_iaq',
'IAQ value measured by the device (0-500)', 'IAQ value measured by the device (0-500)',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.distance_gauge = Gauge( self.distance_gauge = Gauge(
'telemetry_app_distance', 'telemetry_app_distance',
'Distance measured by the device in mm', 'Distance measured by the device in mm',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.lux_gauge = Gauge( self.lux_gauge = Gauge(
'telemetry_app_lux', 'telemetry_app_lux',
'Ambient light measured by the device in Lux', 'Ambient light measured by the device in Lux',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.white_lux_gauge = Gauge( self.white_lux_gauge = Gauge(
'telemetry_app_white_lux', 'telemetry_app_white_lux',
'White light measured by the device in Lux', 'White light measured by the device in Lux',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.ir_lux_gauge = Gauge( self.ir_lux_gauge = Gauge(
'telemetry_app_ir_lux', 'telemetry_app_ir_lux',
'Infrared light measured by the device in Lux', 'Infrared light measured by the device in Lux',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.uv_lux_gauge = Gauge( self.uv_lux_gauge = Gauge(
'telemetry_app_uv_lux', 'telemetry_app_uv_lux',
'Ultraviolet light measured by the device in Lux', 'Ultraviolet light measured by the device in Lux',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.wind_direction_gauge = Gauge( self.wind_direction_gauge = Gauge(
'telemetry_app_wind_direction', 'telemetry_app_wind_direction',
'Wind direction in degrees measured by the device', 'Wind direction in degrees measured by the device',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.wind_speed_gauge = Gauge( self.wind_speed_gauge = Gauge(
'telemetry_app_wind_speed', 'telemetry_app_wind_speed',
'Wind speed in m/s measured by the device', 'Wind speed in m/s measured by the device',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.weight_gauge = Gauge( self.weight_gauge = Gauge(
'telemetry_app_weight', 'telemetry_app_weight',
'Weight in KG measured by the device', 'Weight in KG measured by the device',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
@ -302,14 +308,14 @@ class _Metrics:
self.battery_level_gauge = Gauge( self.battery_level_gauge = Gauge(
'telemetry_app_battery_level', 'telemetry_app_battery_level',
'Battery level of the device (0-100, >100 means powered)', 'Battery level of the device (0-100, >100 means powered)',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.voltage_gauge = Gauge( self.voltage_gauge = Gauge(
'telemetry_app_voltage', 'telemetry_app_voltage',
'Voltage measured by the device', 'Voltage measured by the device',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
@ -317,14 +323,14 @@ class _Metrics:
self.channel_utilization_gauge = Gauge( self.channel_utilization_gauge = Gauge(
'telemetry_app_channel_utilization', 'telemetry_app_channel_utilization',
'Utilization for the current channel, including well-formed TX, RX, and noise', 'Utilization for the current channel, including well-formed TX, RX, and noise',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.air_util_tx_gauge = Gauge( self.air_util_tx_gauge = Gauge(
'telemetry_app_air_util_tx', 'telemetry_app_air_util_tx',
'Percent of airtime for transmission used within the last hour', 'Percent of airtime for transmission used within the last hour',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
@ -332,7 +338,7 @@ class _Metrics:
self.uptime_seconds_counter = Counter( self.uptime_seconds_counter = Counter(
'telemetry_app_uptime_seconds', 'telemetry_app_uptime_seconds',
'How long the device has been running since the last reboot (in seconds)', 'How long the device has been running since the last reboot (in seconds)',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
@ -340,13 +346,13 @@ class _Metrics:
self.route_discovery_counter = Counter( self.route_discovery_counter = Counter(
'route_length', 'route_length',
'Number of nodes in the route', 'Number of nodes in the route',
['client_id'], self._get_common_labels(),
registry=self._registry registry=self._registry
) )
self.route_discovery_response_counter = Counter( self.route_discovery_response_counter = Counter(
'route_response', 'route_response',
'Number of responses to route discovery', 'Number of responses to route discovery',
['client_id', 'response_type'], self._get_common_labels() + ['response_type'],
registry=self._registry registry=self._registry
) )
@ -432,7 +438,7 @@ class TextMessageAppProcessor(Processor):
if os.getenv('HIDE_MESSAGE', 'true') == 'true': if os.getenv('HIDE_MESSAGE', 'true') == 'true':
message = 'Hidden' message = 'Hidden'
self.metrics.message_length_histogram.labels( self.metrics.message_length_histogram.labels(
client_id=client_details.node_id **client_details.to_dict()
).observe(len(message)) ).observe(len(message))
@ -452,16 +458,16 @@ class PositionAppProcessor(Processor):
position = Position() position = Position()
position.ParseFromString(payload) position.ParseFromString(payload)
self.metrics.device_latitude_gauge.labels( self.metrics.device_latitude_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(position.latitude_i) ).set(position.latitude_i)
self.metrics.device_longitude_gauge.labels( self.metrics.device_longitude_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(position.longitude_i) ).set(position.longitude_i)
self.metrics.device_altitude_gauge.labels( self.metrics.device_altitude_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(position.altitude) ).set(position.altitude)
self.metrics.device_position_precision_gauge.labels( self.metrics.device_position_precision_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(position.precision_bits) ).set(position.precision_bits)
pass pass
@ -519,7 +525,6 @@ class NodeInfoAppProcessor(Processor):
self.execute_db_operation(db_operation) self.execute_db_operation(db_operation)
@ProcessorRegistry.register_processor(PortNum.ROUTING_APP) @ProcessorRegistry.register_processor(PortNum.ROUTING_APP)
class RoutingAppProcessor(Processor): class RoutingAppProcessor(Processor):
def process(self, payload: bytes, client_details: ClientDetails): def process(self, payload: bytes, client_details: ClientDetails):
@ -527,11 +532,12 @@ class RoutingAppProcessor(Processor):
routing = Routing() routing = Routing()
routing.ParseFromString(payload) routing.ParseFromString(payload)
self.metrics.route_discovery_response_counter.labels( self.metrics.route_discovery_response_counter.labels(
client_id=client_details.node_id, **client_details.to_dict(),
response_type=self.get_error_name_from_routing(routing.error_reason) response_type=self.get_error_name_from_routing(routing.error_reason)
).inc() ).inc()
def get_error_name_from_routing(self, error_code): @staticmethod
def get_error_name_from_routing(error_code):
for name, value in Routing.Error.__dict__.items(): for name, value in Routing.Error.__dict__.items():
if isinstance(value, int) and value == error_code: if isinstance(value, int) and value == error_code:
return name return name
@ -637,153 +643,153 @@ class TelemetryAppProcessor(Processor):
if telemetry.HasField('device_metrics'): if telemetry.HasField('device_metrics'):
device_metrics: DeviceMetrics = telemetry.device_metrics device_metrics: DeviceMetrics = telemetry.device_metrics
self.metrics.battery_level_gauge.labels( self.metrics.battery_level_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(device_metrics, 'battery_level', 0)) ).set(getattr(device_metrics, 'battery_level', 0))
self.metrics.voltage_gauge.labels( self.metrics.voltage_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(device_metrics, 'voltage', 0)) ).set(getattr(device_metrics, 'voltage', 0))
self.metrics.channel_utilization_gauge.labels( self.metrics.channel_utilization_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(device_metrics, 'channel_utilization', 0)) ).set(getattr(device_metrics, 'channel_utilization', 0))
self.metrics.air_util_tx_gauge.labels( self.metrics.air_util_tx_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(device_metrics, 'air_util_tx', 0)) ).set(getattr(device_metrics, 'air_util_tx', 0))
self.metrics.uptime_seconds_counter.labels( self.metrics.uptime_seconds_counter.labels(
client_id=client_details.node_id, **client_details.to_dict()
).inc(getattr(device_metrics, 'uptime_seconds', 0)) ).inc(getattr(device_metrics, 'uptime_seconds', 0))
if telemetry.HasField('environment_metrics'): if telemetry.HasField('environment_metrics'):
environment_metrics: EnvironmentMetrics = telemetry.environment_metrics environment_metrics: EnvironmentMetrics = telemetry.environment_metrics
self.metrics.temperature_gauge.labels( self.metrics.temperature_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(environment_metrics, 'temperature', 0)) ).set(getattr(environment_metrics, 'temperature', 0))
self.metrics.relative_humidity_gauge.labels( self.metrics.relative_humidity_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(environment_metrics, 'relative_humidity', 0)) ).set(getattr(environment_metrics, 'relative_humidity', 0))
self.metrics.barometric_pressure_gauge.labels( self.metrics.barometric_pressure_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(environment_metrics, 'barometric_pressure', 0)) ).set(getattr(environment_metrics, 'barometric_pressure', 0))
self.metrics.gas_resistance_gauge.labels( self.metrics.gas_resistance_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(environment_metrics, 'gas_resistance', 0)) ).set(getattr(environment_metrics, 'gas_resistance', 0))
self.metrics.iaq_gauge.labels( self.metrics.iaq_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(environment_metrics, 'iaq', 0)) ).set(getattr(environment_metrics, 'iaq', 0))
self.metrics.distance_gauge.labels( self.metrics.distance_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(environment_metrics, 'distance', 0)) ).set(getattr(environment_metrics, 'distance', 0))
self.metrics.lux_gauge.labels( self.metrics.lux_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(environment_metrics, 'lux', 0)) ).set(getattr(environment_metrics, 'lux', 0))
self.metrics.white_lux_gauge.labels( self.metrics.white_lux_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(environment_metrics, 'white_lux', 0)) ).set(getattr(environment_metrics, 'white_lux', 0))
self.metrics.ir_lux_gauge.labels( self.metrics.ir_lux_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(environment_metrics, 'ir_lux', 0)) ).set(getattr(environment_metrics, 'ir_lux', 0))
self.metrics.uv_lux_gauge.labels( self.metrics.uv_lux_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(environment_metrics, 'uv_lux', 0)) ).set(getattr(environment_metrics, 'uv_lux', 0))
self.metrics.wind_direction_gauge.labels( self.metrics.wind_direction_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(environment_metrics, 'wind_direction', 0)) ).set(getattr(environment_metrics, 'wind_direction', 0))
self.metrics.wind_speed_gauge.labels( self.metrics.wind_speed_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(environment_metrics, 'wind_speed', 0)) ).set(getattr(environment_metrics, 'wind_speed', 0))
self.metrics.weight_gauge.labels( self.metrics.weight_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(environment_metrics, 'weight', 0)) ).set(getattr(environment_metrics, 'weight', 0))
if telemetry.HasField('air_quality_metrics'): if telemetry.HasField('air_quality_metrics'):
air_quality_metrics: AirQualityMetrics = telemetry.air_quality_metrics air_quality_metrics: AirQualityMetrics = telemetry.air_quality_metrics
self.metrics.pm10_standard_gauge.labels( self.metrics.pm10_standard_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(air_quality_metrics, 'pm10_standard', 0)) ).set(getattr(air_quality_metrics, 'pm10_standard', 0))
self.metrics.pm25_standard_gauge.labels( self.metrics.pm25_standard_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(air_quality_metrics, 'pm25_standard', 0)) ).set(getattr(air_quality_metrics, 'pm25_standard', 0))
self.metrics.pm100_standard_gauge.labels( self.metrics.pm100_standard_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(air_quality_metrics, 'pm100_standard', 0)) ).set(getattr(air_quality_metrics, 'pm100_standard', 0))
self.metrics.pm10_environmental_gauge.labels( self.metrics.pm10_environmental_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(air_quality_metrics, 'pm10_environmental', 0)) ).set(getattr(air_quality_metrics, 'pm10_environmental', 0))
self.metrics.pm25_environmental_gauge.labels( self.metrics.pm25_environmental_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(air_quality_metrics, 'pm25_environmental', 0)) ).set(getattr(air_quality_metrics, 'pm25_environmental', 0))
self.metrics.pm100_environmental_gauge.labels( self.metrics.pm100_environmental_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(air_quality_metrics, 'pm100_environmental', 0)) ).set(getattr(air_quality_metrics, 'pm100_environmental', 0))
self.metrics.particles_03um_gauge.labels( self.metrics.particles_03um_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(air_quality_metrics, 'particles_03um', 0)) ).set(getattr(air_quality_metrics, 'particles_03um', 0))
self.metrics.particles_05um_gauge.labels( self.metrics.particles_05um_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(air_quality_metrics, 'particles_05um', 0)) ).set(getattr(air_quality_metrics, 'particles_05um', 0))
self.metrics.particles_10um_gauge.labels( self.metrics.particles_10um_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(air_quality_metrics, 'particles_10um', 0)) ).set(getattr(air_quality_metrics, 'particles_10um', 0))
self.metrics.particles_25um_gauge.labels( self.metrics.particles_25um_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(air_quality_metrics, 'particles_25um', 0)) ).set(getattr(air_quality_metrics, 'particles_25um', 0))
self.metrics.particles_50um_gauge.labels( self.metrics.particles_50um_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(air_quality_metrics, 'particles_50um', 0)) ).set(getattr(air_quality_metrics, 'particles_50um', 0))
self.metrics.particles_100um_gauge.labels( self.metrics.particles_100um_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(air_quality_metrics, 'particles_100um', 0)) ).set(getattr(air_quality_metrics, 'particles_100um', 0))
if telemetry.HasField('power_metrics'): if telemetry.HasField('power_metrics'):
power_metrics: PowerMetrics = telemetry.power_metrics power_metrics: PowerMetrics = telemetry.power_metrics
self.metrics.ch1_voltage_gauge.labels( self.metrics.ch1_voltage_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(power_metrics, 'ch1_voltage', 0)) ).set(getattr(power_metrics, 'ch1_voltage', 0))
self.metrics.ch1_current_gauge.labels( self.metrics.ch1_current_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(power_metrics, 'ch1_current', 0)) ).set(getattr(power_metrics, 'ch1_current', 0))
self.metrics.ch2_voltage_gauge.labels( self.metrics.ch2_voltage_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(power_metrics, 'ch2_voltage', 0)) ).set(getattr(power_metrics, 'ch2_voltage', 0))
self.metrics.ch2_current_gauge.labels( self.metrics.ch2_current_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(power_metrics, 'ch2_current', 0)) ).set(getattr(power_metrics, 'ch2_current', 0))
self.metrics.ch3_voltage_gauge.labels( self.metrics.ch3_voltage_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(power_metrics, 'ch3_voltage', 0)) ).set(getattr(power_metrics, 'ch3_voltage', 0))
self.metrics.ch3_current_gauge.labels( self.metrics.ch3_current_gauge.labels(
client_id=client_details.node_id, **client_details.to_dict()
).set(getattr(power_metrics, 'ch3_current', 0)) ).set(getattr(power_metrics, 'ch3_current', 0))
@ -810,7 +816,7 @@ class TraceRouteAppProcessor(Processor):
if traceroute.route: if traceroute.route:
route = traceroute.route route = traceroute.route
self.metrics.route_discovery_counter.labels( self.metrics.route_discovery_counter.labels(
client_id=client_details.node_id **client_details.to_dict()
).inc(len(route)) ).inc(len(route))