Kbox-UniStack Docs

Logging

Subclass BaseLogger to route the stack's diagnostic messages to your transport, with log levels and a zero-cost release story that keeps logging off the hot path.

BaseLogger extension point

The stack emits diagnostics through an abstract BaseLogger. It owns a tiny fixed queue and an enable flag; you subclass it to route messages to whatever transport your platform has (UART, RTT, a ring buffer, ETS bus trace…). It is portable — nothing in the base class assumes an MCU.

class BaseLogger {
 protected:
  FixedVec<LogString, 2> queue;
  LogString PopFromQueue();
  bool enabled;
 public:
  virtual void Log(const LogString& message);
  void Enable();
  void Disable();
  virtual void Work() = 0;
};

Log() enqueues a message; Work() is pure — your subclass implements it to drain the queue and push each line out. Enable() / Disable() gate logging at runtime.

#include <Stack/Logger/BaseLogger.h>

// Route stack logs to a UART on your platform.
class UartLogger : public BaseLogger {
 public:
  void Work() override {
    while (/* queue has messages */) {
      LogString line = PopFromQueue();   // provided by BaseLogger
      // EDIT THIS: write `line` out over your transport (UART, RTT, ...)
    }
  }
};

The queue is a FixedVec<LogString, 2> — bounded, heap-free, and small on purpose. If Work() is not drained often enough, new messages are dropped rather than allocated. Call Work() from your main loop, not from an interrupt.

Log levels

Levels are defined in <Stack/Enums/LogLevelEnum.h>:

enum LogLevelEnum {
  LogLevelEnum_NA,
  LogLevelEnum_Info,
  LogLevelEnum_Warning,
  LogLevelEnum_Error,
  LogLevelEnum_Stack,
  LogLevelEnum_Verbose,
};
LevelMeaning
LogLevelEnum_NAUnset / not applicable.
LogLevelEnum_InfoNormal operational information.
LogLevelEnum_WarningRecoverable anomaly.
LogLevelEnum_ErrorA failure worth attention.
LogLevelEnum_StackKNX protocol-stack trace detail.
LogLevelEnum_VerboseHighest-volume diagnostic detail.

Cost & release builds

Keep logging out of the hot path. Logging is a diagnostic aid, not a runtime feature. Log() copies into a bounded queue and Work() drains it in your main loop — never log from an ISR, and never let a log transport block the bus-driver Work() pump.

For release builds, Disable() the logger (or never construct one). Uncalled code is removed by --gc-sections, so a build that never logs pays zero flash and RAM for it — consistent with the stack's opt-in, zero-cost philosophy.