diff --git a/eden/fs/service/EdenServer.cpp b/eden/fs/service/EdenServer.cpp index 0b9b72d4384d4..715e4217c69c2 100644 --- a/eden/fs/service/EdenServer.cpp +++ b/eden/fs/service/EdenServer.cpp @@ -2761,7 +2761,10 @@ void EdenServer::runEdenDoctor() { folly::CPUThreadPoolExecutor executor(1); auto systemConfigDir = config_->getEdenConfig()->getSystemConfigDir(); auto edenDir = getEdenDir(); - executor.add([systemConfigDir, edenDir] { + auto structuredLogger = structuredLogger_; + executor.add([systemConfigDir, edenDir, structuredLogger] { + auto doctorRunStatus = AutoEdenDoctorRunEvent::Success; + auto statusReason = std::string(); try { XLOG(INFO, "Running periodic eden doctor dry-run."); // Not passing Options field cause "0x57" error. ref: D59783277 @@ -2794,11 +2797,19 @@ void EdenServer::runEdenDoctor() { XLOG( ERR, "EdenFS doctor dry run failed or timed-out. Check edenfs doctor scuba logs for more info."); + doctorRunStatus = AutoEdenDoctorRunEvent::TimeoutOrFailure; } } catch (const std::exception& e) { XLOG(ERR) << "Exception occurred while trying to run periodic doctor dry-run: " << e.what(); + doctorRunStatus = AutoEdenDoctorRunEvent::ProcessCreationFailure; + statusReason = e.what(); + } + + if (structuredLogger) { + structuredLogger->logEvent( + AutoEdenDoctorRunEvent{doctorRunStatus, statusReason}); } }); } diff --git a/eden/fs/telemetry/LogEvent.h b/eden/fs/telemetry/LogEvent.h index 9fc8ee75f3ec7..e5dc757f927f0 100644 --- a/eden/fs/telemetry/LogEvent.h +++ b/eden/fs/telemetry/LogEvent.h @@ -752,4 +752,43 @@ struct FileAccessEvent : public EdenFSFileAccessEvent { } }; +/** + * Used to log status of automatic doctor runs + */ +struct AutoEdenDoctorRunEvent : public EdenFSEvent { + enum RunStatus : uint8_t { + Success = 0, + ProcessCreationFailure = 1, + TimeoutOrFailure = 2 + }; + + RunStatus run_status; + std::string failure_reason; + + explicit AutoEdenDoctorRunEvent( + RunStatus run_status, + std::string failure_reason) + : run_status(run_status), failure_reason(std::move(failure_reason)) {} + + void populate(DynamicEvent& event) const override { + if (run_status == Success) { + event.addString("run_status", "Success"); + } else if (run_status == ProcessCreationFailure) { + event.addString("run_status", "ProcessCreationFailure"); + } else if (run_status == TimeoutOrFailure) { + event.addString("run_status", "TimeoutOrFailure"); + } else { + // Logging numerical value in case there is no string mapping here + event.addString("run_status", std::to_string(run_status)); + } + + // Re-using existing column + event.addString("reason", failure_reason); + } + + const char* getType() const override { + return "auto_eden_doctor_run_events"; + } +}; + } // namespace facebook::eden