1
1
import logging
2
2
import time
3
+ from typing import Any
3
4
4
5
import requests
6
+ from jsonrpcclient import Error , Ok , parse , request_hex
5
7
from prometheus_client import Gauge , Info , start_http_server
6
8
7
9
from . import __version__
@@ -34,27 +36,6 @@ class RouterMetrics:
34
36
"Total transferred data this month (bytes)" ,
35
37
)
36
38
37
- payload = {
38
- "network_info" : {
39
- "id" : "1" ,
40
- "jsonrpc" : "2.0" ,
41
- "method" : "GetNetworkInfo" ,
42
- "params" : {},
43
- },
44
- "system_status" : {
45
- "id" : "1" ,
46
- "jsonrpc" : "2.0" ,
47
- "method" : "GetSystemStatus" ,
48
- "params" : {},
49
- },
50
- "usage_record" : {
51
- "id" : "1" ,
52
- "jsonrpc" : "2.0" ,
53
- "method" : "GetUsageRecord" ,
54
- "params" : {},
55
- },
56
- }
57
-
58
39
def __init__ (
59
40
self ,
60
41
request_key : str ,
@@ -72,24 +53,36 @@ def __init__(
72
53
"Referer" : f"http://{ self .box_addr } /index.html" ,
73
54
}
74
55
75
- def run_metrics_loop (self ):
56
+ def run_metrics_loop (self ) -> None :
76
57
"""Metrics fetching loop"""
77
58
78
59
while True :
79
60
logging .debug ("Fetching metrics." )
80
- # self.fetch()
81
- self .fetch_new ()
61
+ self .fetch_metrics ()
82
62
time .sleep (self .polling_interval_seconds )
83
63
84
- def _box_api_request (self , json : dict ) -> dict :
64
+ def _box_api_request (self , method : str ) -> dict [ str , Any ] :
85
65
response = requests .post (
86
- self .url , json = json , headers = self .headers , timeout = self .timeout
66
+ self .url ,
67
+ json = request_hex (method ),
68
+ headers = self .headers ,
69
+ timeout = self .timeout ,
87
70
)
88
- logging .debug ("Response JSON: %s" , response .json ())
89
- return response .json ().get ("result" , {})
71
+ logging .debug ("Method: %s; response: %s" , method , response .json ())
72
+ match parse (response .json ()):
73
+ case Ok (result , _):
74
+ return result
75
+ case Error (_, message , _, _):
76
+ logging .error (
77
+ "API error: method: %s; message: %s" , method , message
78
+ )
79
+ raise RuntimeError (message )
80
+ case _:
81
+ assert False , "Impossible parsed response received."
90
82
91
83
def _read_network_info (self ) -> None :
92
- results = self ._box_api_request (json = self .payload ["network_info" ])
84
+ """Requesting, parsing, and updating network info metrics."""
85
+ results = self ._box_api_request ("GetNetworkInfo" )
93
86
logging .debug ("Network info: %s" , results )
94
87
95
88
# Set Prometheus metrics
@@ -114,15 +107,17 @@ def _read_network_info(self) -> None:
114
107
)
115
108
116
109
def _read_system_status (self ) -> None :
117
- results = self ._box_api_request (json = self .payload ["system_status" ])
110
+ """Requesting, parsing, and updating system status metrics."""
111
+ results = self ._box_api_request ("GetSystemStatus" )
118
112
logging .debug ("System status: %s" , results )
119
113
120
114
# Set Prometheus metrics
121
115
if value := results .get ("TotalConnNum" ):
122
116
self .connected_devices .set (value )
123
117
124
118
def _read_usage_record (self ) -> None :
125
- results = self ._box_api_request (json = self .payload ["usage_record" ])
119
+ """Requesting, parsing, and updating usage record metrics."""
120
+ results = self ._box_api_request ("GetUsageRecord" )
126
121
logging .debug ("Usage record: %s" , results )
127
122
128
123
# Set Prometheus metrics
@@ -135,13 +130,14 @@ def _read_usage_record(self) -> None:
135
130
if value := results .get ("HUseData" ):
136
131
self .total_transfer_this_month .set (value )
137
132
138
- def fetch_new (self ):
133
+ def fetch_metrics (self ) -> None :
134
+ """Fetch all relevant metrics."""
139
135
self ._read_network_info ()
140
136
self ._read_system_status ()
141
137
self ._read_usage_record ()
142
138
143
139
144
- def main ():
140
+ def main () -> None :
145
141
"""Main entry point for the exporter"""
146
142
logging .info ("Linkhub Prometheus Exporter, version %s" , __version__ )
147
143
0 commit comments