diff options
author | Klaus Aehlig <klaus.aehlig@huawei.com> | 2024-05-03 13:20:24 +0200 |
---|---|---|
committer | Klaus Aehlig <klaus.aehlig@huawei.com> | 2024-05-03 16:00:11 +0200 |
commit | aa3f72ba653c1444f4238ecb6e596aac6c20d1cb (patch) | |
tree | a5d572f36a1301a782edd06347cf0aed029da39e | |
parent | 573f9070257aa9161ac58d85386e3bca46ed0cc2 (diff) | |
download | justbuild-aa3f72ba653c1444f4238ecb6e596aac6c20d1cb.tar.gz |
Include environment in action reporting on the command line
Compared to the command line, the environment usually is quite
short. So including it in messages reporting about commands does
not introduce a lot of additional noise. However, knowing the
environment can help understanding an error message. Therefore, it
seems a good trade off to include it. Do so.
-rw-r--r-- | src/buildtool/execution_engine/executor/executor.hpp | 50 | ||||
-rw-r--r-- | test/end-to-end/actions/error-reporting.sh | 20 |
2 files changed, 42 insertions, 28 deletions
diff --git a/src/buildtool/execution_engine/executor/executor.hpp b/src/buildtool/execution_engine/executor/executor.hpp index ca174c84..f7afb077 100644 --- a/src/buildtool/execution_engine/executor/executor.hpp +++ b/src/buildtool/execution_engine/executor/executor.hpp @@ -524,7 +524,7 @@ class ExecutorImpl { } progress->TaskTracker().Stop(action->Content().Id()); - PrintInfo(logger, action->Command(), response); + PrintInfo(logger, action, response); bool should_fail_outputs = false; for (auto const& [local_path, node] : action->Dependencies()) { should_fail_outputs |= node->Content().Info()->failed; @@ -573,34 +573,36 @@ class ExecutorImpl { /// \brief Write out if response is empty and otherwise, write out /// standard error/output if they are present - void static PrintInfo(Logger const& logger, - std::vector<std::string> const& command, - IExecutionResponse::Ptr const& response) noexcept { + void static PrintInfo( + Logger const& logger, + gsl::not_null<DependencyGraph::ActionNode const*> const& action, + IExecutionResponse::Ptr const& response) noexcept { if (!response) { logger.Emit(LogLevel::Error, "response is empty"); return; } auto const has_err = response->HasStdErr(); auto const has_out = response->HasStdOut(); - auto build_message = - [has_err, has_out, &logger, &command, &response]() { - using namespace std::string_literals; - auto message = ""s; - if (has_err or has_out) { - message += (has_err and has_out ? "Stdout and stderr"s - : has_out ? "Stdout"s - : "Stderr"s) + - " of command: "; - } - message += nlohmann::json(command).dump() + "\n"; - if (response->HasStdOut()) { - message += response->StdOut(); - } - if (response->HasStdErr()) { - message += response->StdErr(); - } - return message; - }; + auto build_message = [has_err, has_out, &logger, &action, &response]() { + using namespace std::string_literals; + auto message = ""s; + if (has_err or has_out) { + message += (has_err and has_out ? "Stdout and stderr"s + : has_out ? "Stdout"s + : "Stderr"s) + + " of command "; + } + message += nlohmann::json(action->Command()).dump() + + " in environment " + + nlohmann::json(action->Env()).dump() + "\n"; + if (response->HasStdOut()) { + message += response->StdOut(); + } + if (response->HasStdErr()) { + message += response->StdErr(); + } + return message; + }; logger.Emit((has_err or has_out) ? LogLevel::Info : LogLevel::Debug, std::move(build_message)); } @@ -612,6 +614,8 @@ class ExecutorImpl { std::ostringstream msg{}; msg << "Failed to execute command "; msg << nlohmann::json(action->Command()).dump(); + msg << " in evenironment "; + msg << nlohmann::json(action->Env()).dump(); auto const& origin_map = progress->OriginMap(); auto origins = origin_map.find(action->Content().Id()); if (origins != origin_map.end() and !origins->second.empty()) { diff --git a/test/end-to-end/actions/error-reporting.sh b/test/end-to-end/actions/error-reporting.sh index 8705e6ec..e33b4b77 100644 --- a/test/end-to-end/actions/error-reporting.sh +++ b/test/end-to-end/actions/error-reporting.sh @@ -25,7 +25,7 @@ touch ROOT cat > TARGETS <<'EOF' { "theTargetCausingTheFailure": { "type": "generic" - , "arguments_config": ["foo", "bar"] + , "arguments_config": ["foo", "bar", "magic"] , "outs": ["a.txt"] , "cmds": [ { "type": "join" @@ -33,11 +33,17 @@ cat > TARGETS <<'EOF' [ "echo -n stdout-of-; echo failing-target-" , {"type": "var", "name": "foo", "default": ""} , {"type": "var", "name": "bar", "default": ""} + , "-$MAGIC_VAR" ] } , "touch a.txt" , "exit 42" ] + , "env": + { "type": "singleton_map" + , "key": "MAGIC_VAR" + , "value": {"type": "var", "name": "magic", "default": "unknown"} + } } } EOF @@ -49,7 +55,7 @@ echo mkdir -p "${OUT}" "${JUST}" build --local-build-root "${LBR}" \ -f "${OUT}/log" --log-limit 0 \ - -D '{"foo": "FOO", "irrelevant": "abc"}' \ + -D '{"foo": "FOO", "irrelevant": "abc", "magic":"xyz"}' \ 2>&1 && exit 1 || : # The exit code should be reported @@ -60,15 +66,19 @@ grep theTargetCausingTheFailure "${OUT}/log" # The pruned effective configuration should be reported in canonical # compact form. -grep '{"foo":"FOO"}' "${OUT}/log" +grep '{"foo":"FOO","magic":"xyz"}' "${OUT}/log" # At default level we should also find stdout of the target echo "${JUST}" build --local-build-root "${LBR}" \ -f "${OUT}/log.default" \ - -D '{"foo": "FOO", "irrelevant": "abc"}' \ + -D '{"foo": "FOO", "irrelevant": "abc", "magic":"xyz"}' \ 2>&1 && exit 1 || : -grep stdout-of-failing-target-FOO "${OUT}/log.default" +grep stdout-of-failing-target-FOO-xyz "${OUT}/log.default" + +# ... as well as command and environment in canonical compact form +grep 'echo -n stdout-of-;' "${OUT}/log.default" +grep '{"MAGIC_VAR":"xyz"}' "${OUT}/log.default" echo OK |