Skip to content

Commit 6874aa9

Browse files
authored
[wrangler] Add Issues observability configuration (#15684)
1 parent 2b39fc2 commit 6874aa9

11 files changed

Lines changed: 117 additions & 4 deletions

File tree

‎.changeset/brave-issues-observe.md‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
"@cloudflare/config": minor
3+
"@cloudflare/workers-utils": minor
4+
"wrangler": minor
5+
---
6+
7+
Add support for configuring real-time Issues with `observability.issues.enabled`
8+
9+
Wrangler now validates and uploads the Issues setting alongside the existing logs and traces observability options. The experimental configuration format supports the equivalent `observability.issues.enabled` option.

‎packages/config/src/__tests__/convert.test.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ describe("convertToWranglerConfig", () => {
5656
enabled: true,
5757
headSamplingRate: 0.5,
5858
redactQueryString: true,
59+
issues: { enabled: true },
5960
logs: {
6061
enabled: true,
6162
headSamplingRate: 0.25,
@@ -75,6 +76,7 @@ describe("convertToWranglerConfig", () => {
7576
enabled: true,
7677
head_sampling_rate: 0.5,
7778
redact_query_string: true,
79+
issues: { enabled: true },
7880
logs: {
7981
enabled: true,
8082
head_sampling_rate: 0.25,

‎packages/config/src/convert.ts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,9 @@ function convertObservability(
262262
if (observability.redactQueryString !== undefined) {
263263
out.redact_query_string = observability.redactQueryString;
264264
}
265+
if (observability.issues !== undefined) {
266+
out.issues = { enabled: observability.issues.enabled };
267+
}
265268
if (observability.logs !== undefined) {
266269
const logs: NonNullable<NonNullable<RawConfig["observability"]>["logs"]> =
267270
{};

‎packages/config/src/schema.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,7 @@ const ObservabilitySchema = z.strictObject({
636636
enabled: z.boolean().optional(),
637637
headSamplingRate: z.number().optional(),
638638
redactQueryString: z.boolean().optional(),
639+
issues: z.strictObject({ enabled: z.boolean().optional() }).optional(),
639640
logs: z
640641
.strictObject({
641642
enabled: z.boolean().optional(),

‎packages/config/src/types.ts‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,11 @@ export interface WorkerConfig {
503503
* @default false
504504
*/
505505
redactQueryString?: boolean;
506+
/** Real-time Issues settings for this Worker. */
507+
issues?: {
508+
/** Whether real-time Issues are enabled. */
509+
enabled?: boolean;
510+
};
506511
logs?: {
507512
enabled?: boolean;
508513
/** The sampling rate. */

‎packages/workers-utils/src/config/environment.ts‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1915,6 +1915,11 @@ export interface Observability {
19151915
* @default false
19161916
*/
19171917
redact_query_string?: boolean;
1918+
/** Real-time Issues settings for this Worker. */
1919+
issues?: {
1920+
/** Whether real-time Issues are enabled. */
1921+
enabled?: boolean;
1922+
};
19181923
logs?: {
19191924
enabled?: boolean;
19201925
/** The sampling rate */

‎packages/workers-utils/src/config/validation.ts‎

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7274,7 +7274,7 @@ const validateObservability: ValidatorFn = (diagnostics, field, value) => {
72747274
let isValid = true;
72757275

72767276
/**
7277-
* One of observability.enabled, observability.logs.enabled, observability.traces.enabled must be defined
7277+
* At least one observability feature's enabled flag must be defined.
72787278
*/
72797279
isValid =
72807280
validateAtLeastOnePropertyRequired(diagnostics, field, [
@@ -7293,6 +7293,11 @@ const validateObservability: ValidatorFn = (diagnostics, field, value) => {
72937293
value: val.traces?.enabled,
72947294
type: "boolean",
72957295
},
7296+
{
7297+
key: "issues.enabled",
7298+
value: val.issues?.enabled,
7299+
type: "boolean",
7300+
},
72967301
]) && isValid;
72977302

72987303
isValid =
@@ -7313,6 +7318,18 @@ const validateObservability: ValidatorFn = (diagnostics, field, value) => {
73137318
"boolean"
73147319
) && isValid;
73157320

7321+
const issuesIsObject =
7322+
val.issues === undefined ||
7323+
(val.issues !== null &&
7324+
typeof val.issues === "object" &&
7325+
!Array.isArray(val.issues));
7326+
if (!issuesIsObject) {
7327+
diagnostics.errors.push(
7328+
`"${field}.issues" should be an object but got ${JSON.stringify(val.issues)}.`
7329+
);
7330+
isValid = false;
7331+
}
7332+
73167333
isValid =
73177334
validateOptionalProperty(diagnostics, field, "logs", val.logs, "object") &&
73187335
isValid;
@@ -7331,10 +7348,29 @@ const validateObservability: ValidatorFn = (diagnostics, field, value) => {
73317348
"enabled",
73327349
"head_sampling_rate",
73337350
"redact_query_string",
7351+
"issues",
73347352
"logs",
73357353
"traces",
73367354
]) && isValid;
73377355

7356+
if (val.issues !== undefined && issuesIsObject) {
7357+
isValid =
7358+
validateOptionalProperty(
7359+
diagnostics,
7360+
`${field}.issues`,
7361+
"enabled",
7362+
val.issues.enabled,
7363+
"boolean"
7364+
) && isValid;
7365+
isValid =
7366+
validateAdditionalProperties(
7367+
diagnostics,
7368+
`${field}.issues`,
7369+
Object.keys(val.issues),
7370+
["enabled"]
7371+
) && isValid;
7372+
}
7373+
73387374
/**
73397375
* Validate the optional nested logs configuration
73407376
*/

‎packages/workers-utils/tests/config/validation/normalize-and-validate-config.test.ts‎

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1459,6 +1459,7 @@ describe("normalizeAndValidateConfig()", () => {
14591459
- Expected "observability.enabled" to be of type boolean but got "INVALID".
14601460
- Expected "observability.logs.enabled" to be of type boolean but got "INVALID".
14611461
- Expected "observability.traces.enabled" to be of type boolean but got "INVALID".
1462+
- Expected "observability.issues.enabled" to be of type boolean but got undefined.
14621463
- Expected "observability.head_sampling_rate" to be of type number but got "INVALID".
14631464
- Expected "observability.logs.enabled" to be of type boolean but got "INVALID".
14641465
- Expected "observability.logs.head_sampling_rate" to be of type number but got "INVALID".
@@ -12611,7 +12612,7 @@ describe("normalizeAndValidateConfig()", () => {
1261112612
expect(diagnostics.hasErrors()).toBe(true);
1261212613
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1261312614
"Processing wrangler configuration:
12614-
- "observability.enabled" or "observability.logs.enabled" or "observability.traces.enabled" is required.
12615+
- "observability.enabled" or "observability.logs.enabled" or "observability.traces.enabled" or "observability.issues.enabled" is required.
1261512616
- Expected "observability.head_sampling_rate" to be of type number but got true.
1261612617
- Expected "observability.redact_query_string" to be of type boolean but got "true"."
1261712618
`);
@@ -12633,6 +12634,25 @@ describe("normalizeAndValidateConfig()", () => {
1263312634
`);
1263412635
});
1263512636

12637+
it("should error if observability issues is null", ({ expect }) => {
12638+
const { diagnostics } = normalizeAndValidateConfig(
12639+
{
12640+
observability: { issues: null },
12641+
} as unknown as RawConfig,
12642+
undefined,
12643+
undefined,
12644+
{ env: undefined }
12645+
);
12646+
12647+
expect(diagnostics.hasWarnings()).toBe(false);
12648+
expect(diagnostics.hasErrors()).toBe(true);
12649+
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
12650+
"Processing wrangler configuration:
12651+
- "observability.enabled" or "observability.logs.enabled" or "observability.traces.enabled" or "observability.issues.enabled" is required.
12652+
- "observability.issues" should be an object but got null."
12653+
`);
12654+
});
12655+
1263612656
it("should not warn on full observability config", ({ expect }) => {
1263712657
const { diagnostics } = normalizeAndValidateConfig(
1263812658
{

‎packages/wrangler/src/__tests__/deploy/environments.test.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ describe("deploy", () => {
267267
enabled: true,
268268
head_sampling_rate: 0.5,
269269
redact_query_string: true,
270+
issues: { enabled: true },
270271
},
271272
});
272273
await fs.promises.writeFile("index.js", `export default {};`);
@@ -276,6 +277,7 @@ describe("deploy", () => {
276277
enabled: true,
277278
head_sampling_rate: 0.5,
278279
redact_query_string: true,
280+
issues: { enabled: true },
279281
},
280282
});
281283

‎packages/wrangler/src/__tests__/preview-config.test.ts‎

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,11 @@ describe("Preview configuration conversion", () => {
164164
}) => {
165165
expect(
166166
convertPreviewBaseToPreviewsConfig({
167-
observability: { enabled: true, logs: { enabled: false } },
167+
observability: {
168+
enabled: true,
169+
issues: { enabled: true },
170+
logs: { enabled: false },
171+
},
168172
logpush: false,
169173
limits: { subrequests: 100 },
170174
placement: { mode: "smart" },
@@ -179,7 +183,11 @@ describe("Preview configuration conversion", () => {
179183
} as Parameters<typeof convertPreviewBaseToPreviewsConfig>[0])
180184
).toEqual({
181185
config: {
182-
observability: { enabled: true, logs: { enabled: false } },
186+
observability: {
187+
enabled: true,
188+
issues: { enabled: true },
189+
logs: { enabled: false },
190+
},
183191
logpush: false,
184192
limits: { subrequests: 100 },
185193
placement: { mode: "smart" },
@@ -198,6 +206,22 @@ describe("Preview configuration conversion", () => {
198206
});
199207
});
200208

209+
test("copies an Issues-only Preview Base observability configuration", ({
210+
expect,
211+
}) => {
212+
expect(
213+
convertPreviewBaseToPreviewsConfig({
214+
observability: { issues: { enabled: true } },
215+
} as Parameters<typeof convertPreviewBaseToPreviewsConfig>[0])
216+
).toEqual({
217+
config: {
218+
observability: { issues: { enabled: true } },
219+
},
220+
messages: [],
221+
blockingDeploymentMessages: [],
222+
});
223+
});
224+
201225
test("returns one no-op outcome for ignored and incomplete bindings", ({
202226
expect,
203227
}) => {

0 commit comments

Comments
 (0)