Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better messaging in dev console #7986

Merged
merged 6 commits into from
Feb 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/light-taxis-move.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wrangler": patch
---

docs: clarifies that local resources are "simulated locally" or "connected to remote resource", and adds console messages to help explain local dev
27 changes: 14 additions & 13 deletions packages/wrangler/e2e/__snapshots__/pages-dev.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,30 @@ exports[`Pages 'wrangler pages dev' > should merge (with override) \`wrangler.to
Remote Durable Objects that are affected:
- {"name":"DO_BINDING_1_TOML","class_name":"DO_1_TOML","script_name":"DO_SCRIPT_1_TOML"}
- {"name":"DO_BINDING_2_TOML","class_name":"DO_2_TOML","script_name":"DO_SCRIPT_2_TOML"}
Your Worker and resources are simulated locally via Miniflare. For more information, see: https://developers.cloudflare.com/workers/testing/local-development.
Your worker has access to the following bindings:
- Durable Objects:
- DO_BINDING_1_TOML: NEW_DO_1 (defined in NEW_DO_SCRIPT_1 [not connected]) (local)
- DO_BINDING_2_TOML: DO_2_TOML (defined in DO_SCRIPT_2_TOML [not connected]) (local)
- DO_BINDING_3_ARGS: DO_3_ARGS (defined in DO_SCRIPT_3_ARGS [not connected]) (local)
- DO_BINDING_1_TOML: NEW_DO_1 (defined in NEW_DO_SCRIPT_1 [not connected])
- DO_BINDING_2_TOML: DO_2_TOML (defined in DO_SCRIPT_2_TOML [not connected])
- DO_BINDING_3_ARGS: DO_3_ARGS (defined in DO_SCRIPT_3_ARGS [not connected])
- KV Namespaces:
- KV_BINDING_1_TOML: NEW_KV_ID_1 (local)
- KV_BINDING_2_TOML: KV_ID_2_TOML (local)
- KV_BINDING_3_ARGS: KV_ID_3_ARGS (local)
- KV_BINDING_1_TOML: NEW_KV_ID_1 [simulated locally]
- KV_BINDING_2_TOML: KV_ID_2_TOML [simulated locally]
- KV_BINDING_3_ARGS: KV_ID_3_ARGS [simulated locally]
- D1 Databases:
- D1_BINDING_1_TOML: local-D1_BINDING_1_TOML=NEW_D1_NAME_1 (NEW_D1_NAME_1) (local)
- D1_BINDING_2_TOML: D1_NAME_2_TOML (D1_ID_2_TOML) (local)
- D1_BINDING_3_ARGS: local-D1_BINDING_3_ARGS=D1_NAME_3_ARGS (D1_NAME_3_ARGS) (local)
- D1_BINDING_1_TOML: local-D1_BINDING_1_TOML=NEW_D1_NAME_1 (NEW_D1_NAME_1) [simulated locally]
- D1_BINDING_2_TOML: D1_NAME_2_TOML (D1_ID_2_TOML) [simulated locally]
- D1_BINDING_3_ARGS: local-D1_BINDING_3_ARGS=D1_NAME_3_ARGS (D1_NAME_3_ARGS) [simulated locally]
- R2 Buckets:
- R2_BINDING_1_TOML: NEW_R2_BUCKET_1 (local)
- R2_BINDING_2_TOML: R2_BUCKET_2_TOML (local)
- R2_BINDING_3_TOML: R2_BUCKET_3_ARGS (local)
- R2_BINDING_1_TOML: NEW_R2_BUCKET_1 [simulated locally]
- R2_BINDING_2_TOML: R2_BUCKET_2_TOML [simulated locally]
- R2_BINDING_3_TOML: R2_BUCKET_3_ARGS [simulated locally]
- Services:
- SERVICE_BINDING_1_TOML: NEW_SERVICE_NAME_1 [not connected]
- SERVICE_BINDING_2_TOML: SERVICE_NAME_2_TOML [not connected]
- SERVICE_BINDING_3_TOML: SERVICE_NAME_3_ARGS [not connected]
- AI:
- Name: AI_BINDING_2_TOML
- Name: AI_BINDING_2_TOML [connected to remote resource]
- Vars:
- VAR1: "(hidden)"
- VAR2: "VAR_2_TOML"
Expand Down
10 changes: 5 additions & 5 deletions packages/wrangler/e2e/pages-dev.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,13 +121,13 @@ describe.sequential.each([{ cmd: "wrangler pages dev" }])(
expect(normalizeOutput(worker.currentOutput)).toContain(
dedent`Your worker has access to the following bindings:
- Durable Objects:
- TEST_DO: TestDurableObject (defined in a [not connected]) (local)
- TEST_DO: TestDurableObject (defined in a [not connected])
- KV Namespaces:
- TEST_KV: TEST_KV (local)
- TEST_KV: TEST_KV [simulated locally]
- D1 Databases:
- TEST_D1: local-TEST_D1 (TEST_D1) (local)
- TEST_D1: local-TEST_D1 (TEST_D1) [simulated locally]
- R2 Buckets:
- TEST_R2: TEST_R2 (local)
- TEST_R2: TEST_R2 [simulated locally]
- Services:
- TEST_SERVICE: test-worker [not connected]
`
Expand Down Expand Up @@ -327,7 +327,7 @@ describe.sequential.each([{ cmd: "wrangler pages dev" }])(
expect(normalizeOutput(worker.currentOutput)).toContain(
dedent`Your worker has access to the following bindings:
- KV Namespaces:
- KV_BINDING_TOML: KV_ID_TOML (local)
- KV_BINDING_TOML: KV_ID_TOML [simulated locally]
- Vars:
- PAGES: "⚡️ Pages ⚡️"
`
Expand Down
28 changes: 21 additions & 7 deletions packages/wrangler/src/__tests__/dev.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import registerDevHotKeys from "../dev/hotkeys";
import { getWorkerAccountAndContext } from "../dev/remote";
import { FatalError } from "../errors";
import { CI } from "../is-ci";
import { logger } from "../logger";
import { mockAccountId, mockApiToken } from "./helpers/mock-account-id";
import { mockConsoleMethods } from "./helpers/mock-console";
import { useMockIsTTY } from "./helpers/mock-istty";
Expand Down Expand Up @@ -129,6 +130,7 @@ describe.sequential("wrangler dev", () => {
...mswSuccessOauthHandlers,
...mswSuccessUserHandlers
);
logger.clearHistory();
});

runInTempDir();
Expand Down Expand Up @@ -1208,12 +1210,14 @@ describe.sequential("wrangler dev", () => {
process.platform === "win32" ? "127.0.0.1" : "localhost"
);
expect(std.out).toMatchInlineSnapshot(`
"Your worker has access to the following bindings:
"Your Worker and resources are simulated locally via Miniflare. For more information, see: https://developers.cloudflare.com/workers/testing/local-development.

Your worker has access to the following bindings:
- Durable Objects:
- NAME_1: CLASS_1 (local)
- NAME_2: CLASS_2 (defined in SCRIPT_A [not connected]) (local)
- NAME_3: CLASS_3 (local)
- NAME_4: CLASS_4 (defined in SCRIPT_B [not connected]) (local)
- NAME_1: CLASS_1
- NAME_2: CLASS_2 (defined in SCRIPT_A [not connected])
- NAME_3: CLASS_3
- NAME_4: CLASS_4 (defined in SCRIPT_B [not connected])
"
`);
expect(std.warn).toMatchInlineSnapshot(`
Expand Down Expand Up @@ -1299,6 +1303,8 @@ describe.sequential("wrangler dev", () => {
});
expect(std.out).toMatchInlineSnapshot(`
"Using vars defined in .dev.vars
Your Worker and resources are simulated locally via Miniflare. For more information, see: https://developers.cloudflare.com/workers/testing/local-development.

Your worker has access to the following bindings:
- Vars:
- VAR_1: \\"(hidden)\\"
Expand Down Expand Up @@ -1333,6 +1339,8 @@ describe.sequential("wrangler dev", () => {
expect(varBindings).toEqual({ CUSTOM_VAR: "custom" });
expect(std.out).toMatchInlineSnapshot(`
"Using vars defined in .dev.vars.custom
Your Worker and resources are simulated locally via Miniflare. For more information, see: https://developers.cloudflare.com/workers/testing/local-development.

Your worker has access to the following bindings:
- Vars:
- CUSTOM_VAR: \\"(hidden)\\"
Expand Down Expand Up @@ -1853,7 +1861,9 @@ describe.sequential("wrangler dev", () => {
fs.writeFileSync("index.js", `export default {};`);
await runWranglerUntilConfig("dev index.js");
expect(std.out).toMatchInlineSnapshot(`
"Your worker has access to the following bindings:
"Your Worker and resources are simulated locally via Miniflare. For more information, see: https://developers.cloudflare.com/workers/testing/local-development.

Your worker has access to the following bindings:
- Services:
- WorkerA: A [not connected]
- WorkerB: B [not connected]
Expand All @@ -1874,7 +1884,9 @@ describe.sequential("wrangler dev", () => {
fs.writeFileSync("index.js", `export default {};`);
await runWranglerUntilConfig("dev index.js");
expect(std.out).toMatchInlineSnapshot(`
"Your worker has access to the following bindings:
"Your Worker and resources are simulated locally via Miniflare. For more information, see: https://developers.cloudflare.com/workers/testing/local-development.

Your worker has access to the following bindings:
- Services:
- WorkerA: A [not connected]
- WorkerB: B [not connected]
Expand All @@ -1901,6 +1913,8 @@ describe.sequential("wrangler dev", () => {
await runWranglerUntilConfig("dev index.js");
expect(std.out).toMatchInlineSnapshot(`
"Using vars defined in .dev.vars
Your Worker and resources are simulated locally via Miniflare. For more information, see: https://developers.cloudflare.com/workers/testing/local-development.

Your worker has access to the following bindings:
- Vars:
- variable: 123
Expand Down
14 changes: 8 additions & 6 deletions packages/wrangler/src/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export class Logger {
constructor() {}

private overrideLoggerLevel?: LoggerLevel;
private onceHistory = new Set<string>();

get loggerLevel() {
return this.overrideLoggerLevel ?? getLoggerLevel();
Expand Down Expand Up @@ -107,7 +108,6 @@ export class Logger {
Logger.#afterLogHook?.();
}

static onceHistory = new Set();
get once() {
return {
info: (...args: unknown[]) => this.doLogOnce("info", args),
Expand All @@ -116,14 +116,16 @@ export class Logger {
error: (...args: unknown[]) => this.doLogOnce("error", args),
};
}
doLogOnce(messageLevel: Exclude<LoggerLevel, "none">, args: unknown[]) {
// using this.constructor.onceHistory, instead of hard-coding Logger.onceHistory, allows for subclassing
const { onceHistory } = this.constructor as typeof Logger;

clearHistory() {
this.onceHistory.clear();
}
Comment on lines +120 to +122
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love this!


doLogOnce(messageLevel: Exclude<LoggerLevel, "none">, args: unknown[]) {
const cacheKey = `${messageLevel}: ${args.join(" ")}`;

if (!onceHistory.has(cacheKey)) {
onceHistory.add(cacheKey);
if (!this.onceHistory.has(cacheKey)) {
this.onceHistory.add(cacheKey);
this.doLog(messageLevel, args);
}
}
Expand Down
Loading
Loading