From c3d7b8f79a67d415e9b88b52e72c3d36c8a98b11 Mon Sep 17 00:00:00 2001 From: Jack Kingsman Date: Mon, 9 Mar 2026 00:41:07 -0700 Subject: [PATCH] Improve bot error bubble uo along with a few other spots --- app/fanout/bot.py | 4 ++-- app/fanout/bot_exec.py | 14 +++++++------- app/fanout/mqtt_base.py | 9 ++++++++- app/fanout/mqtt_community.py | 2 +- app/main.py | 8 ++++---- app/radio.py | 2 +- app/radio_sync.py | 10 +++++----- 7 files changed, 28 insertions(+), 21 deletions(-) diff --git a/app/fanout/bot.py b/app/fanout/bot.py index 40a1193..9cd2ef8 100644 --- a/app/fanout/bot.py +++ b/app/fanout/bot.py @@ -130,8 +130,8 @@ class BotModule(FanoutModule): except asyncio.TimeoutError: logger.warning("Bot '%s' execution timed out", self.name) return - except Exception as e: - logger.warning("Bot '%s' execution error: %s", self.name, e) + except Exception: + logger.exception("Bot '%s' execution error", self.name) return if response and self._active: diff --git a/app/fanout/bot_exec.py b/app/fanout/bot_exec.py index e50e2c3..8ca1200 100644 --- a/app/fanout/bot_exec.py +++ b/app/fanout/bot_exec.py @@ -90,8 +90,8 @@ def execute_bot_code( try: # Execute the user's code to define the bot function exec(code, namespace) - except Exception as e: - logger.warning("Bot code compilation failed: %s", e) + except Exception: + logger.exception("Bot code compilation failed") return None # Check if bot function was defined @@ -172,8 +172,8 @@ def execute_bot_code( logger.debug("Bot function returned unsupported type: %s", type(result)) return None - except Exception as e: - logger.warning("Bot function execution failed: %s", e) + except Exception: + logger.exception("Bot function execution failed") return None @@ -249,10 +249,10 @@ async def _send_single_bot_message( logger.warning("Cannot send bot response: no destination") return # Don't update timestamp if we didn't send except HTTPException as e: - logger.error("Bot failed to send response: %s", e.detail) + logger.error("Bot failed to send response: %s", e.detail, exc_info=True) return # Don't update timestamp on failure - except Exception as e: - logger.error("Bot failed to send response: %s", e) + except Exception: + logger.exception("Bot failed to send response") return # Don't update timestamp on failure # Update last send time after successful send diff --git a/app/fanout/mqtt_base.py b/app/fanout/mqtt_base.py index 1427b5d..9588839 100644 --- a/app/fanout/mqtt_base.py +++ b/app/fanout/mqtt_base.py @@ -89,7 +89,13 @@ class BaseMqttPublisher(ABC): try: await self._client.publish(topic, json.dumps(payload), retain=retain) except Exception as e: - logger.warning("%s publish failed on %s: %s", self._log_prefix, topic, e) + logger.warning( + "%s publish failed on %s: %s", + self._log_prefix, + topic, + e, + exc_info=True, + ) self.connected = False # Wake the connection loop so it exits the wait and reconnects self._settings_version += 1 @@ -223,6 +229,7 @@ class BaseMqttPublisher(ABC): self._log_prefix, e, backoff, + exc_info=True, ) try: diff --git a/app/fanout/mqtt_community.py b/app/fanout/mqtt_community.py index ee63180..da6a0a8 100644 --- a/app/fanout/mqtt_community.py +++ b/app/fanout/mqtt_community.py @@ -135,4 +135,4 @@ async def _publish_community_packet( await publisher.publish(topic, packet) except Exception as e: - logger.warning("Community MQTT broadcast error: %s", e) + logger.warning("Community MQTT broadcast error: %s", e, exc_info=True) diff --git a/app/main.py b/app/main.py index 3a188af..4becab6 100644 --- a/app/main.py +++ b/app/main.py @@ -47,8 +47,8 @@ async def _startup_radio_connect_and_setup() -> None: logger.info("Connected to radio") else: logger.warning("Failed to connect to radio on startup") - except Exception as e: - logger.warning("Failed to connect to radio on startup: %s", e) + except Exception: + logger.exception("Failed to connect to radio on startup") @asynccontextmanager @@ -72,8 +72,8 @@ async def lifespan(app: FastAPI): try: await fanout_manager.load_from_db() - except Exception as e: - logger.warning("Failed to start fanout modules: %s", e) + except Exception: + logger.exception("Failed to start fanout modules") startup_radio_task = asyncio.create_task(_startup_radio_connect_and_setup()) app.state.startup_radio_task = startup_radio_task diff --git a/app/radio.py b/app/radio.py index a9e2fbf..9dc9aa6 100644 --- a/app/radio.py +++ b/app/radio.py @@ -509,7 +509,7 @@ class RadioManager: return False except Exception as e: - logger.warning("Reconnection failed: %s", e) + logger.warning("Reconnection failed: %s", e, exc_info=True) broadcast_error("Reconnection failed", str(e)) return False diff --git a/app/radio_sync.py b/app/radio_sync.py index e254897..aa8edc1 100644 --- a/app/radio_sync.py +++ b/app/radio_sync.py @@ -483,7 +483,7 @@ async def send_advertisement(mc: MeshCore, *, force: bool = False) -> bool: logger.warning("Failed to send advertisement: %s", result.payload) return False except Exception as e: - logger.warning("Error sending advertisement: %s", e) + logger.warning("Error sending advertisement: %s", e, exc_info=True) return False @@ -514,7 +514,7 @@ async def _periodic_advert_loop(): logger.info("Periodic advertisement task cancelled") break except Exception as e: - logger.error("Error in periodic advertisement loop: %s", e) + logger.error("Error in periodic advertisement loop: %s", e, exc_info=True) await asyncio.sleep(ADVERT_CHECK_INTERVAL) @@ -554,7 +554,7 @@ async def sync_radio_time(mc: MeshCore) -> bool: logger.debug("Synced radio time to %d", now) return True except Exception as e: - logger.warning("Failed to sync radio time: %s", e) + logger.warning("Failed to sync radio time: %s", e, exc_info=True) return False @@ -580,7 +580,7 @@ async def _periodic_sync_loop(): logger.info("Periodic sync task cancelled") break except Exception as e: - logger.error("Error in periodic sync: %s", e) + logger.error("Error in periodic sync: %s", e, exc_info=True) def start_periodic_sync(): @@ -772,5 +772,5 @@ async def sync_recent_contacts_to_radio(force: bool = False, mc: MeshCore | None return {"loaded": 0, "busy": True} except Exception as e: - logger.error("Error syncing contacts to radio: %s", e) + logger.error("Error syncing contacts to radio: %s", e, exc_info=True) return {"loaded": 0, "error": str(e)}