Skip to content

Commit 27de2a6

Browse files
committed
Add documentation for new logging context API
Document the new context-aware logging API including: - Basic usage examples - Context management - Flight recorder feature - API reference - Testing examples - Migration guide This provides clear guidance for using the new logging features while maintaining backwards compatibility.
1 parent dec7f8f commit 27de2a6

File tree

1 file changed

+221
-0
lines changed

1 file changed

+221
-0
lines changed

docs/LOGGING.md

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
# Logging API Documentation
2+
3+
## Overview
4+
5+
The https_dns_proxy logging system supports both legacy global logging (for backwards compatibility) and new context-aware logging (for testability and future multi-instance support).
6+
7+
## Basic Usage (Legacy API)
8+
9+
The legacy API uses a global logging context and is compatible with all existing code:
10+
11+
```c
12+
#include "logging.h"
13+
14+
// Initialize logging (usually in main)
15+
logging_init(STDERR_FILENO, LOG_INFO, 0);
16+
17+
// Use logging macros anywhere
18+
DLOG("Debug message: %d", value); // Debug level
19+
ILOG("Info message"); // Info level
20+
WLOG("Warning: %s", message); // Warning level
21+
ELOG("Error occurred"); // Error level
22+
SLOG("Statistics: %llu", count); // Stats level
23+
FLOG("Fatal error"); // Fatal (exits program)
24+
```
25+
26+
## Context-Aware API (New)
27+
28+
The context-aware API allows multiple independent logging contexts, useful for testing and future enhancements:
29+
30+
### Creating a Context
31+
32+
```c
33+
#include "logging.h"
34+
35+
// Create and initialize a logging context
36+
logging_context_t my_context;
37+
memset(&my_context, 0, sizeof(my_context));
38+
39+
int logfd = open("mylog.txt", O_WRONLY | O_CREAT | O_APPEND, 0644);
40+
logging_context_init(&my_context, logfd, LOG_DEBUG, 100);
41+
```
42+
43+
### Using Context-Aware Macros
44+
45+
```c
46+
// Log to specific context
47+
DLOG_CTX(&my_context, "Debug message: %d", value);
48+
ILOG_CTX(&my_context, "Info message");
49+
WLOG_CTX(&my_context, "Warning: %s", message);
50+
ELOG_CTX(&my_context, "Error occurred");
51+
SLOG_CTX(&my_context, "Statistics: %llu", count);
52+
FLOG_CTX(&my_context, "Fatal error"); // Exits program
53+
```
54+
55+
### Event Loop Integration
56+
57+
If using libev for timers and signals:
58+
59+
```c
60+
struct ev_loop *loop = EV_DEFAULT;
61+
62+
// Set up periodic flush and signal handlers
63+
logging_context_events_init(&my_context, loop);
64+
65+
// ... run event loop ...
66+
67+
// Clean up before stopping
68+
logging_context_events_cleanup(&my_context);
69+
```
70+
71+
### Cleanup
72+
73+
```c
74+
// Always cleanup when done
75+
logging_context_cleanup(&my_context);
76+
```
77+
78+
## Flight Recorder
79+
80+
The flight recorder feature stores recent log messages in memory and dumps them on fatal errors or SIGUSR2:
81+
82+
```c
83+
// Initialize with flight recorder (store last 1000 messages)
84+
logging_context_init(&ctx, logfd, LOG_ERROR, 1000);
85+
86+
// Even debug messages are recorded (though not written unless debug enabled)
87+
DLOG_CTX(&ctx, "This is stored in memory");
88+
89+
// Manually dump flight recorder
90+
logging_context_flight_recorder_dump(&ctx);
91+
```
92+
93+
## Log Levels
94+
95+
From most verbose to least verbose:
96+
97+
1. `LOG_DEBUG` - Detailed debugging information
98+
2. `LOG_INFO` - Informational messages
99+
3. `LOG_WARNING` - Warning conditions
100+
4. `LOG_ERROR` - Error conditions
101+
5. `LOG_STATS` - Statistics output
102+
6. `LOG_FATAL` - Fatal errors (program exits)
103+
104+
Messages at or above the configured level are written to the log file.
105+
106+
## API Reference
107+
108+
### Context Management
109+
110+
#### `void logging_context_init(logging_context_t *ctx, int fd, int level, unsigned flight_recorder_size)`
111+
112+
Initialize a logging context.
113+
114+
- `ctx`: Pointer to context structure (must be zeroed first)
115+
- `fd`: File descriptor to write logs to (takes ownership)
116+
- `level`: Minimum log level to write (LOG_DEBUG, LOG_INFO, etc.)
117+
- `flight_recorder_size`: Number of messages to keep in memory (0 to disable)
118+
119+
#### `void logging_context_cleanup(logging_context_t *ctx)`
120+
121+
Clean up a logging context and free resources.
122+
123+
#### `void logging_context_events_init(logging_context_t *ctx, struct ev_loop *loop)`
124+
125+
Set up periodic flush timer and SIGUSR2 handler for flight recorder dumps.
126+
127+
#### `void logging_context_events_cleanup(logging_context_t *ctx)`
128+
129+
Stop timers and signal handlers.
130+
131+
### Utility Functions
132+
133+
#### `int logging_context_debug_enabled(logging_context_t *ctx)`
134+
135+
Returns 1 if debug logging is enabled for this context.
136+
137+
#### `void logging_context_flight_recorder_dump(logging_context_t *ctx)`
138+
139+
Manually dump the flight recorder contents to the log file.
140+
141+
#### `void logging_context_log(logging_context_t *ctx, const char *file, int line, int severity, const char *fmt, ...)`
142+
143+
Low-level logging function (use macros instead).
144+
145+
### Legacy API
146+
147+
#### `logging_context_t* logging_get_default_context(void)`
148+
149+
Get the default global logging context.
150+
151+
#### `void logging_init(int fd, int level, unsigned flight_recorder_size)`
152+
153+
Initialize the default global context (legacy API).
154+
155+
#### `void logging_cleanup(void)`
156+
157+
Clean up the default global context.
158+
159+
#### `int logging_debug_enabled(void)`
160+
161+
Check if debug is enabled on default context.
162+
163+
## Testing Example
164+
165+
The context-aware API makes testing easy:
166+
167+
```c
168+
void test_my_function(void) {
169+
// Create isolated logging context for this test
170+
logging_context_t test_ctx;
171+
memset(&test_ctx, 0, sizeof(test_ctx));
172+
173+
char tempfile[] = "/tmp/test_log_XXXXXX";
174+
int fd = mkstemp(tempfile);
175+
176+
logging_context_init(&test_ctx, fd, LOG_DEBUG, 0);
177+
178+
// Pass context to code under test
179+
my_function_with_logging(&test_ctx);
180+
181+
// Verify log output
182+
logging_context_cleanup(&test_ctx);
183+
184+
// Read and check tempfile contents
185+
// ...
186+
187+
close(fd);
188+
unlink(tempfile);
189+
}
190+
```
191+
192+
## Migration Guide
193+
194+
### Existing Code
195+
196+
No changes needed! All existing code using DLOG(), ILOG(), etc. continues to work.
197+
198+
### New Code
199+
200+
For new code or when refactoring, consider using context-aware logging:
201+
202+
1. Add `logging_context_t *log_ctx` parameter to component structures
203+
2. Use `*_CTX()` macros instead of legacy macros
204+
3. Initialize context in component init functions
205+
4. Clean up in component cleanup functions
206+
207+
This provides better testability and flexibility.
208+
209+
## Binary Size Impact
210+
211+
- Context struct: ~80 bytes per context
212+
- New functions: ~600 bytes total
213+
- Production build: **~600 bytes increase**
214+
- Test builds: Additional test code (not in production binary)
215+
216+
## Performance
217+
218+
- Zero overhead for disabled log levels (early return)
219+
- Flight recorder has minimal overhead (memory allocation only)
220+
- Periodic flush reduces syscall frequency
221+
- Context-aware macros have same performance as legacy macros

0 commit comments

Comments
 (0)