mirror of https://github.com/tstack/lnav.git
[docs] add some more text to arch docs and other tweaks
This commit is contained in:
parent
43bb384199
commit
0f238f7972
|
@ -57,7 +57,7 @@ log format has matched yet, each line will be passed through the log format
|
||||||
regular expressions to try and find a match. Each line that is read is added
|
regular expressions to try and find a match. Each line that is read is added
|
||||||
to an index
|
to an index
|
||||||
|
|
||||||
### Why is `mmap()` not used?
|
#### Why is `mmap()` not used?
|
||||||
|
|
||||||
Note that file contents are consumed using `pread(2)`/`read(2)` and not
|
Note that file contents are consumed using `pread(2)`/`read(2)` and not
|
||||||
`mmap(2)` since `mmap(2)` does not react well to files changing out from
|
`mmap(2)` since `mmap(2)` does not react well to files changing out from
|
||||||
|
@ -71,10 +71,21 @@ As files are being indexed, if a matching format is found, the file is
|
||||||
it is added to the [logfile_sub_source](src/logfile_sub_source.hh), which
|
it is added to the [logfile_sub_source](src/logfile_sub_source.hh), which
|
||||||
collates all log messages together into a single index.
|
collates all log messages together into a single index.
|
||||||
|
|
||||||
|
## Log Formats
|
||||||
|
|
||||||
|
[log_format](src/log_format.hh) instances are used to parse lines from files
|
||||||
|
into `logline` objects. The majority of log formats are
|
||||||
|
[external_log_format](src/log_format_ext.hh) objects that are create from
|
||||||
|
[JSON format definitions](https://lnav.readthedocs.io/en/latest/formats.html).
|
||||||
|
The built-in definitions are located in the [formats](src/formats) directory.
|
||||||
|
Log formats that cannot be handled through a simple regular expression are
|
||||||
|
implemented in the [log_format_impls.cc](src/log_format_impls.cc) file.
|
||||||
|
|
||||||
## User Interface
|
## User Interface
|
||||||
|
|
||||||
[![lnav TUI](docs/lnav-tui.png)](https://whimsical.com/lnav-tui-MQjXc7Vx23BxQTHrnuNp5F)
|
[![lnav TUI](docs/lnav-tui.png)](https://whimsical.com/lnav-tui-MQjXc7Vx23BxQTHrnuNp5F)
|
||||||
|
|
||||||
The lnav text-user-interface is built on top of the basic drawing functionality
|
The lnav text-user-interface is built on top of the basic drawing functionality
|
||||||
of [ncurses](https://invisible-island.net/ncurses/announce.html). However,
|
provided by [ncurses](https://invisible-island.net/ncurses/announce.html).
|
||||||
|
However, the higher-level functionality of panels, widgets, and such is not
|
||||||
|
used.
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 208 KiB After Width: | Height: | Size: 360 KiB |
|
@ -208,3 +208,33 @@ const char *date_time_scanner::scan(const char *time_dest,
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void date_time_scanner::to_localtime(time_t t, exttm &tm_out)
|
||||||
|
{
|
||||||
|
if (t < (24 * 60 * 60)) {
|
||||||
|
// Don't convert and risk going past the epoch.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t < this->dts_local_offset_valid ||
|
||||||
|
t >= this->dts_local_offset_expiry) {
|
||||||
|
time_t new_gmt;
|
||||||
|
|
||||||
|
localtime_r(&t, &tm_out.et_tm);
|
||||||
|
#ifdef HAVE_STRUCT_TM_TM_ZONE
|
||||||
|
tm_out.et_tm.tm_zone = nullptr;
|
||||||
|
#endif
|
||||||
|
tm_out.et_tm.tm_isdst = 0;
|
||||||
|
|
||||||
|
new_gmt = tm2sec(&tm_out.et_tm);
|
||||||
|
this->dts_local_offset_cache = t - new_gmt;
|
||||||
|
this->dts_local_offset_valid = t;
|
||||||
|
this->dts_local_offset_expiry = t + (EXPIRE_TIME - 1);
|
||||||
|
this->dts_local_offset_expiry -=
|
||||||
|
this->dts_local_offset_expiry % EXPIRE_TIME;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
time_t adjust_gmt = t - this->dts_local_offset_cache;
|
||||||
|
gmtime_r(&adjust_gmt, &tm_out.et_tm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -39,12 +39,15 @@
|
||||||
|
|
||||||
#include "time_util.hh"
|
#include "time_util.hh"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scans a timestamp string to discover the date-time format using the custom
|
||||||
|
* ptimec parser. Once a format is found, it is locked in so that the next
|
||||||
|
* time a timestamp needs to be scanned, the format does not have to be
|
||||||
|
* rediscovered. The discovered date-time format can also be used to convert
|
||||||
|
* an exttm struct to a string using the ftime() method.
|
||||||
|
*/
|
||||||
struct date_time_scanner {
|
struct date_time_scanner {
|
||||||
date_time_scanner() : dts_keep_base_tz(false),
|
date_time_scanner() {
|
||||||
dts_local_time(false),
|
|
||||||
dts_local_offset_cache(0),
|
|
||||||
dts_local_offset_valid(0),
|
|
||||||
dts_local_offset_expiry(0) {
|
|
||||||
this->clear();
|
this->clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -55,6 +58,9 @@ struct date_time_scanner {
|
||||||
this->dts_fmt_len = -1;
|
this->dts_fmt_len = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unlock this scanner so that the format is rediscovered.
|
||||||
|
*/
|
||||||
void unlock() {
|
void unlock() {
|
||||||
this->dts_fmt_lock = -1;
|
this->dts_fmt_lock = -1;
|
||||||
this->dts_fmt_len = -1;
|
this->dts_fmt_len = -1;
|
||||||
|
@ -72,44 +78,17 @@ struct date_time_scanner {
|
||||||
* every call, so we cache the result and only call it again if the
|
* every call, so we cache the result and only call it again if the
|
||||||
* requested time falls outside of a fifteen minute range.
|
* requested time falls outside of a fifteen minute range.
|
||||||
*/
|
*/
|
||||||
void to_localtime(time_t t, struct exttm &tm_out) {
|
void to_localtime(time_t t, struct exttm &tm_out);
|
||||||
if (t < (24 * 60 * 60)) {
|
|
||||||
// Don't convert and risk going past the epoch.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (t < this->dts_local_offset_valid ||
|
bool dts_keep_base_tz{false};
|
||||||
t >= this->dts_local_offset_expiry) {
|
bool dts_local_time{false};
|
||||||
time_t new_gmt;
|
time_t dts_base_time{0};
|
||||||
|
|
||||||
localtime_r(&t, &tm_out.et_tm);
|
|
||||||
#ifdef HAVE_STRUCT_TM_TM_ZONE
|
|
||||||
tm_out.et_tm.tm_zone = nullptr;
|
|
||||||
#endif
|
|
||||||
tm_out.et_tm.tm_isdst = 0;
|
|
||||||
|
|
||||||
new_gmt = tm2sec(&tm_out.et_tm);
|
|
||||||
this->dts_local_offset_cache = t - new_gmt;
|
|
||||||
this->dts_local_offset_valid = t;
|
|
||||||
this->dts_local_offset_expiry = t + (EXPIRE_TIME - 1);
|
|
||||||
this->dts_local_offset_expiry -=
|
|
||||||
this->dts_local_offset_expiry % EXPIRE_TIME;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
time_t adjust_gmt = t - this->dts_local_offset_cache;
|
|
||||||
gmtime_r(&adjust_gmt, &tm_out.et_tm);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
bool dts_keep_base_tz;
|
|
||||||
bool dts_local_time;
|
|
||||||
time_t dts_base_time;
|
|
||||||
struct exttm dts_base_tm;
|
struct exttm dts_base_tm;
|
||||||
int dts_fmt_lock;
|
int dts_fmt_lock{-1};
|
||||||
int dts_fmt_len;
|
int dts_fmt_len{-1};
|
||||||
time_t dts_local_offset_cache;
|
time_t dts_local_offset_cache{0};
|
||||||
time_t dts_local_offset_valid;
|
time_t dts_local_offset_valid{0};
|
||||||
time_t dts_local_offset_expiry;
|
time_t dts_local_offset_expiry{0};
|
||||||
|
|
||||||
static const int EXPIRE_TIME = 15 * 60;
|
static const int EXPIRE_TIME = 15 * 60;
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,12 @@
|
||||||
|
|
||||||
namespace humanize {
|
namespace humanize {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format the given size as a human-friendly string.
|
||||||
|
*
|
||||||
|
* @param value The value to format.
|
||||||
|
* @return The formatted string.
|
||||||
|
*/
|
||||||
std::string file_size(ssize_t value);
|
std::string file_size(ssize_t value);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Generated by re2c 2.0.3 on Wed Jan 27 16:33:33 2021 */
|
/* Generated by re2c 2.0.3 on Sat Feb 13 21:35:28 2021 */
|
||||||
#line 1 "../../lnav/src/data_scanner_re.re"
|
#line 1 "../../lnav/src/data_scanner_re.re"
|
||||||
/**
|
/**
|
||||||
* Copyright (c) 2015, Timothy Stack
|
* Copyright (c) 2015, Timothy Stack
|
||||||
|
@ -53,7 +53,7 @@ bool data_scanner::tokenize2(pcre_context &pc, data_token_t &token_out)
|
||||||
static const unsigned char *EMPTY = (const unsigned char *) "";
|
static const unsigned char *EMPTY = (const unsigned char *) "";
|
||||||
pcre_input &pi = this->ds_pcre_input;
|
pcre_input &pi = this->ds_pcre_input;
|
||||||
struct _YYCURSOR {
|
struct _YYCURSOR {
|
||||||
const YYCTYPE operator*() const {
|
YYCTYPE operator*() const {
|
||||||
if (this->val < this->lim) {
|
if (this->val < this->lim) {
|
||||||
return *val;
|
return *val;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ bool data_scanner::tokenize2(pcre_context &pc, data_token_t &token_out)
|
||||||
static const unsigned char *EMPTY = (const unsigned char *) "";
|
static const unsigned char *EMPTY = (const unsigned char *) "";
|
||||||
pcre_input &pi = this->ds_pcre_input;
|
pcre_input &pi = this->ds_pcre_input;
|
||||||
struct _YYCURSOR {
|
struct _YYCURSOR {
|
||||||
const YYCTYPE operator*() const {
|
YYCTYPE operator*() const {
|
||||||
if (this->val < this->lim) {
|
if (this->val < this->lim) {
|
||||||
return *val;
|
return *val;
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,9 +62,9 @@ bool files_sub_source::list_input_handle_key(listview_curses &lv, int ch)
|
||||||
auto& lss = lnav_data.ld_log_source;
|
auto& lss = lnav_data.ld_log_source;
|
||||||
auto &lf = fc.fc_files[sel];
|
auto &lf = fc.fc_files[sel];
|
||||||
|
|
||||||
lss.find_data(lf) | [&lss](auto ld) {
|
lss.find_data(lf) | [](auto ld) {
|
||||||
ld->set_visibility(true);
|
ld->set_visibility(true);
|
||||||
lss.text_filters_changed();
|
lnav_data.ld_log_source.text_filters_changed();
|
||||||
};
|
};
|
||||||
|
|
||||||
if (lf->get_format() != nullptr) {
|
if (lf->get_format() != nullptr) {
|
||||||
|
|
|
@ -792,7 +792,7 @@ static void write_sample_file()
|
||||||
extract_metadata(sf.data(), sf.length(), meta);
|
extract_metadata(sf.data(), sf.length(), meta);
|
||||||
snprintf(path, sizeof(path), "formats/default/%s.lnav", meta.sm_name.c_str());
|
snprintf(path, sizeof(path), "formats/default/%s.lnav", meta.sm_name.c_str());
|
||||||
auto script_path = dotlnav_path() / path;
|
auto script_path = dotlnav_path() / path;
|
||||||
if (statp(script_path, &st) == 0 && (size_t) st.st_size == sf.length()) {
|
if (statp(script_path, &st) == 0 && st.st_size == sf.length()) {
|
||||||
// Assume it's the right contents and move on...
|
// Assume it's the right contents and move on...
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -165,7 +165,7 @@ void pcrepp::find_captures(const char *pattern)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ensure(this->p_capture_count == this->p_captures.size());
|
ensure((size_t) this->p_capture_count == this->p_captures.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pcrepp::match(pcre_context &pc, pcre_input &pi, int options) const
|
bool pcrepp::match(pcre_context &pc, pcre_input &pi, int options) const
|
||||||
|
|
|
@ -129,7 +129,7 @@ int main(int argc, char *argv[])
|
||||||
printf(" { \"%s\", ptime_f%d, ftime_f%d },\n", argv[lpc], lpc, lpc);
|
printf(" { \"%s\", ptime_f%d, ftime_f%d },\n", argv[lpc], lpc, lpc);
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf(" { NULL, NULL }\n");
|
printf(" { nullptr, nullptr, nullptr }\n");
|
||||||
printf("};\n");
|
printf("};\n");
|
||||||
|
|
||||||
printf("const char *PTIMEC_FORMAT_STR[] = {\n");
|
printf("const char *PTIMEC_FORMAT_STR[] = {\n");
|
||||||
|
@ -137,7 +137,7 @@ int main(int argc, char *argv[])
|
||||||
printf(" \"%s\",\n", argv[lpc]);
|
printf(" \"%s\",\n", argv[lpc]);
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf(" NULL\n");
|
printf(" nullptr\n");
|
||||||
printf("};\n");
|
printf("};\n");
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
|
|
|
@ -47,13 +47,13 @@
|
||||||
#include "base/time_util.hh"
|
#include "base/time_util.hh"
|
||||||
|
|
||||||
#define PTIME_CONSUME(amount, block) \
|
#define PTIME_CONSUME(amount, block) \
|
||||||
if ((off_inout + amount) > len) { \
|
if ((off_inout + (amount)) > len) { \
|
||||||
return false; \
|
return false; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
block \
|
block \
|
||||||
\
|
\
|
||||||
off_inout += amount;
|
off_inout += (amount);
|
||||||
|
|
||||||
#define PTIME_APPEND(ch) \
|
#define PTIME_APPEND(ch) \
|
||||||
if ((off_inout + 2) >= len) { \
|
if ((off_inout + 2) >= len) { \
|
||||||
|
|
|
@ -514,13 +514,13 @@ CREATE TABLE lnav_view_filters (
|
||||||
text_filter::type_t type,
|
text_filter::type_t type,
|
||||||
pair<string, auto_mem<pcre>> pattern) {
|
pair<string, auto_mem<pcre>> pattern) {
|
||||||
auto view_index = lnav_view_t(rowid >> 32);
|
auto view_index = lnav_view_t(rowid >> 32);
|
||||||
int filter_index = rowid & 0xffffffffLL;
|
auto filter_index = rowid & 0xffffffffLL;
|
||||||
textview_curses &tc = lnav_data.ld_views[view_index];
|
textview_curses &tc = lnav_data.ld_views[view_index];
|
||||||
text_sub_source *tss = tc.get_sub_source();
|
text_sub_source *tss = tc.get_sub_source();
|
||||||
filter_stack &fs = tss->get_filters();
|
filter_stack &fs = tss->get_filters();
|
||||||
auto iter = fs.begin();
|
auto iter = fs.begin();
|
||||||
for (; iter != fs.end(); ++iter) {
|
for (; iter != fs.end(); ++iter) {
|
||||||
if ((*iter)->get_index() == filter_index) {
|
if ((*iter)->get_index() == (size_t) filter_index) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue