Files
Edu/apps/teacher-portal/src/components/observability-provider.tsx
SpecialX d49d211425 feat(teacher-portal): 完成参考项目差距闭环 P3-P7 全量实现
- P3 考试/作业/成绩 mutation + 详情页 + 批改界面 + 乐观更新 + 多 Tab 同步
- P4 知识图谱 SVG 可视化 + 学情分析仪表盘 + parent-portal Remote
- P5 WebSocket 通知中心 + AI 出题(SSE) + AI 教案 + AI 学情报告
- P6 可观测性硬化:Sentry + WebVitals + OTel + A11y + 性能配置 + Cookie 迁移
- P7 参考项目差距闭环:新增 35 个页面覆盖 13 个缺失模块
  - attendance(考勤 4 页)/questions(题库)/textbooks(教材 2 页)
  - classes/[id] 详情 + classes/schedule 课表
  - course-plans(2 页)/diagnostic(2 页)/error-book/practice
  - exams/[id]/build 组卷 + exams/[id]/analytics 考后分析
  - exams/[id]/edit-rich 富文本编辑 + exams/[id]/proctoring 监考
  - grades/entry 批量录入 + grades/stats 统计 + grades/analytics 分析 + grades/report-card 报告卡
  - homework/submissions 列表 + assignments/[id]/submissions 批量批改
  - homework/submissions/[submissionId] 单份批改 + scan-grading 扫描批改
  - lesson-plans 编辑器 + library + calendar + heatmap 5 页
  - elective 选修课 3 页 /leave 请假 /schedule-changes 调课
- P7 基础设施:61 GraphQL operations + 5 handlers + 13 fixtures + 11 viewports
- 集成 browser.ts/server.ts 注册所有 p7 handlers(fallthrough 顺序)
- viewports.ts 扩展 11 个新导航项
- 验证:tsc --noEmit 零错误 + eslint 零错误
- 文档:workline.md 新增 §5 P7 参考项目差距闭环(含完整文件清单)
2026-07-13 14:27:04 +08:00

91 lines
2.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
/**
* 可观测性 Provider 组件P6 硬化)
*
* 整合 Sentry + Web Vitals + OTel 初始化,在应用启动时调用各 init 函数。
* - "use client" 客户端组件
* - 在 useEffect 中按需初始化各可观测性模块(动态 import 避免未安装包问题)
* - 不渲染任何可见 UI返回 children
* - 条件初始化:根据环境变量决定是否启用各模块
*
* 关联02-architecture-design.md §12 可观测性 / project_rules §12 可观测性规范
*/
import { useEffect, type ReactNode } from "react";
/**
* 可观测性 Provider。
*
* 在客户端挂载时初始化 Sentry / Web Vitals / OTel。
* 所有初始化均为条件性:未配置对应环境变量时跳过,未安装包时降级。
*
* 不渲染任何可见 UI仅透传 children。
*/
export function ObservabilityProvider({
children,
}: {
children: ReactNode;
}): ReactNode {
useEffect(() => {
// 并行初始化各可观测性模块(互不依赖)
const initObservability = async (): Promise<void> => {
// 1. Sentry 错误追踪条件NEXT_PUBLIC_SENTRY_DSN 配置时)
try {
const { initSentry } = await import(
"@/lib/observability/sentry"
);
await initSentry();
} catch (err) {
if (typeof console !== "undefined") {
console.warn("[teacher-portal] Sentry 初始化失败", err);
}
}
// 2. Web Vitals RUM 采集(生产环境启用)
if (process.env.NODE_ENV === "production") {
try {
const { initWebVitals } = await import(
"@/lib/observability/web-vitals"
);
await initWebVitals();
} catch (err) {
if (typeof console !== "undefined") {
console.warn("[teacher-portal] Web Vitals 初始化失败", err);
}
}
}
// 3. OTel browser SDK条件NEXT_PUBLIC_OTEL_ENABLED=true 时)
try {
const { initOTel } = await import("@/lib/observability/otel");
await initOTel();
} catch (err) {
if (typeof console !== "undefined") {
console.warn("[teacher-portal] OTel 初始化失败", err);
}
}
// 4. Cookie 迁移条件NEXT_PUBLIC_COOKIE_MIGRATION_ENABLED=true 时)
// 实际迁移在 iam refresh cookie 端点就绪后启用,此处仅做准备
try {
const { migrateTokenToCookie } = await import(
"@/lib/observability/cookie-migration"
);
// 后台执行迁移,不阻塞应用渲染
void migrateTokenToCookie();
} catch {
// 迁移失败不影响应用功能,静默忽略
}
};
// 后台初始化,不阻塞渲染
void initObservability();
}, []);
// 不渲染任何可见 UI仅透传 children
return children;
}
export default ObservabilityProvider;