Keep the root topic out of the log: print endpoint ids and topics without their root
The root topic identifies the account, and Serial logs get posted in issues and forums. "repeated directive on <topic> ignored" and the lines for dropped directives printed the full MQTT topic; they now start with the endpoint id. The lines for subscriptions and publishes print the topic relative to the root (AlexaBridgeLogic::topicForLog), and begin() prints the length of the root topic instead of its text. No line at any level prints the root topic, the username or the password. basicLight: RAM 34,476 -> 34,508 B, flash 338,281 -> 338,533 B; host tests 45 -> 47. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
2ed52c8721
commit
d534f23f27
7 changed files with 79 additions and 25 deletions
|
|
@ -100,8 +100,9 @@ void Alex2ESP::begin(const char *username, const char *password, const char *roo
|
|||
discoverTopicSend = this->rootTopic + "/discover_r";
|
||||
directiveFilter = this->rootTopic + "/+/alexaDirective";
|
||||
|
||||
// Log the root topic (never the credentials)
|
||||
ALEX2ESP_LOGI("root topic %s", this->rootTopic.c_str());
|
||||
// The root topic identifies the account, like the credentials: the log has its length, which is enough to see
|
||||
// that one was passed
|
||||
ALEX2ESP_LOGI("root topic of %u characters", (unsigned)this->rootTopic.length());
|
||||
|
||||
// Reports carry the time of their samples, so the board needs the time of day: UTC from SNTP
|
||||
if (useSntp)
|
||||
|
|
@ -278,11 +279,11 @@ void Alex2ESP::onSubscribe(uint16_t packetId, uint8_t qos)
|
|||
if (qos == SUBSCRIPTION_REFUSED)
|
||||
{
|
||||
// The session stays open and the state SUBSCRIBING: the broker would refuse the same topic again
|
||||
ALEX2ESP_LOGE("the broker refused the subscription to %s: check the root topic passed to begin()", topic.c_str());
|
||||
ALEX2ESP_LOGE("the broker refused the subscription to <root>/%s: check the root topic passed to begin()", logName(topic.c_str()));
|
||||
return;
|
||||
}
|
||||
|
||||
ALEX2ESP_LOGD("subscribed to %s", topic.c_str());
|
||||
ALEX2ESP_LOGD("subscribed to <root>/%s", logName(topic.c_str()));
|
||||
if (subscriptionsPending > 0 && --subscriptionsPending == 0)
|
||||
{
|
||||
state = Alex2ESPState::CONNECTED;
|
||||
|
|
@ -337,7 +338,7 @@ void Alex2ESP::onMessage(char *topic, char *payload, AsyncMqttClientMessagePrope
|
|||
// boards: not an error, and not worth a buffer
|
||||
if (index == 0)
|
||||
{
|
||||
ALEX2ESP_LOGD("directive on %s is for another board", topic);
|
||||
ALEX2ESP_LOGD("%.*s: directive for another board", (int)endpointLength, endpointId);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -345,22 +346,22 @@ void Alex2ESP::onMessage(char *topic, char *payload, AsyncMqttClientMessagePrope
|
|||
switch (directives.append(payload, length, index, total))
|
||||
{
|
||||
case AlexaDirectiveBuffer::Result::TOO_LARGE:
|
||||
ALEX2ESP_LOGE("directive of %u bytes on %s dropped: the limit is %u (ALEX2ESP_MAX_DIRECTIVE)", (unsigned)total, topic, (unsigned)ALEX2ESP_MAX_DIRECTIVE);
|
||||
ALEX2ESP_LOGE("%.*s: directive of %u bytes dropped: the limit is %u (ALEX2ESP_MAX_DIRECTIVE)", (int)endpointLength, endpointId, (unsigned)total, (unsigned)ALEX2ESP_MAX_DIRECTIVE);
|
||||
break;
|
||||
case AlexaDirectiveBuffer::Result::QUEUE_FULL:
|
||||
ALEX2ESP_LOGE("directive of %u bytes on %s dropped: %u directives, %u bytes, already wait for loop()", (unsigned)total, topic, (unsigned)directives.waitingDirectives(), (unsigned)directives.waitingBytes());
|
||||
ALEX2ESP_LOGE("%.*s: directive of %u bytes dropped: %u directives, %u bytes, already wait for loop()", (int)endpointLength, endpointId, (unsigned)total, (unsigned)directives.waitingDirectives(), (unsigned)directives.waitingBytes());
|
||||
break;
|
||||
case AlexaDirectiveBuffer::Result::NO_MEMORY:
|
||||
ALEX2ESP_LOGE("directive of %u bytes on %s dropped: no memory (%u bytes of heap free)", (unsigned)total, topic, (unsigned)ESP.getFreeHeap());
|
||||
ALEX2ESP_LOGE("%.*s: directive of %u bytes dropped: no memory (%u bytes of heap free)", (int)endpointLength, endpointId, (unsigned)total, (unsigned)ESP.getFreeHeap());
|
||||
break;
|
||||
case AlexaDirectiveBuffer::Result::OUT_OF_ORDER:
|
||||
ALEX2ESP_LOGE("directive on %s dropped: the fragment at byte %u of %u does not continue it", topic, (unsigned)index, (unsigned)total);
|
||||
ALEX2ESP_LOGE("%.*s: directive dropped: the fragment at byte %u of %u does not continue it", (int)endpointLength, endpointId, (unsigned)index, (unsigned)total);
|
||||
break;
|
||||
case AlexaDirectiveBuffer::Result::EMPTY:
|
||||
ALEX2ESP_LOGE("directive on %s dropped: it is empty", topic);
|
||||
ALEX2ESP_LOGE("%.*s: directive dropped: it is empty", (int)endpointLength, endpointId);
|
||||
break;
|
||||
case AlexaDirectiveBuffer::Result::DUPLICATE:
|
||||
ALEX2ESP_LOGI("repeated directive on %s ignored", topic);
|
||||
ALEX2ESP_LOGI("%.*s: repeated directive ignored", (int)endpointLength, endpointId);
|
||||
break;
|
||||
case AlexaDirectiveBuffer::Result::INCOMPLETE:
|
||||
case AlexaDirectiveBuffer::Result::COMPLETE:
|
||||
|
|
@ -509,7 +510,7 @@ AlexaSendResult Alex2ESP::publish(const char *topic, JsonDocument &doc)
|
|||
AlexaSendResult result = trySend(topic, doc, &length);
|
||||
if (result == AlexaSendResult::OK)
|
||||
{
|
||||
ALEX2ESP_LOGD("%u bytes -> %s, %u bytes of heap free", (unsigned)length, topic, (unsigned)ESP.getFreeHeap());
|
||||
ALEX2ESP_LOGD("%u bytes -> %s, %u bytes of heap free", (unsigned)length, logName(topic), (unsigned)ESP.getFreeHeap());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -582,28 +583,33 @@ AlexaSendResult Alex2ESP::trySend(const char *topic, JsonDocument &doc, size_t *
|
|||
return result;
|
||||
}
|
||||
|
||||
const char *Alex2ESP::logName(const char *topic) const
|
||||
{
|
||||
return AlexaBridgeLogic::topicForLog(topic, rootTopic.c_str());
|
||||
}
|
||||
|
||||
void Alex2ESP::logRefusal(const char *topic, AlexaSendResult result, size_t length)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
case AlexaSendResult::NOT_CONNECTED:
|
||||
ALEX2ESP_LOGE("%s: %u bytes not sent, no session with the broker", topic, (unsigned)length);
|
||||
ALEX2ESP_LOGE("%s: %u bytes not sent, no session with the broker", logName(topic), (unsigned)length);
|
||||
break;
|
||||
case AlexaSendResult::REFUSED:
|
||||
ALEX2ESP_LOGE("%s: %u bytes not sent, the MQTT client or the heap is full (%u bytes free)", topic, (unsigned)length, (unsigned)ESP.getFreeHeap());
|
||||
ALEX2ESP_LOGE("%s: %u bytes not sent, the MQTT client or the heap is full (%u bytes free)", logName(topic), (unsigned)length, (unsigned)ESP.getFreeHeap());
|
||||
break;
|
||||
case AlexaSendResult::TOO_LARGE:
|
||||
if (length == 0)
|
||||
{
|
||||
ALEX2ESP_LOGE("%s: not sent, the message ran out of memory while it was built", topic);
|
||||
ALEX2ESP_LOGE("%s: not sent, the message ran out of memory while it was built", logName(topic));
|
||||
}
|
||||
else
|
||||
{
|
||||
ALEX2ESP_LOGE("%s: %u bytes not sent, the limit is %u (ALEX2ESP_MAX_MESSAGE)", topic, (unsigned)length, (unsigned)ALEX2ESP_MAX_MESSAGE);
|
||||
ALEX2ESP_LOGE("%s: %u bytes not sent, the limit is %u (ALEX2ESP_MAX_MESSAGE)", logName(topic), (unsigned)length, (unsigned)ALEX2ESP_MAX_MESSAGE);
|
||||
}
|
||||
break;
|
||||
case AlexaSendResult::EMPTY:
|
||||
ALEX2ESP_LOGE("%s: not sent, the message is empty", topic);
|
||||
ALEX2ESP_LOGE("%s: not sent, the message is empty", logName(topic));
|
||||
break;
|
||||
case AlexaSendResult::OK:
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -130,6 +130,7 @@ private:
|
|||
AlexaDevice *findDevice(const char *endpointId, size_t length);
|
||||
AlexaSendResult trySend(const char *topic, JsonDocument &doc, size_t *length);
|
||||
void logRefusal(const char *topic, AlexaSendResult result, size_t length);
|
||||
const char *logName(const char *topic) const; // The topic as the log may print it: without the root topic
|
||||
};
|
||||
|
||||
#endif // ALEX2ESP_H
|
||||
|
|
|
|||
|
|
@ -280,6 +280,22 @@ const char *AlexaBridgeLogic::directiveEndpoint(const char *topic, const char *r
|
|||
return endpointId;
|
||||
}
|
||||
|
||||
const char *AlexaBridgeLogic::topicForLog(const char *topic, const char *rootTopic)
|
||||
{
|
||||
static const char outside[] = "(topic outside the root)";
|
||||
|
||||
if (topic == nullptr || rootTopic == nullptr)
|
||||
{
|
||||
return outside;
|
||||
}
|
||||
size_t rootLength = strlen(rootTopic);
|
||||
if (strncmp(topic, rootTopic, rootLength) != 0 || topic[rootLength] != '/')
|
||||
{
|
||||
return outside;
|
||||
}
|
||||
return topic + rootLength + 1;
|
||||
}
|
||||
|
||||
AlexaSendResult AlexaBridgeLogic::checkMessage(const JsonDocument &doc, size_t maxLength, size_t *length)
|
||||
{
|
||||
if (length != nullptr)
|
||||
|
|
|
|||
|
|
@ -206,6 +206,11 @@ namespace AlexaBridgeLogic
|
|||
// topic that 1.x boards use.
|
||||
const char *directiveEndpoint(const char *topic, const char *rootTopic, size_t *length);
|
||||
|
||||
// The topic as a log line may print it. The root topic identifies the account and a log gets posted in forums
|
||||
// and issues, so "<root>/ESP-01/alexaResponce" is printed as "ESP-01/alexaResponce". A topic that is not under
|
||||
// the root is not printed at all, it may still begin with it: the result is a fixed text then.
|
||||
const char *topicForLog(const char *topic, const char *rootTopic);
|
||||
|
||||
// Decides whether a document may be published and measures it: TOO_LARGE when it is over maxLength bytes or
|
||||
// ran out of memory while it was built (it would be sent truncated), EMPTY when it holds nothing, otherwise OK
|
||||
// with the serialised size in length.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// Serial diagnostics of the library. A line is printed when its level is within the level chosen at run time
|
||||
// (Alex2ESP::setLogLevel, INFO unless changed) and within the ceiling compiled in (ALEX2ESP_LOG_MAX); a line above
|
||||
// the ceiling costs no flash. Whatever the library refuses or drops is reported at ERROR. Credentials and
|
||||
// correlation tokens are never printed.
|
||||
// the ceiling costs no flash. Whatever the library refuses or drops is reported at ERROR. Credentials, the root
|
||||
// topic (it identifies the account) and correlation tokens are never printed.
|
||||
#ifndef ALEXA_LOG_H
|
||||
#define ALEXA_LOG_H
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue