1
1
mirror of https://github.com/tstack/lnav.git synced 2024-09-11 13:05:51 +03:00

[base] refactor duration2str

This commit is contained in:
Timothy Stack 2021-04-03 14:03:18 -07:00
parent d15c1103cf
commit d31aa845f5
10 changed files with 136 additions and 113 deletions

View File

@ -108,7 +108,6 @@ of log lines fed into `lnav` via `journalctl`'s `-b` option.
## Contributing
- [Become a Sponsor on GitHub](https://github.com/sponsors/tstack)
- [Make a one-time donation on Ko-fi](https://ko-fi.com/tstack)
### Building From Source

View File

@ -45,7 +45,7 @@ point point::from_tv(const timeval &tv)
return point(tv);
}
std::string point::as_time_ago()
std::string point::as_time_ago() const
{
struct timeval current_time = this->p_recent_point
.value_or(current_timeval());
@ -89,7 +89,7 @@ std::string point::as_time_ago()
return std::string(buffer);
}
std::string point::as_precise_time_ago()
std::string point::as_precise_time_ago() const
{
struct timeval now, diff;
@ -121,5 +121,77 @@ std::string point::as_precise_time_ago()
}
}
duration duration::from_tv(const struct timeval &tv)
{
return duration{tv};
}
std::string duration::to_string() const
{
/* 24h22m33s111 */
static const struct rel_interval {
uint64_t length;
const char *format;
const char *symbol;
} intervals[] = {
{ 1000, "%03lld%s", "" },
{ 60, "%lld%s", "s" },
{ 60, "%lld%s", "m" },
{ 24, "%lld%s", "h" },
{ 0, "%lld%s", "d" },
};
auto *curr_interval = intervals;
auto usecs = std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::seconds(this->d_timeval.tv_sec)) +
std::chrono::microseconds(this->d_timeval.tv_usec);
auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(usecs);
std::string retval;
bool neg = false;
if (millis < 0s) {
neg = true;
millis = -millis;
}
uint64_t remaining;
if (millis >= 10min) {
remaining = std::chrono::duration_cast<std::chrono::seconds>(millis)
.count();
curr_interval += 1;
} else {
remaining = millis.count();
}
for (; curr_interval != std::end(intervals); curr_interval++) {
uint64_t amount;
char segment[32];
if (curr_interval->length) {
amount = remaining % curr_interval->length;
remaining = remaining / curr_interval->length;
}
else {
amount = remaining;
remaining = 0;
}
if (!amount && !remaining) {
break;
}
snprintf(segment, sizeof(segment), curr_interval->format, amount,
curr_interval->symbol);
retval.insert(0, segment);
}
if (neg) {
retval.insert(0, "-");
}
return retval;
}
}
}

View File

@ -55,9 +55,9 @@ public:
return *this;
}
std::string as_time_ago();
std::string as_time_ago() const;
std::string as_precise_time_ago();
std::string as_precise_time_ago() const;
private:
explicit point(const struct timeval &tv) : p_past_point{tv.tv_sec,
@ -69,6 +69,17 @@ private:
bool p_convert_to_local{false};
};
class duration {
public:
static duration from_tv(const struct timeval& tv);
std::string to_string() const;
private:
explicit duration(const struct timeval& tv) : d_timeval(tv) {}
struct timeval d_timeval;
};
}
}

View File

@ -100,3 +100,29 @@ TEST_CASE("time ago")
.with_recent_point({1612000000, 0})
.as_time_ago() == "23 days ago");
}
TEST_CASE("duration to_string") {
std::string val;
val = humanize::time::duration::from_tv({25 * 60 * 60, 123000})
.to_string();
CHECK(val == "1d1h0m0s");
val = humanize::time::duration::from_tv({10, 123000})
.to_string();
CHECK(val == "10s123");
val = humanize::time::duration::from_tv({10, 0})
.to_string();
CHECK(val == "10s000");
val = humanize::time::duration::from_tv({0, 100000})
.to_string();
CHECK(val == "100");
val = humanize::time::duration::from_tv({0, 0})
.to_string();
CHECK(val == "");
val = humanize::time::duration::from_tv({0, -10000})
.to_string();
CHECK(val == "-010");
val = humanize::time::duration::from_tv({-10, 0})
.to_string();
CHECK(val == "-10s000");
}

View File

@ -117,6 +117,15 @@ bool operator!=(const struct timeval &left, const struct timeval &right) {
left.tv_usec != right.tv_usec;
}
inline
struct timeval operator-(const struct timeval& lhs, const struct timeval& rhs)
{
struct timeval diff;
timersub(&lhs, &rhs, &diff);
return diff;
}
typedef int64_t mstime_t;
inline mstime_t getmstime() {

View File

@ -80,9 +80,9 @@ void field_overlay_source::build_summary_lines(const listview_curses &lv)
humanize::time::point::from_tv(last_line->get_timeval())
.with_convert_to_local(true)
.as_precise_time_ago() + ANSI_NORM;
duration2str(last_line->get_time_in_millis() -
first_line->get_time_in_millis(),
time_span);
time_span = humanize::time::duration::from_tv(
last_line->get_timeval() - first_line->get_timeval())
.to_string();
time_t local_now = convert_log_time_to_local(now);
time_t five_minutes_ago = local_now - (5 * 60 * 60);
@ -325,7 +325,8 @@ void field_overlay_source::build_field_lines(const listview_curses &lv)
timersub(&curr_tv, &actual_tv, &diff_tv);
time_str.append("; Diff: ");
time_lr.lr_start = time_str.length();
str2reltime(diff_tv, time_str);
time_str.append(humanize::time::duration::from_tv(diff_tv)
.to_string());
time_lr.lr_end = time_str.length();
time_line.with_attr(string_attr(
time_lr,

View File

@ -33,6 +33,7 @@
#include <algorithm>
#include <sqlite3.h>
#include "base/humanize.time.hh"
#include "base/string_util.hh"
#include "k_merge_tree.h"
#include "lnav_util.hh"
@ -303,9 +304,8 @@ void logfile_sub_source::text_value_for_line(textview_curses &tc,
}
if (this->lss_flags & F_TIME_OFFSET) {
int64_t curr_millis, diff;
curr_millis = this->lss_token_line->get_time_in_millis();
auto curr_tv = this->lss_token_line->get_timeval();
struct timeval diff_tv;
vis_line_t prev_mark =
tc.get_bookmarks()[&textview_curses::BM_USER].prev(vis_line_t(row));
@ -314,24 +314,19 @@ void logfile_sub_source::text_value_for_line(textview_curses &tc,
if (prev_mark == -1 && next_mark != -1) {
auto next_line = this->find_line(this->at(next_mark));
diff = curr_millis - next_line->get_time_in_millis();
diff_tv = curr_tv - next_line->get_timeval();
} else {
if (prev_mark == -1) {
if (prev_mark == -1_vl) {
prev_mark = 0_vl;
}
auto first_line = this->find_line(this->at(prev_mark));
auto start_millis = first_line->get_time_in_millis();
diff = curr_millis - start_millis;
auto start_tv = first_line->get_timeval();
diff_tv = curr_tv - start_tv;
}
value_out = "|" + value_out;
string relstr;
size_t rel_length = duration2str(diff, relstr);
value_out.insert(0, relstr);
if (rel_length < 12) {
value_out.insert(0, 12 - rel_length, ' ');
}
auto relstr = humanize::time::duration::from_tv(diff_tv).to_string();
value_out = fmt::format(FMT_STRING("{: >12}|{}"), relstr, value_out);
}
this->lss_in_value_for_line = false;
}

View File

@ -820,61 +820,3 @@ nonstd::optional<exttm> relative_time::window_start(
return retval;
}
size_t duration2str(int64_t millis, std::string &value_out)
{
/* 24h22m33s111 */
static struct rel_interval {
long long length;
const char *format;
const char *symbol;
} intervals[] = {
{ 1000, "%03lld%s", "" },
{ 60, "%lld%s", "s" },
{ 60, "%lld%s", "m" },
{ 24, "%lld%s", "h" },
{ 0, "%lld%s", "d" },
};
struct rel_interval *curr_interval = intervals;
size_t retval = 0;
if (millis < 0) {
value_out.append(1, '-');
millis = -millis;
retval += 1;
}
size_t in_len = value_out.length();
if (millis >= (10 * 60 * 1000)) {
millis /= 1000;
curr_interval += 1;
}
for (; curr_interval != end(intervals); curr_interval++) {
long long amount;
char segment[32];
if (curr_interval->length) {
amount = millis % curr_interval->length;
millis = millis / curr_interval->length;
}
else {
amount = millis;
millis = 0;
}
if (!amount && !millis) {
break;
}
snprintf(segment, sizeof(segment), curr_interval->format, amount,
curr_interval->symbol);
retval += strlen(segment);
value_out.insert(in_len, segment);
}
return retval;
}

View File

@ -270,11 +270,4 @@ public:
int rt_absolute_field_end;
};
size_t duration2str(int64_t millis, std::string &value_out);
inline
size_t str2reltime(const struct timeval &tv, std::string &value_out) {
return duration2str(tv.tv_sec * 1000 + tv.tv_usec / 1000, value_out);
};
#endif //LNAV_RELATIVE_TIME_HH

View File

@ -61,31 +61,6 @@ TEST_CASE("overwritten-logfile") {
}
#endif
TEST_CASE("duration2str") {
string val;
duration2str(25 * 60 * 60 * 1000 + 123, val);
CHECK(val == "1d1h0m0s");
val.clear();
duration2str(10 * 1000 + 123, val);
CHECK(val == "10s123");
val.clear();
duration2str(10 * 1000, val);
CHECK(val == "10s000");
val.clear();
duration2str(100, val);
CHECK(val == "100");
val.clear();
duration2str(0, val);
CHECK(val == "");
val.clear();
duration2str(-10, val);
CHECK(val == "-010");
val.clear();
duration2str(-10 * 1000, val);
CHECK(val == "-10s000");
}
TEST_CASE("byte_array") {
using my_array_t = byte_array<8>;