From 0dcaf7915f2404ab4487cfd8187e358a4e22abc5 Mon Sep 17 00:00:00 2001 From: iven Date: Thu, 30 Apr 2026 16:58:04 +0800 Subject: [PATCH] =?UTF-8?q?fix(health):=20=E8=A1=A5=E5=85=85=203=20?= =?UTF-8?q?=E4=B8=AA=E6=A0=B8=E5=BF=83=20service=20=E7=9A=84=20tracing=20?= =?UTF-8?q?=E6=97=A5=E5=BF=97=20=E2=80=94=2038=20=E5=A4=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 审计后续 H3: patient_service(15) + consultation_service(10) + follow_up_service(13) 共计 2526 行代码此前 0 处运维级日志,现已在所有 pub async fn 入口添加 tracing::info! 日志,格式统一为 action + key params。 --- .../src/service/consultation_service.rs | 16 +++++++++++++--- .../erp-health/src/service/follow_up_service.rs | 13 +++++++++++++ .../erp-health/src/service/patient_service.rs | 17 +++++++++++++++++ 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/crates/erp-health/src/service/consultation_service.rs b/crates/erp-health/src/service/consultation_service.rs index 53e289c..0e97224 100644 --- a/crates/erp-health/src/service/consultation_service.rs +++ b/crates/erp-health/src/service/consultation_service.rs @@ -41,6 +41,7 @@ pub async fn create_session( operator_id: Option, req: CreateSessionReq, ) -> HealthResult { + tracing::info!(action = "create_session", patient_id = %req.patient_id, "Creating consultation session"); let now = Utc::now(); // 校验患者存在 @@ -100,6 +101,7 @@ pub async fn get_session( tenant_id: Uuid, session_id: Uuid, ) -> HealthResult { + tracing::info!(action = "get_session", session_id = %session_id, "Fetching consultation session"); let model = consultation_session::Entity::find() .filter(consultation_session::Column::Id.eq(session_id)) .filter(consultation_session::Column::TenantId.eq(tenant_id)) @@ -120,6 +122,7 @@ pub async fn list_sessions( patient_id: Option, doctor_id: Option, ) -> HealthResult> { + tracing::info!(action = "list_sessions", page, page_size, "Listing consultation sessions"); let limit = page_size.min(100); let offset = page.saturating_sub(1) * limit; @@ -152,6 +155,7 @@ pub async fn close_session( operator_id: Option, expected_version: i32, ) -> HealthResult { + tracing::info!(action = "close_session", session_id = %session_id, expected_version, "Closing consultation session"); let model = consultation_session::Entity::find() .filter(consultation_session::Column::Id.eq(session_id)) .filter(consultation_session::Column::TenantId.eq(tenant_id)) @@ -204,6 +208,7 @@ pub async fn export_sessions( page: Option, page_size: Option, ) -> HealthResult> { + tracing::info!(action = "export_sessions", "Exporting consultation sessions"); let limit = page_size.unwrap_or(100).min(500); let page_num = page.unwrap_or(1); let offset = page_num.saturating_sub(1) * limit; @@ -277,6 +282,7 @@ pub async fn list_messages( page_size: u64, after_id: Option, ) -> HealthResult> { + tracing::info!(action = "list_messages", session_id = %session_id, page, page_size, "Listing consultation messages"); let limit = page_size.min(100); let mut query = consultation_message::Entity::find() @@ -290,7 +296,7 @@ pub async fn list_messages( } let offset = page.saturating_sub(1) * limit; - let total = query.clone().count(&state.db).await?; + let _total = query.clone().count(&state.db).await?; let total = query.clone().count(&state.db).await?; let models = query @@ -322,6 +328,7 @@ pub async fn create_message( sender_role: String, req: CreateMessageReq, ) -> HealthResult { + tracing::info!(action = "create_message", session_id = %req.session_id, sender_role = %sender_role, "Creating consultation message"); // 校验会话存在且状态为 active 或 waiting let session = consultation_session::Entity::find() .filter(consultation_session::Column::Id.eq(req.session_id)) @@ -445,9 +452,10 @@ pub async fn mark_session_read( state: &HealthState, tenant_id: Uuid, session_id: Uuid, - user_id: Uuid, + _user_id: Uuid, role: &str, ) -> HealthResult<()> { + tracing::info!(action = "mark_session_read", session_id = %session_id, role, "Marking consultation session as read"); let session = consultation_session::Entity::find() .filter(consultation_session::Column::Id.eq(session_id)) .filter(consultation_session::Column::TenantId.eq(tenant_id)) @@ -499,6 +507,7 @@ pub async fn get_doctor_dashboard( tenant_id: Uuid, doctor_user_id: Uuid, ) -> HealthResult { + tracing::info!(action = "get_doctor_dashboard", doctor_user_id = %doctor_user_id, "Fetching doctor dashboard"); use crate::entity::{doctor_profile, patient_doctor_relation, follow_up_task}; use sea_orm::ColumnTrait; use sea_orm::QueryFilter; @@ -605,8 +614,9 @@ pub async fn enrich_doctor_dashboard_health( doctor_user_id: Uuid, dashboard: &mut DoctorDashboard, ) -> HealthResult<()> { + tracing::info!(action = "enrich_doctor_dashboard_health", doctor_user_id = %doctor_user_id, "Enriching doctor dashboard with health data"); use crate::entity::{lab_report, appointment}; - use sea_orm::{FromQueryResult, Statement, DatabaseBackend}; + // 待审核化验报告 let pending_lab = lab_report::Entity::find() diff --git a/crates/erp-health/src/service/follow_up_service.rs b/crates/erp-health/src/service/follow_up_service.rs index f30eb4e..fb43be8 100644 --- a/crates/erp-health/src/service/follow_up_service.rs +++ b/crates/erp-health/src/service/follow_up_service.rs @@ -32,6 +32,7 @@ pub async fn list_tasks( assigned_to: Option, status: Option, ) -> HealthResult> { + tracing::info!(action = "list_tasks", page, page_size, "Listing follow-up tasks"); let limit = page_size.min(100); let offset = page.saturating_sub(1) * limit; @@ -111,6 +112,7 @@ pub async fn get_task( tenant_id: Uuid, task_id: Uuid, ) -> HealthResult { + tracing::info!(action = "get_task", task_id = %task_id, "Fetching follow-up task"); let m = follow_up_task::Entity::find() .filter(follow_up_task::Column::Id.eq(task_id)) .filter(follow_up_task::Column::TenantId.eq(tenant_id)) @@ -135,6 +137,7 @@ pub async fn create_task( operator_id: Option, req: CreateFollowUpTaskReq, ) -> HealthResult { + tracing::info!(action = "create_task", patient_id = %req.patient_id, "Creating follow-up task"); let now = Utc::now(); validate_follow_up_type(&req.follow_up_type)?; @@ -203,6 +206,7 @@ pub async fn update_task( req: UpdateFollowUpTaskReq, expected_version: i32, ) -> HealthResult { + tracing::info!(action = "update_task", task_id = %task_id, expected_version, "Updating follow-up task"); let model = follow_up_task::Entity::find() .filter(follow_up_task::Column::Id.eq(task_id)) .filter(follow_up_task::Column::TenantId.eq(tenant_id)) @@ -273,6 +277,7 @@ pub async fn delete_task( operator_id: Option, expected_version: i32, ) -> HealthResult<()> { + tracing::info!(action = "delete_task", task_id = %task_id, "Deleting follow-up task"); let model = follow_up_task::Entity::find() .filter(follow_up_task::Column::Id.eq(task_id)) .filter(follow_up_task::Column::TenantId.eq(tenant_id)) @@ -310,6 +315,7 @@ pub async fn batch_create_tasks( operator_id: Option, req: BatchCreateTasksReq, ) -> HealthResult { + tracing::info!(action = "batch_create_tasks", patient_count = req.patient_ids.len(), "Batch creating follow-up tasks"); validate_follow_up_type(&req.follow_up_type)?; let mut succeeded: u32 = 0; let mut errors: Vec = Vec::new(); @@ -394,6 +400,7 @@ pub async fn batch_assign_tasks( operator_id: Option, req: BatchAssignReq, ) -> HealthResult { + tracing::info!(action = "batch_assign_tasks", task_count = req.task_ids.len(), assigned_to = ?req.assigned_to, "Batch assigning follow-up tasks"); let mut succeeded: u32 = 0; let mut errors: Vec = Vec::new(); @@ -450,6 +457,7 @@ pub async fn batch_complete_tasks( operator_id: Option, req: BatchCompleteReq, ) -> HealthResult { + tracing::info!(action = "batch_complete_tasks", task_count = req.task_ids.len(), "Batch completing follow-up tasks"); let mut succeeded: u32 = 0; let mut errors: Vec = Vec::new(); @@ -524,6 +532,7 @@ pub async fn create_record( operator_id: Option, req: CreateFollowUpRecordReq, ) -> HealthResult { + tracing::info!(action = "create_record", task_id = %req.task_id, "Creating follow-up record"); let task = follow_up_task::Entity::find() .filter(follow_up_task::Column::Id.eq(req.task_id)) .filter(follow_up_task::Column::TenantId.eq(tenant_id)) @@ -634,6 +643,7 @@ pub async fn list_records( task_id: Option, patient_id: Option, ) -> HealthResult> { + tracing::info!(action = "list_records", page, page_size, "Listing follow-up records"); let limit = page_size.min(100); let offset = page.saturating_sub(1) * limit; @@ -699,6 +709,7 @@ pub async fn complete_task_by_system( task_id: Uuid, tenant_id: Uuid, ) -> HealthResult<()> { + tracing::info!(action = "complete_task_by_system", task_id = %task_id, "System completing follow-up task"); let model = follow_up_task::Entity::find() .filter(follow_up_task::Column::Id.eq(task_id)) .filter(follow_up_task::Column::TenantId.eq(tenant_id)) @@ -734,6 +745,7 @@ pub async fn complete_task_by_system( /// 批量将 planned_date < 今天 且 status = pending 的随访任务标记为 overdue。 /// 返回受影响的行数。 pub async fn check_overdue_tasks(db: &DatabaseConnection) -> HealthResult { + tracing::info!(action = "check_overdue_tasks", "Checking overdue follow-up tasks"); let today = chrono::Utc::now().date_naive(); let result = follow_up_task::Entity::update_many() .col_expr( @@ -762,6 +774,7 @@ pub async fn check_overdue_tasks(db: &DatabaseConnection) -> HealthResult { /// 只发布**本次新被标记**为 overdue 的事件,避免重复通知。 /// 幂等策略:先查出即将被标记的 pending 任务,批量更新后只为这些任务发事件。 pub async fn check_overdue_and_notify(state: &HealthState) -> HealthResult { + tracing::info!(action = "check_overdue_and_notify", "Checking overdue tasks and sending notifications"); let db = &state.db; let today = chrono::Utc::now().date_naive(); diff --git a/crates/erp-health/src/service/patient_service.rs b/crates/erp-health/src/service/patient_service.rs index f9c825f..ce231d7 100644 --- a/crates/erp-health/src/service/patient_service.rs +++ b/crates/erp-health/src/service/patient_service.rs @@ -37,6 +37,7 @@ pub async fn list_patients( search: Option, tag_id: Option, ) -> HealthResult> { + tracing::info!(action = "list_patients", tenant_id = %tenant_id, page, page_size, "Listing patients"); let limit = page_size.min(100); let offset = page.saturating_sub(1) * limit; @@ -102,6 +103,7 @@ pub async fn create_patient( operator_id: Option, req: CreatePatientReq, ) -> HealthResult { + tracing::info!(action = "create_patient", tenant_id = %tenant_id, name = %req.name, "Creating patient"); let now = Utc::now(); let id = Uuid::now_v7(); @@ -238,6 +240,7 @@ pub async fn get_patient( tenant_id: Uuid, id: Uuid, ) -> HealthResult { + tracing::info!(action = "get_patient", patient_id = %id, "Fetching patient"); let model = find_patient(&state.db, tenant_id, id).await?; Ok(model_to_resp_decrypted(&state.crypto, model)) } @@ -251,6 +254,7 @@ pub async fn update_patient( req: UpdatePatientReq, expected_version: i32, ) -> HealthResult { + tracing::info!(action = "update_patient", patient_id = %id, "Updating patient"); let model = find_patient(&state.db, tenant_id, id).await?; let next_ver = check_version(expected_version, model.version) .map_err(|_| HealthError::VersionMismatch)?; @@ -364,6 +368,7 @@ pub async fn delete_patient( operator_id: Option, expected_version: i32, ) -> HealthResult<()> { + tracing::info!(action = "delete_patient", patient_id = %id, "Soft deleting patient"); let model = find_patient(&state.db, tenant_id, id).await?; let next_ver = check_version(expected_version, model.version) .map_err(|_| HealthError::VersionMismatch)?; @@ -396,6 +401,7 @@ pub async fn manage_patient_tags( req: ManageTagsReq, operator_id: Option, ) -> HealthResult<()> { + tracing::info!(action = "manage_patient_tags", patient_id = %patient_id, tag_count = req.tag_ids.len(), "Managing patient tags"); // 确认患者存在 find_patient(&state.db, tenant_id, patient_id).await?; @@ -471,6 +477,7 @@ pub async fn get_health_summary( tenant_id: Uuid, patient_id: Uuid, ) -> HealthResult { + tracing::info!(action = "get_health_summary", patient_id = %patient_id, "Fetching health summary"); find_patient(&state.db, tenant_id, patient_id).await?; use crate::entity::{vital_signs, lab_report, appointment, follow_up_task}; @@ -532,6 +539,7 @@ pub async fn list_family_members( tenant_id: Uuid, patient_id: Uuid, ) -> HealthResult> { + tracing::info!(action = "list_family_members", patient_id = %patient_id, "Listing family members"); let models = patient_family_member::Entity::find() .filter(patient_family_member::Column::TenantId.eq(tenant_id)) .filter(patient_family_member::Column::PatientId.eq(patient_id)) @@ -568,6 +576,7 @@ pub async fn create_family_member( operator_id: Option, req: FamilyMemberReq, ) -> HealthResult { + tracing::info!(action = "create_family_member", patient_id = %patient_id, name = %req.name, "Creating family member"); find_patient(&state.db, tenant_id, patient_id).await?; let now = Utc::now(); @@ -637,6 +646,7 @@ pub async fn update_family_member( req: FamilyMemberReq, expected_version: i32, ) -> HealthResult { + tracing::info!(action = "update_family_member", patient_id = %patient_id, family_member_id = %family_member_id, "Updating family member"); let model = patient_family_member::Entity::find() .filter(patient_family_member::Column::Id.eq(family_member_id)) .filter(patient_family_member::Column::PatientId.eq(patient_id)) @@ -719,6 +729,7 @@ pub async fn delete_family_member( operator_id: Option, expected_version: i32, ) -> HealthResult<()> { + tracing::info!(action = "delete_family_member", family_member_id = %family_member_id, "Soft deleting family member"); let model = patient_family_member::Entity::find() .filter(patient_family_member::Column::Id.eq(family_member_id)) .filter(patient_family_member::Column::PatientId.eq(patient_id)) @@ -760,6 +771,7 @@ pub async fn assign_doctor( relationship_type: String, operator_id: Option, ) -> HealthResult<()> { + tracing::info!(action = "assign_doctor", patient_id = %patient_id, doctor_id = %doctor_id, "Assigning doctor to patient"); find_patient(&state.db, tenant_id, patient_id).await?; // 验证医生存在 @@ -816,6 +828,7 @@ pub async fn remove_doctor( doctor_id: Uuid, operator_id: Option, ) -> HealthResult<()> { + tracing::info!(action = "remove_doctor", patient_id = %patient_id, doctor_id = %doctor_id, "Removing doctor from patient"); let model = patient_doctor_relation::Entity::find() .filter(patient_doctor_relation::Column::TenantId.eq(tenant_id)) .filter(patient_doctor_relation::Column::PatientId.eq(patient_id)) @@ -927,6 +940,7 @@ pub async fn list_tags( state: &crate::state::HealthState, tenant_id: Uuid, ) -> HealthResult> { + tracing::info!(action = "list_tags", tenant_id = %tenant_id, "Listing patient tags"); use crate::entity::patient_tag; let tags = patient_tag::Entity::find() .filter(patient_tag::Column::TenantId.eq(tenant_id)) @@ -972,6 +986,7 @@ pub async fn create_tag( operator_id: Option, req: CreateTagReq, ) -> HealthResult { + tracing::info!(action = "create_tag", tenant_id = %tenant_id, name = %req.name, "Creating patient tag"); let id = Uuid::now_v7(); let now = Utc::now(); let tag = patient_tag::ActiveModel { @@ -1016,6 +1031,7 @@ pub async fn update_tag( operator_id: Option, req: UpdateTagReq, ) -> HealthResult { + tracing::info!(action = "update_tag", tag_id = %tag_id, "Updating patient tag"); let tag = patient_tag::Entity::find_by_id(tag_id) .one(&state.db) .await? @@ -1068,6 +1084,7 @@ pub async fn delete_tag( operator_id: Option, version: i32, ) -> HealthResult<()> { + tracing::info!(action = "delete_tag", tag_id = %tag_id, "Soft deleting patient tag"); let tag = patient_tag::Entity::find_by_id(tag_id) .one(&state.db) .await?