Skip to content

Commit 0fa5628

Browse files
fix: 🚑️ Initial working fix. Needs further testing and validation.
1 parent 8d21509 commit 0fa5628

15 files changed

Lines changed: 846 additions & 81 deletions

DEBUG_LOGGING.md

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
# Debug Logging Guide for JsonApiToolkit
2+
3+
JsonApiToolkit now includes comprehensive debug logging throughout the query processing pipeline. This guide explains how to activate and configure debug logging in applications using JsonApiToolkit.
4+
5+
## Logging Framework
6+
7+
JsonApiToolkit uses the standard Microsoft.Extensions.Logging framework with the `Intility.Logging.AspNetCore` package for enhanced logging capabilities.
8+
9+
## Configuration
10+
11+
### 1. Basic Setup
12+
13+
To enable debug logging for JsonApiToolkit, configure your logging in `Program.cs` or `appsettings.json`:
14+
15+
#### Option A: Configure in appsettings.json
16+
17+
Add the following to your `appsettings.json` or `appsettings.Development.json`:
18+
19+
```json
20+
{
21+
"Logging": {
22+
"LogLevel": {
23+
"Default": "Information",
24+
"JsonApiToolkit": "Debug"
25+
}
26+
}
27+
}
28+
```
29+
30+
#### Option B: Configure in Program.cs
31+
32+
```csharp
33+
builder.Logging.AddFilter("JsonApiToolkit", LogLevel.Debug);
34+
```
35+
36+
### 2. Specific Component Logging
37+
38+
For more granular control, you can configure logging for specific JsonApiToolkit components:
39+
40+
```json
41+
{
42+
"Logging": {
43+
"LogLevel": {
44+
"Default": "Information",
45+
"JsonApiToolkit.Controllers.JsonApiController": "Debug",
46+
"JsonApiToolkit.Services.JsonApiQueryParserService": "Debug",
47+
"JsonApiToolkit.Extensions.Querying.FilterExpressionBuilder": "Debug",
48+
"JsonApiToolkit.Extensions.Querying.FilterHandler": "Debug",
49+
"JsonApiToolkit.Extensions.Querying.SortingHandler": "Debug",
50+
"JsonApiToolkit.Mapping.JsonApiMapper": "Debug"
51+
}
52+
}
53+
}
54+
```
55+
56+
### 3. Production Safety
57+
58+
For production environments, set JsonApiToolkit logging to `Warning` or `Error` to avoid performance impact:
59+
60+
```json
61+
{
62+
"Logging": {
63+
"LogLevel": {
64+
"Default": "Information",
65+
"JsonApiToolkit": "Warning"
66+
}
67+
}
68+
}
69+
```
70+
71+
## What Gets Logged
72+
73+
When debug logging is enabled, JsonApiToolkit logs detailed information about:
74+
75+
### Query Processing Pipeline
76+
- **Request parsing**: Query parameters parsed from HTTP requests
77+
- **Filter processing**: Filter criteria application and expression building
78+
- **Sorting**: Sort parameter application
79+
- **Pagination**: Page calculation and application
80+
- **Includes**: Relationship loading and mapping
81+
82+
### Filter Expression Building
83+
- **Filter separation**: Main entity vs. included resource filters
84+
- **Expression construction**: LINQ expression building process
85+
- **Property mapping**: Field name to CLR property mapping
86+
- **Operator handling**: Different filter operators (eq, ne, gt, lt, in, etc.)
87+
- **Nested navigation**: Dot notation property access
88+
89+
### Entity Mapping
90+
- **Resource object creation**: Entity to JSON:API resource mapping
91+
- **Attribute extraction**: Property mapping to JSON:API attributes
92+
- **Relationship processing**: Related entity handling
93+
- **Document structure**: JSON:API document assembly
94+
95+
### Performance Insights
96+
- **Query execution**: Database query execution timing
97+
- **Result counts**: Number of entities processed
98+
- **Include processing**: Relationship loading details
99+
100+
## Example Log Output
101+
102+
With debug logging enabled, you'll see detailed logs like:
103+
104+
```
105+
[DBG] Starting JSON:API query processing for resource type 'books'
106+
[DBG] Parsed query parameters: Filters=2, Sorts=1, Includes=1, Pagination=True
107+
[DBG] Mapped 1 include paths to CLR properties: Author
108+
[DBG] Separated filters: MainFilters=1, IncludeFilters=1
109+
[DBG] Applying 1 main entity filters
110+
[DBG] Building filter expression for 1 filters and 0 nested groups with logical operator And
111+
[DBG] Processing filter: Field='title', Operator=Like, Value='API'
112+
[DBG] Successfully built filter expression for field 'title'
113+
[DBG] Using regular includes strategy - applying includes before sorting
114+
[DBG] Applying 1 regular includes
115+
[DBG] Applying 1 sort parameters after includes
116+
[DBG] Executing count query to get total resource count
117+
[DBG] Total count after filtering: 5
118+
[DBG] Applying pagination: Page=1, Size=10
119+
[DBG] Executing final query to retrieve results
120+
[DBG] Retrieved 5 results from database
121+
[DBG] Mapping results to JSON:API document structure
122+
[DBG] Creating JSON:API collection document for entities of type Book with resource type 'books'
123+
[DBG] Successfully completed JSON:API query processing for resource type 'books' with 5 resources and 5 included resources
124+
```
125+
126+
## Performance Considerations
127+
128+
Debug logging adds overhead to request processing. Consider:
129+
130+
1. **Development**: Enable debug logging for troubleshooting
131+
2. **Staging**: Use `Information` or `Warning` level
132+
3. **Production**: Use `Warning` or `Error` level only
133+
4. **Performance testing**: Disable debug logging to get accurate metrics
134+
135+
## Troubleshooting Common Issues
136+
137+
### Filter Problems
138+
Look for logs containing:
139+
- "Property 'fieldName' not found" - Field name doesn't match entity property
140+
- "Failed to convert filter value" - Type conversion issues
141+
- "Filter expression builder returned null" - Invalid filter configuration
142+
143+
### Include Problems
144+
Look for logs containing:
145+
- "Property 'relationship' not found during nested navigation" - Invalid include path
146+
- "Mapped X include paths" - Verify expected relationships are included
147+
148+
### Performance Issues
149+
Look for:
150+
- High result counts without pagination
151+
- Complex filter expressions with many nested groups
152+
- Multiple database queries for includes
153+
154+
## Integration with Intility.Logging.AspNetCore
155+
156+
JsonApiToolkit integrates seamlessly with `Intility.Logging.AspNetCore`. The structured logging provides:
157+
158+
- **Request correlation**: All logs for a request are correlated
159+
- **Structured data**: Filter counts, entity types, and processing steps are logged as structured data
160+
- **Performance metrics**: Query execution timing and result counts
161+
- **Error context**: Detailed context when errors occur
162+
163+
## Best Practices
164+
165+
1. **Use environment-specific configuration** to avoid debug logging in production
166+
2. **Monitor log volume** as debug logging can be verbose
167+
3. **Use structured logging filters** to focus on specific components
168+
4. **Combine with application monitoring** tools for comprehensive observability
169+
5. **Review logs regularly** during development to optimize query patterns
170+
171+
## Disable Logging
172+
173+
To completely disable JsonApiToolkit logging:
174+
175+
```json
176+
{
177+
"Logging": {
178+
"LogLevel": {
179+
"JsonApiToolkit": "None"
180+
}
181+
}
182+
}
183+
```
184+
185+
Or in code:
186+
187+
```csharp
188+
builder.Logging.AddFilter("JsonApiToolkit", LogLevel.None);
189+
```

JsonApiToolkit.Tests/Controllers/JsonApiControllerTests.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,20 @@
22
using JsonApiToolkit.Models.Documents;
33
using JsonApiToolkit.Models.Errors;
44
using JsonApiToolkit.Models.Resources;
5+
using JsonApiToolkit.Services;
56
using JsonApiToolkit.Tests.Models;
67
using Microsoft.AspNetCore.Http;
78
using Microsoft.AspNetCore.Mvc;
9+
using Microsoft.Extensions.Logging;
10+
using Moq;
811

912
namespace JsonApiToolkit.Tests.Controllers;
1013

1114
public class TestJsonApiController : JsonApiController
1215
{
16+
public TestJsonApiController(ILogger<JsonApiController> logger, IJsonApiQueryParser queryParser)
17+
: base(logger, queryParser) { }
18+
1319
public IActionResult TestJsonApiOk(TestEntity entity)
1420
{
1521
return JsonApiOk(entity, "testEntities");
@@ -42,7 +48,14 @@ public class JsonApiControllerTests
4248

4349
public JsonApiControllerTests()
4450
{
45-
_controller = new TestJsonApiController();
51+
var logger = new Mock<ILogger<JsonApiController>>();
52+
var queryParser = new Mock<IJsonApiQueryParser>();
53+
queryParser
54+
.Setup(x => x.Parse(It.IsAny<Microsoft.AspNetCore.Http.HttpRequest>()))
55+
.Returns(
56+
new JsonApiToolkit.Models.Querying.QueryParameters { Include = new List<string>() }
57+
);
58+
_controller = new TestJsonApiController(logger.Object, queryParser.Object);
4659

4760
var httpContext = new DefaultHttpContext();
4861
httpContext.Request.Scheme = "https";

JsonApiToolkit.Tests/Integration/AllowedIncludesIntegrationTests.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@
44
using JsonApiToolkit.Controllers;
55
using JsonApiToolkit.Extensions;
66
using JsonApiToolkit.Models.Errors;
7+
using JsonApiToolkit.Services;
78
using Microsoft.AspNetCore.Builder;
89
using Microsoft.AspNetCore.Hosting;
910
using Microsoft.AspNetCore.Mvc;
1011
using Microsoft.AspNetCore.TestHost;
1112
using Microsoft.EntityFrameworkCore;
1213
using Microsoft.Extensions.DependencyInjection;
1314
using Microsoft.Extensions.Hosting;
15+
using Microsoft.Extensions.Logging;
1416

1517
namespace JsonApiToolkit.Tests.Integration;
1618

@@ -155,6 +157,12 @@ public void Dispose()
155157
[Route("api/test")]
156158
public class TestIntegrationController : JsonApiController
157159
{
160+
public TestIntegrationController(
161+
ILogger<JsonApiController> logger,
162+
IJsonApiQueryParser queryParser
163+
)
164+
: base(logger, queryParser) { }
165+
158166
[HttpGet("with-allowed")]
159167
[AllowedIncludes("author", "posts")]
160168
public IActionResult GetWithAllowed()

0 commit comments

Comments
 (0)