[date_time_scanner] convert timestamps with zones to local time

Related to #703
pull/1161/merge
Tim Stack 9 months ago
parent d1386a8432
commit 155dad6ee1

@ -41,6 +41,14 @@ Features:
is executed asynchronously, so it will not block input
and the result is saved in the session. Annotations are
defined in the `/log/annotations` configuration property.
* Timestamps with numeric timezone offsets (or `Z`) are now
automatically converted to the local time zone. For
example, a timestamp ending in `-03:00` will be treated
as three hours behind UTC and then adjusted to the local
timezone. This feature can be disabled by setting the
`/log/date-time/convert-zoned-to-local` configuration
property to `false`. Timestamps without a zone or have
a symbolic zone name (e.g. `PDT`) are not converted.
* Added the SQLite JSON functions to the online help.
* Added `config get` and `config blame` management CLI
commands to get the current configuration and the file

@ -744,6 +744,19 @@
"title": "/log",
"type": "object",
"properties": {
"date-time": {
"description": "Settings related to log message dates and times",
"title": "/log/date-time",
"type": "object",
"properties": {
"convert-zoned-to-local": {
"title": "/log/date-time/convert-zoned-to-local",
"description": "Convert timestamps with ",
"type": "boolean"
}
},
"additionalProperties": false
},
"watch-expressions": {
"description": "Log message watch expressions",
"title": "/log/watch-expressions",

@ -180,8 +180,8 @@ Environment Variables
.. envvar:: TZ
The timezone setting is used in some log formats to convert UTC timestamps
to the local timezone.
The timezone setting is used in some log formats to convert timestamps
with a timezone to the local timezone.
Examples

@ -227,6 +227,18 @@ The handling of logs is largely determined by the
:ref:`log file formats<log_formats>`, this section covers options that are not
specific to a particular format.
Timezone Conversion (v0.12.0+)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Log messages that have a numeric timezone, like :code:`-03:00` or :code:`Z`
for UTC, will be converted to the local timezone as given by the :envvar:`TZ`
environment variable. For example, a timestamp ending in `-03:00` will be treated
as three hours behind UTC and then adjusted to the local timezone.
This behavior can be disabled by setting the
:code:`/log/date-time/convert-zoned-to-local` configuration property to
:code:`false`.
Watch Expressions (v0.11.0+)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^

@ -34,6 +34,7 @@ add_library(
auto_mem.hh
auto_pid.hh
bus.hh
date_time_scanner.cfg.hh
date_time_scanner.hh
enum_util.hh
fs_util.hh

@ -29,6 +29,7 @@ noinst_HEADERS = \
auto_mem.hh \
auto_pid.hh \
bus.hh \
date_time_scanner.cfg.hh \
date_time_scanner.hh \
enum_util.hh \
file_range.hh \

@ -34,6 +34,8 @@
#include "date_time_scanner.hh"
#include "config.h"
#include "date_time_scanner.cfg.hh"
#include "injector.hh"
#include "ptimec.hh"
#include "scn/scn.h"
@ -94,6 +96,9 @@ date_time_scanner::scan(const char* time_dest,
struct timeval& tv_out,
bool convert_local)
{
static const auto& cfg
= injector::get<const date_time_scanner_ns::config&>();
int curr_time_fmt = -1;
bool found = false;
const char* retval = nullptr;
@ -102,6 +107,7 @@ date_time_scanner::scan(const char* time_dest,
time_fmt = PTIMEC_FORMAT_STR;
}
this->dts_zoned_to_local = cfg.c_zoned_to_local;
while (next_format(time_fmt, curr_time_fmt, this->dts_fmt_lock)) {
*tm_out = this->dts_base_tm;
tm_out->et_flags = 0;
@ -112,7 +118,9 @@ date_time_scanner::scan(const char* time_dest,
if (epoch_scan_res) {
time_t gmt = epoch_scan_res.value();
if (convert_local && this->dts_local_time) {
if (convert_local
&& (this->dts_local_time || this->dts_zoned_to_local))
{
localtime_r(&gmt, &tm_out->et_tm);
#ifdef HAVE_STRUCT_TM_TM_ZONE
tm_out->et_tm.tm_zone = nullptr;
@ -123,7 +131,7 @@ date_time_scanner::scan(const char* time_dest,
tv_out.tv_sec = gmt;
tv_out.tv_usec = 0;
tm_out->et_flags = ETF_DAY_SET | ETF_MONTH_SET | ETF_YEAR_SET
| ETF_MACHINE_ORIENTED | ETF_EPOCH_TIME;
| ETF_MACHINE_ORIENTED | ETF_EPOCH_TIME | ETF_ZONE_SET;
this->dts_fmt_lock = curr_time_fmt;
this->dts_fmt_len = sv.length() - epoch_scan_res.range().size();
@ -148,7 +156,9 @@ date_time_scanner::scan(const char* time_dest,
}
if (convert_local
&& (this->dts_local_time
|| tm_out->et_flags & ETF_EPOCH_TIME))
|| tm_out->et_flags & ETF_EPOCH_TIME
|| (tm_out->et_flags & ETF_ZONE_SET
&& this->dts_zoned_to_local)))
{
time_t gmt = tm_out->to_timeval().tv_sec;
@ -168,7 +178,6 @@ date_time_scanner::scan(const char* time_dest,
tv_out.tv_sec += sec_diff;
tm_out->et_tm.tm_wday = last_tm.tm_wday;
} else {
// log_debug("doing tm2sec");
tv_out = tm_out->to_timeval();
secs2wday(tv_out, &tm_out->et_tm);
}
@ -199,7 +208,9 @@ date_time_scanner::scan(const char* time_dest,
}
if (convert_local
&& (this->dts_local_time
|| tm_out->et_flags & ETF_EPOCH_TIME))
|| tm_out->et_flags & ETF_EPOCH_TIME
|| (tm_out->et_flags & ETF_ZONE_SET
&& this->dts_zoned_to_local)))
{
time_t gmt = tm_out->to_timeval().tv_sec;
@ -293,7 +304,10 @@ date_time_scanner::to_localtime(time_t t, exttm& tm_out)
time_t new_gmt;
localtime_r(&t, &tm_out.et_tm);
// Clear the gmtoff set by localtime_r() otherwise tm2sec() will
// convert the time back again.
#ifdef HAVE_STRUCT_TM_TM_ZONE
tm_out.et_tm.tm_gmtoff = 0;
tm_out.et_tm.tm_zone = nullptr;
#endif
tm_out.et_tm.tm_isdst = 0;
@ -308,4 +322,9 @@ date_time_scanner::to_localtime(time_t t, exttm& tm_out)
time_t adjust_gmt = t - this->dts_local_offset_cache;
gmtime_r(&adjust_gmt, &tm_out.et_tm);
}
tm_out.et_gmtoff = 0;
#ifdef HAVE_STRUCT_TM_TM_ZONE
tm_out.et_tm.tm_gmtoff = 0;
tm_out.et_tm.tm_zone = nullptr;
#endif
}

@ -0,0 +1,43 @@
/**
* Copyright (c) 2020, Timothy Stack
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Timothy Stack nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @file date_time_scanner.hh
*/
#ifndef lnav_date_time_scanner_cfg_hh
#define lnav_date_time_scanner_cfg_hh
namespace date_time_scanner_ns {
struct config {
bool c_zoned_to_local{true};
};
} // namespace date_time_scanner_ns
#endif

@ -95,6 +95,7 @@ struct date_time_scanner {
bool dts_keep_base_tz{false};
bool dts_local_time{false};
bool dts_zoned_to_local{true};
time_t dts_base_time{0};
struct exttm dts_base_tm;
int dts_fmt_lock{-1};

@ -102,6 +102,11 @@ hist_source2::text_attrs_for_line(textview_curses& tc,
bucket.b_values[lpc].hv_value,
value_out);
}
auto alt_row_index = row % 4;
if (alt_row_index == 2 || alt_row_index == 3) {
value_out.emplace_back(line_range{0, -1},
VC_ROLE.value(role_t::VCR_ALT_ROW));
}
}
void

@ -81,6 +81,9 @@ lnav_config_listener* lnav_config_listener::LISTENER_LIST;
static auto a = injector::bind<archive_manager::config>::to_instance(
+[]() { return &lnav_config.lc_archive_manager; });
static auto dtc = injector::bind<date_time_scanner_ns::config>::to_instance(
+[]() { return &lnav_config.lc_log_date_time; });
static auto fvc = injector::bind<file_vtab::config>::to_instance(
+[]() { return &lnav_config.lc_file_vtab; });
@ -1309,7 +1312,18 @@ static const struct json_path_container annotations_handlers = {
.with_children(annotation_handlers),
};
static const struct json_path_container log_date_time_handlers = {
yajlpp::property_handler("convert-zoned-to-local")
.with_description("Convert timestamps with ")
.with_pattern(R"(^[\w\-]+(?!\.lnav)$)")
.for_field(&_lnav_config::lc_log_date_time,
&date_time_scanner_ns::config::c_zoned_to_local),
};
static const struct json_path_container log_source_handlers = {
yajlpp::property_handler("date-time")
.with_description("Settings related to log message dates and times")
.with_children(log_date_time_handlers),
yajlpp::property_handler("watch-expressions")
.with_description("Log message watch expressions")
.with_children(log_source_watch_handlers),

@ -39,6 +39,7 @@
#include <vector>
#include "archive_manager.cfg.hh"
#include "base/date_time_scanner.cfg.hh"
#include "base/file_range.hh"
#include "base/lnav.console.hh"
#include "base/result.h"
@ -111,6 +112,7 @@ struct _lnav_config {
key_map lc_active_keymap;
archive_manager::config lc_archive_manager;
date_time_scanner_ns::config lc_log_date_time;
lnav::piper::config lc_piper;
file_vtab::config lc_file_vtab;
lnav::logfile::config lc_logfile;

@ -1621,8 +1621,9 @@ read_json_field(yajlpp_parse_context* ypc, const unsigned char* str, size_t len)
&tm_out,
tv_out);
// Leave off the machine oriented flag since we convert it anyhow
// in rewrite_json_field()
jlu->jlu_format->lf_timestamp_flags
= tm_out.et_flags & ~ETF_MACHINE_ORIENTED;
= tm_out.et_flags & ~(ETF_MACHINE_ORIENTED | ETF_ZONE_SET);
jlu->jlu_base_line->set_time(tv_out);
} else if (jlu->jlu_format->elf_level_pointer.pp_value != nullptr) {
if (jlu->jlu_format->elf_level_pointer.pp_value

@ -155,10 +155,11 @@ class generic_log_format : public log_format {
return;
}
auto lr = to_line_range(md[fmt.pf_timestamp_index].value());
auto ts_cap = md[fmt.pf_timestamp_index].value();
auto lr = to_line_range(ts_cap.trim());
sa.emplace_back(lr, logline::L_TIMESTAMP.value());
prefix_len = lr.lr_end;
prefix_len = ts_cap.sf_end;
auto level_cap = md[2];
if (level_cap) {
if (string2level(level_cap->data(), level_cap->length(), true)

@ -42,6 +42,7 @@
#include <time.h>
#include "base/ansi_scrubber.hh"
#include "base/date_time_scanner.cfg.hh"
#include "base/fs_util.hh"
#include "base/injector.hh"
#include "base/string_util.hh"
@ -477,6 +478,9 @@ logfile::process_prefix(shared_buffer_ref& sbr,
logfile::rebuild_result_t
logfile::rebuild_index(nonstd::optional<ui_clock::time_point> deadline)
{
static const auto& dts_cfg
= injector::get<const date_time_scanner_ns::config&>();
if (!this->lf_indexing) {
if (this->lf_sort_needed) {
this->lf_sort_needed = false;
@ -485,7 +489,10 @@ logfile::rebuild_index(nonstd::optional<ui_clock::time_point> deadline)
return rebuild_result_t::NO_NEW_LINES;
}
if (this->lf_format != nullptr && this->lf_format->format_changed()) {
if (this->lf_format != nullptr
&& (this->lf_zoned_to_local_state != dts_cfg.c_zoned_to_local
|| this->lf_format->format_changed()))
{
log_info("%s: format has changed, rebuilding",
this->lf_filename.c_str());
this->lf_index.clear();
@ -494,6 +501,7 @@ logfile::rebuild_index(nonstd::optional<ui_clock::time_point> deadline)
this->lf_longest_line = 0;
this->lf_sort_needed = true;
}
this->lf_zoned_to_local_state = dts_cfg.c_zoned_to_local;
auto retval = rebuild_result_t::NO_NEW_LINES;
struct stat st;

@ -435,6 +435,7 @@ private:
bool lf_is_closed{false};
bool lf_indexing{true};
bool lf_partial_line{false};
bool lf_zoned_to_local_state{true};
logline_observer* lf_logline_observer{nullptr};
logfile_observer* lf_logfile_observer{nullptr};
size_t lf_longest_line{0};

@ -273,6 +273,8 @@ logfile_sub_source::text_value_for_line(textview_curses& tc,
}
if ((this->lss_token_file->is_time_adjusted()
|| (format->lf_timestamp_flags & ETF_ZONE_SET
&& format->lf_date_time.dts_zoned_to_local)
|| format->lf_timestamp_flags & ETF_MACHINE_ORIENTED
|| !(format->lf_timestamp_flags & ETF_DAY_SET)
|| !(format->lf_timestamp_flags & ETF_MONTH_SET))
@ -293,8 +295,10 @@ logfile_sub_source::text_value_for_line(textview_curses& tc,
|| !(format->lf_timestamp_flags & ETF_MONTH_SET))
{
adjusted_time = this->lss_token_line->get_timeval();
fmt = "%Y-%m-%d %H:%M:%S.%f";
if (format->lf_timestamp_flags & ETF_MICROS_SET) {
if (format->lf_timestamp_flags
& (ETF_MICROS_SET | ETF_NANOS_SET))
{
fmt = "%Y-%m-%d %H:%M:%S.%f";
struct timeval actual_tv;
struct exttm tm;
if (format->lf_date_time.scan(
@ -307,6 +311,10 @@ logfile_sub_source::text_value_for_line(textview_curses& tc,
{
adjusted_time.tv_usec = actual_tv.tv_usec;
}
} else if (format->lf_timestamp_flags & ETF_MILLIS_SET) {
fmt = "%Y-%m-%d %H:%M:%S.%L";
} else {
fmt = "%Y-%m-%d %H:%M:%S";
}
gmtime_r(&adjusted_time.tv_sec, &adjusted_tm.et_tm);
adjusted_tm.et_nsec

@ -494,8 +494,8 @@ ptime_i(struct exttm* dst, const char* str, off_t& off_inout, ssize_t len)
secs2tm(epoch, &dst->et_tm);
dst->et_flags = ETF_DAY_SET | ETF_MONTH_SET | ETF_YEAR_SET | ETF_HOUR_SET
| ETF_MINUTE_SET | ETF_SECOND_SET | ETF_MACHINE_ORIENTED
| ETF_EPOCH_TIME | ETF_ZONE_SET;
| ETF_MINUTE_SET | ETF_SECOND_SET | ETF_MILLIS_SET
| ETF_MACHINE_ORIENTED | ETF_EPOCH_TIME | ETF_ZONE_SET;
return (epoch_ms > 0);
}
@ -531,8 +531,8 @@ ptime_6(struct exttm* dst, const char* str, off_t& off_inout, ssize_t len)
secs2tm(epoch, &dst->et_tm);
dst->et_flags = ETF_DAY_SET | ETF_MONTH_SET | ETF_YEAR_SET | ETF_HOUR_SET
| ETF_MINUTE_SET | ETF_SECOND_SET | ETF_MACHINE_ORIENTED
| ETF_EPOCH_TIME | ETF_ZONE_SET;
| ETF_MINUTE_SET | ETF_SECOND_SET | ETF_MICROS_SET
| ETF_MACHINE_ORIENTED | ETF_EPOCH_TIME | ETF_ZONE_SET;
return (epoch_us > 0);
}
@ -1111,7 +1111,7 @@ ptime_at(struct exttm* dst, const char* str, off_t& off_inout, ssize_t len)
}
dst->et_flags |= ETF_DAY_SET | ETF_MONTH_SET | ETF_YEAR_SET | ETF_HOUR_SET
| ETF_MINUTE_SET | ETF_SECOND_SET | ETF_MACHINE_ORIENTED
| ETF_MINUTE_SET | ETF_SECOND_SET | ETF_NANOS_SET | ETF_MACHINE_ORIENTED
| ETF_EPOCH_TIME | ETF_ZONE_SET;
return true;

@ -11,6 +11,9 @@
}
},
"log": {
"date-time": {
"convert-zoned-to-local": true
},
"annotations": {
"com.vmware.vmacore.backtrace": {
"description": "Convert a vmacore backtrace into human-readable text",

@ -366,8 +366,12 @@ EXPECTED_FILES = \
$(srcdir)/%reldir%/test_logfile.sh_a7037efd0c4bbf51940137a44e57d94e9307e83e.out \
$(srcdir)/%reldir%/test_logfile.sh_c18e14a26d8261c9f72747118a469266121d5459.err \
$(srcdir)/%reldir%/test_logfile.sh_c18e14a26d8261c9f72747118a469266121d5459.out \
$(srcdir)/%reldir%/test_logfile.sh_ccb0d31813367c8d9dc5b5df383fac5b780711c1.err \
$(srcdir)/%reldir%/test_logfile.sh_ccb0d31813367c8d9dc5b5df383fac5b780711c1.out \
$(srcdir)/%reldir%/test_logfile.sh_e840b674cd65936a72bd64b1dac1524d16fe44c3.err \
$(srcdir)/%reldir%/test_logfile.sh_e840b674cd65936a72bd64b1dac1524d16fe44c3.out \
$(srcdir)/%reldir%/test_logfile.sh_f171f265d8d45a2707e8b9f53e938f574c614d25.err \
$(srcdir)/%reldir%/test_logfile.sh_f171f265d8d45a2707e8b9f53e938f574c614d25.out \
$(srcdir)/%reldir%/test_meta.sh_039c1f127c087ec2c6a23a0ecec4df7992cbc8b4.err \
$(srcdir)/%reldir%/test_meta.sh_039c1f127c087ec2c6a23a0ecec4df7992cbc8b4.out \
$(srcdir)/%reldir%/test_meta.sh_154047fb52e4831aabf7d36512247bad6a6a2cf7.err \

@ -4009,6 +4009,9 @@
}
},
"log": {
"date-time": {
"convert-zoned-to-local": true
},
"watch-expressions": {
},

@ -11,44 +11,45 @@
/global/keymap_def_scroll_horiz -> default-keymap.json:6
/global/keymap_def_text_view -> default-keymap.json:10
/global/keymap_def_zoom -> default-keymap.json:12
/log/annotations/com.vmware.vmacore.backtrace/condition -> root-config.json:17
/log/annotations/com.vmware.vmacore.backtrace/description -> root-config.json:16
/log/annotations/com.vmware.vmacore.backtrace/handler -> root-config.json:18
/log/annotations/com.vmware.vmacore.backtrace/condition -> root-config.json:20
/log/annotations/com.vmware.vmacore.backtrace/description -> root-config.json:19
/log/annotations/com.vmware.vmacore.backtrace/handler -> root-config.json:21
/log/annotations/org.lnav.test/condition -> {test_dir}/configs/installed/anno-test.json:7
/log/annotations/org.lnav.test/description -> {test_dir}/configs/installed/anno-test.json:6
/log/annotations/org.lnav.test/handler -> {test_dir}/configs/installed/anno-test.json:8
/tuning/archive-manager/cache-ttl -> root-config.json:25
/tuning/archive-manager/min-free-space -> root-config.json:24
/tuning/clipboard/impls/MacOS/find/read -> root-config.json:53
/tuning/clipboard/impls/MacOS/find/write -> root-config.json:52
/tuning/clipboard/impls/MacOS/general/read -> root-config.json:49
/tuning/clipboard/impls/MacOS/general/write -> root-config.json:48
/tuning/clipboard/impls/MacOS/test -> root-config.json:46
/tuning/clipboard/impls/NeoVim/general/read -> root-config.json:81
/tuning/clipboard/impls/NeoVim/general/write -> root-config.json:80
/tuning/clipboard/impls/NeoVim/test -> root-config.json:78
/tuning/clipboard/impls/Wayland/general/read -> root-config.json:60
/tuning/clipboard/impls/Wayland/general/write -> root-config.json:59
/tuning/clipboard/impls/Wayland/test -> root-config.json:57
/tuning/clipboard/impls/Windows/general/write -> root-config.json:87
/tuning/clipboard/impls/Windows/test -> root-config.json:85
/tuning/clipboard/impls/X11-xclip/general/read -> root-config.json:67
/tuning/clipboard/impls/X11-xclip/general/write -> root-config.json:66
/tuning/clipboard/impls/X11-xclip/test -> root-config.json:64
/tuning/clipboard/impls/tmux/general/read -> root-config.json:74
/tuning/clipboard/impls/tmux/general/write -> root-config.json:73
/tuning/clipboard/impls/tmux/test -> root-config.json:71
/tuning/piper/max-size -> root-config.json:39
/tuning/piper/rotations -> root-config.json:40
/tuning/piper/ttl -> root-config.json:41
/tuning/remote/ssh/command -> root-config.json:29
/tuning/remote/ssh/config/BatchMode -> root-config.json:31
/tuning/remote/ssh/config/ConnectTimeout -> root-config.json:32
/tuning/remote/ssh/start-command -> root-config.json:34
/tuning/remote/ssh/transfer-command -> root-config.json:35
/tuning/url-scheme/docker/handler -> root-config.json:94
/log/date-time/convert-zoned-to-local -> root-config.json:15
/tuning/archive-manager/cache-ttl -> root-config.json:28
/tuning/archive-manager/min-free-space -> root-config.json:27
/tuning/clipboard/impls/MacOS/find/read -> root-config.json:56
/tuning/clipboard/impls/MacOS/find/write -> root-config.json:55
/tuning/clipboard/impls/MacOS/general/read -> root-config.json:52
/tuning/clipboard/impls/MacOS/general/write -> root-config.json:51
/tuning/clipboard/impls/MacOS/test -> root-config.json:49
/tuning/clipboard/impls/NeoVim/general/read -> root-config.json:84
/tuning/clipboard/impls/NeoVim/general/write -> root-config.json:83
/tuning/clipboard/impls/NeoVim/test -> root-config.json:81
/tuning/clipboard/impls/Wayland/general/read -> root-config.json:63
/tuning/clipboard/impls/Wayland/general/write -> root-config.json:62
/tuning/clipboard/impls/Wayland/test -> root-config.json:60
/tuning/clipboard/impls/Windows/general/write -> root-config.json:90
/tuning/clipboard/impls/Windows/test -> root-config.json:88
/tuning/clipboard/impls/X11-xclip/general/read -> root-config.json:70
/tuning/clipboard/impls/X11-xclip/general/write -> root-config.json:69
/tuning/clipboard/impls/X11-xclip/test -> root-config.json:67
/tuning/clipboard/impls/tmux/general/read -> root-config.json:77
/tuning/clipboard/impls/tmux/general/write -> root-config.json:76
/tuning/clipboard/impls/tmux/test -> root-config.json:74
/tuning/piper/max-size -> root-config.json:42
/tuning/piper/rotations -> root-config.json:43
/tuning/piper/ttl -> root-config.json:44
/tuning/remote/ssh/command -> root-config.json:32
/tuning/remote/ssh/config/BatchMode -> root-config.json:34
/tuning/remote/ssh/config/ConnectTimeout -> root-config.json:35
/tuning/remote/ssh/start-command -> root-config.json:37
/tuning/remote/ssh/transfer-command -> root-config.json:38
/tuning/url-scheme/docker/handler -> root-config.json:97
/tuning/url-scheme/hw/handler -> {test_dir}/configs/installed/hw-url-handler.json:6
/tuning/url-scheme/piper/handler -> root-config.json:97
/tuning/url-scheme/piper/handler -> root-config.json:100
/ui/clock-format -> root-config.json:4
/ui/default-colors -> root-config.json:6
/ui/dim-text -> root-config.json:5

@ -1,4 +1,4 @@
 Thu Nov 03 09:20:00  1 normal 2 errors 0 warnings  0 marks
 Thu Nov 03 09:45:00  1 normal 0 errors 0 warnings 0 marks
 Fri Feb 03 09:20:00  0 normal 1 errors 0 warnings 0 marks
 Wed Jan 03 09:20:00  1 normal 0 errors 0 warnings 0 marks
 Fri Feb 03 09:20:00  0 normal 1 errors 0 warnings 0 marks
 Wed Jan 03 09:20:00  1 normal 0 errors 0 warnings 0 marks

@ -1,3 +1,3 @@
2600-12-03 09:23:00.000000 0:
2600-12-03 09:23:00.000000 0:
2600-12-03 09:23:00.000000 0:
2600-12-03 09:23:00 0:
2600-12-03 09:23:00 0:
2600-12-03 09:23:00 0:

@ -0,0 +1,3 @@
Aug 27 10:22:01 2022 -- 613
Aug 27 10:22:01 2022 -- 694
Aug 27 10:22:01 2022 -- 888

@ -0,0 +1,3 @@
Aug 27 07:22:01 2022 -- 613
Aug 27 07:22:01 2022 -- 694
Aug 27 07:22:01 2022 -- 888

@ -35,6 +35,7 @@
#include "base/date_time_scanner.hh"
#include "config.h"
#include "doctest/doctest.h"
#include "lnav_config.hh"
#include "ptimec.hh"
static const char* GOOD_TIMES[] = {
@ -65,6 +66,7 @@ TEST_CASE("date_time_scanner")
{
setenv("TZ", "UTC", 1);
lnav_config.lc_log_date_time.c_zoned_to_local = false;
for (const auto* good_time : GOOD_TIMES) {
date_time_scanner dts;
struct timeval tv;
@ -72,6 +74,7 @@ TEST_CASE("date_time_scanner")
const char* rc;
rc = dts.scan(good_time, strlen(good_time), nullptr, &tm, tv);
CHECK(dts.dts_zoned_to_local == false);
printf("ret %s %p\n", good_time, rc);
assert(rc != nullptr);

@ -1,5 +1,6 @@
#! /bin/bash
export TZ=UTC
export YES_COLOR=1
# journald json log format is not working"

@ -547,6 +547,10 @@ EOF
run_cap_test ./drive_logfile -t -f generic_log ${test_dir}/logfile_with_zones.0
run_cap_test env TZ=America/Los_Angeles ./drive_logfile -t -f generic_log ${test_dir}/logfile_with_zones.0
run_cap_test env TZ=America/New_York ./drive_logfile -t -f generic_log ${test_dir}/logfile_with_zones.0
touch -t 200711030923 ${srcdir}/logfile_glog.0
run_test ./drive_logfile -t -f glog_log ${srcdir}/logfile_glog.0
@ -630,8 +634,8 @@ EOF
run_test ${lnav_test} -n -I ${test_dir} ${srcdir}/logfile_epoch.0
check_output "rewriting machine-oriented timestamp didn't work?" <<EOF
2015-04-10 02:58:07.123000 Hello, World!
2015-04-10 02:58:07.456000 Goodbye, World!
2015-04-10 02:58:07.123 Hello, World!
2015-04-10 02:58:07.456 Goodbye, World!
EOF
run_test ${lnav_test} -n -I ${test_dir} ${srcdir}/logfile_crlf.0

@ -1,5 +1,6 @@
#! /bin/bash
export TZ=UTC
export YES_COLOR=1
run_cap_test ${lnav_test} -n \

Loading…
Cancel
Save