| 193 | } |
| 194 | |
| 195 | void ProgressTable::writeTable( |
| 196 | WriteBufferFromFileDescriptor & message, std::unique_lock<std::mutex> &, bool show_table, bool toggle_enabled, bool is_final) |
| 197 | { |
| 198 | std::lock_guard lock{mutex}; |
| 199 | message << HIDE_CURSOR; |
| 200 | if (!show_table && toggle_enabled) |
| 201 | { |
| 202 | message << CLEAR_TO_END_OF_SCREEN << "\nPress the space key to toggle the display of the progress table." << moveUpNLines(1); |
| 203 | message.next(); |
| 204 | return; |
| 205 | } |
| 206 | |
| 207 | const auto & event_name_to_event = getEventNameToEvent(); |
| 208 | |
| 209 | auto [terminal_width, terminal_height] = getTerminalSize(in_fd, err_fd); |
| 210 | if (terminal_width < column_event_name_width + COLUMN_VALUE_WIDTH + COLUMN_PROGRESS_WIDTH) |
| 211 | return; |
| 212 | |
| 213 | if (metrics.empty()) |
| 214 | return; |
| 215 | |
| 216 | message << "\n"; |
| 217 | writeWithWidth(message, COLUMN_EVENT_NAME, column_event_name_width); |
| 218 | writeWithWidth(message, COLUMN_VALUE, COLUMN_VALUE_WIDTH); |
| 219 | writeWithWidth(message, COLUMN_PROGRESS, COLUMN_PROGRESS_WIDTH); |
| 220 | auto col_doc_width = getColumnDocumentationWidth(terminal_width); |
| 221 | if (col_doc_width) |
| 222 | writeWithWidth(message, COLUMN_DOCUMENTATION_NAME, col_doc_width); |
| 223 | message << CLEAR_TO_END_OF_LINE; |
| 224 | |
| 225 | double elapsed_sec = watch.elapsedSeconds(); |
| 226 | |
| 227 | /// Sort metrics by the number of iterations passed since update, then by rounded log of the value, then by metric name. |
| 228 | /// This will put fresh metrics on top but also avoid flickering. |
| 229 | |
| 230 | std::vector<Metrics::pointer> sorted_metrics; |
| 231 | sorted_metrics.reserve(metrics.size()); |
| 232 | for (auto & elem : metrics) |
| 233 | { |
| 234 | if (elapsed_sec - elem.second.updateTime() < 1) |
| 235 | elem.second.increaseDisplayPriority(); |
| 236 | |
| 237 | sorted_metrics.emplace_back(&elem); |
| 238 | } |
| 239 | |
| 240 | ::stableSort(sorted_metrics.begin(), sorted_metrics.end(), [](Metrics::const_pointer a, Metrics::const_pointer b) |
| 241 | { |
| 242 | return std::tuple(a->second.getDisplayPriority(), std::floor(std::log10(1 + a->second.getSummaryValue()))) |
| 243 | > std::tuple(b->second.getDisplayPriority(), std::floor(std::log10(1 + b->second.getSummaryValue()))); |
| 244 | }); |
| 245 | |
| 246 | size_t row_num = 0; |
| 247 | for (auto * ptr : sorted_metrics) |
| 248 | { |
| 249 | if (!is_final && row_num + 3 > terminal_height) |
| 250 | break; |
| 251 | |
| 252 | const auto & name = ptr->first; |
no test coverage detected