diff --git a/NEWS.md b/NEWS.md index 2f5828a6..e2bda2cf 100644 --- a/NEWS.md +++ b/NEWS.md @@ -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 diff --git a/docs/schemas/config-v1.schema.json b/docs/schemas/config-v1.schema.json index 374f378d..30c4cd72 100644 --- a/docs/schemas/config-v1.schema.json +++ b/docs/schemas/config-v1.schema.json @@ -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", diff --git a/docs/source/cli.rst b/docs/source/cli.rst index 4956f0f7..f0738045 100644 --- a/docs/source/cli.rst +++ b/docs/source/cli.rst @@ -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 diff --git a/docs/source/config.rst b/docs/source/config.rst index 13b018bf..22437104 100644 --- a/docs/source/config.rst +++ b/docs/source/config.rst @@ -227,6 +227,18 @@ The handling of logs is largely determined by the :ref:`log file 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+) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/base/CMakeLists.txt b/src/base/CMakeLists.txt index 0b87cb92..2498ed17 100644 --- a/src/base/CMakeLists.txt +++ b/src/base/CMakeLists.txt @@ -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 diff --git a/src/base/Makefile.am b/src/base/Makefile.am index 7df65f35..c20736ae 100644 --- a/src/base/Makefile.am +++ b/src/base/Makefile.am @@ -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 \ diff --git a/src/base/date_time_scanner.cc b/src/base/date_time_scanner.cc index 97494440..f25b7155 100644 --- a/src/base/date_time_scanner.cc +++ b/src/base/date_time_scanner.cc @@ -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(); + 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 } diff --git a/src/base/date_time_scanner.cfg.hh b/src/base/date_time_scanner.cfg.hh new file mode 100644 index 00000000..7921aee3 --- /dev/null +++ b/src/base/date_time_scanner.cfg.hh @@ -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 diff --git a/src/base/date_time_scanner.hh b/src/base/date_time_scanner.hh index 94a2f3c6..b5fe1998 100644 --- a/src/base/date_time_scanner.hh +++ b/src/base/date_time_scanner.hh @@ -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}; diff --git a/src/hist_source.cc b/src/hist_source.cc index 8ff65ec9..cf455be4 100644 --- a/src/hist_source.cc +++ b/src/hist_source.cc @@ -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 diff --git a/src/lnav_config.cc b/src/lnav_config.cc index 12a65891..82ae29ce 100644 --- a/src/lnav_config.cc +++ b/src/lnav_config.cc @@ -81,6 +81,9 @@ lnav_config_listener* lnav_config_listener::LISTENER_LIST; static auto a = injector::bind::to_instance( +[]() { return &lnav_config.lc_archive_manager; }); +static auto dtc = injector::bind::to_instance( + +[]() { return &lnav_config.lc_log_date_time; }); + static auto fvc = injector::bind::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), diff --git a/src/lnav_config.hh b/src/lnav_config.hh index 8c846cc5..63dc425b 100644 --- a/src/lnav_config.hh +++ b/src/lnav_config.hh @@ -39,6 +39,7 @@ #include #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; diff --git a/src/log_format.cc b/src/log_format.cc index 8372b2cb..3d453748 100644 --- a/src/log_format.cc +++ b/src/log_format.cc @@ -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 diff --git a/src/log_format_impls.cc b/src/log_format_impls.cc index 6494ca4c..05fff801 100644 --- a/src/log_format_impls.cc +++ b/src/log_format_impls.cc @@ -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) diff --git a/src/logfile.cc b/src/logfile.cc index 21819db8..de5e390d 100644 --- a/src/logfile.cc +++ b/src/logfile.cc @@ -42,6 +42,7 @@ #include #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 deadline) { + static const auto& dts_cfg + = injector::get(); + if (!this->lf_indexing) { if (this->lf_sort_needed) { this->lf_sort_needed = false; @@ -485,7 +489,10 @@ logfile::rebuild_index(nonstd::optional 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 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; diff --git a/src/logfile.hh b/src/logfile.hh index 42462e5a..6a43ef84 100644 --- a/src/logfile.hh +++ b/src/logfile.hh @@ -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}; diff --git a/src/logfile_sub_source.cc b/src/logfile_sub_source.cc index 43a7094d..8ad27c25 100644 --- a/src/logfile_sub_source.cc +++ b/src/logfile_sub_source.cc @@ -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 diff --git a/src/ptimec.hh b/src/ptimec.hh index ddd76cdc..c460cc0e 100644 --- a/src/ptimec.hh +++ b/src/ptimec.hh @@ -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; diff --git a/src/root-config.json b/src/root-config.json index a5cb923f..6b359a28 100644 --- a/src/root-config.json +++ b/src/root-config.json @@ -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", diff --git a/test/expected/expected.am b/test/expected/expected.am index cdcb7760..da91305a 100644 --- a/test/expected/expected.am +++ b/test/expected/expected.am @@ -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 \ diff --git a/test/expected/test_cli.sh_0b3639753916f71254e8c9cce4ebb8bfd9978d3e.out b/test/expected/test_cli.sh_0b3639753916f71254e8c9cce4ebb8bfd9978d3e.out index 58e8635d..04f8e6b5 100644 --- a/test/expected/test_cli.sh_0b3639753916f71254e8c9cce4ebb8bfd9978d3e.out +++ b/test/expected/test_cli.sh_0b3639753916f71254e8c9cce4ebb8bfd9978d3e.out @@ -4009,6 +4009,9 @@ } }, "log": { + "date-time": { + "convert-zoned-to-local": true + }, "watch-expressions": { }, diff --git a/test/expected/test_cli.sh_cc06341dd560f927512e92c7c0985ed8b25827ae.out b/test/expected/test_cli.sh_cc06341dd560f927512e92c7c0985ed8b25827ae.out index a85dde0a..8d03d3fc 100644 --- a/test/expected/test_cli.sh_cc06341dd560f927512e92c7c0985ed8b25827ae.out +++ b/test/expected/test_cli.sh_cc06341dd560f927512e92c7c0985ed8b25827ae.out @@ -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 diff --git a/test/expected/test_cmds.sh_a00943ef715598c7554b85de8502454e41bb9e28.out b/test/expected/test_cmds.sh_a00943ef715598c7554b85de8502454e41bb9e28.out index 01761e9b..95268f80 100644 --- a/test/expected/test_cmds.sh_a00943ef715598c7554b85de8502454e41bb9e28.out +++ b/test/expected/test_cmds.sh_a00943ef715598c7554b85de8502454e41bb9e28.out @@ -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 diff --git a/test/expected/test_logfile.sh_08d731a04c877a34819b35de185e30a74c9fd497.out b/test/expected/test_logfile.sh_08d731a04c877a34819b35de185e30a74c9fd497.out index 9b2a7cd8..0465ab4c 100644 --- a/test/expected/test_logfile.sh_08d731a04c877a34819b35de185e30a74c9fd497.out +++ b/test/expected/test_logfile.sh_08d731a04c877a34819b35de185e30a74c9fd497.out @@ -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: diff --git a/test/expected/test_logfile.sh_ccb0d31813367c8d9dc5b5df383fac5b780711c1.err b/test/expected/test_logfile.sh_ccb0d31813367c8d9dc5b5df383fac5b780711c1.err new file mode 100644 index 00000000..e69de29b diff --git a/test/expected/test_logfile.sh_ccb0d31813367c8d9dc5b5df383fac5b780711c1.out b/test/expected/test_logfile.sh_ccb0d31813367c8d9dc5b5df383fac5b780711c1.out new file mode 100644 index 00000000..1bf2d2a6 --- /dev/null +++ b/test/expected/test_logfile.sh_ccb0d31813367c8d9dc5b5df383fac5b780711c1.out @@ -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 diff --git a/test/expected/test_logfile.sh_f171f265d8d45a2707e8b9f53e938f574c614d25.err b/test/expected/test_logfile.sh_f171f265d8d45a2707e8b9f53e938f574c614d25.err new file mode 100644 index 00000000..e69de29b diff --git a/test/expected/test_logfile.sh_f171f265d8d45a2707e8b9f53e938f574c614d25.out b/test/expected/test_logfile.sh_f171f265d8d45a2707e8b9f53e938f574c614d25.out new file mode 100644 index 00000000..c210568d --- /dev/null +++ b/test/expected/test_logfile.sh_f171f265d8d45a2707e8b9f53e938f574c614d25.out @@ -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 diff --git a/test/test_date_time_scanner.cc b/test/test_date_time_scanner.cc index 3860f58b..86d08a28 100644 --- a/test/test_date_time_scanner.cc +++ b/test/test_date_time_scanner.cc @@ -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); diff --git a/test/test_json_format.sh b/test/test_json_format.sh index 435e8e32..58998222 100644 --- a/test/test_json_format.sh +++ b/test/test_json_format.sh @@ -1,5 +1,6 @@ #! /bin/bash +export TZ=UTC export YES_COLOR=1 # journald json log format is not working" diff --git a/test/test_logfile.sh b/test/test_logfile.sh index eecaeefd..67019e31 100644 --- a/test/test_logfile.sh +++ b/test/test_logfile.sh @@ -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?" <