mirror of
https://github.com/supabase/supabase.git
synced 2026-10-08 19:05:06 +03:00
With the unified logs preview on, an edge function's Logs tab renders the unified logs view scoped to that function: its invocations and runtime output in one list. - UnifiedLogs takes a `scope` prop. A scoped view drops the filter sidebar and the user filter, and only offers the date, log type, level and message filters - The Invocations tab and its shortcut are hidden, and old Invocations links redirect to Logs with their time range and selected log - getEdgeFunctionLogsUrl builds links into the scoped tab; invocation chart clicks use it Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
410 lines
14 KiB
TypeScript
410 lines
14 KiB
TypeScript
import {
|
|
createParser,
|
|
parseAsArrayOf,
|
|
parseAsBoolean,
|
|
parseAsInteger,
|
|
parseAsString,
|
|
parseAsStringLiteral,
|
|
parseAsTimestamp,
|
|
} from 'nuqs'
|
|
|
|
import {
|
|
RANGE_DELIMITER,
|
|
SLIDER_DELIMITER,
|
|
SORT_DELIMITER,
|
|
} from '@/components/ui/DataTable/DataTable.constants'
|
|
|
|
export const REGIONS = ['ams', 'fra', 'gru', 'hkg', 'iad', 'syd'] as const
|
|
export const METHODS = ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'] as const
|
|
export const LOG_TYPES_LABELS = {
|
|
edge: 'API Gateway',
|
|
postgres: 'Postgres',
|
|
postgrest: 'PostgREST',
|
|
auth: 'Auth',
|
|
storage: 'Storage',
|
|
'edge function': 'Edge Function',
|
|
'edge function runtime': 'Edge Function runtime',
|
|
realtime: 'Realtime',
|
|
supavisor: 'Supavisor',
|
|
pgbouncer: 'PgBouncer',
|
|
multigres: 'Multigres',
|
|
compute: 'Compute',
|
|
}
|
|
|
|
type LogType = keyof typeof LOG_TYPES_LABELS
|
|
export const LOG_TYPES = Object.keys(LOG_TYPES_LABELS) as [LogType, ...LogType[]]
|
|
export const DEFAULT_LOG_TYPES = ['postgres', 'edge'] as const
|
|
// An edge function's invocations plus the runtime output (console, boot, shutdown) they produce.
|
|
// These are the only log types a function-scoped view queries or offers as filters.
|
|
export const EDGE_FUNCTION_LOG_TYPES = [
|
|
'edge function',
|
|
'edge function runtime',
|
|
] as const satisfies readonly LogType[]
|
|
// Filters a function-scoped view offers: the time range, message search and severity its old
|
|
// Invocations and Logs tabs had, plus log type to tell invocations and runtime output apart.
|
|
export const EDGE_FUNCTION_FILTER_FIELDS = ['date', 'log_type', 'level', 'event_message'] as const
|
|
|
|
export const LOG_TYPE_TO_SOURCE: Record<Exclude<LogType, 'compute'>, string> = {
|
|
edge: 'edge_logs',
|
|
postgrest: 'postgrest_logs',
|
|
storage: 'storage_logs',
|
|
postgres: 'postgres_logs',
|
|
'edge function': 'function_edge_logs',
|
|
'edge function runtime': 'function_logs',
|
|
auth: 'auth_logs',
|
|
realtime: 'realtime_logs',
|
|
supavisor: 'supavisor_logs',
|
|
pgbouncer: 'pgbouncer_logs',
|
|
multigres: 'multigres_logs',
|
|
}
|
|
|
|
const parseAsSort = createParser({
|
|
parse(queryValue: string) {
|
|
const [id, desc] = queryValue.split(SORT_DELIMITER)
|
|
if (!id && !desc) return null
|
|
return { id, desc: desc === 'desc' }
|
|
},
|
|
serialize(value: { id: string; desc: boolean }) {
|
|
return `${value.id}.${value.desc ? 'desc' : 'asc'}`
|
|
},
|
|
})
|
|
|
|
export const SEARCH_PARAMS_PARSER = {
|
|
// Equality filters. Repeatable `?filter=column:opAbbrev:value` (e.g. `level:eq:info`,
|
|
// `host:neq:foo`). Parsed with the helpers in `UnifiedLogs.filters.ts`.
|
|
filter: parseAsArrayOf(parseAsString),
|
|
|
|
// Range/special filters keep their dedicated keys — their semantics are inherently
|
|
// multi-value (sliders, time ranges) and don't fit the eq/neq model.
|
|
latency: parseAsArrayOf(parseAsInteger, SLIDER_DELIMITER),
|
|
'timing.dns': parseAsArrayOf(parseAsInteger, SLIDER_DELIMITER),
|
|
'timing.connection': parseAsArrayOf(parseAsInteger, SLIDER_DELIMITER),
|
|
'timing.tls': parseAsArrayOf(parseAsInteger, SLIDER_DELIMITER),
|
|
'timing.ttfb': parseAsArrayOf(parseAsInteger, SLIDER_DELIMITER),
|
|
'timing.transfer': parseAsArrayOf(parseAsInteger, SLIDER_DELIMITER),
|
|
date: parseAsArrayOf(parseAsTimestamp, RANGE_DELIMITER),
|
|
|
|
// REQUIRED FOR SORTING & PAGINATION
|
|
sort: parseAsSort,
|
|
size: parseAsInteger.withDefault(40),
|
|
start: parseAsInteger.withDefault(0),
|
|
|
|
// REQUIRED FOR INFINITE SCROLLING (Live Mode and Load More)
|
|
direction: parseAsStringLiteral(['prev', 'next']).withDefault('next'),
|
|
cursor: parseAsTimestamp.withDefault(new Date()),
|
|
live: parseAsBoolean.withDefault(false),
|
|
|
|
uuid: parseAsString,
|
|
id: parseAsString,
|
|
|
|
// View options
|
|
show_connection_logs: parseAsBoolean.withDefault(true),
|
|
edge_auth: parseAsBoolean.withDefault(true),
|
|
edge_storage: parseAsBoolean.withDefault(true),
|
|
edge_postgrest: parseAsBoolean.withDefault(true),
|
|
|
|
// Support searching for user against user ID
|
|
// See userAttributionCondition in UnifiedLogs.queries.ts.
|
|
user: parseAsString,
|
|
}
|
|
|
|
const POSTGRES_STATUS_CODE_LABELS = {
|
|
'00000': 'Successful Completion',
|
|
'01000': 'Warning',
|
|
'0100C': 'Dynamic Result Sets Returned',
|
|
'01008': 'Implicit Zero Bit Padding',
|
|
'01003': 'Null Value Eliminated In Set Function',
|
|
'01007': 'Privilege Not Granted',
|
|
'01006': 'Privilege Not Revoked',
|
|
'01004': 'String Data Right Truncation',
|
|
'01P01': 'Deprecated Feature',
|
|
'02000': 'No Data',
|
|
'02001': 'No Additional Dynamic Result Sets Returned',
|
|
'03000': 'SQL Statement Not Yet Complete',
|
|
'08000': 'Connection Exception',
|
|
'08003': 'Connection Does Not Exist',
|
|
'08006': 'Connection Failure',
|
|
'08001': 'SQL Client Unable To Establish SQL Connection',
|
|
'08004': 'SQL Server Rejected Establishment Of SQL Connection',
|
|
'08007': 'Transaction Resolution Unknown',
|
|
'08P01': 'Protocol Violation',
|
|
'09000': 'Triggered Action Exception',
|
|
'0A000': 'Feature Not Supported',
|
|
'0B000': 'Invalid Transaction Initiation',
|
|
'0F000': 'Locator Exception',
|
|
'0F001': 'Invalid Locator Specification',
|
|
'0L000': 'Invalid Grantor',
|
|
'0LP01': 'Invalid Grant Operation',
|
|
'0P000': 'Invalid Role Specification',
|
|
'0Z000': 'Diagnostics Exception',
|
|
'0Z002': 'Stacked Diagnostics Accessed Without Active Handler',
|
|
'20000': 'Case Not Found',
|
|
'21000': 'Cardinality Violation',
|
|
'22000': 'Data Exception',
|
|
'2202E': 'Array Subscript Error',
|
|
'22021': 'Character Not In Repertoire',
|
|
'22008': 'Datetime Field Overflow',
|
|
'22012': 'Division By Zero',
|
|
'22005': 'Error In Assignment',
|
|
'2200B': 'Escape Character Conflict',
|
|
'22022': 'Indicator Overflow',
|
|
'22015': 'Interval Field Overflow',
|
|
'2201E': 'Invalid Argument For Logarithm',
|
|
'22014': 'Invalid Argument For Ntile Function',
|
|
'22016': 'Invalid Argument For Nth Value Function',
|
|
'2201F': 'Invalid Argument For Power Function',
|
|
'2201G': 'Invalid Argument For Width Bucket Function',
|
|
'22018': 'Invalid Character Value For Cast',
|
|
'22007': 'Invalid Datetime Format',
|
|
'22019': 'Invalid Escape Character',
|
|
'2200D': 'Invalid Escape Octet',
|
|
'22025': 'Invalid Escape Sequence',
|
|
'22P06': 'Nonstandard Use Of Escape Character',
|
|
'22010': 'Invalid Indicator Parameter Value',
|
|
'22023': 'Invalid Parameter Value',
|
|
'2201B': 'Invalid Regular Expression',
|
|
'2201W': 'Invalid Row Count In Limit Clause',
|
|
'2201X': 'Invalid Row Count In Result Offset Clause',
|
|
'22009': 'Invalid Time Zone Displacement Value',
|
|
'2200C': 'Invalid Use Of Escape Character',
|
|
'2200G': 'Most Specific Type Mismatch',
|
|
'22004': 'Null Value Not Allowed',
|
|
'22002': 'Null Value No Indicator Parameter',
|
|
'22003': 'Numeric Value Out Of Range',
|
|
'22026': 'String Data Length Mismatch',
|
|
'22001': 'String Data Right Truncation',
|
|
'22011': 'Substring Error',
|
|
'22027': 'Trim Error',
|
|
'22024': 'Unterminated C String',
|
|
'2200F': 'Zero Length Character String',
|
|
'22P01': 'Floating Point Exception',
|
|
'22P02': 'Invalid Text Representation',
|
|
'22P03': 'Invalid Binary Representation',
|
|
'22P04': 'Bad Copy File Format',
|
|
'22P05': 'Untranslatable Character',
|
|
'2200L': 'Not An XML Document',
|
|
'2200M': 'Invalid XML Document',
|
|
'2200N': 'Invalid XML Content',
|
|
'2200S': 'Invalid XML Comment',
|
|
'2200T': 'Invalid XML Processing Instruction',
|
|
'23000': 'Integrity Constraint Violation',
|
|
'23001': 'Restrict Violation',
|
|
'23502': 'Not Null Violation',
|
|
'23503': 'Foreign Key Violation',
|
|
'23505': 'Unique Violation',
|
|
'23514': 'Check Violation',
|
|
'23P01': 'Exclusion Violation',
|
|
'24000': 'Invalid Cursor State',
|
|
'25000': 'Invalid Transaction State',
|
|
'25001': 'Active SQL Transaction',
|
|
'25002': 'Branch Transaction Already Active',
|
|
'25008': 'Held Cursor Requires Same Isolation Level',
|
|
'25003': 'Inappropriate Access Mode For Branch Transaction',
|
|
'25004': 'Inappropriate Isolation Level For Branch Transaction',
|
|
'25005': 'No Active SQL Transaction For Branch Transaction',
|
|
'25006': 'Read Only SQL Transaction',
|
|
'25007': 'Schema And Data Statement Mixing Not Supported',
|
|
'25P01': 'No Active SQL Transaction',
|
|
'25P02': 'In Failed SQL Transaction',
|
|
'25P03': 'Idle In Transaction Session Timeout',
|
|
'26000': 'Invalid SQL Statement Name',
|
|
'27000': 'Triggered Data Change Violation',
|
|
'28000': 'Invalid Authorization Specification',
|
|
'28P01': 'Invalid Password',
|
|
'2B000': 'Dependent Privilege Descriptors Still Exist',
|
|
'2BP01': 'Dependent Objects Still Exist',
|
|
'2D000': 'Invalid Transaction Termination',
|
|
'2F000': 'SQL Routine Exception',
|
|
'2F005': 'Function Executed No Return Statement',
|
|
'2F002': 'Modifying SQL Data Not Permitted',
|
|
'2F003': 'Prohibited SQL Statement Attempted',
|
|
'2F004': 'Reading SQL Data Not Permitted',
|
|
'34000': 'Invalid Cursor Name',
|
|
'38000': 'External Routine Exception',
|
|
'38001': 'Containing SQL Not Permitted',
|
|
'38002': 'Modifying SQL Data Not Permitted',
|
|
'38003': 'Prohibited SQL Statement Attempted',
|
|
'38004': 'Reading SQL Data Not Permitted',
|
|
'39000': 'External Routine Invocation Exception',
|
|
'39001': 'Invalid SQLSTATE Returned',
|
|
'39004': 'Null Value Not Allowed',
|
|
'39P01': 'Trigger Protocol Violated',
|
|
'39P02': 'SRF Protocol Violated',
|
|
'39P03': 'Event Trigger Protocol Violated',
|
|
'3B000': 'Savepoint Exception',
|
|
'3B001': 'Invalid Savepoint Specification',
|
|
'3D000': 'Invalid Catalog Name',
|
|
'3F000': 'Invalid Schema Name',
|
|
'40000': 'Transaction Rollback',
|
|
'40002': 'Transaction Integrity Constraint Violation',
|
|
'40001': 'Serialization Failure',
|
|
'40003': 'Statement Completion Unknown',
|
|
'40P01': 'Deadlock Detected',
|
|
'42000': 'Syntax Error Or Access Rule Violation',
|
|
'42601': 'Syntax Error',
|
|
'42501': 'Insufficient Privilege',
|
|
'42846': 'Cannot Coerce',
|
|
'42803': 'Grouping Error',
|
|
'42P20': 'Windowing Error',
|
|
'42P19': 'Invalid Recursion',
|
|
'42830': 'Invalid Foreign Key',
|
|
'42602': 'Invalid Name',
|
|
'42622': 'Name Too Long',
|
|
'42939': 'Reserved Name',
|
|
'42804': 'Datatype Mismatch',
|
|
'42P18': 'Indeterminate Datatype',
|
|
'42809': 'Wrong Object Type',
|
|
'428C9': 'Generated Always',
|
|
'42703': 'Undefined Column',
|
|
'42883': 'Undefined Function',
|
|
'42P01': 'Undefined Table',
|
|
'42P02': 'Undefined Parameter',
|
|
'42704': 'Undefined Object',
|
|
'42701': 'Duplicate Column',
|
|
'42P03': 'Duplicate Cursor',
|
|
'42P04': 'Duplicate Database',
|
|
'42723': 'Duplicate Function',
|
|
'42P05': 'Duplicate Prepared Statement',
|
|
'42P06': 'Duplicate Schema',
|
|
'42P07': 'Duplicate Table',
|
|
'42712': 'Duplicate Alias',
|
|
'42710': 'Duplicate Object',
|
|
'42702': 'Ambiguous Column',
|
|
'42725': 'Ambiguous Function',
|
|
'42P08': 'Ambiguous Parameter',
|
|
'42P09': 'Ambiguous Alias',
|
|
'42P10': 'Invalid Column Reference',
|
|
'42611': 'Invalid Column Definition',
|
|
'42P11': 'Invalid Cursor Definition',
|
|
'42P12': 'Invalid Database Definition',
|
|
'42P13': 'Invalid Function Definition',
|
|
'42P14': 'Invalid Prepared Statement Definition',
|
|
'42P15': 'Invalid Schema Definition',
|
|
'42P16': 'Invalid Table Definition',
|
|
'42P17': 'Invalid Object Definition',
|
|
'44000': 'With Check Option Violation',
|
|
'53000': 'Insufficient Resources',
|
|
'53100': 'Disk Full',
|
|
'53200': 'Out Of Memory',
|
|
'53300': 'Too Many Connections',
|
|
'53400': 'Configuration Limit Exceeded',
|
|
'54000': 'Program Limit Exceeded',
|
|
'54001': 'Statement Too Complex',
|
|
'54011': 'Too Many Columns',
|
|
'54023': 'Too Many Arguments',
|
|
'55000': 'Object Not In Prerequisite State',
|
|
'55006': 'Object In Use',
|
|
'55P02': "Can't Change Runtime Param",
|
|
'55P03': 'Lock Not Available',
|
|
'55P04': 'Unsafe New Enum Value Usage',
|
|
'57000': 'Operator Intervention',
|
|
'57014': 'Query Canceled',
|
|
'57P01': 'Admin Shutdown',
|
|
'57P02': 'Crash Shutdown',
|
|
'57P03': 'Cannot Connect Now',
|
|
'57P04': 'Database Dropped',
|
|
'58000': 'System Error',
|
|
'58030': 'IO Error',
|
|
'58P01': 'Undefined File',
|
|
'58P02': 'Duplicate File',
|
|
F0000: 'Config File Error',
|
|
F0001: 'Lock File Exists',
|
|
HV000: 'FDW Error',
|
|
HV005: 'FDW Column Name Not Found',
|
|
HV002: 'FDW Dynamic Parameter Value Needed',
|
|
HV010: 'FDW Function Sequence Error',
|
|
HV021: 'FDW Inconsistent Data',
|
|
HV024: 'FDW Invalid Attribute Value',
|
|
HV007: 'FDW Invalid Column Name',
|
|
HV008: 'FDW Invalid Column Number',
|
|
HV004: 'FDW Invalid Data Type',
|
|
HV006: 'FDW Invalid Data Type Descriptors',
|
|
HV091: 'FDW Invalid Handle',
|
|
HV00B: 'FDW Invalid Option Index',
|
|
HV00C: 'FDW Invalid Option Name',
|
|
HV00D: 'FDW Invalid String Length Or Buffer Length',
|
|
HV090: 'FDW Invalid String Format',
|
|
HV00A: 'FDW Invalid Use Of Null Pointer',
|
|
HV009: 'FDW Too Many Handles',
|
|
HV014: 'FDW Out Of Memory',
|
|
HV001: 'FDW Unsupported Function',
|
|
P0000: 'PL/pgSQL Error',
|
|
P0001: 'Raise Exception',
|
|
P0002: 'No Data Found',
|
|
P0003: 'Too Many Rows',
|
|
P0004: 'Assert Failure',
|
|
XX000: 'Internal Error',
|
|
XX001: 'Data Corrupted',
|
|
XX002: 'Index Corrupted',
|
|
}
|
|
|
|
const HTTP_STATUS_CODE_LABELS = {
|
|
'100': 'Continue',
|
|
'101': 'Switching Protocols',
|
|
'102': 'Processing',
|
|
'103': 'Early Hints',
|
|
'200': 'OK',
|
|
'201': 'Created',
|
|
'202': 'Accepted',
|
|
'203': 'Non-Authoritative Information',
|
|
'204': 'No Content',
|
|
'205': 'Reset Content',
|
|
'206': 'Partial Content',
|
|
'207': 'Multi-Status',
|
|
'208': 'Already Reported',
|
|
'226': 'IM Used',
|
|
'300': 'Multiple Choices',
|
|
'301': 'Moved Permanently',
|
|
'302': 'Found',
|
|
'303': 'See Other',
|
|
'304': 'Not Modified',
|
|
'305': 'Use Proxy',
|
|
'307': 'Temporary Redirect',
|
|
'308': 'Permanent Redirect',
|
|
'400': 'Bad Request',
|
|
'401': 'Unauthorized',
|
|
'402': 'Payment Required',
|
|
'403': 'Forbidden',
|
|
'404': 'Not Found',
|
|
'405': 'Method Not Allowed',
|
|
'406': 'Not Acceptable',
|
|
'407': 'Proxy Authentication Required',
|
|
'408': 'Request Timeout',
|
|
'409': 'Conflict',
|
|
'410': 'Gone',
|
|
'411': 'Length Required',
|
|
'412': 'Precondition Failed',
|
|
'413': 'Payload Too Large',
|
|
'414': 'URI Too Long',
|
|
'415': 'Unsupported Media Type',
|
|
'416': 'Range Not Satisfiable',
|
|
'417': 'Expectation Failed',
|
|
'418': "I'm a teapot",
|
|
'421': 'Misdirected Request',
|
|
'422': 'Unprocessable Entity',
|
|
'423': 'Locked',
|
|
'424': 'Failed Dependency',
|
|
'425': 'Too Early',
|
|
'426': 'Upgrade Required',
|
|
'428': 'Precondition Required',
|
|
'429': 'Too Many Requests',
|
|
'431': 'Request Header Fields Too Large',
|
|
'451': 'Unavailable For Legal Reasons',
|
|
'500': 'Internal Server Error',
|
|
'501': 'Not Implemented',
|
|
'502': 'Bad Gateway',
|
|
'503': 'Service Unavailable',
|
|
'504': 'Gateway Timeout',
|
|
'505': 'HTTP Version Not Supported',
|
|
'506': 'Variant Also Negotiates',
|
|
'507': 'Insufficient Storage',
|
|
'508': 'Loop Detected',
|
|
'510': 'Not Extended',
|
|
'511': 'Network Authentication Required',
|
|
}
|
|
|
|
export const STATUS_CODE_LABELS = {
|
|
...HTTP_STATUS_CODE_LABELS,
|
|
...POSTGRES_STATUS_CODE_LABELS,
|
|
}
|