Debugging and Logging
Relevant source files
The following files were used as context for generating this wiki page:
The Debugging and Logging system in libfastjson provides a centralized mechanism for tracking internal library states, error conditions, and informational messages. It supports output redirection to either standard streams (stdout/stderr) or the system logger (syslog), depending on the environment and configuration.
The system is designed with a "maintainer mode" that allow developers to toggle extensive debug output. During parsing or utility operations, internal errors are captured and reported through this infrastructure to assist in troubleshooting malformed JSON data or resource exhaustion.
Core Logging Infrastructure
The library utilizes a set of internal global variables and functions to manage logging state and output. The behavior is primarily governed by whether debug mode is enabled and whether output should be directed to the system log.
Components and State Management
The logging state is maintained via static integers _debug and _syslog. These are managed through specific setter and getter functions.
| Function | Purpose |
|---|---|
mc_set_debug(int debug) | Enables (1) or disables (0) the global debug flag. |
mc_get_debug() | Returns the current state of the debug flag. |
mc_set_syslog(int use_syslog) | Toggles whether messages are sent to syslog instead of stderr/stdout. |
Sources: debug.c:21-28, debug.h:23-26
Message Levels
The system defines three primary categories of messages:
- Debug (
mc_debug): Conditional output that only appears if_debugis set to non-zero. - Error (
mc_error): Critical failure messages, typically sent tostderr. - Info (
mc_info): General informational messages, also typically directed tostderr.
Sources: debug.c:30-74, debug.h:28-30
Logic Flow for Log Output
When a logging function is called, the library checks the output destination and the global debug state.
The diagram shows how the library decides between standard output and the system logger based on internal configuration. Sources: debug.c:30-74
Maintainer Mode and Macros
To minimize overhead in production environments, libfastjson uses preprocessor macros to control logging. When MC_MAINTAINER_MODE is not defined, many logging calls are optimized away by the compiler using if (0) blocks.
| Macro | Maintainer Mode Action | Default Production Action |
|---|---|---|
MC_DEBUG(x, ...) | Calls mc_debug() | Optimized out (if (0)) |
MC_INFO(x, ...) | Calls mc_info() | Optimized out (if (0)) |
MC_ERROR(x, ...) | Calls mc_error() | Calls mc_error() |
JASSERT(cond) | Aborts on failure with file/line info | No-op (does nothing) |
Sources: debug.h:40-70
Assertion Logic
The JASSERT macro provides a mechanism for internal consistency checks. If PARSER_BROKEN_FIXED is defined, it validates a condition; if it fails, it logs an error via mc_error containing the source file and line number, then triggers a null pointer dereference to force a crash and aborts.
Sources: debug.h:40-54
Internal Library Usage
Logging is integrated throughout the library's utility and parsing functions to report operational failures.
Utility and IO Errors
Functions in json_util.c use MC_ERROR to report file system and memory errors:
- File Access: Errors during
open(),read(), orwrite()of JSON files. - Memory: Failures in buffer allocation (e.g.,
printbuf_newreturning NULL). - Parsing: Failed attempts to parse integers or convert types.
Sources: json_util.c:54-124, json_util.c:266-269
Tokenizer Debugging
The JSON tokener uses MC_DEBUG to track the progress of parsing complex structures like comments.
Sources: json_tokener.c:338-348, json_tokener.c:641
Testbench Logging and Validation
The project's test suite, defined in tests/test-defs.sh, utilizes environment variables to control logging verbosity during automated tests.
- VERBOSE Variable: If
VERBOSEis set to 0, output is redirected to/dev/null. If set to 1, output is displayed. - Valgrind Integration: The test runner can execute programs under Valgrind, redirecting memory debug information to
.vg.outfiles and checking for "0 errors" in the final summary. - Output Comparison: Test failures are logged by comparing current output against
.expectedfiles. If they differ, the system logs the specificdiffbetween the results.
Sources: tests/test-defs.sh:31-45, tests/test-defs.sh:91-118
Conclusion
The Debugging and Logging system in libfastjson provides a flexible framework that balances the need for detailed developer insights with the performance requirements of a production library. By utilizing maintainer-mode macros and supporting both standard I/O and syslog, it ensures that errors are captured across diverse deployment environments while allowing for deep inspection during development.