import "server-only" /** * 监控埋点接口(预留) * * 在关键 Server Action 中调用 trackEvent 记录业务事件,用于: * - 公告阅读率、消息回复率等关键指标统计 * - 通知发送失败告警 * - 用户行为漏斗分析 * * 当前实现:输出到 console.info,不阻塞主流程。 * 后续扩展:可接入外部监控服务(如 Sentry / PostHog / 自建埋点系统), * 只需在 trackEventToSink 中替换实现即可,调用方无需改动。 */ /** 事件名称(使用点号分隔的命名空间,如 "announcement.published") */ export type EventName = | "announcement.created" | "announcement.updated" | "announcement.published" | "announcement.archived" | "announcement.deleted" | "message.sent" | "message.deleted" | "message.marked_read" | "notification.marked_read" | "notification.marked_all_read" | "notification.sent" | "notification.send_failed" | "attendance.recorded" | "attendance.batch_recorded" | "attendance.updated" | "attendance.deleted" | "attendance.rules_saved" | "elective.course_created" | "elective.course_updated" | "elective.course_deleted" | "elective.selection_opened" | "elective.selection_closed" | "elective.course_selected" | "elective.course_dropped" | "elective.lottery_completed" /** 埋点事件负载 */ export interface TrackEventPayload { /** 事件名称 */ event: EventName /** 当前用户 ID(可选,未登录场景为 undefined) */ userId?: string /** 目标对象 ID(如公告 ID、消息 ID) */ targetId?: string /** 目标对象类型(如 "announcement"、"message") */ targetType?: string /** 附加属性(如受众人数、渠道类型) */ properties?: Record } /** * 将事件发送到外部监控服务。 * * 当前为占位实现:仅输出到 console.info。 * 接入真实服务时替换此函数体即可。 */ function trackEventToSink(payload: TrackEventPayload): void { console.info( `[TrackEvent] ${payload.event} userId=${payload.userId ?? "-"} targetId=${payload.targetId ?? "-"}${payload.properties ? ` properties=${JSON.stringify(payload.properties)}` : ""}` ) } /** * 记录一个监控事件。 * * 非阻塞:任何异常都被吞掉,确保不影响主业务流程。 * * @example * ```ts * await trackEvent({ * event: "announcement.published", * userId: ctx.userId, * targetId: id, * targetType: "announcement", * properties: { audienceSize: userIds.length }, * }) * ``` */ export async function trackEvent(payload: TrackEventPayload): Promise { try { trackEventToSink(payload) } catch { // 埋点失败不影响主流程 } }