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);
86 if (ImGui::CollapsingHeader(
label, ImGuiTreeNodeFlags_DefaultOpen)) {
87 std::string_view inputs(
states.statesBuffer.data() + view.first, view.size);
88 auto beginInputs = inputs.begin();
89 auto endInputs = beginInputs + view.size;
90 char const* input = beginInputs;
93 while (input != endInputs) {
94 auto end = std::find(input, endInputs,
';');
95 if ((
end - input) == 0) {
98 auto getLifetime = [&routes, &
i]() ->
Lifetime {
99 if (std::get_if<std::vector<InputRoute>>(&routes)) {
100 return std::get<std::vector<InputRoute>>(routes)[
i].matcher.lifetime;
102 return std::get<std::vector<OutputRoute>>(routes)[
i].matcher.lifetime;
106 if (ImGui::IsItemHovered()) {
107 ImGui::BeginTooltip();
118 boost::property_tree::ptree
const& currentProvenance)
120 if (currentConfig.empty()) {
123 if (ImGui::CollapsingHeader(
"Current Config", ImGuiTreeNodeFlags_DefaultOpen)) {
125 auto labels = {
"Name",
"Value"};
126 for (
auto&
label : labels) {
127 ImGui::TextUnformatted(
label);
130 for (
auto& option : currentConfig) {
131 ImGui::TextUnformatted(option.first.c_str());
132 if (ImGui::IsItemHovered()) {
133 ImGui::BeginTooltip();
134 ImGui::TextUnformatted(option.first.c_str());
138 ImGui::Text(
"%s (%s)", option.second.data().c_str(), currentProvenance.get<std::string>(option.first).c_str());
139 if (ImGui::IsItemHovered()) {
140 ImGui::BeginTooltip();
141 ImGui::Text(
"%s (%s)", option.second.data().c_str(), currentProvenance.get<std::string>(option.first).c_str());
152 if (options.empty()) {
155 if (ImGui::CollapsingHeader(
label, ImGuiTreeNodeFlags_DefaultOpen)) {
157 auto labels = {
"Name",
"Value"};
158 for (
auto&
label : labels) {
159 ImGui::TextUnformatted(
label);
162 for (
auto& option : options) {
163 ImGui::TextUnformatted(option.name.c_str());
165 auto currentValueIt = control.
options.find(option.name);
168 if (currentValueIt == control.
options.end()) {
169 switch (option.type) {
171 ImGui::Text(R
"("%s" (default))", option.defaultValue.get<const char*>());
174 ImGui::Text(
"%d (default)", option.defaultValue.get<
int>());
177 ImGui::Text(
"%d (default)", option.defaultValue.get<int8_t>());
180 ImGui::Text(
"%d (default)", option.defaultValue.get<int16_t>());
183 ImGui::Text(
"%" PRId64
" (default)", option.defaultValue.get<int64_t>());
186 ImGui::Text(
"%d (default)", option.defaultValue.get<uint8_t>());
189 ImGui::Text(
"%d (default)", option.defaultValue.get<uint16_t>());
192 ImGui::Text(
"%d (default)", option.defaultValue.get<uint32_t>());
195 ImGui::Text(
"%" PRIu64
" (default)", option.defaultValue.get<uint64_t>());
198 ImGui::Text(
"%f (default)", option.defaultValue.get<
float>());
201 ImGui::Text(
"%f (default)", option.defaultValue.get<
double>());
204 ImGui::TextUnformatted(
"");
207 ImGui::TextUnformatted(
"unknown");
210 ImGui::TextUnformatted(currentValueIt->second.c_str());
265 ImGui::Text(
"Name: %s", spec.
name.c_str());
266 ImGui::Text(
"Executable: %s", metadata.
executable.c_str());
268 ImGui::Text(
"Pid: %d", info.
pid);
270 ImGui::Text(
"Pid: %d (exit status: %d)", info.
pid, info.
exitStatus);
272 ImGui::Text(
"Device state: %s", info.
deviceState.data());
275 if (ImGui::Button(ICON_FA_BUG
"Attach debugger")) {
277 setenv(
"O2DEBUGGEDPID",
pid.c_str(), 1);
279 std::string defaultAppleDebugCommand =
280 "osascript -e 'tell application \"Terminal\" to activate'"
281 " -e 'tell application \"Terminal\" to do script \"lldb -p \" & (system attribute \"O2DEBUGGEDPID\") & \"; exit\"'";
282 setenv(
"O2DPLDEBUG", defaultAppleDebugCommand.c_str(), 0);
284 setenv(
"O2DPLDEBUG",
"xterm -hold -e gdb attach $O2DEBUGGEDPID &", 0);
286 int retVal = system(getenv(
"O2DPLDEBUG"));
291 if (ImGui::Button(
"Profile 30s")) {
293 setenv(
"O2PROFILEDPID",
pid.c_str(), 1);
295 auto defaultAppleProfileCommand = fmt::format(
296 "osascript -e 'tell application \"Terminal\"'"
298 " -e 'do script \"xcrun xctrace record --output dpl-profile-{0}.trace"
299 " --instrument os_signpost --time-limit 30s --template Time\\\\ Profiler --attach {0} "
300 " && open dpl-profile-{0}.trace && exit\"'"
304 setenv(
"O2DPLPROFILE", defaultAppleProfileCommand.c_str(), 0);
306 setenv(
"O2DPLPROFILE",
"xterm -hold -e perf record -a -g -p $O2PROFILEDPID > perf-$O2PROFILEDPID.data &", 0);
308 LOG(error) << getenv(
"O2DPLPROFILE");
309 int retVal = system(getenv(
"O2DPLPROFILE"));
314 if (ImGui::Button(
"Profile Allocations 30s")) {
316 setenv(
"O2PROFILEDPID",
pid.c_str(), 1);
317 auto defaultAppleProfileCommand = fmt::format(
318 "osascript -e 'tell application \"Terminal\"'"
320 " -e 'do script \"xcrun xctrace record --output dpl-profile-{0}.trace"
321 " --time-limit 30s --instrument os_signpost --template Allocations --attach {0} "
322 " && open dpl-profile-{0}.trace && exit\"'"
326 setenv(
"O2DPLPROFILE", defaultAppleProfileCommand.c_str(), 0);
327 LOG(error) << getenv(
"O2DPLPROFILE");
328 int retVal = system(getenv(
"O2DPLPROFILE"));
334 if (ImGui::Button(
"Offer SHM")) {
335 control.
controller->
write(
"/shm-offer 1000", strlen(
"/shm-offer 1000"));
339 ImGui::Text(ICON_FA_CLOCK_O);
341 if (ImGui::Button(
"Restart")) {
353 if (ImGui::CollapsingHeader(
"Labels", ImGuiTreeNodeFlags_DefaultOpen)) {
355 ImGui::Text(
"%s",
label.value.c_str());
359 if (ImGui::CollapsingHeader(
"Command line arguments", ImGuiTreeNodeFlags_DefaultOpen)) {
360 static ImGuiTextFilter
filter;
361 filter.Draw(ICON_FA_SEARCH);
363 if (
filter.PassFilter(arg.c_str())) {
364 ImGui::TextUnformatted(arg.c_str());
369 if (ImGui::CollapsingHeader(
"Channels", ImGuiTreeNodeFlags_DefaultOpen)) {
374 if (ImGui::CollapsingHeader(
"Policies")) {
380 if (ImGui::CollapsingHeader(
"Signals", ImGuiTreeNodeFlags_DefaultOpen)) {
381 if (ImGui::Button(
"SIGSTOP")) {
382 kill(info.
pid, SIGSTOP);
385 if (ImGui::Button(
"SIGTERM")) {
386 kill(info.
pid, SIGTERM);
389 if (ImGui::Button(
"SIGKILL")) {
390 kill(info.
pid, SIGKILL);
392 if (ImGui::Button(
"SIGCONT")) {
393 kill(info.
pid, SIGCONT);
396 if (ImGui::Button(
"SIGUSR1")) {
397 kill(info.
pid, SIGUSR1);
400 if (ImGui::Button(
"SIGUSR2")) {
401 kill(info.
pid, SIGUSR2);
405 bool logsChanged =
false;
406 if (ImGui::CollapsingHeader(
"Signposts", ImGuiTreeNodeFlags_DefaultOpen)) {
413 std::string cmd = fmt::format(
"/log-streams {}", control.
logStreams);
418 bool flagsChanged =
false;
419 if (ImGui::CollapsingHeader(
"Event loop tracing", ImGuiTreeNodeFlags_DefaultOpen)) {
440 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.