Skip to content

Commit b40a98b

Browse files
committed
feat(routes): implement request ID middleware for enhanced logging & debugging
- Add RequestId class to serve as a unique identifier for each HTTP request - Integrate UUID package for generating version 4 UUIDs - Implement middleware to generate and provide RequestId for each incoming request - Document the purpose and usage of RequestId for improved traceability in logs
1 parent 7dab24a commit b40a98b

File tree

1 file changed

+58
-0
lines changed

1 file changed

+58
-0
lines changed

routes/_middleware.dart

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// routes/_middleware.dart
12
//
23
// ignore_for_file: avoid_slow_async_io, avoid_catches_without_on_clauses
34

@@ -10,6 +11,49 @@ import 'package:ht_api/src/registry/model_registry.dart';
1011
import 'package:ht_data_inmemory/ht_data_inmemory.dart';
1112
import 'package:ht_data_repository/ht_data_repository.dart';
1213
import 'package:ht_shared/ht_shared.dart';
14+
import 'package:uuid/uuid.dart'; // Import the uuid package
15+
16+
// --- Request ID Wrapper ---
17+
18+
/// {@template request_id}
19+
/// A wrapper class holding a unique identifier (UUID v4) generated for each
20+
/// incoming HTTP request.
21+
///
22+
/// **Purpose:**
23+
/// The primary role of this ID is **traceability for logging and debugging**.
24+
/// It allows developers to follow the entire lifecycle of a *single request*
25+
/// through various middleware, route handlers, repository calls, and potential
26+
/// external service interactions by searching logs for this specific ID.
27+
/// If an error occurs during a request, this ID provides a way to isolate all
28+
/// related log entries for that specific transaction, simplifying debugging.
29+
///
30+
/// **Scope:**
31+
/// - The ID is **transient** for the request itself; it exists only during the
32+
/// request-response cycle.
33+
/// - It is **not persisted** in the main application database alongside models
34+
/// like Headlines or Categories.
35+
/// - Its value lies in being included in **persistent logs**.
36+
///
37+
/// **Distinction from other IDs:**
38+
/// - **User ID:** Identifies the authenticated user making the request. Often
39+
/// logged alongside the `request_id` for user-specific debugging.
40+
/// - **Session ID:** Tracks a user's session across multiple requests.
41+
/// - **Correlation ID:** Often generated by the *client* and passed in headers
42+
/// to link related requests initiated by the client for a larger workflow.
43+
///
44+
/// **Implementation:**
45+
/// This class ensures type safety when providing and reading the request ID
46+
/// from the Dart Frog context using `context.provide<RequestId>` and
47+
/// `context.read<RequestId>()`. This prevents potential ambiguity if other raw
48+
/// strings were provided into the context.
49+
/// {@endtemplate}
50+
class RequestId {
51+
/// {@macro request_id}
52+
const RequestId(this.id);
53+
54+
/// The unique identifier string (UUID v4).
55+
final String id;
56+
}
1357

1458
// --- Helper Function to Load Fixtures ---
1559
// Note:
@@ -114,8 +158,22 @@ Handler middleware(Handler handler) {
114158
final sourceRepository = _createSourceRepository();
115159
final countryRepository = _createCountryRepository();
116160

161+
// Create a UUID generator instance
162+
const uuid = Uuid();
163+
117164
// Chain the providers and other middleware
118165
return handler
166+
// --- Request ID Provider ---
167+
// Generate a unique ID for each request and provide it via context.
168+
// Using the RequestId wrapper ensures type safety for context reads.
169+
.use((innerHandler) {
170+
return (context) {
171+
final requestIdValue = uuid.v4();
172+
final requestId = RequestId(requestIdValue);
173+
// Provide the RequestId instance to downstream handlers/middleware
174+
return innerHandler(context.provide<RequestId>(() => requestId));
175+
};
176+
})
119177
// Provide the Model Registry Map
120178
.use(
121179
modelRegistryProvider,

0 commit comments

Comments
 (0)