58 static std::vector<char> statesActive(
states.statesViews.size(),
false);
59 if (statesActive.size() !=
states.statesViews.size()) {
60 statesActive.resize(
states.statesViews.size(),
false);
63 if (ImGui::CollapsingHeader(
"Remote state", ImGuiTreeNodeFlags_DefaultOpen)) {
64 for (
size_t i = 0;
i <
states.stateNames.size(); ++
i) {
65 if (
states.stateNames[
i].empty()) {
68 auto& view =
states.statesViews[
i];
72 ImGui::Checkbox(
states.stateNames[
i].c_str(), (
bool*)&statesActive[
i]);
73 if (view.size && statesActive[
i] != 0) {
74 ImGui::Begin(
states.stateNames[
i].c_str());
75 ImGui::Text(
"%d-%d\n %.*s", view.first, view.first + view.size, view.size,
states.statesBuffer.data() + view.first);
87 if (ImGui::CollapsingHeader(
label, ImGuiTreeNodeFlags_DefaultOpen)) {
88 std::string_view inputs(
states.statesBuffer.data() + view.first, view.size);
89 auto beginInputs = inputs.begin();
90 auto endInputs = beginInputs + view.size;
91 char const* input = beginInputs;
94 while (input != endInputs) {
95 auto end = std::find(input, endInputs,
';');
96 if ((
end - input) == 0) {
100 if (ImGui::IsItemHovered()) {
101 ImGui::BeginTooltip();
112 boost::property_tree::ptree
const& currentProvenance)
114 if (currentConfig.empty()) {
117 if (ImGui::CollapsingHeader(
"Current Config", ImGuiTreeNodeFlags_DefaultOpen)) {
119 auto labels = {
"Name",
"Value"};
121 ImGui::TextUnformatted(
label);
124 for (
auto& option : currentConfig) {
125 ImGui::TextUnformatted(option.first.c_str());
126 if (ImGui::IsItemHovered()) {
127 ImGui::BeginTooltip();
128 ImGui::TextUnformatted(option.first.c_str());
132 ImGui::Text(
"%s (%s)", option.second.data().c_str(), currentProvenance.get<std::string>(option.first).c_str());
133 if (ImGui::IsItemHovered()) {
134 ImGui::BeginTooltip();
135 ImGui::Text(
"%s (%s)", option.second.data().c_str(), currentProvenance.get<std::string>(option.first).c_str());
146 if (options.empty()) {
149 if (ImGui::CollapsingHeader(
label, ImGuiTreeNodeFlags_DefaultOpen)) {
151 auto labels = {
"Name",
"Value"};
153 ImGui::TextUnformatted(
label);
156 for (
auto& option : options) {
157 ImGui::TextUnformatted(option.name.c_str());
159 auto currentValueIt = control.
options.find(option.name);
162 if (currentValueIt == control.
options.end()) {
163 switch (option.type) {
165 ImGui::Text(R
"("%s" (default))", option.defaultValue.get<const char*>());
168 ImGui::Text(
"%d (default)", option.defaultValue.get<
int>());
171 ImGui::Text(
"%d (default)", option.defaultValue.get<int8_t>());
174 ImGui::Text(
"%d (default)", option.defaultValue.get<int16_t>());
177 ImGui::Text(
"%" PRId64
" (default)", option.defaultValue.get<int64_t>());
180 ImGui::Text(
"%d (default)", option.defaultValue.get<uint8_t>());
183 ImGui::Text(
"%d (default)", option.defaultValue.get<uint16_t>());
186 ImGui::Text(
"%d (default)", option.defaultValue.get<uint32_t>());
189 ImGui::Text(
"%" PRIu64
" (default)", option.defaultValue.get<uint64_t>());
192 ImGui::Text(
"%f (default)", option.defaultValue.get<
float>());
195 ImGui::Text(
"%f (default)", option.defaultValue.get<
double>());
198 ImGui::TextUnformatted(
"");
201 ImGui::TextUnformatted(
"unknown");
204 ImGui::TextUnformatted(currentValueIt->second.c_str());
259 ImGui::Text(
"Name: %s", spec.
name.c_str());
260 ImGui::Text(
"Executable: %s", metadata.
executable.c_str());
262 ImGui::Text(
"Pid: %d", info.pid);
264 ImGui::Text(
"Pid: %d (exit status: %d)", info.pid, info.exitStatus);
266 ImGui::Text(
"Device state: %s", info.deviceState.data());
269 if (ImGui::Button(ICON_FA_BUG
"Attach debugger")) {
271 setenv(
"O2DEBUGGEDPID",
pid.c_str(), 1);
273 std::string defaultAppleDebugCommand =
274 "osascript -e 'tell application \"Terminal\" to activate'"
275 " -e 'tell application \"Terminal\" to do script \"lldb -p \" & (system attribute \"O2DEBUGGEDPID\") & \"; exit\"'";
276 setenv(
"O2DPLDEBUG", defaultAppleDebugCommand.c_str(), 0);
278 setenv(
"O2DPLDEBUG",
"xterm -hold -e gdb attach $O2DEBUGGEDPID &", 0);
280 int retVal = system(getenv(
"O2DPLDEBUG"));
285 if (ImGui::Button(
"Profile 30s")) {
287 setenv(
"O2PROFILEDPID",
pid.c_str(), 1);
289 auto defaultAppleProfileCommand = fmt::format(
290 "osascript -e 'tell application \"Terminal\"'"
292 " -e 'do script \"xcrun xctrace record --output dpl-profile-{0}.trace"
293 " --instrument os_signpost --time-limit 30s --template Time\\\\ Profiler --attach {0} "
294 " && open dpl-profile-{0}.trace && exit\"'"
298 setenv(
"O2DPLPROFILE", defaultAppleProfileCommand.c_str(), 0);
300 setenv(
"O2DPLPROFILE",
"xterm -hold -e perf record -a -g -p $O2PROFILEDPID > perf-$O2PROFILEDPID.data &", 0);
302 LOG(error) << getenv(
"O2DPLPROFILE");
303 int retVal = system(getenv(
"O2DPLPROFILE"));
308 if (ImGui::Button(
"Profile Allocations 30s")) {
310 setenv(
"O2PROFILEDPID",
pid.c_str(), 1);
311 auto defaultAppleProfileCommand = fmt::format(
312 "osascript -e 'tell application \"Terminal\"'"
314 " -e 'do script \"xcrun xctrace record --output dpl-profile-{0}.trace"
315 " --time-limit 30s --instrument os_signpost --template Allocations --attach {0} "
316 " && open dpl-profile-{0}.trace && exit\"'"
320 setenv(
"O2DPLPROFILE", defaultAppleProfileCommand.c_str(), 0);
321 LOG(error) << getenv(
"O2DPLPROFILE");
322 int retVal = system(getenv(
"O2DPLPROFILE"));
328 if (ImGui::Button(
"Offer SHM")) {
329 control.
controller->
write(
"/shm-offer 1000", strlen(
"/shm-offer 1000"));
332 if (ImGui::Button(
"Offer timeslices")) {
333 control.
controller->
write(
"/timeslice-offer 1", strlen(
"/timeslice-offer 1"));
337 ImGui::Text(ICON_FA_CLOCK_O);
339 if (ImGui::Button(
"Restart")) {
351 if (ImGui::CollapsingHeader(
"Labels", ImGuiTreeNodeFlags_DefaultOpen)) {
353 ImGui::Text(
"%s",
label.value.c_str());
357 if (ImGui::CollapsingHeader(
"Command line arguments", ImGuiTreeNodeFlags_DefaultOpen)) {
358 static ImGuiTextFilter
filter;
359 filter.Draw(ICON_FA_SEARCH);
361 if (
filter.PassFilter(arg.c_str())) {
362 ImGui::TextUnformatted(arg.c_str());
367 if (ImGui::CollapsingHeader(
"Channels", ImGuiTreeNodeFlags_DefaultOpen)) {
372 if (ImGui::CollapsingHeader(
"Policies")) {
378 if (ImGui::CollapsingHeader(
"Signals", ImGuiTreeNodeFlags_DefaultOpen)) {
379 if (ImGui::Button(
"SIGSTOP")) {
380 kill(info.pid, SIGSTOP);
383 if (ImGui::Button(
"SIGTERM")) {
384 kill(info.pid, SIGTERM);
387 if (ImGui::Button(
"SIGKILL")) {
388 kill(info.pid, SIGKILL);
390 if (ImGui::Button(
"SIGCONT")) {
391 kill(info.pid, SIGCONT);
394 if (ImGui::Button(
"SIGUSR1")) {
395 kill(info.pid, SIGUSR1);
398 if (ImGui::Button(
"SIGUSR2")) {
399 kill(info.pid, SIGUSR2);
403 if (ImGui::CollapsingHeader(
"Signposts", ImGuiTreeNodeFlags_DefaultOpen)) {
404 static const struct {
407 const char* fullName;
415 for (
auto const& s : kStreams) {
418 std::string cmd =
enabled ? fmt::format(
"/signpost:enable {}", s.fullName)
419 : fmt::format(
"/signpost:disable {}", s.fullName);
425 bool flagsChanged =
false;
426 if (ImGui::CollapsingHeader(
"Event loop tracing", ImGuiTreeNodeFlags_DefaultOpen)) {
447 std::string cmd = fmt::format(
"/trace {}", control.
tracingFlags);
void displayDeviceInspector(DeviceSpec const &spec, DeviceInfo const &info, DataProcessingStates const &states, DeviceMetricsInfo const &metrics, DataProcessorInfo const &metadata, DeviceControl &control)
Helper to display information about a device.