From 5b234cfd554aff08d065b96d7d49dfb36f40caa3 Mon Sep 17 00:00:00 2001 From: Joshua Johnson Date: Mon, 8 May 2023 13:50:25 -0500 Subject: [PATCH] Add output for tail being in sampling mode (#3146) --- .changeset/witty-pumpkins-swim.md | 5 +++ .../__tests__/pages-deployment-tail.test.ts | 2 + packages/wrangler/src/__tests__/tail.test.ts | 45 ++++++++++++++++--- packages/wrangler/src/tail/createTail.ts | 9 ++++ packages/wrangler/src/tail/printing.ts | 10 +++++ 5 files changed, 64 insertions(+), 7 deletions(-) create mode 100644 .changeset/witty-pumpkins-swim.md diff --git a/.changeset/witty-pumpkins-swim.md b/.changeset/witty-pumpkins-swim.md new file mode 100644 index 000000000000..db8b8e39f191 --- /dev/null +++ b/.changeset/witty-pumpkins-swim.md @@ -0,0 +1,5 @@ +--- +"wrangler": patch +--- + +Added output for tail being in "sampling mode" diff --git a/packages/wrangler/src/__tests__/pages-deployment-tail.test.ts b/packages/wrangler/src/__tests__/pages-deployment-tail.test.ts index 7e4d234562c2..14dd73c40a85 100644 --- a/packages/wrangler/src/__tests__/pages-deployment-tail.test.ts +++ b/packages/wrangler/src/__tests__/pages-deployment-tail.test.ts @@ -13,6 +13,7 @@ import type { ScheduledEvent, AlarmEvent, EmailEvent, + TailInfo, } from "../tail/createTail"; import type { RequestInit } from "undici"; import type WebSocket from "ws"; @@ -655,6 +656,7 @@ function isRequest( | RequestEvent | AlarmEvent | EmailEvent + | TailInfo | undefined | null ): event is RequestEvent { diff --git a/packages/wrangler/src/__tests__/tail.test.ts b/packages/wrangler/src/__tests__/tail.test.ts index 5c72d8aaca4b..581b2233833d 100644 --- a/packages/wrangler/src/__tests__/tail.test.ts +++ b/packages/wrangler/src/__tests__/tail.test.ts @@ -14,6 +14,7 @@ import type { ScheduledEvent, AlarmEvent, EmailEvent, + TailInfo, } from "../tail/createTail"; import type { RequestInit } from "undici"; import type WebSocket from "ws"; @@ -56,10 +57,10 @@ describe("tail", () => { await runWrangler("tail durable-object--websocket--response"); expect(std.out).toMatchInlineSnapshot(`""`); expect(std.warn).toMatchInlineSnapshot(` -"▲ [WARNING] Beginning log collection requires restarting the Durable Objects associated with durable-object--websocket--response. Any WebSocket connections or other non-persisted state will be lost as part of this restart. + "▲ [WARNING] Beginning log collection requires restarting the Durable Objects associated with durable-object--websocket--response. Any WebSocket connections or other non-persisted state will be lost as part of this restart. -" -`); + " + `); expect(std.err).toMatchInlineSnapshot(`""`); }); it("creates and then delete tails", async () => { @@ -503,10 +504,31 @@ describe("tail", () => { ) .replace(mockTailExpiration.toISOString(), "[mock expiration date]") ).toMatchInlineSnapshot(` - "Successfully created tail, expires at [mock expiration date] - Connected to test-worker, waiting for logs... - Email from:${mockEmailEventFrom} to:${mockEmailEventTo} size:${mockEmailEventSize} @ [mock event timestamp] - Ok" - `); + "Successfully created tail, expires at [mock expiration date] + Connected to test-worker, waiting for logs... + Email from:from@example.com to:to@example.com size:45416 @ [mock event timestamp] - Ok" + `); + }); + + it("logs tail overload message", async () => { + const api = mockWebsocketAPIs(); + await runWrangler("tail test-worker --format pretty"); + + const event = generateTailInfo(); + const message = generateMockEventMessage({ event }); + const serializedMessage = serialize(message); + + api.ws.send(serializedMessage); + expect( + std.out.replace( + mockTailExpiration.toISOString(), + "[mock expiration date]" + ) + ).toMatchInlineSnapshot(` + "Successfully created tail, expires at [mock expiration date] + Connected to test-worker, waiting for logs... + Tail is currently in sampling mode due to the high volume of messages. To prevent messages from being dropped consider adding filters." + `); }); it("should not crash when the tail message has a void event", async () => { @@ -675,6 +697,7 @@ function isRequest( | RequestEvent | AlarmEvent | EmailEvent + | TailInfo | undefined | null ): event is RequestEvent { @@ -956,3 +979,11 @@ function generateMockEmailEvent(opts?: Partial): EmailEvent { rawSize: opts?.rawSize || mockEmailEventSize, }; } + +function generateTailInfo(): TailInfo { + return { + message: + "Tail is currently in sampling mode due to the high volume of messages. To prevent messages from being dropped consider adding filters.", + type: "overload", + }; +} diff --git a/packages/wrangler/src/tail/createTail.ts b/packages/wrangler/src/tail/createTail.ts index bd447a98dd1e..89d470726155 100644 --- a/packages/wrangler/src/tail/createTail.ts +++ b/packages/wrangler/src/tail/createTail.ts @@ -252,6 +252,7 @@ export type TailEventMessage = { | ScheduledEvent | AlarmEvent | EmailEvent + | TailInfo | undefined | null; }; @@ -404,3 +405,11 @@ export type EmailEvent = { */ rawSize: number; }; + +/** + * Message from tail with information about the tail itself + */ +export type TailInfo = { + message: string; + type: string; +}; diff --git a/packages/wrangler/src/tail/printing.ts b/packages/wrangler/src/tail/printing.ts index 43d1bf5a2708..abf609a28f4f 100644 --- a/packages/wrangler/src/tail/printing.ts +++ b/packages/wrangler/src/tail/printing.ts @@ -1,9 +1,11 @@ +import chalk from "chalk"; import { logger } from "../logger"; import type { AlarmEvent, EmailEvent, RequestEvent, ScheduledEvent, + TailInfo, TailEventMessage, } from "./createTail"; import type { Outcome } from "./filters"; @@ -48,6 +50,10 @@ export function prettyPrintLogs(data: WebSocket.RawData): void { ).toLocaleString(); logger.log(`Alarm @ ${datetime} - ${outcome}`); + } else if (isTailInfo(eventMessage.event)) { + if (eventMessage.event.type === "overload") { + logger.log(`${chalk.red.bold(eventMessage.event.message)}`); + } } else { // Unknown event type const outcome = prettifyOutcome(eventMessage.outcome); @@ -103,6 +109,10 @@ function isAlarmEvent(event: TailEventMessage["event"]): event is AlarmEvent { return Boolean(event && "scheduledTime" in event && !("cron" in event)); } +function isTailInfo(event: TailEventMessage["event"]): event is TailInfo { + return Boolean(event && "message" in event && "type" in event); +} + function prettifyOutcome(outcome: Outcome): string { switch (outcome) { case "ok":