mirror of
https://github.com/agessaman/MeshCore.git
synced 2026-08-28 18:08:16 +00:00
chore(mqtt): silence periodic stats log for production; add get mqtt.stats CLI
The 30s "MQTT: Memory" line was useful during the outbox/sync-publish investigation but is spam for production. Gate the periodic logMemoryStatus() call in the MQTT task loop behind MQTT_MEMORY_DEBUG (a dedicated diagnostics flag, not enabled by plain MQTT_DEBUG or production builds) and stop the heltec_v3 variant from force-enabling MQTT_MEMORY_DEBUG on its observer_mqtt envs (now commented out to match heltec_v4). logMemoryStatus() itself is kept intact for opt-in debugging. Expose the same data on demand via a new `get mqtt.stats` CLI command backed by MQTTBridge::formatMqttStatsReply(): free/max heap, queue depth, outbox total, and per-slot publish ok/err counts (1-based, matching the msgs: line). Fits the 160-byte reply buffer at 6 slots; returns "(bridge not running)" when down.
This commit is contained in:
@@ -695,6 +695,8 @@ bool CommonCLI::handleObserverGetCmd(uint32_t sender_timestamp, const char* conf
|
||||
start = (int)_atoi(start_arg);
|
||||
}
|
||||
formatMQTTPresetListReply(reply, 160, start);
|
||||
} else if (memcmp(config, "mqtt.stats", 10) == 0) {
|
||||
MQTTBridge::formatMqttStatsReply(reply, 160);
|
||||
} else if (memcmp(config, "mqtt.status", 11) == 0) {
|
||||
MQTTBridge::formatMqttStatusReply(reply, 160, &_mqtt_prefs);
|
||||
} else if (memcmp(config, "mqtt.packets", 12) == 0) {
|
||||
|
||||
@@ -250,6 +250,45 @@ void MQTTBridge::formatMqttStatusReply(char* buf, size_t bufsize, const MQTTPref
|
||||
snprintf(buf + pos, bufsize - pos, ", q:%d", q);
|
||||
}
|
||||
|
||||
// On-demand publish-health + heap snapshot for the `get mqtt.stats` CLI command.
|
||||
// Same data as the (MQTT_MEMORY_DEBUG-only) periodic logMemoryStatus() line, but
|
||||
// returned as a reply instead of logged. Per-slot "sN=ok/err": ok = cumulative
|
||||
// accepted publishes, err = cumulative failures (socket error / network timeout).
|
||||
// Outbox should read ~0 (QoS0 publishes synchronously); a rising err isolates a
|
||||
// broker whose uplink is dropping writes.
|
||||
void MQTTBridge::formatMqttStatsReply(char* buf, size_t bufsize) {
|
||||
if (buf == nullptr || bufsize == 0) return;
|
||||
if (s_mqtt_bridge_instance == nullptr || !s_mqtt_bridge_instance->_initialized) {
|
||||
snprintf(buf, bufsize, "> (bridge not running)");
|
||||
return;
|
||||
}
|
||||
MQTTBridge* b = s_mqtt_bridge_instance;
|
||||
|
||||
int q = 0;
|
||||
#ifdef ESP_PLATFORM
|
||||
if (b->_packet_queue_handle != nullptr) {
|
||||
q = (int)uxQueueMessagesWaiting(b->_packet_queue_handle);
|
||||
}
|
||||
#else
|
||||
q = b->_queue_count;
|
||||
#endif
|
||||
|
||||
size_t outbox_total = 0;
|
||||
for (int i = 0; i < RUNTIME_MQTT_SLOTS; i++) {
|
||||
if (b->_slots[i].client) outbox_total += b->_slots[i].client->getOutboxSize();
|
||||
}
|
||||
|
||||
int pos = snprintf(buf, bufsize, "> Free=%d Max=%d q:%d/%d Outbox=%u |",
|
||||
(int)ESP.getFreeHeap(), (int)ESP.getMaxAllocHeap(),
|
||||
q, MAX_QUEUE_SIZE, (unsigned)outbox_total);
|
||||
for (int i = 0; i < RUNTIME_MQTT_SLOTS && pos < (int)bufsize - 1; i++) {
|
||||
if (!b->_slots[i].enabled || !b->_slots[i].client) continue;
|
||||
pos += snprintf(buf + pos, bufsize - pos, " s%d=%lu/%lu", i + 1,
|
||||
b->_slots[i].client->getPublishOk(),
|
||||
b->_slots[i].client->getPublishErr());
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t MQTTBridge::getLastWifiDisconnectReason() { return s_wifi_disconnect_reason; }
|
||||
unsigned long MQTTBridge::getLastWifiDisconnectTime() { return s_wifi_disconnect_time; }
|
||||
|
||||
@@ -899,14 +938,17 @@ void MQTTBridge::mqttTaskLoop() {
|
||||
|
||||
unsigned long now = millis();
|
||||
|
||||
// Periodic heap + outbox snapshot (compiles to nothing unless MQTT_DEBUG is set).
|
||||
// Outbox= is the value to watch: it should sit near 0 on a healthy uplink and
|
||||
// plateau at the configured cap (not climb) during a stall.
|
||||
// Periodic heap + publish-health snapshot. Gated behind MQTT_MEMORY_DEBUG (a
|
||||
// dedicated diagnostics flag, NOT enabled on production or plain MQTT_DEBUG builds)
|
||||
// so it stays off by default — the same data is available on demand via the
|
||||
// `get mqtt.stats` CLI command (formatMqttStatsReply / logMemoryStatus()).
|
||||
#ifdef MQTT_MEMORY_DEBUG
|
||||
static unsigned long last_mem_log = 0;
|
||||
if (now - last_mem_log >= 30000) {
|
||||
last_mem_log = now;
|
||||
logMemoryStatus();
|
||||
}
|
||||
#endif
|
||||
|
||||
bool wifi_just_connected = handleWiFiConnection(now);
|
||||
if (wifi_just_connected) {
|
||||
|
||||
@@ -468,6 +468,9 @@ public:
|
||||
* (for LoRa). Returns false if the bridge is not running. */
|
||||
bool ntpDiag(char* reply, size_t reply_size, bool verbose);
|
||||
static void formatMqttStatusReply(char* buf, size_t bufsize, const MQTTPrefs* obs);
|
||||
/** On-demand publish-health + heap snapshot for `get mqtt.stats` (per-slot ok/err,
|
||||
* outbox size, free/max heap, queue depth). */
|
||||
static void formatMqttStatsReply(char* buf, size_t bufsize);
|
||||
/** True when WiFi is set and at least one MQTT slot can run (preset + custom host if needed). */
|
||||
static bool isConfigValid(const MQTTPrefs* obs);
|
||||
static void formatSlotDiagReply(char* buf, size_t bufsize, int slot_index);
|
||||
|
||||
@@ -127,7 +127,8 @@ build_flags =
|
||||
-D MAX_MQTT_BROKERS=3
|
||||
-D MQTT_MAX_PACKET_SIZE=1024
|
||||
-D MQTT_DEBUG=1
|
||||
-D MQTT_MEMORY_DEBUG=1
|
||||
; Periodic 30s heap/pub-stats serial log — enable only for debugging (use `get mqtt.stats` on demand instead).
|
||||
; -D MQTT_MEMORY_DEBUG=1
|
||||
; Keep default observer profile less verbose to reduce runtime contention.
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
@@ -486,7 +487,8 @@ build_flags =
|
||||
-D MAX_MQTT_BROKERS=3
|
||||
-D MQTT_MAX_PACKET_SIZE=1024
|
||||
-D MQTT_DEBUG=1
|
||||
-D MQTT_MEMORY_DEBUG=1
|
||||
; Periodic 30s heap/pub-stats serial log — enable only for debugging (use `get mqtt.stats` on demand instead).
|
||||
; -D MQTT_MEMORY_DEBUG=1
|
||||
; Keep default observer profile less verbose to reduce runtime contention.
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
|
||||
Reference in New Issue
Block a user