P6 硬化(5 项全部完成):
- CDC 多实例水平扩展: _INSTANCE_ID + get_lag() 真实 lag 计算
- ExamCache Redis 化: key data_ana:exam:{exam_id}, TTL 30 天 + 内存 LRU fallback
- ClickHouse TTL 归档: 5 表均加 TTL(1-3 年),分区级删除
- Prometheus 监控: 18 个指标(CDC/CH/ExamCache/DataScope/gRPC/业务)
- readyz 深度硬化: 4 依赖超时检查(CH 1s/Redis 200ms/iam 2s/CDC lag<1000)
v2 新增 6 个 RPC(analytics.proto 扩展为 18 RPC):
- GetStudentGrowth / GetAssignmentAnalysis / GetMasterySummary
- ListDiagnosticReports(占位,待 ai 服务)/ ListErrorBookItems / GetErrorBookStats
监控与可观测性: lifespan 预热 + gRPC ServerInterceptor + CDC 消费者指标
Docker 本地测试 19 项全部通过(healthz/readyz/metrics + 11 HTTP + 10 gRPC + ruff)
nextstep-v2.md: 上游需求对齐 + 下游要求(iam/core-edu/content/ai/SRE)
423 lines
12 KiB
Protocol Buffer
423 lines
12 KiB
Protocol Buffer
syntax = "proto3";
|
||
|
||
package next_edu_cloud.analytics.v1;
|
||
|
||
// AnalyticsService 数据分析服务契约(D6 智能洞察领域).
|
||
// P4 启用 gRPC server 端口 50055,HTTP 3006 保留作 Gateway 直连降级.
|
||
// 所有 RPC 返回 ActionState 信封(success/data/error/details.degraded).
|
||
service AnalyticsService {
|
||
// 班级成绩分析(平均分/及格率/参考人数).
|
||
rpc GetClassPerformance(GetClassPerformanceRequest) returns (ClassPerformance);
|
||
// 学生薄弱知识点(mastery_level < 0.6).
|
||
rpc GetStudentWeakness(GetStudentWeaknessRequest) returns (StudentWeakness);
|
||
// 学习趋势(历史成绩曲线).
|
||
rpc GetLearningTrend(GetLearningTrendRequest) returns (LearningTrend);
|
||
// 教师仪表盘聚合(班级概览 + 待办 + 预警).
|
||
rpc GetTeacherDashboard(GetTeacherDashboardRequest) returns (TeacherDashboard);
|
||
// 学生仪表盘(个人学情 + 排名 + 薄弱点).
|
||
rpc GetStudentDashboard(GetStudentDashboardRequest) returns (StudentDashboard);
|
||
// 家长仪表盘(孩子学情概览).
|
||
rpc GetParentDashboard(GetParentDashboardRequest) returns (ParentDashboard);
|
||
// 管理员仪表盘(全校统计 + AI 用量).
|
||
rpc GetAdminDashboard(GetAdminDashboardRequest) returns (AdminDashboard);
|
||
// 预警列表查询(按班级/严重度/时间过滤).
|
||
rpc GetWarnings(GetWarningsRequest) returns (WarningList);
|
||
// 手动触发预警(管理员/教师主动标记关注).
|
||
rpc TriggerWarning(TriggerWarningRequest) returns (TriggerWarningResponse);
|
||
// 班级掌握度分布(mastered/progressing/weak 三档).
|
||
rpc GetMasteryDistribution(GetMasteryDistributionRequest) returns (MasteryDistribution);
|
||
// 学生知识点掌握度明细.
|
||
rpc GetStudentMastery(GetStudentMasteryRequest) returns (StudentMastery);
|
||
// 订阅掌握度更新(server-streaming,P5+ AI 个性化推荐实时推送通道).
|
||
rpc SubscribeMasteryUpdate(SubscribeMasteryUpdateRequest) returns (stream MasteryUpdateEvent);
|
||
|
||
// ===== P6+ v2 扩展 RPC(响应上游 parent-bff / student-bff v2 请求) =====
|
||
// 学生成长档案(综合成绩趋势 + 掌握度变化 + 考勤统计,供 parent-bff GrowthArchiveService).
|
||
rpc GetStudentGrowth(GetStudentGrowthRequest) returns (StudentGrowth);
|
||
// 作业/考试分析(单次作业/考试维度统计,供 student-bff / parent-bff).
|
||
rpc GetAssignmentAnalysis(GetAssignmentAnalysisRequest) returns (AssignmentAnalysis);
|
||
// 学生掌握度汇总(轻量级,仅返回总体掌握度 + 三档分布,供 parent-bff MasteryService.GetSummary).
|
||
rpc GetMasterySummary(GetMasterySummaryRequest) returns (MasterySummary);
|
||
// 诊断报告列表(占位实现,真实数据需 ai 服务集成,供 parent-bff / student-bff).
|
||
rpc ListDiagnosticReports(ListDiagnosticReportsRequest) returns (DiagnosticReportList);
|
||
// 错题本列表(gRPC 版本,供 parent-bff ErrorBookService.List).
|
||
rpc ListErrorBookItems(ListErrorBookItemsRequest) returns (ErrorBookList);
|
||
// 错题本统计(按知识点聚合,供 parent-bff ErrorBookService.GetStats).
|
||
rpc GetErrorBookStats(GetErrorBookStatsRequest) returns (ErrorBookStats);
|
||
}
|
||
|
||
// ===== 请求消息 =====
|
||
|
||
message GetClassPerformanceRequest {
|
||
string class_id = 1;
|
||
string subject_id = 2;
|
||
int64 start_date = 3; // Unix timestamp(秒)
|
||
int64 end_date = 4;
|
||
}
|
||
|
||
message GetStudentWeaknessRequest {
|
||
string student_id = 1;
|
||
string subject_id = 2;
|
||
}
|
||
|
||
message GetLearningTrendRequest {
|
||
string student_id = 1;
|
||
int64 start_date = 2;
|
||
int64 end_date = 3;
|
||
string subject_id = 4;
|
||
}
|
||
|
||
message GetTeacherDashboardRequest {
|
||
string user_id = 1;
|
||
string class_id = 2; // 可选,不传则返回教师全部班级
|
||
}
|
||
|
||
message GetStudentDashboardRequest {
|
||
string user_id = 1;
|
||
}
|
||
|
||
message GetParentDashboardRequest {
|
||
string user_id = 1;
|
||
string student_id = 2; // 家长查看指定孩子
|
||
}
|
||
|
||
message GetAdminDashboardRequest {
|
||
string user_id = 1;
|
||
string scope = 2; // ALL / SCHOOL / DISTRICT
|
||
string scope_id = 3; // 具体范围 ID
|
||
}
|
||
|
||
message GetWarningsRequest {
|
||
string class_id = 1;
|
||
string severity = 2; // INFO / WARN / CRITICAL
|
||
int64 since = 3; // Unix timestamp(秒)
|
||
}
|
||
|
||
message TriggerWarningRequest {
|
||
string target_id = 1; // 学生 ID
|
||
string warning_type = 2; // LOW_MASTERY / SCORE_DROP / ABSENT_FREQUENT
|
||
string severity = 3; // INFO / WARN / CRITICAL
|
||
}
|
||
|
||
message GetMasteryDistributionRequest {
|
||
string class_id = 1;
|
||
string subject_id = 2;
|
||
string knowledge_point_id = 3; // 可选
|
||
}
|
||
|
||
message GetStudentMasteryRequest {
|
||
string student_id = 1;
|
||
string subject_id = 2; // 可选
|
||
}
|
||
|
||
message SubscribeMasteryUpdateRequest {
|
||
string student_id = 1; // 可选,订阅指定学生
|
||
string class_id = 2; // 可选,订阅指定班级全部学生
|
||
}
|
||
|
||
// ===== P6+ v2 扩展 RPC 请求消息 =====
|
||
|
||
message GetStudentGrowthRequest {
|
||
string student_id = 1;
|
||
int64 start_date = 2; // Unix timestamp(秒)
|
||
int64 end_date = 3;
|
||
string subject_id = 4; // 可选
|
||
}
|
||
|
||
message GetAssignmentAnalysisRequest {
|
||
string class_id = 1;
|
||
string assignment_id = 2; // exam_id 或 homework_id
|
||
string subject_id = 3; // 可选
|
||
}
|
||
|
||
message GetMasterySummaryRequest {
|
||
string student_id = 1;
|
||
string subject_id = 2; // 可选
|
||
}
|
||
|
||
message ListDiagnosticReportsRequest {
|
||
string student_id = 1;
|
||
int64 since = 2; // Unix timestamp(秒)
|
||
int32 limit = 3; // 默认 10
|
||
}
|
||
|
||
message ListErrorBookItemsRequest {
|
||
string student_id = 1;
|
||
string subject_id = 2; // 可选,按学科过滤
|
||
int32 limit = 3; // 默认 100
|
||
int32 offset = 4; // 分页偏移
|
||
}
|
||
|
||
message GetErrorBookStatsRequest {
|
||
string student_id = 1;
|
||
string subject_id = 2; // 可选
|
||
}
|
||
|
||
// ===== 响应消息 =====
|
||
|
||
message ClassPerformance {
|
||
string class_id = 1;
|
||
double average_score = 2;
|
||
double pass_rate = 3;
|
||
int32 total_students = 4;
|
||
repeated StudentScore scores = 5;
|
||
}
|
||
|
||
message StudentScore {
|
||
string student_id = 1;
|
||
double score = 2;
|
||
string grade = 3;
|
||
}
|
||
|
||
message StudentWeakness {
|
||
string student_id = 1;
|
||
repeated WeakPoint weak_points = 2;
|
||
}
|
||
|
||
message WeakPoint {
|
||
string knowledge_point_id = 1;
|
||
string title = 2;
|
||
double mastery = 3;
|
||
int32 error_count = 4;
|
||
}
|
||
|
||
message LearningTrend {
|
||
string student_id = 1;
|
||
repeated TrendPoint points = 2;
|
||
}
|
||
|
||
message TrendPoint {
|
||
int64 date = 1;
|
||
double score = 2;
|
||
}
|
||
|
||
message TeacherDashboard {
|
||
string user_id = 1;
|
||
int32 total_classes = 2;
|
||
int32 total_students = 3;
|
||
double class_avg_score = 4;
|
||
int32 pending_homework_count = 5;
|
||
repeated ClassSummary classes = 6;
|
||
repeated StudentSummary top_students = 7;
|
||
repeated WarningInfo recent_warnings = 8;
|
||
}
|
||
|
||
message ClassSummary {
|
||
string class_id = 1;
|
||
string class_name = 2;
|
||
int32 student_count = 3;
|
||
double average_score = 4;
|
||
}
|
||
|
||
message StudentSummary {
|
||
string student_id = 1;
|
||
string student_name = 2;
|
||
double score = 3;
|
||
int32 rank_in_class = 4;
|
||
}
|
||
|
||
message StudentDashboard {
|
||
string user_id = 1;
|
||
double avg_score = 2;
|
||
int32 class_rank = 3;
|
||
int32 total_students = 4;
|
||
repeated WeakPoint weak_points = 5;
|
||
repeated TrendPoint recent_trends = 6;
|
||
int32 pending_homework = 7;
|
||
}
|
||
|
||
message ParentDashboard {
|
||
string user_id = 1;
|
||
string student_id = 2;
|
||
double child_avg_score = 3;
|
||
int32 child_class_rank = 4;
|
||
int32 total_class_students = 5;
|
||
repeated WeakPoint child_weak_points = 6;
|
||
repeated WarningInfo child_warnings = 7;
|
||
}
|
||
|
||
message AdminDashboard {
|
||
string user_id = 1;
|
||
int32 total_teachers = 2;
|
||
int32 total_students = 3;
|
||
int32 total_classes = 4;
|
||
double school_avg_score = 5;
|
||
repeated WarningInfo recent_warnings = 6;
|
||
AIUsageSummary ai_usage = 7;
|
||
}
|
||
|
||
message AIUsageSummary {
|
||
int64 total_requests = 1;
|
||
int64 total_tokens = 2;
|
||
int64 total_cost_cents = 3;
|
||
repeated AIUsageByProvider by_provider = 4;
|
||
}
|
||
|
||
message AIUsageByProvider {
|
||
string provider = 1;
|
||
int64 request_count = 2;
|
||
int64 total_tokens = 3;
|
||
int64 cost_cents = 4;
|
||
}
|
||
|
||
message WarningList {
|
||
repeated WarningInfo warnings = 1;
|
||
int32 total = 2;
|
||
}
|
||
|
||
message WarningInfo {
|
||
string warning_id = 1;
|
||
string warning_type = 2; // LOW_MASTERY / CRITICAL_LOW / SCORE_DROP / ABSENT_FREQUENT / TREND_DECLINE
|
||
string target_id = 3; // 学生 ID
|
||
string target_name = 4;
|
||
double threshold = 5;
|
||
double current_value = 6;
|
||
string severity = 7; // INFO / WARN / CRITICAL
|
||
int64 occurred_at = 8; // Unix timestamp(秒)
|
||
}
|
||
|
||
message TriggerWarningResponse {
|
||
string warning_id = 1;
|
||
bool triggered = 2;
|
||
}
|
||
|
||
message MasteryDistribution {
|
||
string class_id = 1;
|
||
int32 mastered_count = 2; // mastery >= 0.8
|
||
int32 progressing_count = 3; // 0.4 <= mastery < 0.8
|
||
int32 weak_count = 4; // mastery < 0.4
|
||
int32 total_students = 5;
|
||
}
|
||
|
||
message StudentMastery {
|
||
string student_id = 1;
|
||
repeated KnowledgePointMastery knowledge_points = 2;
|
||
double overall_mastery = 3;
|
||
}
|
||
|
||
message KnowledgePointMastery {
|
||
string knowledge_point_id = 1;
|
||
string title = 2;
|
||
string subject_id = 3;
|
||
double mastery_level = 4; // 0.0-1.0
|
||
string mastery_label = 5; // mastered / progressing / weak
|
||
int64 calculated_at = 6; // Unix timestamp(秒)
|
||
}
|
||
|
||
message MasteryUpdateEvent {
|
||
string event_id = 1;
|
||
string student_id = 2;
|
||
string knowledge_point_id = 3;
|
||
double mastery_level = 4;
|
||
double previous_level = 5;
|
||
int64 calculated_at = 6; // Unix timestamp(秒)
|
||
}
|
||
|
||
// ===== P6+ v2 扩展 RPC 响应消息 =====
|
||
|
||
message StudentGrowth {
|
||
string student_id = 1;
|
||
// 成绩趋势(来自 LearningTrend)
|
||
repeated TrendPoint score_trend = 2;
|
||
// 掌握度变化趋势(按时间排序的快照)
|
||
repeated MasteryTrendPoint mastery_trend = 3;
|
||
// 考勤统计
|
||
AttendanceSummary attendance = 4;
|
||
// 总体成长评分(综合分数、掌握度、考勤计算)
|
||
double growth_score = 5;
|
||
// 成长等级(excellent / good / average / needs_improvement)
|
||
string growth_level = 6;
|
||
}
|
||
|
||
message MasteryTrendPoint {
|
||
int64 calculated_at = 1;
|
||
double overall_mastery = 2;
|
||
}
|
||
|
||
message AttendanceSummary {
|
||
int32 total_days = 1;
|
||
int32 present_days = 2;
|
||
int32 absent_days = 3;
|
||
int32 late_days = 4;
|
||
double attendance_rate = 5; // 出勤率 0.0-1.0
|
||
}
|
||
|
||
message AssignmentAnalysis {
|
||
string assignment_id = 1;
|
||
string class_id = 2;
|
||
string subject_id = 3;
|
||
double average_score = 4;
|
||
double highest_score = 5;
|
||
double lowest_score = 6;
|
||
int32 total_students = 7;
|
||
int32 submitted_count = 8;
|
||
double pass_rate = 9; // 及格率
|
||
// 分数段分布(90-100 / 80-89 / 70-79 / 60-69 / <60)
|
||
repeated ScoreRange ranges = 10;
|
||
}
|
||
|
||
message ScoreRange {
|
||
string label = 1; // "90-100" / "80-89" etc.
|
||
int32 count = 2;
|
||
double percentage = 3; // 占比 0.0-1.0
|
||
}
|
||
|
||
message MasterySummary {
|
||
string student_id = 1;
|
||
double overall_mastery = 2; // 0.0-1.0
|
||
int32 mastered_count = 3; // mastery >= 0.8
|
||
int32 progressing_count = 4; // 0.4 <= mastery < 0.8
|
||
int32 weak_count = 5; // mastery < 0.4
|
||
int32 total_knowledge_points = 6;
|
||
string mastery_level = 7; // mastered / progressing / weak(总体)
|
||
}
|
||
|
||
message DiagnosticReportList {
|
||
string student_id = 1;
|
||
repeated DiagnosticReport reports = 2;
|
||
int32 total = 3;
|
||
}
|
||
|
||
message DiagnosticReport {
|
||
string report_id = 1;
|
||
string student_id = 2;
|
||
string report_type = 3; // KNOWLEDGE_GAP / LEARNING_STYLE / WEAKNESS_ANALYSIS
|
||
string title = 4;
|
||
string summary = 5; // 报告摘要
|
||
int64 generated_at = 6; // Unix timestamp(秒)
|
||
string status = 7; // pending / completed / failed
|
||
}
|
||
|
||
message ErrorBookList {
|
||
string student_id = 1;
|
||
repeated ErrorBookItem items = 2;
|
||
int32 total = 3;
|
||
}
|
||
|
||
message ErrorBookItem {
|
||
string question_id = 1;
|
||
string knowledge_point_id = 2;
|
||
string knowledge_point_title = 3;
|
||
int32 error_count = 4;
|
||
int64 last_error_time = 5; // Unix timestamp(秒)
|
||
string content = 6; // 题目内容摘要
|
||
}
|
||
|
||
message ErrorBookStats {
|
||
string student_id = 1;
|
||
int32 total_error_questions = 2;
|
||
int32 total_error_count = 3; // 总错误次数
|
||
// 按知识点聚合的错题统计
|
||
repeated KnowledgePointErrorStats by_knowledge_point = 4;
|
||
// 最近 7 天错误次数
|
||
int32 recent_7d_errors = 5;
|
||
}
|
||
|
||
message KnowledgePointErrorStats {
|
||
string knowledge_point_id = 1;
|
||
string title = 2;
|
||
int32 error_count = 3;
|
||
int32 question_count = 4;
|
||
double error_rate = 5; // 错误率 0.0-1.0
|
||
}
|