[date_time_scanner] convert timestamps with zones to local time

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

@ -41,6 +41,14 @@ Features:
is executed asynchronously, so it will not block input is executed asynchronously, so it will not block input
and the result is saved in the session. Annotations are and the result is saved in the session. Annotations are
defined in the `/log/annotations` configuration property. 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 the SQLite JSON functions to the online help.
* Added `config get` and `config blame` management CLI * Added `config get` and `config blame` management CLI
commands to get the current configuration and the file commands to get the current configuration and the file

@ -744,6 +744,19 @@
"title": "/log", "title": "/log",
"type": "object", "type": "object",
"properties": { "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": { "watch-expressions": {
"description": "Log message watch expressions", "description": "Log message watch expressions",
"title": "/log/watch-expressions", "title": "/log/watch-expressions",

@ -180,8 +180,8 @@ Environment Variables
.. envvar:: TZ .. envvar:: TZ
The timezone setting is used in some log formats to convert UTC timestamps The timezone setting is used in some log formats to convert timestamps
to the local timezone. with a timezone to the local timezone.
Examples 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 :ref:`log file formats<log_formats>`, this section covers options that are not
specific to a particular format. 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+) Watch Expressions (v0.11.0+)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

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

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

@ -34,6 +34,8 @@
#include "date_time_scanner.hh" #include "date_time_scanner.hh"
#include "config.h" #include "config.h"
#include "date_time_scanner.cfg.hh"
#include "injector.hh"
#include "ptimec.hh" #include "ptimec.hh"
#include "scn/scn.h" #include "scn/scn.h"
@ -94,6 +96,9 @@ date_time_scanner::scan(const char* time_dest,
struct timeval& tv_out, struct timeval& tv_out,
bool convert_local) bool convert_local)
{ {
static const auto& cfg
= injector::get<const date_time_scanner_ns::config&>();
int curr_time_fmt = -1; int curr_time_fmt = -1;
bool found = false; bool found = false;
const char* retval = nullptr; const char* retval = nullptr;
@ -102,6 +107,7 @@ date_time_scanner::scan(const char* time_dest,
time_fmt = PTIMEC_FORMAT_STR; 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)) { while (next_format(time_fmt, curr_time_fmt, this->dts_fmt_lock)) {
*tm_out = this->dts_base_tm; *tm_out = this->dts_base_tm;
tm_out->et_flags = 0; tm_out->et_flags = 0;
@ -112,7 +118,9 @@ date_time_scanner::scan(const char* time_dest,
if (epoch_scan_res) { if (epoch_scan_res) {
time_t gmt = epoch_scan_res.value(); 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); localtime_r(&gmt, &tm_out->et_tm);
#ifdef HAVE_STRUCT_TM_TM_ZONE #ifdef HAVE_STRUCT_TM_TM_ZONE
tm_out->et_tm.tm_zone = nullptr; 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_sec = gmt;
tv_out.tv_usec = 0; tv_out.tv_usec = 0;
tm_out->et_flags = ETF_DAY_SET | ETF_MONTH_SET | ETF_YEAR_SET 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_lock = curr_time_fmt;
this->dts_fmt_len = sv.length() - epoch_scan_res.range().size(); 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 if (convert_local
&& (this->dts_local_time && (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; 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; tv_out.tv_sec += sec_diff;
tm_out->et_tm.tm_wday = last_tm.tm_wday; tm_out->et_tm.tm_wday = last_tm.tm_wday;
} else { } else {
// log_debug("doing tm2sec");
tv_out = tm_out->to_timeval(); tv_out = tm_out->to_timeval();
secs2wday(tv_out, &tm_out->et_tm); secs2wday(tv_out, &tm_out->et_tm);
} }
@ -199,7 +208,9 @@ date_time_scanner::scan(const char* time_dest,
} }
if (convert_local if (convert_local
&& (this->dts_local_time && (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; 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; time_t new_gmt;
localtime_r(&t, &tm_out.et_tm); 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 #ifdef HAVE_STRUCT_TM_TM_ZONE
tm_out.et_tm.tm_gmtoff = 0;
tm_out.et_tm.tm_zone = nullptr; tm_out.et_tm.tm_zone = nullptr;
#endif #endif
tm_out.et_tm.tm_isdst = 0; 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; time_t adjust_gmt = t - this->dts_local_offset_cache;
gmtime_r(&adjust_gmt, &tm_out.et_tm); 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_keep_base_tz{false};
bool dts_local_time{false}; bool dts_local_time{false};
bool dts_zoned_to_local{true};
time_t dts_base_time{0}; time_t dts_base_time{0};
struct exttm dts_base_tm; struct exttm dts_base_tm;
int dts_fmt_lock{-1}; int dts_fmt_lock{-1};

@ -102,6 +102,11 @@ hist_source2::text_attrs_for_line(textview_curses& tc,
bucket.b_values[lpc].hv_value, bucket.b_values[lpc].hv_value,
value_out); 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 void

@ -81,6 +81,9 @@ lnav_config_listener* lnav_config_listener::LISTENER_LIST;
static auto a = injector::bind<archive_manager::config>::to_instance( static auto a = injector::bind<archive_manager::config>::to_instance(
+[]() { return &lnav_config.lc_archive_manager; }); +[]() { 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( static auto fvc = injector::bind<file_vtab::config>::to_instance(
+[]() { return &lnav_config.lc_file_vtab; }); +[]() { return &lnav_config.lc_file_vtab; });
@ -1309,7 +1312,18 @@ static const struct json_path_container annotations_handlers = {
.with_children(annotation_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 = { 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") yajlpp::property_handler("watch-expressions")
.with_description("Log message watch expressions") .with_description("Log message watch expressions")
.with_children(log_source_watch_handlers), .with_children(log_source_watch_handlers),

@ -39,6 +39,7 @@
#include <vector> #include <vector>
#include "archive_manager.cfg.hh" #include "archive_manager.cfg.hh"
#include "base/date_time_scanner.cfg.hh"
#include "base/file_range.hh" #include "base/file_range.hh"
#include "base/lnav.console.hh" #include "base/lnav.console.hh"
#include "base/result.h" #include "base/result.h"
@ -111,6 +112,7 @@ struct _lnav_config {
key_map lc_active_keymap; key_map lc_active_keymap;
archive_manager::config lc_archive_manager; archive_manager::config lc_archive_manager;
date_time_scanner_ns::config lc_log_date_time;
lnav::piper::config lc_piper; lnav::piper::config lc_piper;
file_vtab::config lc_file_vtab; file_vtab::config lc_file_vtab;
lnav::logfile::config lc_logfile; 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, &tm_out,
tv_out); tv_out);
// Leave off the machine oriented flag since we convert it anyhow // Leave off the machine oriented flag since we convert it anyhow
// in rewrite_json_field()
jlu->jlu_format->lf_timestamp_flags 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); jlu->jlu_base_line->set_time(tv_out);
} else if (jlu->jlu_format->elf_level_pointer.pp_value != nullptr) { } else if (jlu->jlu_format->elf_level_pointer.pp_value != nullptr) {
if (jlu->jlu_format->elf_level_pointer.pp_value if (jlu->jlu_format->elf_level_pointer.pp_value

@ -155,10 +155,11 @@ class generic_log_format : public log_format {
return; 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()); sa.emplace_back(lr, logline::L_TIMESTAMP.value());
prefix_len = lr.lr_end; prefix_len = ts_cap.sf_end;
auto level_cap = md[2]; auto level_cap = md[2];
if (level_cap) { if (level_cap) {
if (string2level(level_cap->data(), level_cap->length(), true) if (string2level(level_cap->data(), level_cap->length(), true)

@ -42,6 +42,7 @@
#include <time.h> #include <time.h>
#include "base/ansi_scrubber.hh" #include "base/ansi_scrubber.hh"
#include "base/date_time_scanner.cfg.hh"
#include "base/fs_util.hh" #include "base/fs_util.hh"
#include "base/injector.hh" #include "base/injector.hh"
#include "base/string_util.hh" #include "base/string_util.hh"
@ -477,6 +478,9 @@ logfile::process_prefix(shared_buffer_ref& sbr,
logfile::rebuild_result_t logfile::rebuild_result_t
logfile::rebuild_index(nonstd::optional<ui_clock::time_point> deadline) 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_indexing) {
if (this->lf_sort_needed) { if (this->lf_sort_needed) {
this->lf_sort_needed = false; 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; 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", log_info("%s: format has changed, rebuilding",
this->lf_filename.c_str()); this->lf_filename.c_str());
this->lf_index.clear(); 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_longest_line = 0;
this->lf_sort_needed = true; 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; auto retval = rebuild_result_t::NO_NEW_LINES;
struct stat st; struct stat st;

@ -435,6 +435,7 @@ private:
bool lf_is_closed{false}; bool lf_is_closed{false};
bool lf_indexing{true}; bool lf_indexing{true};
bool lf_partial_line{false}; bool lf_partial_line{false};
bool lf_zoned_to_local_state{true};
logline_observer* lf_logline_observer{nullptr}; logline_observer* lf_logline_observer{nullptr};
logfile_observer* lf_logfile_observer{nullptr}; logfile_observer* lf_logfile_observer{nullptr};
size_t lf_longest_line{0}; 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() 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_MACHINE_ORIENTED
|| !(format->lf_timestamp_flags & ETF_DAY_SET) || !(format->lf_timestamp_flags & ETF_DAY_SET)
|| !(format->lf_timestamp_flags & ETF_MONTH_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)) || !(format->lf_timestamp_flags & ETF_MONTH_SET))
{ {
adjusted_time = this->lss_token_line->get_timeval(); adjusted_time = this->lss_token_line->get_timeval();
fmt = "%Y-%m-%d %H:%M:%S.%f"; if (format->lf_timestamp_flags
if (format->lf_timestamp_flags & ETF_MICROS_SET) { & (ETF_MICROS_SET | ETF_NANOS_SET))
{
fmt = "%Y-%m-%d %H:%M:%S.%f";
struct timeval actual_tv; struct timeval actual_tv;
struct exttm tm; struct exttm tm;
if (format->lf_date_time.scan( 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; 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); gmtime_r(&adjusted_time.tv_sec, &adjusted_tm.et_tm);
adjusted_tm.et_nsec 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); secs2tm(epoch, &dst->et_tm);
dst->et_flags = ETF_DAY_SET | ETF_MONTH_SET | ETF_YEAR_SET | ETF_HOUR_SET 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_MILLIS_SET
| ETF_EPOCH_TIME | ETF_ZONE_SET; | ETF_MACHINE_ORIENTED | ETF_EPOCH_TIME | ETF_ZONE_SET;
return (epoch_ms > 0); 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); secs2tm(epoch, &dst->et_tm);
dst->et_flags = ETF_DAY_SET | ETF_MONTH_SET | ETF_YEAR_SET | ETF_HOUR_SET 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_MICROS_SET
| ETF_EPOCH_TIME | ETF_ZONE_SET; | ETF_MACHINE_ORIENTED | ETF_EPOCH_TIME | ETF_ZONE_SET;
return (epoch_us > 0); 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 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; | ETF_EPOCH_TIME | ETF_ZONE_SET;
return true; return true;

@ -11,6 +11,9 @@
} }
}, },
"log": { "log": {
"date-time": {
"convert-zoned-to-local": true
},
"annotations": { "annotations": {
"com.vmware.vmacore.backtrace": { "com.vmware.vmacore.backtrace": {
"description": "Convert a vmacore backtrace into human-readable text", "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_a7037efd0c4bbf51940137a44e57d94e9307e83e.out \
$(srcdir)/%reldir%/test_logfile.sh_c18e14a26d8261c9f72747118a469266121d5459.err \ $(srcdir)/%reldir%/test_logfile.sh_c18e14a26d8261c9f72747118a469266121d5459.err \
$(srcdir)/%reldir%/test_logfile.sh_c18e14a26d8261c9f72747118a469266121d5459.out \ $(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.err \
$(srcdir)/%reldir%/test_logfile.sh_e840b674cd65936a72bd64b1dac1524d16fe44c3.out \ $(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.err \
$(srcdir)/%reldir%/test_meta.sh_039c1f127c087ec2c6a23a0ecec4df7992cbc8b4.out \ $(srcdir)/%reldir%/test_meta.sh_039c1f127c087ec2c6a23a0ecec4df7992cbc8b4.out \
$(srcdir)/%reldir%/test_meta.sh_154047fb52e4831aabf7d36512247bad6a6a2cf7.err \ $(srcdir)/%reldir%/test_meta.sh_154047fb52e4831aabf7d36512247bad6a6a2cf7.err \

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

@ -11,44 +11,45 @@
/global/keymap_def_scroll_horiz -> default-keymap.json:6 /global/keymap_def_scroll_horiz -> default-keymap.json:6
/global/keymap_def_text_view -> default-keymap.json:10 /global/keymap_def_text_view -> default-keymap.json:10
/global/keymap_def_zoom -> default-keymap.json:12 /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/condition -> root-config.json:20
/log/annotations/com.vmware.vmacore.backtrace/description -> root-config.json:16 /log/annotations/com.vmware.vmacore.backtrace/description -> root-config.json:19
/log/annotations/com.vmware.vmacore.backtrace/handler -> root-config.json:18 /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/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/description -> {test_dir}/configs/installed/anno-test.json:6
/log/annotations/org.lnav.test/handler -> {test_dir}/configs/installed/anno-test.json:8 /log/annotations/org.lnav.test/handler -> {test_dir}/configs/installed/anno-test.json:8
/tuning/archive-manager/cache-ttl -> root-config.json:25 /log/date-time/convert-zoned-to-local -> root-config.json:15
/tuning/archive-manager/min-free-space -> root-config.json:24 /tuning/archive-manager/cache-ttl -> root-config.json:28
/tuning/clipboard/impls/MacOS/find/read -> root-config.json:53 /tuning/archive-manager/min-free-space -> root-config.json:27
/tuning/clipboard/impls/MacOS/find/write -> root-config.json:52 /tuning/clipboard/impls/MacOS/find/read -> root-config.json:56
/tuning/clipboard/impls/MacOS/general/read -> root-config.json:49 /tuning/clipboard/impls/MacOS/find/write -> root-config.json:55
/tuning/clipboard/impls/MacOS/general/write -> root-config.json:48 /tuning/clipboard/impls/MacOS/general/read -> root-config.json:52
/tuning/clipboard/impls/MacOS/test -> root-config.json:46 /tuning/clipboard/impls/MacOS/general/write -> root-config.json:51
/tuning/clipboard/impls/NeoVim/general/read -> root-config.json:81 /tuning/clipboard/impls/MacOS/test -> root-config.json:49
/tuning/clipboard/impls/NeoVim/general/write -> root-config.json:80 /tuning/clipboard/impls/NeoVim/general/read -> root-config.json:84
/tuning/clipboard/impls/NeoVim/test -> root-config.json:78 /tuning/clipboard/impls/NeoVim/general/write -> root-config.json:83
/tuning/clipboard/impls/Wayland/general/read -> root-config.json:60 /tuning/clipboard/impls/NeoVim/test -> root-config.json:81
/tuning/clipboard/impls/Wayland/general/write -> root-config.json:59 /tuning/clipboard/impls/Wayland/general/read -> root-config.json:63
/tuning/clipboard/impls/Wayland/test -> root-config.json:57 /tuning/clipboard/impls/Wayland/general/write -> root-config.json:62
/tuning/clipboard/impls/Windows/general/write -> root-config.json:87 /tuning/clipboard/impls/Wayland/test -> root-config.json:60
/tuning/clipboard/impls/Windows/test -> root-config.json:85 /tuning/clipboard/impls/Windows/general/write -> root-config.json:90
/tuning/clipboard/impls/X11-xclip/general/read -> root-config.json:67 /tuning/clipboard/impls/Windows/test -> root-config.json:88
/tuning/clipboard/impls/X11-xclip/general/write -> root-config.json:66 /tuning/clipboard/impls/X11-xclip/general/read -> root-config.json:70
/tuning/clipboard/impls/X11-xclip/test -> root-config.json:64 /tuning/clipboard/impls/X11-xclip/general/write -> root-config.json:69
/tuning/clipboard/impls/tmux/general/read -> root-config.json:74 /tuning/clipboard/impls/X11-xclip/test -> root-config.json:67
/tuning/clipboard/impls/tmux/general/write -> root-config.json:73 /tuning/clipboard/impls/tmux/general/read -> root-config.json:77
/tuning/clipboard/impls/tmux/test -> root-config.json:71 /tuning/clipboard/impls/tmux/general/write -> root-config.json:76
/tuning/piper/max-size -> root-config.json:39 /tuning/clipboard/impls/tmux/test -> root-config.json:74
/tuning/piper/rotations -> root-config.json:40 /tuning/piper/max-size -> root-config.json:42
/tuning/piper/ttl -> root-config.json:41 /tuning/piper/rotations -> root-config.json:43
/tuning/remote/ssh/command -> root-config.json:29 /tuning/piper/ttl -> root-config.json:44
/tuning/remote/ssh/config/BatchMode -> root-config.json:31 /tuning/remote/ssh/command -> root-config.json:32
/tuning/remote/ssh/config/ConnectTimeout -> root-config.json:32 /tuning/remote/ssh/config/BatchMode -> root-config.json:34
/tuning/remote/ssh/start-command -> root-config.json:34 /tuning/remote/ssh/config/ConnectTimeout -> root-config.json:35
/tuning/remote/ssh/transfer-command -> root-config.json:35 /tuning/remote/ssh/start-command -> root-config.json:37
/tuning/url-scheme/docker/handler -> root-config.json:94 /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/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/clock-format -> root-config.json:4
/ui/default-colors -> root-config.json:6 /ui/default-colors -> root-config.json:6
/ui/dim-text -> root-config.json:5 /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:20:00  1 normal 2 errors 0 warnings  0 marks
 Thu Nov 03 09:45:00  1 normal 0 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  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  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 0:
2600-12-03 09:23:00.000000 0: 2600-12-03 09:23:00 0:
2600-12-03 09:23:00.000000 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 "base/date_time_scanner.hh"
#include "config.h" #include "config.h"
#include "doctest/doctest.h" #include "doctest/doctest.h"
#include "lnav_config.hh"
#include "ptimec.hh" #include "ptimec.hh"
static const char* GOOD_TIMES[] = { static const char* GOOD_TIMES[] = {
@ -65,6 +66,7 @@ TEST_CASE("date_time_scanner")
{ {
setenv("TZ", "UTC", 1); setenv("TZ", "UTC", 1);
lnav_config.lc_log_date_time.c_zoned_to_local = false;
for (const auto* good_time : GOOD_TIMES) { for (const auto* good_time : GOOD_TIMES) {
date_time_scanner dts; date_time_scanner dts;
struct timeval tv; struct timeval tv;
@ -72,6 +74,7 @@ TEST_CASE("date_time_scanner")
const char* rc; const char* rc;
rc = dts.scan(good_time, strlen(good_time), nullptr, &tm, tv); 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); printf("ret %s %p\n", good_time, rc);
assert(rc != nullptr); assert(rc != nullptr);

@ -1,5 +1,6 @@
#! /bin/bash #! /bin/bash
export TZ=UTC
export YES_COLOR=1 export YES_COLOR=1
# journald json log format is not working" # 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 ./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 touch -t 200711030923 ${srcdir}/logfile_glog.0
run_test ./drive_logfile -t -f glog_log ${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 run_test ${lnav_test} -n -I ${test_dir} ${srcdir}/logfile_epoch.0
check_output "rewriting machine-oriented timestamp didn't work?" <<EOF 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.123 Hello, World!
2015-04-10 02:58:07.456000 Goodbye, World! 2015-04-10 02:58:07.456 Goodbye, World!
EOF EOF
run_test ${lnav_test} -n -I ${test_dir} ${srcdir}/logfile_crlf.0 run_test ${lnav_test} -n -I ${test_dir} ${srcdir}/logfile_crlf.0

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

Loading…
Cancel
Save