1//===-- CommandObjectStats.cpp --------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "CommandObjectStats.h"
10#include "lldb/Core/Debugger.h"
11#include "lldb/Host/OptionParser.h"
12#include "lldb/Interpreter/CommandInterpreter.h"
13#include "lldb/Interpreter/CommandOptionArgumentTable.h"
14#include "lldb/Interpreter/CommandReturnObject.h"
15#include "lldb/Interpreter/OptionArgParser.h"
16#include "lldb/Target/Target.h"
17
18using namespace lldb;
19using namespace lldb_private;
20
21class CommandObjectStatsEnable : public CommandObjectParsed {
22public:
23 CommandObjectStatsEnable(CommandInterpreter &interpreter)
24 : CommandObjectParsed(interpreter, "enable",
25 "Enable statistics collection", nullptr,
26 eCommandProcessMustBePaused) {}
27
28 ~CommandObjectStatsEnable() override = default;
29
30protected:
31 void DoExecute(Args &command, CommandReturnObject &result) override {
32 if (DebuggerStats::GetCollectingStats()) {
33 result.AppendError(in_string: "statistics already enabled");
34 return;
35 }
36
37 DebuggerStats::SetCollectingStats(true);
38 result.SetStatus(eReturnStatusSuccessFinishResult);
39 }
40};
41
42class CommandObjectStatsDisable : public CommandObjectParsed {
43public:
44 CommandObjectStatsDisable(CommandInterpreter &interpreter)
45 : CommandObjectParsed(interpreter, "disable",
46 "Disable statistics collection", nullptr,
47 eCommandProcessMustBePaused) {}
48
49 ~CommandObjectStatsDisable() override = default;
50
51protected:
52 void DoExecute(Args &command, CommandReturnObject &result) override {
53 if (!DebuggerStats::GetCollectingStats()) {
54 result.AppendError(in_string: "need to enable statistics before disabling them");
55 return;
56 }
57
58 DebuggerStats::SetCollectingStats(false);
59 result.SetStatus(eReturnStatusSuccessFinishResult);
60 }
61};
62
63#define LLDB_OPTIONS_statistics_dump
64#include "CommandOptions.inc"
65
66class CommandObjectStatsDump : public CommandObjectParsed {
67 class CommandOptions : public Options {
68 public:
69 CommandOptions() { OptionParsingStarting(execution_context: nullptr); }
70
71 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
72 ExecutionContext *execution_context) override {
73 Status error;
74 const int short_option = m_getopt_table[option_idx].val;
75
76 switch (short_option) {
77 case 'a':
78 m_all_targets = true;
79 break;
80 case 's':
81 m_stats_options.SetSummaryOnly(true);
82 break;
83 case 'f':
84 m_stats_options.SetLoadAllDebugInfo(true);
85 break;
86 case 'r':
87 if (llvm::Expected<bool> bool_or_error =
88 OptionArgParser::ToBoolean(option_name: "--targets", option_arg))
89 m_stats_options.SetIncludeTargets(*bool_or_error);
90 else
91 error = Status::FromError(error: bool_or_error.takeError());
92 break;
93 case 'm':
94 if (llvm::Expected<bool> bool_or_error =
95 OptionArgParser::ToBoolean(option_name: "--modules", option_arg))
96 m_stats_options.SetIncludeModules(*bool_or_error);
97 else
98 error = Status::FromError(error: bool_or_error.takeError());
99 break;
100 case 't':
101 if (llvm::Expected<bool> bool_or_error =
102 OptionArgParser::ToBoolean(option_name: "--transcript", option_arg))
103 m_stats_options.SetIncludeTranscript(*bool_or_error);
104 else
105 error = Status::FromError(error: bool_or_error.takeError());
106 break;
107 case 'p':
108 if (llvm::Expected<bool> bool_or_error =
109 OptionArgParser::ToBoolean(option_name: "--plugins", option_arg))
110 m_stats_options.SetIncludePlugins(*bool_or_error);
111 else
112 error = Status::FromError(error: bool_or_error.takeError());
113 break;
114 default:
115 llvm_unreachable("Unimplemented option");
116 }
117 return error;
118 }
119
120 void OptionParsingStarting(ExecutionContext *execution_context) override {
121 m_all_targets = false;
122 m_stats_options = StatisticsOptions();
123 }
124
125 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
126 return llvm::ArrayRef(g_statistics_dump_options);
127 }
128
129 const StatisticsOptions &GetStatisticsOptions() { return m_stats_options; }
130
131 bool m_all_targets = false;
132 StatisticsOptions m_stats_options = StatisticsOptions();
133 };
134
135public:
136 CommandObjectStatsDump(CommandInterpreter &interpreter)
137 : CommandObjectParsed(
138 interpreter, "statistics dump", "Dump metrics in JSON format",
139 "statistics dump [<options>]", eCommandRequiresTarget) {}
140
141 ~CommandObjectStatsDump() override = default;
142
143 Options *GetOptions() override { return &m_options; }
144
145protected:
146 void DoExecute(Args &command, CommandReturnObject &result) override {
147 Target *target = nullptr;
148 if (!m_options.m_all_targets)
149 target = m_exe_ctx.GetTargetPtr();
150
151 // Check if transcript is requested but transcript saving is disabled
152 const StatisticsOptions &stats_options = m_options.GetStatisticsOptions();
153 if (stats_options.GetIncludeTranscript() &&
154 !GetDebugger().GetCommandInterpreter().GetSaveTranscript()) {
155 result.AppendWarning(
156 in_string: "transcript requested but none was saved. Enable with "
157 "'settings set interpreter.save-transcript true'");
158 }
159
160 result.AppendMessageWithFormatv(
161 format: "{0:2}",
162 args: DebuggerStats::ReportStatistics(debugger&: GetDebugger(), target, options: stats_options));
163 result.SetStatus(eReturnStatusSuccessFinishResult);
164 }
165
166 CommandOptions m_options;
167};
168
169CommandObjectStats::CommandObjectStats(CommandInterpreter &interpreter)
170 : CommandObjectMultiword(interpreter, "statistics",
171 "Print statistics about a debugging session",
172 "statistics <subcommand> [<subcommand-options>]") {
173 LoadSubCommand(cmd_name: "enable",
174 command_obj: CommandObjectSP(new CommandObjectStatsEnable(interpreter)));
175 LoadSubCommand(cmd_name: "disable",
176 command_obj: CommandObjectSP(new CommandObjectStatsDisable(interpreter)));
177 LoadSubCommand(cmd_name: "dump",
178 command_obj: CommandObjectSP(new CommandObjectStatsDump(interpreter)));
179}
180
181CommandObjectStats::~CommandObjectStats() = default;
182

source code of lldb/source/Commands/CommandObjectStats.cpp