
### Summary Currently, if the setting `interpreter.save-transcript` is enabled, whenever we call "statistics dump", it'll default to reporting a huge list of transcripts which can be a bit noisy. This is because the current check `GetIncludeTranscript` returns `!GetSummaryOnly()` by default if no specific transcript-setting option is given in the statistics dump command (ie. `statistics dump --transcripts=false` or `statistics dump --transcripts=true`). Then when `interpreter.save-transcript` is enabled, this saves a list of transcripts, and the transcript list ends up getting logged by default. These changes default the option to log transcripts in the `statistics dump` command to "false". This can still be enabled via the `--transcripts` option if users want to see a transcript. Since `interpreter.save-transcript` is false by default, the main delta is that if `interpreter.save-transcript` is true and summary mode is false, we now disable saving the transcript. This also adds a warning to 'statistics dump --transcript=true' when interpreter.save-transcript is disabled, which should help users understand why transcript data is empty. ### Testing #### Manual testing Tested with `settings set interpreter.save-transcript true` enabled at startup on a toy hello-world program: ``` (lldb) settings set interpreter.save-transcript true (lldb) target create "/home/qxy11/hello-world/a.out" Current executable set to '/home/qxy11/hello-world/a.out' (x86_64). (lldb) statistics dump { /* no transcript */ } (lldb) statistics dump --transcript=true { "transcript": [ { "command": "statistics dump", "commandArguments": "", "commandName": "statistics dump", "durationInSeconds": 0.0019650000000000002, "error": "", "output": "{... }, { "command": "statistics dump --transcript=true", "commandArguments": "--transcript=true", "commandName": "statistics dump", "timestampInEpochSeconds": 1750720021 } ] } ``` Without `settings set interpreter.save-transcript true`: ``` (lldb) target create "/home/qxy11/hello-world/a.out" Current executable set to '/home/qxy11/hello-world/a.out' (x86_64). (lldb) statistics dump { /* no transcript */ } (lldb) statistics dump --transcript=true { /* no transcript */ } warning: transcript requested but none was saved. Enable with 'settings set interpreter.save-transcript true' ``` #### Unit tests Changed unit tests to account for new expected default behavior to `false`, and added a couple new tests around expected behavior with `--transcript=true`. ``` lldb-dotest -p TestStats ~/llvm-sand/external/llvm-project/lldb/test/API/commands/statistics/basic/ ```
182 lines
6.3 KiB
C++
182 lines
6.3 KiB
C++
//===-- CommandObjectStats.cpp --------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "CommandObjectStats.h"
|
|
#include "lldb/Core/Debugger.h"
|
|
#include "lldb/Host/OptionParser.h"
|
|
#include "lldb/Interpreter/CommandInterpreter.h"
|
|
#include "lldb/Interpreter/CommandOptionArgumentTable.h"
|
|
#include "lldb/Interpreter/CommandReturnObject.h"
|
|
#include "lldb/Interpreter/OptionArgParser.h"
|
|
#include "lldb/Target/Target.h"
|
|
|
|
using namespace lldb;
|
|
using namespace lldb_private;
|
|
|
|
class CommandObjectStatsEnable : public CommandObjectParsed {
|
|
public:
|
|
CommandObjectStatsEnable(CommandInterpreter &interpreter)
|
|
: CommandObjectParsed(interpreter, "enable",
|
|
"Enable statistics collection", nullptr,
|
|
eCommandProcessMustBePaused) {}
|
|
|
|
~CommandObjectStatsEnable() override = default;
|
|
|
|
protected:
|
|
void DoExecute(Args &command, CommandReturnObject &result) override {
|
|
if (DebuggerStats::GetCollectingStats()) {
|
|
result.AppendError("statistics already enabled");
|
|
return;
|
|
}
|
|
|
|
DebuggerStats::SetCollectingStats(true);
|
|
result.SetStatus(eReturnStatusSuccessFinishResult);
|
|
}
|
|
};
|
|
|
|
class CommandObjectStatsDisable : public CommandObjectParsed {
|
|
public:
|
|
CommandObjectStatsDisable(CommandInterpreter &interpreter)
|
|
: CommandObjectParsed(interpreter, "disable",
|
|
"Disable statistics collection", nullptr,
|
|
eCommandProcessMustBePaused) {}
|
|
|
|
~CommandObjectStatsDisable() override = default;
|
|
|
|
protected:
|
|
void DoExecute(Args &command, CommandReturnObject &result) override {
|
|
if (!DebuggerStats::GetCollectingStats()) {
|
|
result.AppendError("need to enable statistics before disabling them");
|
|
return;
|
|
}
|
|
|
|
DebuggerStats::SetCollectingStats(false);
|
|
result.SetStatus(eReturnStatusSuccessFinishResult);
|
|
}
|
|
};
|
|
|
|
#define LLDB_OPTIONS_statistics_dump
|
|
#include "CommandOptions.inc"
|
|
|
|
class CommandObjectStatsDump : public CommandObjectParsed {
|
|
class CommandOptions : public Options {
|
|
public:
|
|
CommandOptions() { OptionParsingStarting(nullptr); }
|
|
|
|
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
|
|
ExecutionContext *execution_context) override {
|
|
Status error;
|
|
const int short_option = m_getopt_table[option_idx].val;
|
|
|
|
switch (short_option) {
|
|
case 'a':
|
|
m_all_targets = true;
|
|
break;
|
|
case 's':
|
|
m_stats_options.SetSummaryOnly(true);
|
|
break;
|
|
case 'f':
|
|
m_stats_options.SetLoadAllDebugInfo(true);
|
|
break;
|
|
case 'r':
|
|
if (llvm::Expected<bool> bool_or_error =
|
|
OptionArgParser::ToBoolean("--targets", option_arg))
|
|
m_stats_options.SetIncludeTargets(*bool_or_error);
|
|
else
|
|
error = Status::FromError(bool_or_error.takeError());
|
|
break;
|
|
case 'm':
|
|
if (llvm::Expected<bool> bool_or_error =
|
|
OptionArgParser::ToBoolean("--modules", option_arg))
|
|
m_stats_options.SetIncludeModules(*bool_or_error);
|
|
else
|
|
error = Status::FromError(bool_or_error.takeError());
|
|
break;
|
|
case 't':
|
|
if (llvm::Expected<bool> bool_or_error =
|
|
OptionArgParser::ToBoolean("--transcript", option_arg))
|
|
m_stats_options.SetIncludeTranscript(*bool_or_error);
|
|
else
|
|
error = Status::FromError(bool_or_error.takeError());
|
|
break;
|
|
case 'p':
|
|
if (llvm::Expected<bool> bool_or_error =
|
|
OptionArgParser::ToBoolean("--plugins", option_arg))
|
|
m_stats_options.SetIncludePlugins(*bool_or_error);
|
|
else
|
|
error = Status::FromError(bool_or_error.takeError());
|
|
break;
|
|
default:
|
|
llvm_unreachable("Unimplemented option");
|
|
}
|
|
return error;
|
|
}
|
|
|
|
void OptionParsingStarting(ExecutionContext *execution_context) override {
|
|
m_all_targets = false;
|
|
m_stats_options = StatisticsOptions();
|
|
}
|
|
|
|
llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
|
|
return llvm::ArrayRef(g_statistics_dump_options);
|
|
}
|
|
|
|
const StatisticsOptions &GetStatisticsOptions() { return m_stats_options; }
|
|
|
|
bool m_all_targets = false;
|
|
StatisticsOptions m_stats_options = StatisticsOptions();
|
|
};
|
|
|
|
public:
|
|
CommandObjectStatsDump(CommandInterpreter &interpreter)
|
|
: CommandObjectParsed(
|
|
interpreter, "statistics dump", "Dump metrics in JSON format",
|
|
"statistics dump [<options>]", eCommandRequiresTarget) {}
|
|
|
|
~CommandObjectStatsDump() override = default;
|
|
|
|
Options *GetOptions() override { return &m_options; }
|
|
|
|
protected:
|
|
void DoExecute(Args &command, CommandReturnObject &result) override {
|
|
Target *target = nullptr;
|
|
if (!m_options.m_all_targets)
|
|
target = m_exe_ctx.GetTargetPtr();
|
|
|
|
// Check if transcript is requested but transcript saving is disabled
|
|
const StatisticsOptions &stats_options = m_options.GetStatisticsOptions();
|
|
if (stats_options.GetIncludeTranscript() &&
|
|
!GetDebugger().GetCommandInterpreter().GetSaveTranscript()) {
|
|
result.AppendWarning(
|
|
"transcript requested but none was saved. Enable with "
|
|
"'settings set interpreter.save-transcript true'");
|
|
}
|
|
|
|
result.AppendMessageWithFormatv(
|
|
"{0:2}",
|
|
DebuggerStats::ReportStatistics(GetDebugger(), target, stats_options));
|
|
result.SetStatus(eReturnStatusSuccessFinishResult);
|
|
}
|
|
|
|
CommandOptions m_options;
|
|
};
|
|
|
|
CommandObjectStats::CommandObjectStats(CommandInterpreter &interpreter)
|
|
: CommandObjectMultiword(interpreter, "statistics",
|
|
"Print statistics about a debugging session",
|
|
"statistics <subcommand> [<subcommand-options>]") {
|
|
LoadSubCommand("enable",
|
|
CommandObjectSP(new CommandObjectStatsEnable(interpreter)));
|
|
LoadSubCommand("disable",
|
|
CommandObjectSP(new CommandObjectStatsDisable(interpreter)));
|
|
LoadSubCommand("dump",
|
|
CommandObjectSP(new CommandObjectStatsDump(interpreter)));
|
|
}
|
|
|
|
CommandObjectStats::~CommandObjectStats() = default;
|