You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/adrs/006-logging-strategy.md
+34-41Lines changed: 34 additions & 41 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,7 +7,7 @@ Proposed
7
7
## Context
8
8
9
9
The AI SDK identified some challenges with debugging and problem resolution that can be addressed with better logging.
10
-
Typically, users had to enable wire logs to access information necessary for troubleshooting which along with helpful log surfaces a large volume of unrelated one.
10
+
Typically, users had to enable wire logs to access information necessary for troubleshooting which, along with helpful logs, surfaces a large volume of unrelated ones.
11
11
Additionally, we identified the need to improve visibility into what's happening behind the scenes about application progress to the user.
12
12
13
13
Key challenges that drove this decision:
@@ -19,27 +19,34 @@ Key challenges that drove this decision:
19
19
20
20
## Decision
21
21
22
-
Devise and follow a comprehensive logging guidelines that prioritizes **debugging capability** and **user visibility** while maintaining **security** and **performance**. The approach emphasizes descriptive, human-readable logs with structured request tracking through MDC (Mapped Diagnostic Context).
22
+
Devise and follow comprehensive logging guidelines that prioritize **debugging capability** and **user visibility** while maintaining **security** and **performance**.
23
+
The approach emphasizes descriptive, human-readable logs with structured request tracking through MDC (Mapped Diagnostic Context).
23
24
24
25
## Guidelines
25
26
26
27
### 1. Content and Security
27
28
28
29
***Avoid sensitive information.**
29
-
Do not log any personally identifiable or confidential data such as names, IDs, tokens, or payload content. As a general rule, avoid logging full request or response bodies.
30
+
As a general rule, avoid logging full request or response bodies.
31
+
Do not log any personally identifiable or confidential data such as names, IDs, tokens, or payload content.
30
32
31
33
***Keep logs concise and relevant.**
32
-
Every log should convey meaningful information without redundancy. Avoid verbose, repetitive, or cosmetic details.
34
+
Every log should convey meaningful information without redundancy.
35
+
Avoid verbose, repetitive, or cosmetic details.
33
36
34
37
***Use descriptive, human-readable formats.**
35
-
Logs should read naturally and provide enough context for a developer to understand what happened without consulting the code. Include details such as the invoked service, endpoint etc. as applicable.
36
-
37
-
***Maintain extensible readability.**
38
-
While logs are intended for humans, follow the `metric=value` pattern where practical. This improves future extensibility and allows easier parsing if machine analysis becomes necessary.
38
+
Logs should read naturally and provide enough context for a developer to understand what happened without consulting the code.
39
+
While descriptiveness is a priority, follow the `metric=value` pattern where practical to include additional details with extensibility in mind.
40
+
Check out the example below.
41
+
```[reqId=e3eaa45c] OpenAI request completed successfully with duration=1628ms, size=1,2KB.```
39
42
40
43
***Correlate related logs.**
41
44
Include a request identifier (e.g., `reqId`) in per-request logs to assist with correlation and debugging.
42
45
46
+
***Exception logging security.**
47
+
When logging exceptions, use standard logging methods (e.g., `log.error("Operation failed", exception)`) rather than serializing exception objects.
48
+
Exception objects may contain custom fields with sensitive data that could be exposed through JSON serialization or custom `toString()` implementations.
49
+
43
50
---
44
51
45
52
### 2. Log Levels and Scope
@@ -51,13 +58,17 @@ Devise and follow a comprehensive logging guidelines that prioritizes **debuggin
51
58
Prefer **INFO level** for one-time or startup/shutdown logs that occur once per application run.
52
59
53
60
***Avoid unnecessary warnings.**
54
-
Use the WARNING level only for actionable or genuinely concerning conditions. Do not use it as a placeholder or for expected transient states.
61
+
Use the WARNING level only for actionable or genuinely concerning conditions.
62
+
Do not use it as a placeholder or for expected transient states.
55
63
56
64
***Explicit request lifecycle logging.**
57
-
Always log at **request start** to provide immediate visibility that an operation has begun. Do not rely solely on response-time logging — requests may fail, hang, or take long durations (e.g., streaming cases). This helps users understand that their request is being processed even before a result is available.
65
+
Always log at **request start** to provide immediate visibility that an operation has begun.
66
+
This helps users understand that their request is being processed even before a result is available.
67
+
Do not rely solely on response-time logging — requests may fail, hang, or take long durations.
68
+
This approach also avoids the need for stack-trace investigation when surface error responses are ambiguous.
58
69
59
70
***Performance-aware logging.**
60
-
If a log statement requires computation or inference to generate information, guard it with a log-level check (e.g., `if (log.isDebugEnabled())`) to avoid unnecessary overhead when that level is disabled.
71
+
If a log statement requires computation or inference to generate information, guard it with a log-level check (e.g., `if (log.isDebugEnabled())`) or other available context to avoid unnecessary overhead when that level is disabled.
61
72
62
73
---
63
74
@@ -67,45 +78,27 @@ Devise and follow a comprehensive logging guidelines that prioritizes **debuggin
67
78
MDC is used to carry contextual information (e.g., `reqId`, `endpoint`, `service`) across execution blocks within the same thread.
68
79
69
80
***Setting and clearing context.**
70
-
Set MDC values deliberately and close to their scope of relevance. Per-request MDC context must be cleared when the response completes. Avoid setting per-request values in long-lived objects that outlive the request lifecycle, as this can result in corrupted or incomplete log context.
81
+
Set MDC values deliberately and close to their scope of relevance.
82
+
Per-request MDC context must be cleared when the response completes.
83
+
Avoid setting per-request values in long-lived objects that outlive the request lifecycle, as this can result in corrupted or incomplete log context.
84
+
Setting per-request context outside of blocks or objects that are not invoked per-request can lead to incomplete MDC states which will corrupt logs produced.
71
85
72
86
***Granular clearing only.**
73
-
Never clear the entire MDC context. Instead, remove entries key-by-key to preserve unrelated context items that may remain valid for longer periods.
87
+
Never clear the entire MDC context.
88
+
Instead, remove entries key-by-key to preserve unrelated context items that may remain valid for longer periods.
74
89
75
90
***Centralized MDC management.**
76
-
Avoid using magic strings for MDC keys or values. Define them in a dedicated structure or utility (e.g., `MdcKeys` class) to ensure discoverability and prevent errors during refactoring.
91
+
Avoid using magic strings for MDC keys or values.
92
+
Define them in a dedicated structure or utility (e.g., `MdcKeys` class) to ensure discoverability and prevent errors during refactoring.
77
93
78
94
***Responsibility and ownership.**
79
-
The component or class that sets MDC context values is also responsible for clearing them. This maintains clarity and ensures proper lifecycle management.
95
+
The component or class that sets MDC context values is also responsible for clearing them.
96
+
This maintains clarity and ensures proper lifecycle management.
80
97
81
98
---
82
99
83
100
### 4. Logging Boundaries and Generation
84
101
85
102
***Deliberate logging boundaries.**
86
-
Generated code (such as those in modules like *document-grounding* or *prompt-registry*) should log minimally and preferably avoid. Logging should be centralized in higher-level components to maintain consistency and reduce noise.
87
-
88
-
## Alternatives
89
-
90
-
### Logging Framework Options
91
-
92
-
1.**slf4j-simple** (previous): Simple but limited configuration and poor production suitability
93
-
2.**logback-classic** (chosen): Industry standard with rich configuration, performance, and features
94
-
95
-
### Log Format Approaches
96
-
97
-
1.**Structured JSON logging**: Machine-readable but harder for human debugging
98
-
2.**Descriptive human-readable** (chosen): Prioritizes developer and user experience while maintaining some structure
99
-
100
-
## Consequences
101
-
102
-
### Positive
103
-
104
-
-**Improved debugging**: Comprehensive request tracking enables faster problem resolution
105
-
-**Better user experience**: Users can see progress of long-running AI operations
106
-
-**Security compliance**: Systematic approach prevents accidental logging of sensitive data
107
-
108
-
### Negative
109
-
110
-
-**Increased debug log volume**: More detailed logging may increase storage and processing overhead
111
-
-**Development overhead**: Developers must be mindful of proper MDC management as improper MDC handling could lead to incorrect request correlation
103
+
Generated code (such as those in modules like *document-grounding* or *prompt-registry*) should log minimally or preferably be avoided entirely.
104
+
Logging should be centralized in higher-level components to maintain consistency and reduce noise.
0 commit comments