Skip to content

Commit 1eee565

Browse files
feat: add system logging to middleware handler (#174)
* feat: add system logging to middleware handler * chore: remove log line * chore: add docs for system logging * chore: expand README * chore: remove docs from README
1 parent 8fbeb31 commit 1eee565

File tree

12 files changed

+651
-456
lines changed

12 files changed

+651
-456
lines changed

README.md

+5-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,11 @@ How to add new integration test scenarios to the application:
1717
4. Add your test
1818

1919
> Currently the tests require a built version of the `dist/run/handlers/cache.cjs` so you need to
20-
> run `npm run build` before executing the integration tests. In addition, the integration tests
21-
> need to be prepared before first use. You can do this by running `npm run pretest`.
20+
> run `npm run build` before executing the integration tests.
21+
22+
In addition, the integration tests need to be prepared before first use. You can do this by running
23+
`npm run pretest`. To speed up this process and build only the fixtures whose name starts with a
24+
given prefix, run `npm run pretest -- <prefix>`.
2225

2326
### E2E testing
2427

edge-runtime/lib/headers.ts

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
export const InternalHeaders = {
2+
NFDebugLogging: 'x-nf-debug-logging',
3+
NFRequestID: 'x-nf-request-id',
4+
}
5+
16
// Next 13 supports request header mutations and has the side effect of prepending header values with 'x-middleware-request'
27
// as part of invoking NextResponse.next() in the middleware. We need to remove that before sending the response the user
38
// as the code that removes it in Next isn't run based on how we handle the middleware

edge-runtime/lib/logging.ts

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export {
2+
logger,
3+
LogLevel,
4+
StructuredLogger,
5+
} from '../vendor/v1-7-0--edge-utils.netlify.app/logger/mod.ts'

edge-runtime/lib/response.ts

+15-8
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { Context } from '@netlify/edge-functions'
22
import { HTMLRewriter } from '../vendor/deno.land/x/[email protected]/index.ts'
33

44
import { updateModifiedHeaders } from './headers.ts'
5+
import type { StructuredLogger } from './logging.ts'
56
import { normalizeDataUrl, relativizeURL } from './util.ts'
67
import { addMiddlewareHeaders, isMiddlewareRequest, isMiddlewareResponse } from './middleware.ts'
78

@@ -10,15 +11,18 @@ export interface FetchEventResult {
1011
waitUntil: Promise<any>
1112
}
1213

13-
export const buildResponse = async ({
14-
result,
15-
request,
16-
context,
17-
}: {
18-
result: FetchEventResult
19-
request: Request
14+
interface BuildResponseOptions {
2015
context: Context
21-
}) => {
16+
logger: StructuredLogger
17+
request: Request
18+
result: FetchEventResult
19+
}
20+
21+
export const buildResponse = async ({ context, logger, request, result }: BuildResponseOptions) => {
22+
logger
23+
.withFields({ is_nextresponse_next: result.response.headers.has('x-middleware-next') })
24+
.debug('Building Next.js response')
25+
2226
updateModifiedHeaders(request.headers, result.response.headers)
2327

2428
// They've returned the MiddlewareRequest directly, so we'll call `next()` for them.
@@ -102,6 +106,8 @@ export const buildResponse = async ({
102106
const isDataReq = request.headers.get('x-nextjs-data')
103107

104108
if (rewrite) {
109+
logger.withFields({ rewrite_url: rewrite }).debug('Is rewrite')
110+
105111
const rewriteUrl = new URL(rewrite, request.url)
106112
const baseUrl = new URL(request.url)
107113
const relativeUrl = relativizeURL(rewrite, request.url)
@@ -142,5 +148,6 @@ export const buildResponse = async ({
142148
res.headers.delete('x-middleware-next')
143149
return addMiddlewareHeaders(context.next(), res)
144150
}
151+
145152
return res
146153
}

edge-runtime/middleware.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import type { Context } from '@netlify/edge-functions'
22

33
import matchers from './matchers.json' assert { type: 'json' }
44

5+
import { InternalHeaders } from './lib/headers.ts'
6+
import { logger, LogLevel } from './lib/logging.ts'
57
import { buildNextRequest, RequestData } from './lib/next-request.ts'
68
import { buildResponse } from './lib/response.ts'
79
import { FetchEventResult } from './lib/response.ts'
@@ -31,18 +33,26 @@ export async function handleMiddleware(
3133
) {
3234
const nextRequest = buildNextRequest(request, context)
3335
const url = new URL(request.url)
36+
const reqLogger = logger
37+
.withLogLevel(
38+
request.headers.has(InternalHeaders.NFDebugLogging) ? LogLevel.Debug : LogLevel.Log,
39+
)
40+
.withFields({ url_path: url.pathname })
41+
.withRequestID(request.headers.get(InternalHeaders.NFRequestID))
3442

3543
// While we have already checked the path when mapping to the edge function,
3644
// Next.js supports extra rules that we need to check here too, because we
3745
// might be running an edge function for a path we should not. If we find
3846
// that's the case, short-circuit the execution.
3947
if (!matchesMiddleware(url.pathname, request, searchParamsToUrlQuery(url.searchParams))) {
48+
reqLogger.debug('Aborting middleware due to runtime rules')
49+
4050
return
4151
}
4252

4353
try {
4454
const result = await nextHandler({ request: nextRequest })
45-
const response = await buildResponse({ result, request: request, context })
55+
const response = await buildResponse({ context, logger: reqLogger, request, result })
4656

4757
return response
4858
} catch (error) {

edge-runtime/vendor.ts

+2
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,5 @@ import 'https://deno.land/x/[email protected]/index.ts'
1616

1717
import 'https://esm.sh/v91/[email protected]/deno/dist/server/web/spec-extension/request.js'
1818
import 'https://esm.sh/v91/[email protected]/deno/dist/server/web/spec-extension/response.js'
19+
20+
import 'https://v1-7-0--edge-utils.netlify.app/logger/mod.ts'

0 commit comments

Comments
 (0)