| <!--* freshness: { reviewed: '2026-10-12' } *--> |
| |
| # Shared Debugger Logging (`logging`) |
| |
| ## Overview |
| |
| `//src/developer/debug/shared/logging` provides the logging infrastructure |
| shared by `zxdb` and `debug_agent`. It supports severity-based general logging |
| with pluggable backends, category-filtered hierarchical debug logging with |
| duration tracking, and source-location capture. |
| |
| ## Interface |
| |
| Public headers expose these macros, enums, and classes: |
| |
| - `LOGS(severity)`, `DEBUG_LOG(category)`, `DEBUG_LOG_WITH_LOCATION(category, |
| location)`: Macros that emit severity logs and category-filtered scoped debug |
| logs (`logging.h`, `debug.h`). |
| - `FROM_HERE`, `FROM_HERE_NO_FUNC`, `STRINGIFY(x, y)`, `STRINGIFY_INTERNAL(x, |
| y)`: Source location and preprocessor stringification macros |
| (`file_line_function.h`). |
| - `debug::LogSeverity`: Severity enum (`kInfo`, `kWarn`, `kError`) |
| (`logging.h`). |
| - `debug::LogStatement`: Scoped log accumulator (`LogStatement`, |
| `~LogStatement`, `stream`) (`logging.h`). |
| - `debug::LogBackend`: Pluggable sink interface for general log statements |
| (`WriteLog`, `Set`, `Unset`, `~LogBackend`) (`logging.h`). |
| - `debug::LogCategory`: Category enum (`debug.h`) for `kAgent`, `kArchArm64`, |
| `kArchx64`, `kBreakpoint`, `kJob`, `kMessageLoop`, `kProcess`, `kRemoteAPI`, |
| `kSession`, `kSetting`, `kTest`, `kTiming`, `kThread`, and `kWatchpoint`. Also |
| includes `kWorkerPool`, `kDebugAdapter`, `kBuildIDIndex`, `kProcessSymbols`, |
| `kModuleSymbols`, `kSystemSymbols`, `kDownloadManager`, `kAll`, and `kNone`. |
| - `debug::SetDebugLogging(bool activate)`, `debug::IsDebugLoggingActive()`, |
| `debug::SetLogCategories(std::initializer_list<LogCategory> categories)`: |
| Functions that control debug logging activation and active category filters |
| (`debug.h`). |
| - `debug::DebugLogStatement`: Scoped hierarchical debug log entry with duration |
| tracking (`DebugLogStatement`, `~DebugLogStatement`, `stream`, `origin`, |
| `category`, `start_time`) (`debug.h`). |
| - `debug::FileLineFunction`: Value type holding source file, line number, and |
| function name (`FileLineFunction`, `is_valid`, `file`, `line`, `function`, |
| `ToString`, `operator<`, `operator==`, `operator!=`) (`file_line_function.h`). |
| |
| ## Invariants |
| |
| Callers and implementations must preserve these invariants: |
| |
| - `FileLineFunction` stores raw `const char*` pointers for file and function |
| names without taking ownership. Callers must ensure string literals outlive |
| the `FileLineFunction` instance. |
| - `FileLineFunction::is_valid()` requires a non-null `file_` pointer and `line_ |
| > 0`. |
| - `FileLineFunction` comparison operators (`<`, `==`, `!=`) compare the line |
| number and `file_` pointer address (not string content) and ignore |
| `function_`. |
| - `DEBUG_LOG_WITH_LOCATION` declares a block-scoped `DebugLogStatement` tied to |
| `__LINE__`. Nested debug logs in the same scope form a parent-child tree that |
| flushes when the root `DebugLogStatement` destructs. |
| - A `LogCategory` is active when `fuchsia_logging` `Trace` severity is active, |
| or when `Debug` severity is active and the active set contains `kAll` or that |
| category. |
| - `PushLogEntry` and `PopLogEntry` lock `gLogMutex` before mutating the global |
| debug log tree. `LogBackend::Set`, `LogBackend::Unset`, and `SetLogCategories` |
| update global state without a mutex. |
| |
| ## Side Effects |
| |
| These logging primitives produce the following global and I/O side effects: |
| |
| - `LogStatement::~LogStatement()` sends the formatted string to `log_backend` |
| via `WriteLog()` and writes to `fuchsia_logging::LogMessage` when |
| `log_enable_syslog` is `true`. |
| - `LogBackend::Set()` and `LogBackend::Unset()` update the module-global |
| `log_backend` pointer and `log_enable_syslog` flag. |
| - `SetDebugLogging()` re-initializes process-wide Fuchsia syslog settings via |
| `fuchsia_logging::LogSettingsBuilder::BuildAndInitialize()`. |
| - `SetLogCategories()` updates the static active `LogCategory` set in |
| `debug.cc`. |
| - `DebugLogStatement` construction and destruction update the global log tree |
| (`gRootSlot`, `gCurrentSlot`) under `gLogMutex`. When the root statement |
| destructs, it writes the tree via `FX_LOGS(DEBUG)` on Fuchsia or `fprintf` to |
| `stderr` on host platforms. |
| |
| ## Verification |
| |
| Run this command to build `shared/logging`: |
| |
| - Build: `fx build //src/developer/debug/shared/logging` |