mirror of
https://github.com/zyycn/codex-proxy-rs.git
synced 2026-11-06 16:06:08 +00:00
Consolidate request diagnostics into typed request_observation_json with migration 0025, preserving historical facts and query constraints. Use upstream response timestamps for output throughput, align TTFT event boundaries, and surface official timing metrics in the latency popover. Co-authored-by: Codex <noreply@openai.com>
444 lines
27 KiB
PL/PgSQL
444 lines
27 KiB
PL/PgSQL
-- 请求观测以类型化 JSON 保存,业务状态保留列,查询通过只读投影取值
|
|
create function model_request_observation_valid(document jsonb) returns boolean
|
|
language plpgsql immutable parallel safe as $$
|
|
declare
|
|
spec record;
|
|
item jsonb;
|
|
number numeric;
|
|
begin
|
|
if document is null or jsonb_typeof(document) <> 'object'
|
|
or octet_length(document::text) > 1048576 then
|
|
return false;
|
|
end if;
|
|
for spec in select * from (values
|
|
('{}'::text[], array['account','continuation','error','recovery','request','response','routing','scheduling','timings','transport']::text[]),
|
|
('{request}'::text[], array['clientIp','compact','configRevision','endpoint','protocol','reasoningEffort','reasoningPreset','subagentKind','userAgent']::text[]),
|
|
('{account}'::text[], array['authenticationKind','email','name']::text[]),
|
|
('{routing}'::text[], array['groupNamesSnapshot','groupRefs','scope']::text[]),
|
|
('{error}'::text[], array['message','providerErrorCode','retryAfterMs']::text[]),
|
|
('{timings}'::text[], array['local','upstream']::text[]),
|
|
('{timings,local}'::text[], array['connectMs','firstEventMs','firstReasoningMs','firstTextMs','firstTokenMs','headersMs','latencyMs','transportDecisionWaitMs']::text[]),
|
|
('{timings,upstream}'::text[], array['processingMs','responseMs','apiOverheadMs','engineMs','engineIapiTtftMs','engineServiceTtftMs','engineIapiTbtMs','engineServiceTbtMs']::text[]),
|
|
('{scheduling}'::text[], array['accountSelectionWaitMs','admissionDecisionMs','capacityTotalSlots','capacityUsedSlots']::text[]),
|
|
('{transport}'::text[], array['connection','httpVersion','websocketPool']::text[]),
|
|
('{transport,connection}'::text[], array['ageMs','exitReason','id','idleMs']::text[]),
|
|
('{response}'::text[], array['responseModel']::text[]),
|
|
('{continuation}'::text[], array['previousResponseIdHash','unavailableReason']::text[]),
|
|
('{recovery}'::text[], array['retryDelayMs','totalLatencyMs']::text[])) as groups(path, allowed_keys) loop
|
|
item := document #> spec.path;
|
|
if item is not null and (jsonb_typeof(item) <> 'object' or item - spec.allowed_keys <> '{}'::jsonb) then
|
|
return false;
|
|
end if;
|
|
end loop;
|
|
for spec in select * from (values
|
|
('{request,configRevision}'::text[], 'number'),
|
|
('{request,protocol}'::text[], 'string'),
|
|
('{request,endpoint}'::text[], 'string'),
|
|
('{account,name}'::text[], 'string'),
|
|
('{account,email}'::text[], 'string'),
|
|
('{account,authenticationKind}'::text[], 'string'),
|
|
('{routing,scope}'::text[], 'string'),
|
|
('{routing,groupRefs}'::text[], 'array'),
|
|
('{routing,groupNamesSnapshot}'::text[], 'array'),
|
|
('{error,providerErrorCode}'::text[], 'string'),
|
|
('{error,message}'::text[], 'string'),
|
|
('{error,retryAfterMs}'::text[], 'number'),
|
|
('{request,clientIp}'::text[], 'string'),
|
|
('{request,userAgent}'::text[], 'string'),
|
|
('{request,reasoningEffort}'::text[], 'string'),
|
|
('{request,reasoningPreset}'::text[], 'string'),
|
|
('{request,subagentKind}'::text[], 'string'),
|
|
('{request,compact}'::text[], 'boolean'),
|
|
('{timings,local,transportDecisionWaitMs}'::text[], 'number'),
|
|
('{timings,local,connectMs}'::text[], 'number'),
|
|
('{timings,local,headersMs}'::text[], 'number'),
|
|
('{timings,local,firstEventMs}'::text[], 'number'),
|
|
('{timings,local,firstReasoningMs}'::text[], 'number'),
|
|
('{timings,local,firstTextMs}'::text[], 'number'),
|
|
('{timings,local,firstTokenMs}'::text[], 'number'),
|
|
('{timings,local,latencyMs}'::text[], 'number'),
|
|
('{timings,upstream,processingMs}'::text[], 'number'),
|
|
('{timings,upstream,apiOverheadMs}'::text[], 'milliseconds'),
|
|
('{timings,upstream,engineMs}'::text[], 'milliseconds'),
|
|
('{timings,upstream,engineIapiTtftMs}'::text[], 'milliseconds'),
|
|
('{timings,upstream,engineServiceTtftMs}'::text[], 'milliseconds'),
|
|
('{timings,upstream,engineIapiTbtMs}'::text[], 'milliseconds'),
|
|
('{timings,upstream,engineServiceTbtMs}'::text[], 'milliseconds'),
|
|
('{scheduling,admissionDecisionMs}'::text[], 'number'),
|
|
('{scheduling,accountSelectionWaitMs}'::text[], 'number'),
|
|
('{scheduling,capacityUsedSlots}'::text[], 'number'),
|
|
('{scheduling,capacityTotalSlots}'::text[], 'number'),
|
|
('{transport,httpVersion}'::text[], 'string'),
|
|
('{transport,websocketPool}'::text[], 'string'),
|
|
('{transport,connection,id}'::text[], 'string'),
|
|
('{transport,connection,exitReason}'::text[], 'string'),
|
|
('{transport,connection,ageMs}'::text[], 'number'),
|
|
('{transport,connection,idleMs}'::text[], 'number'),
|
|
('{response,responseModel}'::text[], 'string'),
|
|
('{continuation,previousResponseIdHash}'::text[], 'string'),
|
|
('{continuation,unavailableReason}'::text[], 'string'),
|
|
('{recovery,retryDelayMs}'::text[], 'number'),
|
|
('{recovery,totalLatencyMs}'::text[], 'number'),
|
|
('{timings,upstream,responseMs}'::text[], 'number')) as fields(path, kind) loop
|
|
item := document #> spec.path;
|
|
if item is null or item = 'null'::jsonb then continue; end if;
|
|
if spec.kind = 'milliseconds' then
|
|
if jsonb_typeof(item) <> 'number' then return false; end if;
|
|
number := (item #>> '{}')::numeric;
|
|
if number < 0 or number > 9223372036854775807 then return false; end if;
|
|
continue;
|
|
end if;
|
|
if jsonb_typeof(item) <> spec.kind then return false; end if;
|
|
if spec.kind = 'number' then
|
|
number := (item #>> '{}')::numeric;
|
|
if item #>> '{}' !~ '^[0-9]+$' or number > 9223372036854775807 then return false; end if;
|
|
elsif spec.kind = 'array' then
|
|
if exists (select 1 from jsonb_array_elements(item) member where jsonb_typeof(member) <> 'string') then return false; end if;
|
|
end if;
|
|
end loop;
|
|
if (document #> '{request,configRevision}' is not null
|
|
and document #> '{request,configRevision}' <> 'null'::jsonb
|
|
and document #> '{request,compact}' in ('true'::jsonb, 'false'::jsonb)
|
|
and coalesce(length(document #>> '{request,protocol}'), 0) > 0
|
|
and coalesce(length(document #>> '{request,endpoint}'), 0) > 0
|
|
and document #>> '{routing,scope}' in ('legacy_provider', 'all', 'groups')
|
|
and jsonb_typeof(document #> '{routing,groupRefs}') = 'array'
|
|
and jsonb_typeof(document #> '{routing,groupNamesSnapshot}') = 'array') is not true then
|
|
return false;
|
|
end if;
|
|
if document #>> '{request,clientIp}' is not null then
|
|
perform (document #>> '{request,clientIp}')::inet;
|
|
end if;
|
|
return true;
|
|
exception when invalid_text_representation or numeric_value_out_of_range then
|
|
return false;
|
|
end;
|
|
$$;
|
|
|
|
alter table model_requests add column request_observation_json jsonb;
|
|
|
|
update model_requests set request_observation_json = jsonb_strip_nulls(jsonb_build_object(
|
|
'request', jsonb_build_object(
|
|
'configRevision', config_revision,
|
|
'protocol', protocol,
|
|
'endpoint', endpoint,
|
|
'clientIp', client_ip::text,
|
|
'userAgent', user_agent,
|
|
'reasoningEffort', reasoning_effort,
|
|
'reasoningPreset', reasoning_preset,
|
|
'subagentKind', subagent_kind,
|
|
'compact', compact),
|
|
'account', jsonb_build_object(
|
|
'name', provider_account_name_snapshot,
|
|
'email', provider_account_email_snapshot,
|
|
'authenticationKind', provider_account_authentication_kind_snapshot),
|
|
'routing', jsonb_build_object(
|
|
'scope', routing_scope,
|
|
'groupRefs', routing_group_refs,
|
|
'groupNamesSnapshot', routing_group_names_snapshot),
|
|
'error', jsonb_build_object(
|
|
'providerErrorCode', provider_error_code,
|
|
'message', error_message,
|
|
'retryAfterMs', retry_after_ms),
|
|
'timings', jsonb_build_object(
|
|
'local', jsonb_build_object(
|
|
'transportDecisionWaitMs', transport_decision_wait_ms,
|
|
'connectMs', connect_ms,
|
|
'headersMs', headers_ms,
|
|
'firstEventMs', first_event_ms,
|
|
'firstReasoningMs', first_reasoning_ms,
|
|
'firstTextMs', first_text_ms,
|
|
'firstTokenMs', first_token_ms,
|
|
'latencyMs', latency_ms),
|
|
'upstream', jsonb_build_object(
|
|
'processingMs', provider_processing_ms)),
|
|
'scheduling', jsonb_build_object(
|
|
'admissionDecisionMs', admission_decision_ms,
|
|
'accountSelectionWaitMs', account_selection_wait_ms,
|
|
'capacityUsedSlots', capacity_used_slots,
|
|
'capacityTotalSlots', capacity_total_slots),
|
|
'transport', jsonb_build_object(
|
|
'httpVersion', http_version,
|
|
'websocketPool', websocket_pool,
|
|
'connection', jsonb_build_object(
|
|
'id', upstream_connection_id,
|
|
'exitReason', upstream_connection_exit_reason,
|
|
'ageMs', upstream_connection_age_ms,
|
|
'idleMs', upstream_connection_idle_ms)),
|
|
'response', jsonb_build_object(
|
|
'responseModel', upstream_response_model),
|
|
'continuation', jsonb_build_object(
|
|
'previousResponseIdHash', continuation_previous_response_id_hash,
|
|
'unavailableReason', continuation_unavailable_reason),
|
|
'recovery', jsonb_build_object(
|
|
'retryDelayMs', recovery_retry_delay_ms,
|
|
'totalLatencyMs', recovery_total_latency_ms)));
|
|
|
|
alter table model_requests
|
|
alter column request_observation_json set not null,
|
|
drop constraint model_requests_revision_attempt_ck,
|
|
drop constraint model_requests_status_ck,
|
|
drop constraint model_requests_websocket_pool_ck,
|
|
drop constraint model_requests_routing_scope_ck,
|
|
drop constraint model_requests_routing_group_names_ck,
|
|
drop constraint model_requests_latency_ck,
|
|
drop constraint model_requests_runtime_pressure_ck,
|
|
drop constraint model_requests_continuation_hashes_ck,
|
|
drop constraint model_requests_continuation_reason_ck,
|
|
drop constraint model_requests_upstream_connection_ck,
|
|
drop constraint model_requests_recovery_ck,
|
|
drop constraint model_requests_fact_completeness_ck,
|
|
drop column config_revision,
|
|
drop column protocol,
|
|
drop column endpoint,
|
|
drop column provider_account_name_snapshot,
|
|
drop column provider_account_email_snapshot,
|
|
drop column provider_account_authentication_kind_snapshot,
|
|
drop column routing_scope,
|
|
drop column routing_group_refs,
|
|
drop column routing_group_names_snapshot,
|
|
drop column provider_error_code,
|
|
drop column error_message,
|
|
drop column retry_after_ms,
|
|
drop column client_ip,
|
|
drop column user_agent,
|
|
drop column reasoning_effort,
|
|
drop column reasoning_preset,
|
|
drop column subagent_kind,
|
|
drop column compact,
|
|
drop column transport_decision_wait_ms,
|
|
drop column connect_ms,
|
|
drop column headers_ms,
|
|
drop column first_event_ms,
|
|
drop column first_reasoning_ms,
|
|
drop column first_text_ms,
|
|
drop column first_token_ms,
|
|
drop column latency_ms,
|
|
drop column provider_processing_ms,
|
|
drop column admission_decision_ms,
|
|
drop column account_selection_wait_ms,
|
|
drop column capacity_used_slots,
|
|
drop column capacity_total_slots,
|
|
drop column http_version,
|
|
drop column websocket_pool,
|
|
drop column upstream_connection_id,
|
|
drop column upstream_connection_exit_reason,
|
|
drop column upstream_connection_age_ms,
|
|
drop column upstream_connection_idle_ms,
|
|
drop column upstream_response_model,
|
|
drop column continuation_previous_response_id_hash,
|
|
drop column continuation_unavailable_reason,
|
|
drop column recovery_retry_delay_ms,
|
|
drop column recovery_total_latency_ms;
|
|
|
|
alter table model_requests
|
|
add constraint model_requests_observation_shape_ck check (model_request_observation_valid(request_observation_json) is true),
|
|
add constraint model_requests_upstream_duration_ck check ((request_observation_json #>> '{timings,upstream,responseMs}')::bigint > 0),
|
|
add constraint model_requests_revision_attempt_ck check (
|
|
(request_observation_json #>> '{request,configRevision}')::bigint > 0 and attempt_count >= 0
|
|
),
|
|
add constraint model_requests_status_ck check (
|
|
(client_status_code is null or client_status_code between 100 and 599)
|
|
and (upstream_status_code is null or upstream_status_code between 100 and 599)
|
|
and ((request_observation_json #>> '{error,retryAfterMs}')::bigint is null or (request_observation_json #>> '{error,retryAfterMs}')::bigint >= 0)
|
|
),
|
|
add constraint model_requests_websocket_pool_ck check (
|
|
(request_observation_json #>> '{transport,websocketPool}') is null or (request_observation_json #>> '{transport,websocketPool}') in ('new', 'reuse')
|
|
),
|
|
add constraint model_requests_routing_scope_ck check (
|
|
(request_observation_json #>> '{routing,scope}') in ('legacy_provider', 'all', 'groups')
|
|
),
|
|
add constraint model_requests_routing_group_names_ck check (
|
|
jsonb_typeof((request_observation_json #> '{routing,groupNamesSnapshot}')) = 'array'
|
|
and (
|
|
(
|
|
(request_observation_json #>> '{routing,scope}') in ('legacy_provider', 'all')
|
|
and jsonb_array_length(request_observation_json #> '{routing,groupRefs}') = 0
|
|
and jsonb_array_length((request_observation_json #> '{routing,groupNamesSnapshot}')) = 0
|
|
)
|
|
or (
|
|
(request_observation_json #>> '{routing,scope}') = 'groups'
|
|
and jsonb_array_length(request_observation_json #> '{routing,groupRefs}') > 0
|
|
and not jsonb_path_exists(request_observation_json, '$.routing.groupRefs[*] ? (@ == null)')
|
|
and jsonb_array_length((request_observation_json #> '{routing,groupNamesSnapshot}'))
|
|
= jsonb_array_length(request_observation_json #> '{routing,groupRefs}')
|
|
)
|
|
)
|
|
),
|
|
add constraint model_requests_latency_ck check (
|
|
((request_observation_json #>> '{timings,local,transportDecisionWaitMs}')::bigint is null or (request_observation_json #>> '{timings,local,transportDecisionWaitMs}')::bigint >= 0)
|
|
and ((request_observation_json #>> '{timings,local,connectMs}')::bigint is null or (request_observation_json #>> '{timings,local,connectMs}')::bigint >= 0)
|
|
and ((request_observation_json #>> '{timings,local,headersMs}')::bigint is null or (request_observation_json #>> '{timings,local,headersMs}')::bigint >= 0)
|
|
and ((request_observation_json #>> '{timings,local,firstEventMs}')::bigint is null or (request_observation_json #>> '{timings,local,firstEventMs}')::bigint >= 0)
|
|
and ((request_observation_json #>> '{timings,local,firstReasoningMs}')::bigint is null or (request_observation_json #>> '{timings,local,firstReasoningMs}')::bigint >= 0)
|
|
and ((request_observation_json #>> '{timings,local,firstTextMs}')::bigint is null or (request_observation_json #>> '{timings,local,firstTextMs}')::bigint >= 0)
|
|
and ((request_observation_json #>> '{timings,local,firstTokenMs}')::bigint is null or (request_observation_json #>> '{timings,local,firstTokenMs}')::bigint >= 0)
|
|
and ((request_observation_json #>> '{timings,upstream,processingMs}')::bigint is null or (request_observation_json #>> '{timings,upstream,processingMs}')::bigint >= 0)
|
|
and ((request_observation_json #>> '{timings,local,latencyMs}')::bigint is null or (request_observation_json #>> '{timings,local,latencyMs}')::bigint >= 0)
|
|
and (
|
|
(request_observation_json #>> '{timings,local,latencyMs}')::bigint is null
|
|
or (
|
|
((request_observation_json #>> '{timings,local,transportDecisionWaitMs}')::bigint is null or (request_observation_json #>> '{timings,local,transportDecisionWaitMs}')::bigint <= (request_observation_json #>> '{timings,local,latencyMs}')::bigint)
|
|
and ((request_observation_json #>> '{timings,local,connectMs}')::bigint is null or (request_observation_json #>> '{timings,local,connectMs}')::bigint <= (request_observation_json #>> '{timings,local,latencyMs}')::bigint)
|
|
and ((request_observation_json #>> '{timings,local,headersMs}')::bigint is null or (request_observation_json #>> '{timings,local,headersMs}')::bigint <= (request_observation_json #>> '{timings,local,latencyMs}')::bigint)
|
|
and ((request_observation_json #>> '{timings,local,firstEventMs}')::bigint is null or (request_observation_json #>> '{timings,local,firstEventMs}')::bigint <= (request_observation_json #>> '{timings,local,latencyMs}')::bigint)
|
|
and ((request_observation_json #>> '{timings,local,firstReasoningMs}')::bigint is null or (request_observation_json #>> '{timings,local,firstReasoningMs}')::bigint <= (request_observation_json #>> '{timings,local,latencyMs}')::bigint)
|
|
and ((request_observation_json #>> '{timings,local,firstTextMs}')::bigint is null or (request_observation_json #>> '{timings,local,firstTextMs}')::bigint <= (request_observation_json #>> '{timings,local,latencyMs}')::bigint)
|
|
and ((request_observation_json #>> '{timings,local,firstTokenMs}')::bigint is null or (request_observation_json #>> '{timings,local,firstTokenMs}')::bigint <= (request_observation_json #>> '{timings,local,latencyMs}')::bigint)
|
|
)
|
|
)
|
|
),
|
|
add constraint model_requests_runtime_pressure_ck check (
|
|
((request_observation_json #>> '{scheduling,admissionDecisionMs}')::bigint is null or (request_observation_json #>> '{scheduling,admissionDecisionMs}')::bigint >= 0)
|
|
and ((request_observation_json #>> '{scheduling,accountSelectionWaitMs}')::bigint is null or (request_observation_json #>> '{scheduling,accountSelectionWaitMs}')::bigint >= 0)
|
|
and (
|
|
((request_observation_json #>> '{scheduling,capacityUsedSlots}')::bigint is null and (request_observation_json #>> '{scheduling,capacityTotalSlots}')::bigint is null)
|
|
or (
|
|
(request_observation_json #>> '{scheduling,capacityUsedSlots}')::bigint >= 0
|
|
and (request_observation_json #>> '{scheduling,capacityTotalSlots}')::bigint > 0
|
|
and (request_observation_json #>> '{scheduling,capacityUsedSlots}')::bigint <= (request_observation_json #>> '{scheduling,capacityTotalSlots}')::bigint
|
|
)
|
|
)
|
|
),
|
|
add constraint model_requests_continuation_hashes_ck check (
|
|
(continuation_affinity_hash is null
|
|
or continuation_affinity_hash ~ '^[0-9a-f]{64}$')
|
|
and ((request_observation_json #>> '{continuation,previousResponseIdHash}') is null
|
|
or (request_observation_json #>> '{continuation,previousResponseIdHash}') ~ '^[0-9a-f]{64}$')
|
|
and (continuation_requested
|
|
or (request_observation_json #>> '{continuation,previousResponseIdHash}') is null)
|
|
),
|
|
add constraint model_requests_continuation_reason_ck check (
|
|
(request_observation_json #>> '{continuation,unavailableReason}') is null
|
|
or (
|
|
octet_length((request_observation_json #>> '{continuation,unavailableReason}')) between 1 and 64
|
|
and (request_observation_json #>> '{continuation,unavailableReason}') ~ '^[a-z][a-z0-9_]*$'
|
|
)
|
|
),
|
|
add constraint model_requests_upstream_connection_ck check (
|
|
(
|
|
(request_observation_json #>> '{transport,connection,id}') is null
|
|
and (request_observation_json #>> '{transport,connection,exitReason}') is null
|
|
and (request_observation_json #>> '{transport,connection,ageMs}')::bigint is null
|
|
and (request_observation_json #>> '{transport,connection,idleMs}')::bigint is null
|
|
)
|
|
or (
|
|
octet_length((request_observation_json #>> '{transport,connection,id}')) between 1 and 128
|
|
and (request_observation_json #>> '{transport,connection,id}') !~ '[[:cntrl:]]'
|
|
and octet_length((request_observation_json #>> '{transport,connection,exitReason}')) between 1 and 64
|
|
and (request_observation_json #>> '{transport,connection,exitReason}') ~ '^[a-z][a-z0-9_]*$'
|
|
and (request_observation_json #>> '{transport,connection,ageMs}')::bigint >= 0
|
|
and (request_observation_json #>> '{transport,connection,idleMs}')::bigint between 0 and (request_observation_json #>> '{transport,connection,ageMs}')::bigint
|
|
)
|
|
),
|
|
add constraint model_requests_recovery_ck check (
|
|
recovery_attempt_count >= 0
|
|
and (
|
|
(
|
|
recovered_at is null
|
|
and recovery_request_id is null
|
|
and (request_observation_json #>> '{recovery,retryDelayMs}')::bigint is null
|
|
and (request_observation_json #>> '{recovery,totalLatencyMs}')::bigint is null
|
|
)
|
|
or (
|
|
recovered_at is not null
|
|
and recovered_at >= completed_at
|
|
and recovery_request_id is not null
|
|
and octet_length(recovery_request_id) between 1 and 128
|
|
and recovery_attempt_count > 0
|
|
and (request_observation_json #>> '{recovery,retryDelayMs}')::bigint >= 0
|
|
and (request_observation_json #>> '{recovery,totalLatencyMs}')::bigint >= (request_observation_json #>> '{recovery,retryDelayMs}')::bigint
|
|
)
|
|
)
|
|
),
|
|
add constraint model_requests_fact_completeness_ck check (
|
|
(provider_account_id is null or provider_account_ref is not null)
|
|
and (cost_source = 'unavailable' or cost_currency is not null)
|
|
and num_nonnulls((request_observation_json #>> '{scheduling,capacityUsedSlots}')::bigint, (request_observation_json #>> '{scheduling,capacityTotalSlots}')::bigint) in (0, 2)
|
|
and num_nonnulls(
|
|
(request_observation_json #>> '{transport,connection,id}'), (request_observation_json #>> '{transport,connection,exitReason}'),
|
|
(request_observation_json #>> '{transport,connection,ageMs}')::bigint, (request_observation_json #>> '{transport,connection,idleMs}')::bigint
|
|
) in (0, 4)
|
|
and (
|
|
recovered_at is null
|
|
or (
|
|
completed_at is not null
|
|
and (request_observation_json #>> '{recovery,retryDelayMs}')::bigint is not null
|
|
and (request_observation_json #>> '{recovery,totalLatencyMs}')::bigint is not null
|
|
)
|
|
)
|
|
);
|
|
|
|
-- 只读视图集中 JSON 路径与类型转换,不保存冗余事实
|
|
-- 计时与调度投影逐行计算一次,避免聚合的多个分位数重复提取同一个 JSON 值
|
|
-- 请求与账号筛选保留在主扫描上,分页后才计算所需观测
|
|
create view model_request_observations as
|
|
select mr.*,
|
|
(mr.request_observation_json #>> '{request,configRevision}')::bigint as config_revision,
|
|
(mr.request_observation_json #>> '{request,protocol}') as protocol,
|
|
(mr.request_observation_json #>> '{request,endpoint}') as endpoint,
|
|
(mr.request_observation_json #>> '{account,name}') as provider_account_name_snapshot,
|
|
(mr.request_observation_json #>> '{account,email}') as provider_account_email_snapshot,
|
|
(mr.request_observation_json #>> '{account,authenticationKind}') as provider_account_authentication_kind_snapshot,
|
|
(mr.request_observation_json #>> '{routing,scope}') as routing_scope,
|
|
array(select jsonb_array_elements_text(mr.request_observation_json #> '{routing,groupRefs}')) as routing_group_refs,
|
|
(mr.request_observation_json #> '{routing,groupNamesSnapshot}') as routing_group_names_snapshot,
|
|
(mr.request_observation_json #>> '{error,providerErrorCode}') as provider_error_code,
|
|
(mr.request_observation_json #>> '{error,message}') as error_message,
|
|
(mr.request_observation_json #>> '{error,retryAfterMs}')::bigint as retry_after_ms,
|
|
(mr.request_observation_json #>> '{request,clientIp}')::inet as client_ip,
|
|
(mr.request_observation_json #>> '{request,userAgent}') as user_agent,
|
|
(mr.request_observation_json #>> '{request,reasoningEffort}') as reasoning_effort,
|
|
(mr.request_observation_json #>> '{request,reasoningPreset}') as reasoning_preset,
|
|
(mr.request_observation_json #>> '{request,subagentKind}') as subagent_kind,
|
|
(mr.request_observation_json #>> '{request,compact}')::boolean as compact,
|
|
measured.transport_decision_wait_ms as transport_decision_wait_ms,
|
|
measured.connect_ms as connect_ms,
|
|
measured.headers_ms as headers_ms,
|
|
measured.first_event_ms as first_event_ms,
|
|
measured.first_reasoning_ms as first_reasoning_ms,
|
|
measured.first_text_ms as first_text_ms,
|
|
measured.first_token_ms as first_token_ms,
|
|
measured.latency_ms as latency_ms,
|
|
measured.provider_processing_ms as provider_processing_ms,
|
|
measured.admission_decision_ms as admission_decision_ms,
|
|
measured.account_selection_wait_ms as account_selection_wait_ms,
|
|
measured.capacity_used_slots as capacity_used_slots,
|
|
measured.capacity_total_slots as capacity_total_slots,
|
|
(mr.request_observation_json #>> '{transport,httpVersion}') as http_version,
|
|
(mr.request_observation_json #>> '{transport,websocketPool}') as websocket_pool,
|
|
(mr.request_observation_json #>> '{transport,connection,id}') as upstream_connection_id,
|
|
(mr.request_observation_json #>> '{transport,connection,exitReason}') as upstream_connection_exit_reason,
|
|
(mr.request_observation_json #>> '{transport,connection,ageMs}')::bigint as upstream_connection_age_ms,
|
|
(mr.request_observation_json #>> '{transport,connection,idleMs}')::bigint as upstream_connection_idle_ms,
|
|
(mr.request_observation_json #>> '{response,responseModel}') as upstream_response_model,
|
|
(mr.request_observation_json #>> '{continuation,previousResponseIdHash}') as continuation_previous_response_id_hash,
|
|
(mr.request_observation_json #>> '{continuation,unavailableReason}') as continuation_unavailable_reason,
|
|
(mr.request_observation_json #>> '{recovery,retryDelayMs}')::bigint as recovery_retry_delay_ms,
|
|
(mr.request_observation_json #>> '{recovery,totalLatencyMs}')::bigint as recovery_total_latency_ms,
|
|
(mr.request_observation_json #>> '{timings,upstream,apiOverheadMs}')::double precision as upstream_api_overhead_ms,
|
|
(mr.request_observation_json #>> '{timings,upstream,engineMs}')::double precision as upstream_engine_ms,
|
|
(mr.request_observation_json #>> '{timings,upstream,engineIapiTtftMs}')::double precision as upstream_engine_iapi_ttft_ms,
|
|
(mr.request_observation_json #>> '{timings,upstream,engineServiceTtftMs}')::double precision as upstream_engine_service_ttft_ms,
|
|
(mr.request_observation_json #>> '{timings,upstream,engineIapiTbtMs}')::double precision as upstream_engine_iapi_tbt_ms,
|
|
(mr.request_observation_json #>> '{timings,upstream,engineServiceTbtMs}')::double precision as upstream_engine_service_tbt_ms,
|
|
measured.upstream_response_ms as upstream_response_ms
|
|
from model_requests mr
|
|
cross join lateral (
|
|
select (mr.request_observation_json #>> '{timings,local,transportDecisionWaitMs}')::bigint as transport_decision_wait_ms,
|
|
(mr.request_observation_json #>> '{timings,local,connectMs}')::bigint as connect_ms,
|
|
(mr.request_observation_json #>> '{timings,local,headersMs}')::bigint as headers_ms,
|
|
(mr.request_observation_json #>> '{timings,local,firstEventMs}')::bigint as first_event_ms,
|
|
(mr.request_observation_json #>> '{timings,local,firstReasoningMs}')::bigint as first_reasoning_ms,
|
|
(mr.request_observation_json #>> '{timings,local,firstTextMs}')::bigint as first_text_ms,
|
|
(mr.request_observation_json #>> '{timings,local,firstTokenMs}')::bigint as first_token_ms,
|
|
(mr.request_observation_json #>> '{timings,local,latencyMs}')::bigint as latency_ms,
|
|
(mr.request_observation_json #>> '{timings,upstream,processingMs}')::bigint as provider_processing_ms,
|
|
(mr.request_observation_json #>> '{scheduling,admissionDecisionMs}')::bigint as admission_decision_ms,
|
|
(mr.request_observation_json #>> '{scheduling,accountSelectionWaitMs}')::bigint as account_selection_wait_ms,
|
|
(mr.request_observation_json #>> '{scheduling,capacityUsedSlots}')::bigint as capacity_used_slots,
|
|
(mr.request_observation_json #>> '{scheduling,capacityTotalSlots}')::bigint as capacity_total_slots,
|
|
(mr.request_observation_json #>> '{timings,upstream,responseMs}')::bigint as upstream_response_ms
|
|
offset 0
|
|
) measured;
|