Skip to content
This repository was archived by the owner on Mar 13, 2025. It is now read-only.

Commit dae7719

Browse files
authored
Merge pull request #550 from cloudflare/jspspike/response-print
Add logging for requests to miniflare
2 parents 6ec5ee3 + 3de1b29 commit dae7719

File tree

3 files changed

+71
-1
lines changed

3 files changed

+71
-1
lines changed

packages/tre/src/index.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,13 @@ import {
6767
Clock,
6868
HttpError,
6969
Log,
70+
LogLevel,
7071
MiniflareCoreError,
7172
Mutex,
7273
NoOpLog,
7374
OptionalZodTypeOf,
7475
defaultClock,
76+
formatResponse,
7577
} from "./shared";
7678
import { anyAbortSignal } from "./shared/signal";
7779
import { waitForRequest } from "./wait";
@@ -510,6 +512,13 @@ export class Miniflare {
510512
this.#workerSrcOpts,
511513
request
512514
);
515+
} else if (url.pathname === "/core/log") {
516+
if (this.#log.level < LogLevel.INFO) {
517+
return;
518+
}
519+
520+
const response = await formatResponse(request);
521+
this.#log.log(response);
513522
} else {
514523
// TODO: check for proxying/outbound fetch header first (with plans for fetch mocking)
515524
response = await this.#handleLoopbackPlugins(request, url);

packages/tre/src/plugins/core/index.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ export const SCRIPT_ENTRY = `
130130
const matchRoutes = ${matchRoutes.toString()};
131131
132132
async function handleEvent(event) {
133+
const startTime = Date.now();
133134
const probe = event.request.headers.get("${HEADER_PROBE}");
134135
if (probe !== null) {
135136
const probeMin = parseInt(probe);
@@ -178,6 +179,18 @@ async function handleEvent(event) {
178179
}
179180
}
180181
182+
event.waitUntil(${BINDING_SERVICE_LOOPBACK}.fetch("http://localhost/core/log", {
183+
method: "POST",
184+
headers: { "Content-Type": "application/json" },
185+
body: JSON.stringify({
186+
"status": response.status,
187+
"statusText": response.statusText,
188+
"method": event.request.method,
189+
"url": response.url,
190+
"time": Date.now() - startTime,
191+
}),
192+
}));
193+
181194
const liveReloadScript = globalThis.${BINDING_DATA_LIVE_RELOAD_SCRIPT};
182195
if (
183196
liveReloadScript !== undefined &&

packages/tre/src/shared/log.ts

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
import path from "path";
2-
import { Colorize, dim, green, grey, red, reset, yellow } from "kleur/colors";
2+
import {
3+
Colorize,
4+
blue,
5+
bold,
6+
dim,
7+
green,
8+
grey,
9+
red,
10+
reset,
11+
yellow,
12+
} from "kleur/colors";
13+
import { z } from "zod";
14+
import { Request } from "../http";
315

416
const cwd = process.cwd();
517
const cwdNodeModules = path.join(cwd, "node_modules");
@@ -121,3 +133,39 @@ export class NoOpLog extends Log {
121133
throw message;
122134
}
123135
}
136+
137+
export interface ResponseInfo {
138+
status: number;
139+
statusText: string;
140+
method: string;
141+
url: string;
142+
time: number;
143+
}
144+
145+
const ResponseInfoSchema = z.object({
146+
status: z.number(),
147+
statusText: z.string(),
148+
method: z.string(),
149+
url: z.string(),
150+
time: z.number(),
151+
});
152+
153+
export async function formatResponse(request: Request) {
154+
const info = ResponseInfoSchema.parse(await request.json());
155+
const url = new URL(info.url);
156+
157+
return [
158+
`${bold(info.method)} ${url.pathname} `,
159+
colourFromHTTPStatus(info.status)(
160+
`${bold(info.status)} ${info.statusText} `
161+
),
162+
grey(`(${info.time}ms)`),
163+
].join("");
164+
}
165+
166+
function colourFromHTTPStatus(status: number): Colorize {
167+
if (200 <= status && status < 300) return green;
168+
if (400 <= status && status < 500) return yellow;
169+
if (500 <= status) return red;
170+
return blue;
171+
}

0 commit comments

Comments
 (0)