Skip to content

Commit

Permalink
feat: Add prometheus metrics tracking Xpra performance
Browse files Browse the repository at this point in the history
Add several metrics from Xpra (using the xpra info command behind the scenes). This can be useful
for troubleshooting any potential session issues.
  • Loading branch information
zusorio committed Nov 29, 2024
1 parent 350bafe commit b449d89
Showing 1 changed file with 145 additions and 0 deletions.
145 changes: 145 additions & 0 deletions remote/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import logging
import os
import subprocess
import typing as t
from wsgiref import simple_server

import prometheus_client
Expand Down Expand Up @@ -56,8 +57,152 @@ def get_idletime(self) -> float:
return round(current_idle_time, 2)


class XpraCollector(prometheus_client.registry.Collector):
def collect(self) -> t.Iterable[prometheus_client.Metric]:
"""Collect metrics from xpra info command output."""
client_batch_delay_metric = (
prometheus_client.metrics_core.GaugeMetricFamily(
"xpra_client_batch_delay_ms",
"Batch delay in ms",
labels=["type"],
)
)
client_connection_client_ping_latency_metric = (
prometheus_client.metrics_core.GaugeMetricFamily(
"xpra_connection_client_ping_latency_ms",
"Ping latency of xpra client in ms",
labels=["type"],
)
)
client_damage_data_queue_size_metric = (
prometheus_client.metrics_core.GaugeMetricFamily(
"xpra_client_damage_data_queue_size",
"Amount of items in the compression data queue",
labels=["type"],
)
)
client_damage_in_latency_metric = (
prometheus_client.metrics_core.GaugeMetricFamily(
"xpra_client_damage_in_latency_ms",
"How long it takes for a damage request to be sent in ms",
labels=["type"],
)
)
client_damage_packet_queue_size_metric = (
prometheus_client.metrics_core.GaugeMetricFamily(
"xpra_client_damage_packet_queue_size",
"Amount of packets in the damage packet queue",
labels=["type"],
)
)
client_encoding_quality_metric = (
prometheus_client.metrics_core.GaugeMetricFamily(
"xpra_client_encoding_quality",
"Encoder quality parameter (0-100)",
labels=["type"],
)
)
client_encoding_speed_metric = (
prometheus_client.metrics_core.GaugeMetricFamily(
"xpra_client_encoding_speed",
"Encoder speed parameter (0-100)",
labels=["type"],
)
)

client_latency_metric = (
prometheus_client.metrics_core.GaugeMetricFamily(
"xpra_client_latency_ms",
"Latency of xpra client in milliseconds (excludes ping)",
)
)

client_jitter_metric = (
prometheus_client.metrics_core.GaugeMetricFamily(
"xpra_client_jitter_ms",
"Jitter of xpra client in milliseconds",
)
)

proc = subprocess.run(
["xpra", "info"],
check=False,
capture_output=True,
encoding="utf-8",
)

xpra_metrics = {
line.split("=")[0]: line.split("=")[1]
for line in proc.stdout.splitlines()
if "=" in line
}

types = ["50p", "80p", "90p", "avg", "cur", "max", "min"]
for metric_type in types:
if val := xpra_metrics.get(f"client.batch.delay.{metric_type}"):
client_batch_delay_metric.add_metric([metric_type], float(val))

if val := xpra_metrics.get(
f"client.connection.client.ping_latency.{metric_type}"
):
client_connection_client_ping_latency_metric.add_metric(
[metric_type], float(val)
)

if val := xpra_metrics.get(
f"client.damage.data_queue.size.{metric_type}"
):
client_damage_data_queue_size_metric.add_metric(
[metric_type], float(val)
)

if val := xpra_metrics.get(
f"client.damage.in_latency.{metric_type}"
):
client_damage_in_latency_metric.add_metric(
[metric_type], float(val)
)

if val := xpra_metrics.get(
f"client.damage.packet_queue.size.{metric_type}"
):
client_damage_packet_queue_size_metric.add_metric(
[metric_type], float(val)
)

if val := xpra_metrics.get(
f"client.encoding.quality.{metric_type}"
):
client_encoding_quality_metric.add_metric(
[metric_type], float(val)
)

if val := xpra_metrics.get(f"client.encoding.speed.{metric_type}"):
client_encoding_speed_metric.add_metric(
[metric_type], float(val)
)

if val := xpra_metrics.get("client.damage.client-latency"):
client_latency_metric.add_metric([], float(val))

if val := xpra_metrics.get("client.jitter"):
client_jitter_metric.add_metric([], float(val))

yield client_batch_delay_metric
yield client_connection_client_ping_latency_metric
yield client_damage_data_queue_size_metric
yield client_damage_in_latency_metric
yield client_damage_packet_queue_size_metric
yield client_encoding_quality_metric
yield client_encoding_speed_metric
yield client_latency_metric
yield client_jitter_metric


IDLETIME.set_function(IdleTimer().get_idletime)

prometheus_client.REGISTRY.register(XpraCollector())


def start_server(
addr: str,
Expand Down

0 comments on commit b449d89

Please sign in to comment.