feat: improve error handling and reporting

This commit is contained in:
Vlad Stan 2023-06-26 12:20:06 +03:00
parent dabc26f8a6
commit f8d578e6aa
6 changed files with 101 additions and 42 deletions

View file

@ -8,12 +8,18 @@ from pydantic import BaseModel, Field
from lnbits.helpers import urlsafe_short_hash
class RelayStatus(BaseModel):
num_sent_events: Optional[int] = 0
num_received_events: Optional[int] = 0
error_counter: Optional[int] = 0
error_list: Optional[List] = []
class Relay(BaseModel):
id: Optional[str] = None
url: Optional[str] = None
connected: Optional[bool] = None
connected_string: Optional[str] = None
status: Optional[str] = None
status: Optional[RelayStatus] = None
active: Optional[bool] = None
ping: Optional[int] = None

View file

@ -3,13 +3,20 @@ class ClientMessageType:
REQUEST = "REQ"
CLOSE = "CLOSE"
class RelayMessageType:
EVENT = "EVENT"
NOTICE = "NOTICE"
END_OF_STORED_EVENTS = "EOSE"
COMMAND_RESULT = "OK"
@staticmethod
def is_valid(type: str) -> bool:
if type == RelayMessageType.EVENT or type == RelayMessageType.NOTICE or type == RelayMessageType.END_OF_STORED_EVENTS:
if (
type == RelayMessageType.EVENT
or type == RelayMessageType.NOTICE
or type == RelayMessageType.END_OF_STORED_EVENTS
or type == RelayMessageType.COMMAND_RESULT
):
return True
return False

View file

@ -2,6 +2,7 @@ import json
import time
from queue import Queue
from threading import Lock
from typing import List
from loguru import logger
from websocket import WebSocketApp
@ -39,6 +40,7 @@ class Relay:
self.shutdown: bool = False
self.error_counter: int = 0
self.error_threshold: int = 100
self.error_list: List[str] = []
self.num_received_events: int = 0
self.num_sent_events: int = 0
self.num_subscriptions: int = 0
@ -100,7 +102,7 @@ class Relay:
self.ws.send(message)
except Exception as e:
if self.shutdown:
logger.warning(f"Closing queue worker for {self.url}")
logger.warning(f"Closing queue worker for '{self.url}'.")
break
else:
time.sleep(0.1)
@ -133,18 +135,14 @@ class Relay:
logger.warning(f"Connection to relay {self.url} closed. Status: '{status_code}'. Message: '{message}'.")
self.close()
def _on_message(self, _, message: str):
if self._is_valid_message(message):
self.num_received_events += 1
self.message_pool.add_message(message, self.url)
else:
logger.debug(f"Invalid relay message: '{message}'.")
def _on_error(self, _, error):
logger.warning(f"Relay error: '{str(error)}'")
self._append_error_message(str(error))
self.connected = False
self.error_counter += 1
@ -161,9 +159,19 @@ class Relay:
message_json = json.loads(message)
message_type = message_json[0]
if not RelayMessageType.is_valid(message_type):
return False
if message_type == RelayMessageType.EVENT:
return self._is_valid_event_message(message_json)
if message_type == RelayMessageType.COMMAND_RESULT:
return self._is_valid_command_result_message(message, message_json)
return True
def _is_valid_event_message(self, message_json):
if not len(message_json) == 3:
return False
@ -191,3 +199,17 @@ class Relay:
return False
return True
def _is_valid_command_result_message(self, message, message_json):
if not len(message_json) < 3:
return False
if message_json[2] != True:
logger.warning(f"Relay '{self.url}' negative command result: '{message}'")
self._append_error_message(message)
return False
return True
def _append_error_message(self, message):
self.error_list = ([message] + self.error_list)[:20]

View file

@ -103,3 +103,4 @@ class RelayManager:
self.remove_relay(relay.url)
new_relay = self.add_relay(relay.url)
new_relay.error_counter = relay.error_counter
new_relay.error_list = relay.error_list

View file

@ -51,6 +51,18 @@
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props" auto-width>
<div v-if="col.name == 'id'"></div>
<div v-else-if="col.name == 'status'">
<div>
⬆️ <span v-text="col.value.sentEvents"></span>
⬇️ <span v-text="col.value.receveidEvents"></span>
⚠️ <span v-text="col.value.errorCount">
</span>
<q-tooltip>
<span v-for="e in col.value.errorList" v-text="e"></span><br>
</q-tooltip>
</div>
</div>
<div v-else>
<div v-if="col.value == true" style="background-color: green">
{{ col.value }}
@ -196,6 +208,13 @@
obj._data = _.clone(obj)
obj.theTime = obj.time * 60 - (Date.now() / 1000 - obj.timestamp)
obj.time = obj.time + 'mins'
obj.status = {
sentEvents: obj.status.num_sent_events,
receveidEvents: obj.status.num_received_events,
errorCount: obj.status.error_counter,
errorList: obj.status.error_list
}
obj.ping = obj.ping + ' ms'

View file

@ -24,19 +24,23 @@ all_routers: list[NostrRouter] = []
async def api_get_relays() -> RelayList:
relays = RelayList(__root__=[])
for url, r in nostr.client.relay_manager.relays.items():
status_text = (
f"⬆️ {r.num_sent_events} ⬇️ {r.num_received_events} ⚠️ {r.error_counter}"
)
connected_text = "🟢" if r.connected else "🔴"
# status_text = (
# f"⬆️ {r.num_sent_events} ⬇️ {r.num_received_events} ⚠️ {r.error_counter}"
# )
# connected_text = "🟢" if r.connected else "🔴"
relay_id = urlsafe_short_hash()
relays.__root__.append(
Relay(
id=relay_id,
url=url,
connected_string=connected_text,
status=status_text,
connected=r.connected,
status={
"num_sent_events": r.num_sent_events,
"num_received_events": r.num_received_events,
"error_counter": r.error_counter,
"error_list": r.error_list
},
ping=r.ping,
connected=True,
active=True,
)
)