Spaces:
Sleeping
Sleeping
| -- HR 对话质量评估系统 - Supabase 数据库表结构(含日志) | |
| -- 在 Supabase SQL Editor 中执行此脚本 | |
| -- ============================================ | |
| -- 1. 对话历史表(已有) | |
| -- ============================================ | |
| CREATE TABLE IF NOT EXISTS conversation_history ( | |
| id UUID DEFAULT gen_random_uuid() PRIMARY KEY, | |
| session_id TEXT NOT NULL, | |
| user_message TEXT NOT NULL, | |
| assistant_message TEXT NOT NULL, | |
| analysis_report JSONB, | |
| context_summary JSONB, | |
| metadata JSONB, | |
| created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() | |
| ); | |
| CREATE INDEX IF NOT EXISTS idx_conversation_history_session_id ON conversation_history(session_id); | |
| CREATE INDEX IF NOT EXISTS idx_conversation_history_created_at ON conversation_history(created_at DESC); | |
| -- ============================================ | |
| -- 2. API 访问日志表(新增) | |
| -- ============================================ | |
| CREATE TABLE IF NOT EXISTS api_access_logs ( | |
| id UUID DEFAULT gen_random_uuid() PRIMARY KEY, | |
| timestamp TIMESTAMP WITH TIME ZONE DEFAULT NOW(), | |
| -- 请求信息 | |
| endpoint TEXT NOT NULL, | |
| method TEXT NOT NULL, | |
| path TEXT, | |
| query_params JSONB, | |
| -- 客户端信息 | |
| client_ip TEXT, | |
| user_agent TEXT, | |
| session_id TEXT, | |
| -- 性能指标 | |
| response_time_ms INTEGER, | |
| status_code INTEGER, | |
| -- 附加信息 | |
| metadata JSONB | |
| ); | |
| -- 索引优化 | |
| CREATE INDEX IF NOT EXISTS idx_api_logs_timestamp ON api_access_logs(timestamp DESC); | |
| CREATE INDEX IF NOT EXISTS idx_api_logs_endpoint ON api_access_logs(endpoint); | |
| CREATE INDEX IF NOT EXISTS idx_api_logs_session_id ON api_access_logs(session_id); | |
| CREATE INDEX IF NOT EXISTS idx_api_logs_status_code ON api_access_logs(status_code); | |
| -- 分区(按月)- 可选,大数据量时使用 | |
| -- CREATE TABLE api_access_logs_y2025m01 PARTITION OF api_access_logs | |
| -- FOR VALUES FROM ('2025-01-01') TO ('2025-02-01'); | |
| -- ============================================ | |
| -- 3. 错误日志表(新增) | |
| -- ============================================ | |
| CREATE TABLE IF NOT EXISTS error_logs ( | |
| id UUID DEFAULT gen_random_uuid() PRIMARY KEY, | |
| timestamp TIMESTAMP WITH TIME ZONE DEFAULT NOW(), | |
| -- 错误信息 | |
| error_type TEXT NOT NULL, -- 'validation', 'model_load', 'api_error', etc. | |
| error_message TEXT NOT NULL, | |
| error_stack TEXT, | |
| -- 上下文 | |
| endpoint TEXT, | |
| session_id TEXT, | |
| user_input TEXT, | |
| -- 请求详情 | |
| request_data JSONB, | |
| -- 元数据 | |
| metadata JSONB | |
| ); | |
| CREATE INDEX IF NOT EXISTS idx_error_logs_timestamp ON error_logs(timestamp DESC); | |
| CREATE INDEX IF NOT EXISTS idx_error_logs_type ON error_logs(error_type); | |
| CREATE INDEX IF NOT EXISTS idx_error_logs_session_id ON error_logs(session_id); | |
| -- ============================================ | |
| -- 4. 模型性能日志表(新增) | |
| -- ============================================ | |
| CREATE TABLE IF NOT EXISTS model_performance_logs ( | |
| id UUID DEFAULT gen_random_uuid() PRIMARY KEY, | |
| timestamp TIMESTAMP WITH TIME ZONE DEFAULT NOW(), | |
| -- 模型信息 | |
| model_name TEXT NOT NULL, | |
| model_type TEXT NOT NULL, -- 'sbert', 'sentiment', 'compliance', 'llm' | |
| -- 性能指标 | |
| load_time_ms INTEGER, | |
| inference_time_ms INTEGER, | |
| total_time_ms INTEGER, | |
| -- 输入输出 | |
| input_text TEXT, | |
| output_summary TEXT, | |
| -- 附加信息 | |
| metadata JSONB | |
| ); | |
| CREATE INDEX IF NOT EXISTS idx_model_perf_timestamp ON model_performance_logs(timestamp DESC); | |
| CREATE INDEX IF NOT EXISTS idx_model_perf_model_name ON model_performance_logs(model_name); | |
| CREATE INDEX IF NOT EXISTS idx_model_perf_type ON model_performance_logs(model_type); | |
| -- ============================================ | |
| -- 5. 调试日志表(新增)- 用于开发调试 | |
| -- ============================================ | |
| CREATE TABLE IF NOT EXISTS debug_logs ( | |
| id UUID DEFAULT gen_random_uuid() PRIMARY KEY, | |
| timestamp TIMESTAMP WITH TIME ZONE DEFAULT NOW(), | |
| -- 日志信息 | |
| level TEXT NOT NULL, -- 'DEBUG', 'INFO', 'WARNING', 'ERROR' | |
| logger TEXT NOT NULL, -- 模块名称,如 'intelligence_analyzer' | |
| message TEXT NOT NULL, | |
| -- 上下文 | |
| session_id TEXT, | |
| function_name TEXT, | |
| line_number INTEGER, | |
| -- 结构化数据 | |
| data JSONB, | |
| -- 附加信息 | |
| metadata JSONB | |
| ); | |
| CREATE INDEX IF NOT EXISTS idx_debug_logs_timestamp ON debug_logs(timestamp DESC); | |
| CREATE INDEX IF NOT EXISTS idx_debug_logs_level ON debug_logs(level); | |
| CREATE INDEX IF NOT EXISTS idx_debug_logs_logger ON debug_logs(logger); | |
| CREATE INDEX IF NOT EXISTS idx_debug_logs_session_id ON debug_logs(session_id); | |
| -- ============================================ | |
| -- 6. 用户行为分析表(新增) | |
| -- ============================================ | |
| CREATE TABLE IF NOT EXISTS user_behavior_logs ( | |
| id UUID DEFAULT gen_random_uuid() PRIMARY KEY, | |
| timestamp TIMESTAMP WITH TIME ZONE DEFAULT NOW(), | |
| -- 用户标识 | |
| session_id TEXT NOT NULL, | |
| user_id TEXT, -- 可选,如果有多用户系统 | |
| -- 行为类型 | |
| action_type TEXT NOT NULL, -- 'chat', 'evaluate', 'config_check', etc. | |
| action_detail TEXT, | |
| -- 内容 | |
| input_text TEXT, | |
| intent_detected TEXT, | |
| scenario_detected TEXT, | |
| -- 结果 | |
| success BOOLEAN, | |
| error_message TEXT, | |
| -- 元数据 | |
| metadata JSONB | |
| ); | |
| CREATE INDEX IF NOT EXISTS idx_user_behavior_timestamp ON user_behavior_logs(timestamp DESC); | |
| CREATE INDEX IF NOT EXISTS idx_user_behavior_session_id ON user_behavior_logs(session_id); | |
| CREATE INDEX IF NOT EXISTS idx_user_behavior_action_type ON user_behavior_logs(action_type); | |
| -- ============================================ | |
| -- 启用行级安全性 (RLS) | |
| -- ============================================ | |
| ALTER TABLE api_access_logs ENABLE ROW LEVEL SECURITY; | |
| ALTER TABLE error_logs ENABLE ROW LEVEL SECURITY; | |
| ALTER TABLE model_performance_logs ENABLE ROW LEVEL SECURITY; | |
| ALTER TABLE debug_logs ENABLE ROW LEVEL SECURITY; | |
| ALTER TABLE user_behavior_logs ENABLE ROW LEVEL SECURITY; | |
| -- 允许所有操作(演示环境) | |
| CREATE POLICY "Enable all access for api_access_logs" ON api_access_logs FOR ALL USING (true); | |
| CREATE POLICY "Enable all access for error_logs" ON error_logs FOR ALL USING (true); | |
| CREATE POLICY "Enable all access for model_performance_logs" ON model_performance_logs FOR ALL USING (true); | |
| CREATE POLICY "Enable all access for debug_logs" ON debug_logs FOR ALL USING (true); | |
| CREATE POLICY "Enable all access for user_behavior_logs" ON user_behavior_logs FOR ALL USING (true); | |
| -- ============================================ | |
| -- 实用函数 | |
| -- ============================================ | |
| -- 清理旧日志(保留最近 N 天) | |
| CREATE OR REPLACE FUNCTION cleanup_old_logs(days_to_keep INTEGER DEFAULT 30) | |
| RETURNS TABLE ( | |
| api_logs_deleted BIGINT, | |
| error_logs_deleted BIGINT, | |
| debug_logs_deleted BIGINT, | |
| model_perf_logs_deleted BIGINT | |
| ) | |
| LANGUAGE plpgsql | |
| AS $$ | |
| DECLARE | |
| api_count BIGINT; | |
| error_count BIGINT; | |
| debug_count BIGINT; | |
| model_count BIGINT; | |
| BEGIN | |
| -- 清理 API 日志 | |
| DELETE FROM api_access_logs | |
| WHERE timestamp < NOW() - (days_to_keep || ' days')::INTERVAL; | |
| GET DIAGNOSTICS api_count = ROW_COUNT; | |
| -- 清理错误日志(保留更久) | |
| DELETE FROM error_logs | |
| WHERE timestamp < NOW() - ((days_to_keep * 2) || ' days')::INTERVAL; | |
| GET DIAGNOSTICS error_count = ROW_COUNT; | |
| -- 清理调试日志(保留更短时间) | |
| DELETE FROM debug_logs | |
| WHERE timestamp < NOW() - ((days_to_keep / 2) || ' days')::INTERVAL; | |
| GET DIAGNOSTICS debug_count = ROW_COUNT; | |
| -- 清理模型性能日志 | |
| DELETE FROM model_performance_logs | |
| WHERE timestamp < NOW() - (days_to_keep || ' days')::INTERVAL; | |
| GET DIAGNOSTICS model_count = ROW_COUNT; | |
| RETURN QUERY SELECT api_count, error_count, debug_count, model_count; | |
| END; | |
| $$; | |
| -- 获取 API 统计 | |
| CREATE OR REPLACE FUNCTION get_api_statistics(hours_ago INTEGER DEFAULT 24) | |
| RETURNS TABLE ( | |
| endpoint TEXT, | |
| request_count BIGINT, | |
| avg_response_time NUMERIC, | |
| error_rate NUMERIC, | |
| p95_response_time NUMERIC | |
| ) | |
| LANGUAGE plpgsql | |
| AS $$ | |
| BEGIN | |
| RETURN QUERY | |
| SELECT | |
| endpoint, | |
| COUNT(*) as request_count, | |
| AVG(response_time_ms) as avg_response_time, | |
| COUNT(*) FILTER (WHERE status_code >= 400) * 100.0 / COUNT(*) as error_rate, | |
| PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY response_time_ms) as p95_response_time | |
| FROM api_access_logs | |
| WHERE timestamp >= NOW() - (hours_ago || ' hours')::INTERVAL | |
| GROUP BY endpoint | |
| ORDER BY request_count DESC; | |
| END; | |
| $$; | |
| -- 获取错误统计 | |
| CREATE OR REPLACE FUNCTION get_error_summary(hours_ago INTEGER DEFAULT 24) | |
| RETURNS TABLE ( | |
| error_type TEXT, | |
| error_count BIGINT, | |
| most_common_message TEXT | |
| ) | |
| LANGUAGE plpgsql | |
| AS $$ | |
| BEGIN | |
| RETURN QUERY | |
| SELECT | |
| error_type, | |
| COUNT(*) as error_count, | |
| mode() WITHIN GROUP (ORDER BY error_message) as most_common_message | |
| FROM error_logs | |
| WHERE timestamp >= NOW() - (hours_ago || ' hours')::INTERVAL | |
| GROUP BY error_type | |
| ORDER BY error_count DESC; | |
| END; | |
| $$; | |
| -- 搜索日志 | |
| CREATE OR REPLACE FUNCTION search_logs( | |
| search_term TEXT, | |
| log_type TEXT DEFAULT 'all', -- 'api', 'error', 'debug', 'all' | |
| hours_ago INTEGER DEFAULT 24, | |
| limit_count INTEGER DEFAULT 100 | |
| ) | |
| RETURNS TABLE ( | |
| log_type TEXT, | |
| log_id UUID, | |
| timestamp TIMESTAMP WITH TIME ZONE, | |
| summary TEXT | |
| ) | |
| LANGUAGE plpgsql | |
| AS $$ | |
| BEGIN | |
| -- API 日志 | |
| IF log_type = 'api' OR log_type = 'all' THEN | |
| RETURN QUERY | |
| SELECT | |
| 'api'::TEXT as log_type, | |
| id as log_id, | |
| timestamp, | |
| endpoint || ' - ' || status_code::TEXT as summary | |
| FROM api_access_logs | |
| WHERE ( | |
| search_term ILIKE '%' || search_term || '%' | |
| OR endpoint ILIKE '%' || search_term || '%' | |
| OR path ILIKE '%' || search_term || '%' | |
| ) | |
| AND timestamp >= NOW() - (hours_ago || ' hours')::INTERVAL | |
| LIMIT limit_count; | |
| END IF; | |
| -- 错误日志 | |
| IF log_type = 'error' OR log_type = 'all' THEN | |
| RETURN QUERY | |
| SELECT | |
| 'error'::TEXT as log_type, | |
| id as log_id, | |
| timestamp, | |
| error_type || ' - ' || LEFT(error_message, 50) as summary | |
| FROM error_logs | |
| WHERE error_message ILIKE '%' || search_term || '%' | |
| AND timestamp >= NOW() - (hours_ago || ' hours')::INTERVAL | |
| LIMIT limit_count; | |
| END IF; | |
| -- 调试日志 | |
| IF log_type = 'debug' OR log_type = 'all' THEN | |
| RETURN QUERY | |
| SELECT | |
| 'debug'::TEXT as log_type, | |
| id as log_id, | |
| timestamp, | |
| level || ' - ' || logger || ' - ' || LEFT(message, 50) as summary | |
| FROM debug_logs | |
| WHERE message ILIKE '%' || search_term || '%' | |
| AND timestamp >= NOW() - (hours_ago || ' hours')::INTERVAL | |
| LIMIT limit_count; | |
| END IF; | |
| END; | |
| $$; | |
| -- ============================================ | |
| -- 定时清理任务(可选) | |
| -- ============================================ | |
| -- 创建一个函数来定期清理日志 | |
| CREATE OR REPLACE FUNCTION auto_cleanup_logs() | |
| RETURNS VOID | |
| LANGUAGE plpgsql | |
| AS $$ | |
| BEGIN | |
| -- 清理 7 天前的调试日志 | |
| DELETE FROM debug_logs | |
| WHERE timestamp < NOW() - INTERVAL '7 days'; | |
| -- 清理 30 天前的 API 日志 | |
| DELETE FROM api_access_logs | |
| WHERE timestamp < NOW() - INTERVAL '30 days'; | |
| -- 清理 90 天前的模型性能日志 | |
| DELETE FROM model_performance_logs | |
| WHERE timestamp < NOW() - INTERVAL '90 days'; | |
| -- 错误日志保留 180 天 | |
| DELETE FROM error_logs | |
| WHERE timestamp < NOW() - INTERVAL '180 days'; | |
| END; | |
| $$; | |
| -- 在 Supabase Dashboard 中设置 cron job 来调用这个函数 | |
| -- 或者使用 pg_cron 扩展(如果可用) | |
| -- SELECT cron.schedule('cleanup-logs', '0 2 * * *', 'SELECT auto_cleanup_logs()'); | |
| -- ============================================ | |
| -- 视图 - 方便查询 | |
| -- ============================================ | |
| -- 综合日志视图 | |
| CREATE OR REPLACE VIEW v_recent_logs AS | |
| SELECT | |
| 'api' as log_type, | |
| timestamp, | |
| endpoint as title, | |
| status_code::TEXT as detail, | |
| session_id | |
| FROM api_access_logs | |
| WHERE timestamp >= NOW() - INTERVAL '24 hours' | |
| UNION ALL | |
| SELECT | |
| 'error' as log_type, | |
| timestamp, | |
| error_type as title, | |
| LEFT(error_message, 50) as detail, | |
| session_id | |
| FROM error_logs | |
| WHERE timestamp >= NOW() - INTERVAL '24 hours' | |
| UNION ALL | |
| SELECT | |
| 'debug' as log_type, | |
| timestamp, | |
| logger as title, | |
| level || ' - ' || LEFT(message, 30) as detail, | |
| session_id | |
| FROM debug_logs | |
| WHERE timestamp >= NOW() - INTERVAL '24 hours' | |
| ORDER BY timestamp DESC | |
| LIMIT 100; | |
| -- ============================================ | |
| -- 注释 | |
| -- ============================================ | |
| COMMENT ON TABLE api_access_logs IS 'API 访问日志'; | |
| COMMENT ON TABLE error_logs IS '错误日志'; | |
| COMMENT ON TABLE model_performance_logs IS '模型性能日志'; | |
| COMMENT ON TABLE debug_logs IS '调试日志'; | |
| COMMENT ON TABLE user_behavior_logs IS '用户行为日志'; | |
| COMMENT ON FUNCTION cleanup_old_logs IS '清理旧日志,默认保留 30 天'; | |
| COMMENT ON FUNCTION get_api_statistics IS '获取 API 统计信息'; | |
| COMMENT ON FUNCTION get_error_summary IS '获取错误摘要'; | |
| COMMENT ON FUNCTION search_logs IS '搜索日志内容'; | |
| COMMENT ON FUNCTION auto_cleanup_logs IS '自动清理日志'; | |
| COMMENT ON VIEW v_recent_logs IS '最近 24 小时的综合日志视图'; | |