From 762114b7c4d28027cdc7a673035f87664cc0fe68 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 13 Mar 2025 19:42:52 +0100 Subject: [PATCH] Log BuildResult --- src/libstore/build-result.cc | 25 ++++++++++++ src/libstore/build-result.hh | 52 +++++++++++++++---------- src/libstore/build/derivation-goal.cc | 7 ++++ src/libstore/build/substitution-goal.cc | 11 ++++++ src/libutil/logging.hh | 1 + 5 files changed, 75 insertions(+), 21 deletions(-) diff --git a/src/libstore/build-result.cc b/src/libstore/build-result.cc index 96cbfd62f..3e316f679 100644 --- a/src/libstore/build-result.cc +++ b/src/libstore/build-result.cc @@ -1,8 +1,33 @@ #include "build-result.hh" +#include + namespace nix { bool BuildResult::operator==(const BuildResult &) const noexcept = default; std::strong_ordering BuildResult::operator<=>(const BuildResult &) const noexcept = default; +void to_json(nlohmann::json & json, const BuildResult & buildResult) +{ + json = nlohmann::json::object(); + json["status"] = BuildResult::statusToString(buildResult.status); + if (buildResult.errorMsg != "") + json["errorMsg"] = buildResult.errorMsg; + if (buildResult.timesBuilt) + json["timesBuilt"] = buildResult.timesBuilt; + if (buildResult.isNonDeterministic) + json["isNonDeterministic"] = buildResult.isNonDeterministic; + if (buildResult.startTime) + json["startTime"] = buildResult.startTime; + if (buildResult.stopTime) + json["stopTime"] = buildResult.stopTime; +} + +nlohmann::json KeyedBuildResult::toJSON(Store & store) const +{ + auto json = nlohmann::json((const BuildResult &) *this); + json["path"] = path.toJSON(store); + return json; +} + } diff --git a/src/libstore/build-result.hh b/src/libstore/build-result.hh index 8c66cfeb3..f56817f19 100644 --- a/src/libstore/build-result.hh +++ b/src/libstore/build-result.hh @@ -8,6 +8,8 @@ #include #include +#include + namespace nix { struct BuildResult @@ -46,28 +48,32 @@ struct BuildResult */ std::string errorMsg; + static std::string_view statusToString(Status status) + { + switch (status) { + case Built: return "Built"; + case Substituted: return "Substituted"; + case AlreadyValid: return "AlreadyValid"; + case PermanentFailure: return "PermanentFailure"; + case InputRejected: return "InputRejected"; + case OutputRejected: return "OutputRejected"; + case TransientFailure: return "TransientFailure"; + case CachedFailure: return "CachedFailure"; + case TimedOut: return "TimedOut"; + case MiscFailure: return "MiscFailure"; + case DependencyFailed: return "DependencyFailed"; + case LogLimitExceeded: return "LogLimitExceeded"; + case NotDeterministic: return "NotDeterministic"; + case ResolvesToAlreadyValid: return "ResolvesToAlreadyValid"; + case NoSubstituters: return "NoSubstituters"; + default: return "Unknown"; + }; + } + std::string toString() const { - auto strStatus = [&]() { - switch (status) { - case Built: return "Built"; - case Substituted: return "Substituted"; - case AlreadyValid: return "AlreadyValid"; - case PermanentFailure: return "PermanentFailure"; - case InputRejected: return "InputRejected"; - case OutputRejected: return "OutputRejected"; - case TransientFailure: return "TransientFailure"; - case CachedFailure: return "CachedFailure"; - case TimedOut: return "TimedOut"; - case MiscFailure: return "MiscFailure"; - case DependencyFailed: return "DependencyFailed"; - case LogLimitExceeded: return "LogLimitExceeded"; - case NotDeterministic: return "NotDeterministic"; - case ResolvesToAlreadyValid: return "ResolvesToAlreadyValid"; - case NoSubstituters: return "NoSubstituters"; - default: return "Unknown"; - }; - }(); - return strStatus + ((errorMsg == "") ? "" : " : " + errorMsg); + return + std::string(statusToString(status)) + + ((errorMsg == "") ? "" : " : " + errorMsg); } /** @@ -128,6 +134,10 @@ struct KeyedBuildResult : BuildResult KeyedBuildResult(BuildResult res, DerivedPath path) : BuildResult(std::move(res)), path(std::move(path)) { } + + nlohmann::json toJSON(Store & store) const; }; +void to_json(nlohmann::json & json, const BuildResult & buildResult); + } diff --git a/src/libstore/build/derivation-goal.cc b/src/libstore/build/derivation-goal.cc index 714dc87c8..6c335e17c 100644 --- a/src/libstore/build/derivation-goal.cc +++ b/src/libstore/build/derivation-goal.cc @@ -1563,6 +1563,13 @@ Goal::Done DerivationGoal::done( fs << worker.store.printStorePath(drvPath) << "\t" << buildResult.toString() << std::endl; } + logger->result( + act ? act->id : getCurActivity(), + resBuildResult, + KeyedBuildResult( + buildResult, + DerivedPath::Built{.drvPath = makeConstantStorePathRef(drvPath), .outputs = wantedOutputs}).toJSON(worker.store)); + return amDone(buildResult.success() ? ecSuccess : ecFailed, std::move(ex)); } diff --git a/src/libstore/build/substitution-goal.cc b/src/libstore/build/substitution-goal.cc index 983c86601..625e64781 100644 --- a/src/libstore/build/substitution-goal.cc +++ b/src/libstore/build/substitution-goal.cc @@ -3,8 +3,11 @@ #include "nar-info.hh" #include "finally.hh" #include "signals.hh" + #include +#include + namespace nix { PathSubstitutionGoal::PathSubstitutionGoal(const StorePath & storePath, Worker & worker, RepairFlag repair, std::optional ca) @@ -35,6 +38,14 @@ Goal::Done PathSubstitutionGoal::done( debug(*errorMsg); buildResult.errorMsg = *errorMsg; } + + logger->result( + getCurActivity(), + resBuildResult, + KeyedBuildResult( + buildResult, + DerivedPath::Opaque{storePath}).toJSON(worker.store)); + return amDone(result); } diff --git a/src/libutil/logging.hh b/src/libutil/logging.hh index 9d655f735..aeb058526 100644 --- a/src/libutil/logging.hh +++ b/src/libutil/logging.hh @@ -39,6 +39,7 @@ typedef enum { resPostBuildLogLine = 107, resFetchStatus = 108, resHashMismatch = 109, + resBuildResult = 110, } ResultType; typedef uint64_t ActivityId;