mirror of
https://github.com/supabase/supabase.git
synced 2026-09-09 03:19:36 +08:00
## Problem Unified Logs does not expose Workers logs, so users cannot search Workers ingress, runtime, or build events alongside other services. ## Fix Add a Workers log type that classifies all three Workers OTEL streams. Gate the option and any persisted Workers filters with the existing Workers feature flag. ## How to test - Enable the Workers feature flag and open Unified Logs. - Select Workers from the Log Type filter. - Expected result: Unified Logs shows ingress, runtime, and build events with the Workers icon. - Disable the Workers feature flag and load a URL containing `log_type:eq:workers`. - Expected result: the Workers option and filter are removed, and Workers logs are not queried. - Run `./node_modules/.bin/vitest --run components/interfaces/UnifiedLogs/UnifiedLogs.queries.test.ts components/interfaces/UnifiedLogs/UnifiedLogs.utils.test.ts data/workers/worker-logs-query.test.ts` from `apps/studio`. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added Workers as a selectable log type in Unified Logs. * Unified Logs now combines worker ingress, guest, and API streams under the Workers category. * Added a dedicated Workers icon and worker log filtering. * **Improvements** * Worker filters and URL parameters respect feature availability. * Worker details show relevant metadata while omitting unavailable HTTP fields. * Improved handling of worker log levels, statuses, and raw data. * Added stronger validation for unified log data. * **Tests** * Added coverage for worker routing, filtering, feature visibility, parsing, and metadata redaction. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
84 lines
2.4 KiB
TypeScript
84 lines
2.4 KiB
TypeScript
import { z } from 'zod'
|
|
|
|
import { LOG_TYPES, METHODS, REGIONS } from './UnifiedLogs.constants'
|
|
import {
|
|
ARRAY_DELIMITER,
|
|
LEVELS,
|
|
RANGE_DELIMITER,
|
|
} from '@/components/ui/DataTable/DataTable.constants'
|
|
|
|
export const columnSchema = z.object({
|
|
id: z.string(),
|
|
log_type: z.enum(LOG_TYPES),
|
|
method: z.enum(METHODS).nullable(),
|
|
pathname: z.string().nullable(),
|
|
level: z.enum(LEVELS).nullable(),
|
|
status: z.number().nullable(),
|
|
date: z.date(),
|
|
timestamp: z.number(),
|
|
event_message: z.string().optional(),
|
|
log_count: z.number().optional(), // used to count function logs for a given execution_id
|
|
logs: z.array(z.any()).optional(), // array of function logs
|
|
auth_user: z.string().nullable().optional(),
|
|
metadata: z.record(z.string(), z.unknown()).nullable().optional(),
|
|
})
|
|
|
|
export type ColumnSchema = z.infer<typeof columnSchema>
|
|
|
|
export const columnFilterSchema = z.object({
|
|
level: z
|
|
.string()
|
|
.transform((val) => val.split(ARRAY_DELIMITER))
|
|
.pipe(z.enum(LEVELS).array())
|
|
.optional(),
|
|
method: z
|
|
.string()
|
|
.transform((val) => val.split(ARRAY_DELIMITER))
|
|
.pipe(z.enum(METHODS).array())
|
|
.optional(),
|
|
pathname: z.string().optional(),
|
|
status: z
|
|
.string()
|
|
.transform((val) => val.split(ARRAY_DELIMITER))
|
|
.pipe(z.string().array())
|
|
.optional(),
|
|
regions: z
|
|
.string()
|
|
.transform((val) => val.split(ARRAY_DELIMITER))
|
|
.pipe(z.enum(REGIONS).array())
|
|
.optional(),
|
|
date: z
|
|
.string()
|
|
.transform((val) => val.split(RANGE_DELIMITER).map(Number))
|
|
.pipe(z.coerce.date().array())
|
|
.optional(),
|
|
auth_user: z.string().optional(),
|
|
})
|
|
|
|
export type ColumnFilterSchema = z.infer<typeof columnFilterSchema>
|
|
|
|
export const facetMetadataSchema = z.object({
|
|
rows: z.array(z.object({ value: z.any(), total: z.number() })),
|
|
total: z.number(),
|
|
min: z.number().optional(),
|
|
max: z.number().optional(),
|
|
})
|
|
|
|
export type FacetMetadataSchema = z.infer<typeof facetMetadataSchema>
|
|
|
|
export type BaseChartSchema = { timestamp: number; [key: string]: number }
|
|
|
|
export const timelineChartSchema = z.object({
|
|
timestamp: z.number(), // UNIX
|
|
...LEVELS.reduce(
|
|
(acc, level) => ({
|
|
...acc,
|
|
[level]: z.number().default(0),
|
|
}),
|
|
{} as Record<(typeof LEVELS)[number], z.ZodNumber>
|
|
),
|
|
// REMINDER: make sure to have the `timestamp` field in the object
|
|
}) satisfies z.ZodType<BaseChartSchema>
|
|
|
|
export type TimelineChartSchema = z.infer<typeof timelineChartSchema>
|