aprsd 3.4.4__py3-none-any.whl → 4.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aprsd/cli_helper.py +12 -5
- aprsd/client/aprsis.py +31 -9
- aprsd/client/base.py +13 -2
- aprsd/client/drivers/aprsis.py +6 -3
- aprsd/client/drivers/fake.py +15 -20
- aprsd/client/factory.py +0 -2
- aprsd/client/fake.py +0 -2
- aprsd/client/kiss.py +17 -2
- aprsd/client/stats.py +1 -3
- aprsd/cmds/completion.py +7 -4
- aprsd/cmds/dev.py +38 -42
- aprsd/cmds/fetch_stats.py +140 -143
- aprsd/cmds/healthcheck.py +5 -3
- aprsd/cmds/list_plugins.py +140 -134
- aprsd/cmds/listen.py +13 -9
- aprsd/cmds/server.py +53 -27
- aprsd/conf/__init__.py +1 -2
- aprsd/conf/client.py +3 -4
- aprsd/conf/common.py +19 -93
- aprsd/conf/log.py +2 -4
- aprsd/conf/opts.py +5 -4
- aprsd/conf/plugin_common.py +11 -121
- aprsd/exception.py +2 -0
- aprsd/log/log.py +7 -46
- aprsd/main.py +10 -4
- aprsd/packets/__init__.py +14 -4
- aprsd/packets/core.py +57 -67
- aprsd/packets/log.py +8 -8
- aprsd/packets/packet_list.py +9 -6
- aprsd/plugin.py +22 -11
- aprsd/plugins/notify.py +1 -4
- aprsd/plugins/weather.py +10 -8
- aprsd/stats/collector.py +5 -2
- aprsd/threads/__init__.py +3 -2
- aprsd/threads/aprsd.py +12 -7
- aprsd/threads/{keep_alive.py → keepalive.py} +14 -45
- aprsd/threads/registry.py +3 -3
- aprsd/threads/rx.py +9 -6
- aprsd/threads/stats.py +2 -2
- aprsd/threads/tx.py +3 -4
- aprsd/utils/__init__.py +42 -10
- aprsd/utils/json.py +9 -4
- aprsd/utils/keepalive_collector.py +55 -0
- aprsd/utils/trace.py +0 -2
- aprsd-4.0.1.dist-info/AUTHORS +1 -0
- {aprsd-3.4.4.dist-info → aprsd-4.0.1.dist-info}/METADATA +307 -408
- aprsd-4.0.1.dist-info/RECORD +74 -0
- {aprsd-3.4.4.dist-info → aprsd-4.0.1.dist-info}/WHEEL +1 -1
- aprsd/cmds/admin.py +0 -57
- aprsd/cmds/webchat.py +0 -662
- aprsd/conf/plugin_email.py +0 -105
- aprsd/plugins/email.py +0 -715
- aprsd/plugins/location.py +0 -181
- aprsd/threads/log_monitor.py +0 -121
- aprsd/web/__init__.py +0 -0
- aprsd/web/admin/__init__.py +0 -0
- aprsd/web/admin/static/css/index.css +0 -84
- aprsd/web/admin/static/css/prism.css +0 -4
- aprsd/web/admin/static/css/tabs.css +0 -35
- aprsd/web/admin/static/images/Untitled.png +0 -0
- aprsd/web/admin/static/images/aprs-symbols-16-0.png +0 -0
- aprsd/web/admin/static/images/aprs-symbols-16-1.png +0 -0
- aprsd/web/admin/static/images/aprs-symbols-64-0.png +0 -0
- aprsd/web/admin/static/images/aprs-symbols-64-1.png +0 -0
- aprsd/web/admin/static/images/aprs-symbols-64-2.png +0 -0
- aprsd/web/admin/static/js/charts.js +0 -235
- aprsd/web/admin/static/js/echarts.js +0 -465
- aprsd/web/admin/static/js/logs.js +0 -26
- aprsd/web/admin/static/js/main.js +0 -231
- aprsd/web/admin/static/js/prism.js +0 -12
- aprsd/web/admin/static/js/send-message.js +0 -114
- aprsd/web/admin/static/js/tabs.js +0 -28
- aprsd/web/admin/templates/index.html +0 -196
- aprsd/web/chat/static/css/chat.css +0 -115
- aprsd/web/chat/static/css/index.css +0 -66
- aprsd/web/chat/static/css/style.css.map +0 -1
- aprsd/web/chat/static/css/tabs.css +0 -41
- aprsd/web/chat/static/css/upstream/bootstrap.min.css +0 -6
- aprsd/web/chat/static/css/upstream/font.woff2 +0 -0
- aprsd/web/chat/static/css/upstream/google-fonts.css +0 -23
- aprsd/web/chat/static/css/upstream/jquery-ui.css +0 -1311
- aprsd/web/chat/static/css/upstream/jquery.toast.css +0 -28
- aprsd/web/chat/static/css/upstream/themes/default/assets/fonts/LatoLatin-Bold.woff +0 -0
- aprsd/web/chat/static/css/upstream/themes/default/assets/fonts/LatoLatin-Bold.woff2 +0 -0
- aprsd/web/chat/static/css/upstream/themes/default/assets/fonts/LatoLatin-Regular.woff +0 -0
- aprsd/web/chat/static/css/upstream/themes/default/assets/fonts/LatoLatin-Regular.woff2 +0 -0
- aprsd/web/chat/static/css/upstream/themes/default/assets/fonts/icons.woff +0 -0
- aprsd/web/chat/static/css/upstream/themes/default/assets/fonts/icons.woff2 +0 -0
- aprsd/web/chat/static/css/upstream/themes/default/assets/fonts/outline-icons.woff +0 -0
- aprsd/web/chat/static/css/upstream/themes/default/assets/fonts/outline-icons.woff2 +0 -0
- aprsd/web/chat/static/images/Untitled.png +0 -0
- aprsd/web/chat/static/images/aprs-symbols-16-0.png +0 -0
- aprsd/web/chat/static/images/aprs-symbols-16-1.png +0 -0
- aprsd/web/chat/static/images/aprs-symbols-64-0.png +0 -0
- aprsd/web/chat/static/images/aprs-symbols-64-1.png +0 -0
- aprsd/web/chat/static/images/aprs-symbols-64-2.png +0 -0
- aprsd/web/chat/static/images/globe.svg +0 -3
- aprsd/web/chat/static/js/gps.js +0 -84
- aprsd/web/chat/static/js/main.js +0 -45
- aprsd/web/chat/static/js/send-message.js +0 -612
- aprsd/web/chat/static/js/tabs.js +0 -28
- aprsd/web/chat/static/js/upstream/bootstrap.bundle.min.js +0 -7
- aprsd/web/chat/static/js/upstream/jquery-3.7.1.min.js +0 -2
- aprsd/web/chat/static/js/upstream/jquery-ui.min.js +0 -13
- aprsd/web/chat/static/js/upstream/jquery.toast.js +0 -374
- aprsd/web/chat/static/js/upstream/semantic.min.js +0 -11
- aprsd/web/chat/static/js/upstream/socket.io.min.js +0 -7
- aprsd/web/chat/templates/index.html +0 -139
- aprsd/wsgi.py +0 -322
- aprsd-3.4.4.dist-info/AUTHORS +0 -13
- aprsd-3.4.4.dist-info/RECORD +0 -134
- {aprsd-3.4.4.dist-info → aprsd-4.0.1.dist-info}/LICENSE +0 -0
- {aprsd-3.4.4.dist-info → aprsd-4.0.1.dist-info}/entry_points.txt +0 -0
- {aprsd-3.4.4.dist-info → aprsd-4.0.1.dist-info}/top_level.txt +0 -0
@@ -5,14 +5,12 @@ import tracemalloc
|
|
5
5
|
|
6
6
|
from loguru import logger
|
7
7
|
from oslo_config import cfg
|
8
|
-
import timeago
|
9
8
|
|
10
9
|
from aprsd import packets, utils
|
11
|
-
from aprsd.client import client_factory
|
12
10
|
from aprsd.log import log as aprsd_log
|
13
11
|
from aprsd.stats import collector
|
14
12
|
from aprsd.threads import APRSDThread, APRSDThreadList
|
15
|
-
|
13
|
+
from aprsd.utils import keepalive_collector
|
16
14
|
|
17
15
|
CONF = cfg.CONF
|
18
16
|
LOG = logging.getLogger("APRSD")
|
@@ -36,18 +34,14 @@ class KeepAliveThread(APRSDThread):
|
|
36
34
|
thread_list = APRSDThreadList()
|
37
35
|
now = datetime.datetime.now()
|
38
36
|
|
39
|
-
if
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
else:
|
44
|
-
email_thread_time = "N/A"
|
45
|
-
else:
|
46
|
-
email_thread_time = "N/A"
|
47
|
-
|
48
|
-
if "APRSClientStats" in stats_json and stats_json["APRSClientStats"].get("transport") == "aprsis":
|
37
|
+
if (
|
38
|
+
"APRSClientStats" in stats_json
|
39
|
+
and stats_json["APRSClientStats"].get("transport") == "aprsis"
|
40
|
+
):
|
49
41
|
if stats_json["APRSClientStats"].get("server_keepalive"):
|
50
|
-
last_msg_time = utils.strfdelta(
|
42
|
+
last_msg_time = utils.strfdelta(
|
43
|
+
now - stats_json["APRSClientStats"]["server_keepalive"]
|
44
|
+
)
|
51
45
|
else:
|
52
46
|
last_msg_time = "N/A"
|
53
47
|
else:
|
@@ -64,7 +58,7 @@ class KeepAliveThread(APRSDThread):
|
|
64
58
|
|
65
59
|
keepalive = (
|
66
60
|
"{} - Uptime {} RX:{} TX:{} Tracker:{} Msgs TX:{} RX:{} "
|
67
|
-
"Last:{}
|
61
|
+
"Last:{} - RAM Current:{} Peak:{} Threads:{} LoggingQueue:{}"
|
68
62
|
).format(
|
69
63
|
stats_json["APRSDStats"]["callsign"],
|
70
64
|
stats_json["APRSDStats"]["uptime"],
|
@@ -74,7 +68,6 @@ class KeepAliveThread(APRSDThread):
|
|
74
68
|
tx_msg,
|
75
69
|
rx_msg,
|
76
70
|
last_msg_time,
|
77
|
-
email_thread_time,
|
78
71
|
stats_json["APRSDStats"]["memory_current_str"],
|
79
72
|
stats_json["APRSDStats"]["memory_peak_str"],
|
80
73
|
len(thread_list),
|
@@ -97,35 +90,11 @@ class KeepAliveThread(APRSDThread):
|
|
97
90
|
LOGU.opt(colors=True).info(thread_msg)
|
98
91
|
# LOG.info(f"{key: <15} Alive? {str(alive): <5} {str(age): <20}")
|
99
92
|
|
100
|
-
#
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
keepalive = timeago.format(ka)
|
106
|
-
else:
|
107
|
-
keepalive = "N/A"
|
108
|
-
LOGU.opt(colors=True).info(f"<green>Client keepalive {keepalive}</green>")
|
109
|
-
# Reset the connection if it's dead and this isn't our
|
110
|
-
# First time through the loop.
|
111
|
-
# The first time through the loop can happen at startup where
|
112
|
-
# The keepalive thread starts before the client has a chance
|
113
|
-
# to make it's connection the first time.
|
114
|
-
if not cl.is_alive() and self.cntr > 0:
|
115
|
-
LOG.error(f"{cl.__class__.__name__} is not alive!!! Resetting")
|
116
|
-
client_factory.create().reset()
|
117
|
-
# else:
|
118
|
-
# # See if we should reset the aprs-is client
|
119
|
-
# # Due to losing a keepalive from them
|
120
|
-
# delta_dict = utils.parse_delta_str(last_msg_time)
|
121
|
-
# delta = datetime.timedelta(**delta_dict)
|
122
|
-
#
|
123
|
-
# if delta > self.max_delta:
|
124
|
-
# # We haven't gotten a keepalive from aprs-is in a while
|
125
|
-
# # reset the connection.a
|
126
|
-
# if not client.KISSClient.is_enabled():
|
127
|
-
# LOG.warning(f"Resetting connection to APRS-IS {delta}")
|
128
|
-
# client.factory.create().reset()
|
93
|
+
# Go through the registered keepalive collectors
|
94
|
+
# and check them as well as call log.
|
95
|
+
collect = keepalive_collector.KeepAliveCollector()
|
96
|
+
collect.check()
|
97
|
+
collect.log()
|
129
98
|
|
130
99
|
# Check version every day
|
131
100
|
delta = now - self.checker_time
|
aprsd/threads/registry.py
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
import logging
|
2
2
|
import time
|
3
3
|
|
4
|
-
from oslo_config import cfg
|
5
4
|
import requests
|
5
|
+
from oslo_config import cfg
|
6
6
|
|
7
7
|
import aprsd
|
8
8
|
from aprsd import threads as aprsd_threads
|
9
9
|
|
10
|
-
|
11
10
|
CONF = cfg.CONF
|
12
11
|
LOG = logging.getLogger("APRSD")
|
13
12
|
|
14
13
|
|
15
14
|
class APRSRegistryThread(aprsd_threads.APRSDThread):
|
16
15
|
"""This sends service information to the configured APRS Registry."""
|
16
|
+
|
17
17
|
_loop_cnt: int = 1
|
18
18
|
|
19
19
|
def __init__(self):
|
@@ -41,7 +41,7 @@ class APRSRegistryThread(aprsd_threads.APRSDThread):
|
|
41
41
|
"description": CONF.aprs_registry.description,
|
42
42
|
"service_website": CONF.aprs_registry.service_website,
|
43
43
|
"software": f"APRSD version {aprsd.__version__} "
|
44
|
-
|
44
|
+
"https://github.com/craigerl/aprsd",
|
45
45
|
}
|
46
46
|
try:
|
47
47
|
requests.post(
|
aprsd/threads/rx.py
CHANGED
@@ -13,7 +13,6 @@ from aprsd.packets import log as packet_log
|
|
13
13
|
from aprsd.threads import APRSDThread, tx
|
14
14
|
from aprsd.utils import trace
|
15
15
|
|
16
|
-
|
17
16
|
CONF = cfg.CONF
|
18
17
|
LOG = logging.getLogger("APRSD")
|
19
18
|
|
@@ -53,7 +52,9 @@ class APRSDRXThread(APRSDThread):
|
|
53
52
|
# kwargs. :(
|
54
53
|
# https://github.com/rossengeorgiev/aprs-python/pull/56
|
55
54
|
self._client.consumer(
|
56
|
-
self._process_packet,
|
55
|
+
self._process_packet,
|
56
|
+
raw=False,
|
57
|
+
blocking=False,
|
57
58
|
)
|
58
59
|
except (
|
59
60
|
aprslib.exceptions.ConnectionDrop,
|
@@ -138,7 +139,9 @@ class APRSDDupeRXThread(APRSDRXThread):
|
|
138
139
|
elif packet.timestamp - found.timestamp < CONF.packet_dupe_timeout:
|
139
140
|
# If the packet came in within N seconds of the
|
140
141
|
# Last time seeing the packet, then we drop it as a dupe.
|
141
|
-
LOG.warning(
|
142
|
+
LOG.warning(
|
143
|
+
f"Packet {packet.from_call}:{packet.msgNo} already tracked, dropping."
|
144
|
+
)
|
142
145
|
else:
|
143
146
|
LOG.warning(
|
144
147
|
f"Packet {packet.from_call}:{packet.msgNo} already tracked "
|
@@ -149,7 +152,7 @@ class APRSDDupeRXThread(APRSDRXThread):
|
|
149
152
|
|
150
153
|
|
151
154
|
class APRSDPluginRXThread(APRSDDupeRXThread):
|
152
|
-
""""Process received packets.
|
155
|
+
""" "Process received packets.
|
153
156
|
|
154
157
|
For backwards compatibility, we keep the APRSDPluginRXThread.
|
155
158
|
"""
|
@@ -249,7 +252,8 @@ class APRSDProcessPacketThread(APRSDThread):
|
|
249
252
|
self.process_other_packet(packet, for_us=False)
|
250
253
|
else:
|
251
254
|
self.process_other_packet(
|
252
|
-
packet,
|
255
|
+
packet,
|
256
|
+
for_us=(to_call.lower() == our_call),
|
253
257
|
)
|
254
258
|
LOG.debug(f"Packet processing complete for pkt '{packet.key}'")
|
255
259
|
return False
|
@@ -349,7 +353,6 @@ class APRSDPluginProcessPacketThread(APRSDProcessPacketThread):
|
|
349
353
|
# If the message was for us and we didn't have a
|
350
354
|
# response, then we send a usage statement.
|
351
355
|
if to_call == CONF.callsign and not replied:
|
352
|
-
|
353
356
|
# Tailor the messages accordingly
|
354
357
|
if CONF.load_help_plugin:
|
355
358
|
LOG.warning("Sending help!")
|
aprsd/threads/stats.py
CHANGED
@@ -2,20 +2,20 @@ import logging
|
|
2
2
|
import threading
|
3
3
|
import time
|
4
4
|
|
5
|
-
from oslo_config import cfg
|
6
5
|
import wrapt
|
6
|
+
from oslo_config import cfg
|
7
7
|
|
8
8
|
from aprsd.stats import collector
|
9
9
|
from aprsd.threads import APRSDThread
|
10
10
|
from aprsd.utils import objectstore
|
11
11
|
|
12
|
-
|
13
12
|
CONF = cfg.CONF
|
14
13
|
LOG = logging.getLogger("APRSD")
|
15
14
|
|
16
15
|
|
17
16
|
class StatsStore(objectstore.ObjectStoreMixin):
|
18
17
|
"""Container to save the stats from the collector."""
|
18
|
+
|
19
19
|
lock = threading.Lock()
|
20
20
|
data = {}
|
21
21
|
|
aprsd/threads/tx.py
CHANGED
@@ -2,20 +2,18 @@ import logging
|
|
2
2
|
import threading
|
3
3
|
import time
|
4
4
|
|
5
|
+
import wrapt
|
5
6
|
from oslo_config import cfg
|
6
7
|
from rush import quota, throttle
|
7
8
|
from rush.contrib import decorator
|
8
9
|
from rush.limiters import periodic
|
9
10
|
from rush.stores import dictionary
|
10
|
-
import wrapt
|
11
11
|
|
12
12
|
from aprsd import conf # noqa
|
13
13
|
from aprsd import threads as aprsd_threads
|
14
14
|
from aprsd.client import client_factory
|
15
|
-
from aprsd.packets import collector, core
|
15
|
+
from aprsd.packets import collector, core, tracker
|
16
16
|
from aprsd.packets import log as packet_log
|
17
|
-
from aprsd.packets import tracker
|
18
|
-
|
19
17
|
|
20
18
|
CONF = cfg.CONF
|
21
19
|
LOG = logging.getLogger("APRSD")
|
@@ -238,6 +236,7 @@ class BeaconSendThread(aprsd_threads.APRSDThread):
|
|
238
236
|
|
239
237
|
Settings are in the [DEFAULT] section of the config file.
|
240
238
|
"""
|
239
|
+
|
241
240
|
_loop_cnt: int = 1
|
242
241
|
|
243
242
|
def __init__(self):
|
aprsd/utils/__init__.py
CHANGED
@@ -13,11 +13,11 @@ import update_checker
|
|
13
13
|
import aprsd
|
14
14
|
|
15
15
|
from .fuzzyclock import fuzzy # noqa: F401
|
16
|
+
|
16
17
|
# Make these available by anyone importing
|
17
18
|
# aprsd.utils
|
18
19
|
from .ring_buffer import RingBuffer # noqa: F401
|
19
20
|
|
20
|
-
|
21
21
|
if sys.version_info.major == 3 and sys.version_info.minor >= 3:
|
22
22
|
from collections.abc import MutableMapping
|
23
23
|
else:
|
@@ -26,11 +26,13 @@ else:
|
|
26
26
|
|
27
27
|
def singleton(cls):
|
28
28
|
"""Make a class a Singleton class (only one instance)"""
|
29
|
+
|
29
30
|
@functools.wraps(cls)
|
30
31
|
def wrapper_singleton(*args, **kwargs):
|
31
32
|
if wrapper_singleton.instance is None:
|
32
33
|
wrapper_singleton.instance = cls(*args, **kwargs)
|
33
34
|
return wrapper_singleton.instance
|
35
|
+
|
34
36
|
wrapper_singleton.instance = None
|
35
37
|
return wrapper_singleton
|
36
38
|
|
@@ -170,7 +172,10 @@ def load_entry_points(group):
|
|
170
172
|
try:
|
171
173
|
ep.load()
|
172
174
|
except Exception as e:
|
173
|
-
print(
|
175
|
+
print(
|
176
|
+
f"Extension {ep.name} of group {group} failed to load with {e}",
|
177
|
+
file=sys.stderr,
|
178
|
+
)
|
174
179
|
print(traceback.format_exc(), file=sys.stderr)
|
175
180
|
|
176
181
|
|
@@ -200,8 +205,7 @@ def calculate_initial_compass_bearing(point_a, point_b):
|
|
200
205
|
|
201
206
|
x = math.sin(diff_long) * math.cos(lat2)
|
202
207
|
y = math.cos(lat1) * math.sin(lat2) - (
|
203
|
-
math.sin(lat1)
|
204
|
-
* math.cos(lat2) * math.cos(diff_long)
|
208
|
+
math.sin(lat1) * math.cos(lat2) * math.cos(diff_long)
|
205
209
|
)
|
206
210
|
|
207
211
|
initial_bearing = math.atan2(x, y)
|
@@ -218,15 +222,43 @@ def calculate_initial_compass_bearing(point_a, point_b):
|
|
218
222
|
def degrees_to_cardinal(bearing, full_string=False):
|
219
223
|
if full_string:
|
220
224
|
directions = [
|
221
|
-
"North",
|
222
|
-
"
|
223
|
-
"
|
225
|
+
"North",
|
226
|
+
"North-Northeast",
|
227
|
+
"Northeast",
|
228
|
+
"East-Northeast",
|
229
|
+
"East",
|
230
|
+
"East-Southeast",
|
231
|
+
"Southeast",
|
232
|
+
"South-Southeast",
|
233
|
+
"South",
|
234
|
+
"South-Southwest",
|
235
|
+
"Southwest",
|
236
|
+
"West-Southwest",
|
237
|
+
"West",
|
238
|
+
"West-Northwest",
|
239
|
+
"Northwest",
|
240
|
+
"North-Northwest",
|
241
|
+
"North",
|
224
242
|
]
|
225
243
|
else:
|
226
244
|
directions = [
|
227
|
-
"N",
|
228
|
-
"
|
229
|
-
"
|
245
|
+
"N",
|
246
|
+
"NNE",
|
247
|
+
"NE",
|
248
|
+
"ENE",
|
249
|
+
"E",
|
250
|
+
"ESE",
|
251
|
+
"SE",
|
252
|
+
"SSE",
|
253
|
+
"S",
|
254
|
+
"SSW",
|
255
|
+
"SW",
|
256
|
+
"WSW",
|
257
|
+
"W",
|
258
|
+
"WNW",
|
259
|
+
"NW",
|
260
|
+
"NNW",
|
261
|
+
"N",
|
230
262
|
]
|
231
263
|
|
232
264
|
cardinal = directions[round(bearing / 22.5)]
|
aprsd/utils/json.py
CHANGED
@@ -10,8 +10,13 @@ class EnhancedJSONEncoder(json.JSONEncoder):
|
|
10
10
|
def default(self, obj):
|
11
11
|
if isinstance(obj, datetime.datetime):
|
12
12
|
args = (
|
13
|
-
"year",
|
14
|
-
"
|
13
|
+
"year",
|
14
|
+
"month",
|
15
|
+
"day",
|
16
|
+
"hour",
|
17
|
+
"minute",
|
18
|
+
"second",
|
19
|
+
"microsecond",
|
15
20
|
)
|
16
21
|
return {
|
17
22
|
"__type__": "datetime.datetime",
|
@@ -63,10 +68,10 @@ class SimpleJSONEncoder(json.JSONEncoder):
|
|
63
68
|
|
64
69
|
|
65
70
|
class EnhancedJSONDecoder(json.JSONDecoder):
|
66
|
-
|
67
71
|
def __init__(self, *args, **kwargs):
|
68
72
|
super().__init__(
|
69
|
-
*args,
|
73
|
+
*args,
|
74
|
+
object_hook=self.object_hook,
|
70
75
|
**kwargs,
|
71
76
|
)
|
72
77
|
|
@@ -0,0 +1,55 @@
|
|
1
|
+
import logging
|
2
|
+
from typing import Callable, Protocol, runtime_checkable
|
3
|
+
|
4
|
+
from aprsd.utils import singleton
|
5
|
+
|
6
|
+
LOG = logging.getLogger("APRSD")
|
7
|
+
|
8
|
+
|
9
|
+
@runtime_checkable
|
10
|
+
class KeepAliveProducer(Protocol):
|
11
|
+
"""The KeepAliveProducer protocol is used to define the interface for running Keepalive checks."""
|
12
|
+
|
13
|
+
def keepalive_check(self) -> dict:
|
14
|
+
"""Check for keepalive."""
|
15
|
+
...
|
16
|
+
|
17
|
+
def keepalive_log(self):
|
18
|
+
"""Log any keepalive information."""
|
19
|
+
...
|
20
|
+
|
21
|
+
|
22
|
+
@singleton
|
23
|
+
class KeepAliveCollector:
|
24
|
+
"""The Collector class is used to collect stats from multiple StatsProducer instances."""
|
25
|
+
|
26
|
+
def __init__(self):
|
27
|
+
self.producers: list[Callable] = []
|
28
|
+
|
29
|
+
def check(self) -> None:
|
30
|
+
"""Do any keepalive checks."""
|
31
|
+
for name in self.producers:
|
32
|
+
cls = name()
|
33
|
+
try:
|
34
|
+
cls.keepalive_check()
|
35
|
+
except Exception as e:
|
36
|
+
LOG.error(f"Error in producer {name} (check): {e}")
|
37
|
+
|
38
|
+
def log(self) -> None:
|
39
|
+
"""Log any relevant information during a KeepAlive check"""
|
40
|
+
for name in self.producers:
|
41
|
+
cls = name()
|
42
|
+
try:
|
43
|
+
cls.keepalive_log()
|
44
|
+
except Exception as e:
|
45
|
+
LOG.error(f"Error in producer {name} (check): {e}")
|
46
|
+
|
47
|
+
def register(self, producer_name: Callable):
|
48
|
+
if not isinstance(producer_name, KeepAliveProducer):
|
49
|
+
raise TypeError(f"Producer {producer_name} is not a KeepAliveProducer")
|
50
|
+
self.producers.append(producer_name)
|
51
|
+
|
52
|
+
def unregister(self, producer_name: Callable):
|
53
|
+
if not isinstance(producer_name, KeepAliveProducer):
|
54
|
+
raise TypeError(f"Producer {producer_name} is not a KeepAliveProducer")
|
55
|
+
self.producers.remove(producer_name)
|
aprsd/utils/trace.py
CHANGED
@@ -5,7 +5,6 @@ import logging
|
|
5
5
|
import time
|
6
6
|
import types
|
7
7
|
|
8
|
-
|
9
8
|
VALID_TRACE_FLAGS = {"method", "api"}
|
10
9
|
TRACE_API = False
|
11
10
|
TRACE_METHOD = False
|
@@ -27,7 +26,6 @@ def trace(*dec_args, **dec_kwargs):
|
|
27
26
|
"""
|
28
27
|
|
29
28
|
def _decorator(f):
|
30
|
-
|
31
29
|
func_name = f.__qualname__
|
32
30
|
func_file = "/".join(f.__code__.co_filename.split("/")[-4:])
|
33
31
|
|
@@ -0,0 +1 @@
|
|
1
|
+
waboring@hemna.com : 1
|