Repository: maxfischer2781/cms_perf

Issue:
Feature: Provide connection load sensor
Add a sensor for number of open connections. This is an indication for the number of requests the system must handle, and possibly if connections are stalling.

See [``psutil.net_connections``](https://psutil.readthedocs.io/en/latest/#psutil.net_connections) for a potential backend.

Comments:

Patch:
diff --git a/cms_perf/cli.py b/cms_perf/cli.py
index 5f504eb..3dc73e6 100644
--- a/cms_perf/cli.py
+++ b/cms_perf/cli.py
@@ -1,6 +1,7 @@
 import argparse
 
 from . import xrd_load
+from . import net_load
 from . import __version__ as lib_version
 
 
@@ -68,6 +69,27 @@ CLI_PAG = CLI.add_subparsers(
     title="pag plugins", description="Sensor to use for the pag measurement",
 )
 
+# pag System Plugins
+CLI_PAG_NUMSOCK = CLI_PAG.add_parser(
+    "pag=num_sockets", help="Total sockets across all processes",
+)
+CLI_PAG_NUMSOCK.add_argument(
+    "--max-sockets",
+    default=1000,
+    help="Maximum total sockets considered 100%%",
+    type=int,
+)
+CLI_PAG_NUMSOCK.add_argument(
+    "--socket-kind",
+    help="Which sockets to count",
+    choices=list(net_load.ConnectionKind.__members__),
+    default="tcp",
+)
+CLI_PAG_NUMSOCK.set_defaults(
+    __make_pag__=lambda args: net_load.prepare_num_sockets(
+        net_load.ConnectionKind.__getitem__(args.socket_kind), args.max_sockets
+    )
+)
 
 # pag XRootD Plugins
 CLI_PAG_XIOWAIT = CLI_PAG.add_parser(
diff --git a/cms_perf/net_load.py b/cms_perf/net_load.py
new file mode 100644
index 0000000..ebf8003
--- /dev/null
+++ b/cms_perf/net_load.py
@@ -0,0 +1,28 @@
+"""
+Sensor for network load
+"""
+import enum
+
+import psutil
+
+
+class ConnectionKind(enum.Enum):
+    inet = enum.auto()
+    inet4 = enum.auto()
+    inet6 = enum.auto()
+    tcp = enum.auto()
+    tcp4 = enum.auto()
+    tcp6 = enum.auto()
+    udp = enum.auto()
+    udp4 = enum.auto()
+    udp6 = enum.auto()
+    unix = enum.auto()
+    all = enum.auto()
+
+
+def prepare_num_sockets(kind: ConnectionKind, max_sockets):
+    return lambda: 100.0 * num_sockets(kind) / max_sockets
+
+
+def num_sockets(kind: ConnectionKind) -> float:
+    return len(psutil.net_connections(kind=kind.name))
diff --git a/cms_perf/xrd_load.py b/cms_perf/xrd_load.py
index 0c4813f..46c4b18 100644
--- a/cms_perf/xrd_load.py
+++ b/cms_perf/xrd_load.py
@@ -13,17 +13,17 @@ def rescan(interval):
 
 def prepare_iowait(interval: float):
     tracker = XrootdTracker(rescan_interval=rescan(interval))
-    return tracker.io_wait
+    return lambda: 100.0 * tracker.io_wait()
 
 
 def prepare_numfds(interval: float, max_core_fds: float):
     tracker = XrootdTracker(rescan_interval=rescan(interval))
-    return lambda: tracker.num_fds() / max_core_fds / psutil.cpu_count()
+    return lambda: 100.0 * tracker.num_fds() / max_core_fds / psutil.cpu_count()
 
 
 def prepare_threads(interval: float, max_core_threads: float):
     tracker = XrootdTracker(rescan_interval=rescan(interval))
-    return lambda: tracker.num_threads() / max_core_threads / psutil.cpu_count()
+    return lambda: 100.0 * tracker.num_threads() / max_core_threads / psutil.cpu_count()
 
 
 def is_alive(proc: psutil.Process) -> bool:


Test patch:
diff --git a/tests/test_cli.py b/tests/test_cli.py
index a9e4617..ace0296 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -37,7 +37,7 @@ def test_run_sched(executable: List[str]):
         assert total == readings[0]
 
 
-PAG_PLUGINS = ["xrootd.io_wait", "xrootd.num_fds", "xrootd.num_threads"]
+PAG_PLUGINS = ["num_sockets", "xrootd.io_wait", "xrootd.num_fds", "xrootd.num_threads"]
 
 
 @mimicry.skipif_unsuported