[xml/xpath] suggest xpath() calls for xml fields

pull/857/head
Timothy Stack 3 years ago
parent 6deb7032a6
commit 351ad7a8fc

@ -279,6 +279,7 @@ add_library(diag STATIC
lnav_util.cc
log_accel.cc
log_actions.cc
log_data_helper.cc
log_data_table.cc
log_format.cc
log_format_loader.cc
@ -333,6 +334,7 @@ add_library(diag STATIC
vt52_curses.cc
vtab_module.cc
log_vtab_impl.cc
xml_util.cc
xpath_vtab.cc
xterm_mouse.cc
yajlpp/yajlpp.cc
@ -454,6 +456,7 @@ add_library(diag STATIC
vtab_module_json.hh
yajlpp/yajlpp.hh
yajlpp/yajlpp_def.hh
xml_util.hh
xpath_vtab.hh
mapbox/recursive_wrapper.hpp

@ -378,6 +378,7 @@ noinst_HEADERS = \
vtab_module_json.hh \
log_vtab_impl.hh \
log_format_impls.cc \
xml_util.hh \
xpath_vtab.hh \
xterm_mouse.hh \
spookyhash/SpookyV2.h \
@ -434,6 +435,7 @@ libdiag_a_SOURCES = \
lnav_util.cc \
log_accel.cc \
log_actions.cc \
log_data_helper.cc \
log_data_table.cc \
log_format.cc \
log_format_loader.cc \
@ -482,6 +484,7 @@ libdiag_a_SOURCES = \
vt52_curses.cc \
vtab_module.cc \
log_vtab_impl.cc \
xml_util.cc \
xpath_vtab.cc \
xterm_mouse.cc \
spookyhash/SpookyV2.cpp

@ -486,6 +486,23 @@ void field_overlay_source::build_field_lines(const listview_curses &lv)
}
}
if (!this->fos_log_helper.ldh_xml_pairs.empty()) {
this->fos_lines.emplace_back(" XML fields:");
}
for (const auto& xml_pair : this->fos_log_helper.ldh_xml_pairs) {
auto_mem<char, sqlite3_free> qname;
auto_mem<char, sqlite3_free> xp_call;
qname = sql_quote_ident(xml_pair.first.first.get());
xp_call = sqlite3_mprintf("xpath(%Q, %s)",
xml_pair.first.second.c_str(),
qname.in());
this->fos_lines.emplace_back(fmt::format(
" {} = {}", xp_call, xml_pair.second));
this->add_key_line_attrs(0);
}
if (this->fos_log_helper.ldh_parser->dp_pairs.empty()) {
this->fos_lines.emplace_back(" No discovered message fields");
}

@ -170,7 +170,8 @@
"boolean",
"json",
"struct",
"quoted"
"quoted",
"xml"
]
},
"collate": {

@ -0,0 +1,199 @@
/**
* Copyright (c) 2021, 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 log_data_helper.cc
*/
#include "config.h"
#include "log_data_helper.hh"
void log_data_helper::clear()
{
this->ldh_file = nullptr;
this->ldh_msg.disown();
this->ldh_parser.reset();
this->ldh_scanner.reset();
this->ldh_namer.reset();
this->ldh_json_pairs.clear();
this->ldh_xml_pairs.clear();
this->ldh_line_attrs.clear();
}
bool log_data_helper::parse_line(content_line_t line, bool allow_middle)
{
logfile::iterator ll;
bool retval = false;
this->ldh_source_line = this->ldh_line_index = line;
this->ldh_file = this->ldh_log_source.find(this->ldh_line_index);
ll = this->ldh_file->begin() + this->ldh_line_index;
this->ldh_y_offset = 0;
while (allow_middle && ll->is_continued()) {
--ll;
this->ldh_y_offset += 1;
}
this->ldh_line = ll;
if (!ll->is_message()) {
this->ldh_parser.reset();
this->ldh_scanner.reset();
this->ldh_namer.reset();
this->ldh_json_pairs.clear();
this->ldh_xml_pairs.clear();
this->ldh_line_attrs.clear();
}
else {
auto format = this->ldh_file->get_format();
struct line_range body;
auto& sa = this->ldh_line_attrs;
this->ldh_line_attrs.clear();
this->ldh_line_values.clear();
this->ldh_file->read_full_message(ll, this->ldh_msg);
format->annotate(this->ldh_line_index, this->ldh_msg, sa, this->ldh_line_values);
body = find_string_attr_range(sa, &SA_BODY);
if (body.lr_start == -1) {
body.lr_start = this->ldh_msg.length();
body.lr_end = this->ldh_msg.length();
}
this->ldh_scanner = std::make_unique<data_scanner>(
this->ldh_msg, body.lr_start, body.lr_end);
this->ldh_parser = std::make_unique<data_parser>(this->ldh_scanner.get());
this->ldh_msg_format.clear();
this->ldh_parser->dp_msg_format = &this->ldh_msg_format;
this->ldh_parser->parse();
this->ldh_namer = std::make_unique<column_namer>();
this->ldh_json_pairs.clear();
this->ldh_xml_pairs.clear();
for (const auto& lv : this->ldh_line_values) {
this->ldh_namer->cn_builtin_names.emplace_back(lv.lv_meta.lvm_name.get());
}
for (auto & ldh_line_value : this->ldh_line_values) {
switch (ldh_line_value.lv_meta.lvm_kind) {
case value_kind_t::VALUE_JSON: {
json_ptr_walk jpw;
if (jpw.parse(ldh_line_value.lv_sbr.get_data(), ldh_line_value.lv_sbr.length()) == yajl_status_ok &&
jpw.complete_parse() == yajl_status_ok) {
this->ldh_json_pairs[ldh_line_value.lv_meta.lvm_name] = jpw.jpw_values;
}
break;
}
case value_kind_t::VALUE_XML: {
auto col_name = ldh_line_value.lv_meta.lvm_name;
pugi::xml_document doc;
auto parse_res = doc.load_buffer(
ldh_line_value.lv_sbr.get_data(),
ldh_line_value.lv_sbr.length());
if (parse_res) {
pugi::xpath_query query("//*");
auto node_set = doc.select_nodes(query);
for (auto& xpath_node : node_set) {
auto node_path = lnav::pugixml::get_actual_path(xpath_node.node());
for (auto& attr : xpath_node.node().attributes()) {
auto attr_path = fmt::format(
"{}/@{}", node_path, attr.name());
this->ldh_xml_pairs[
std::make_pair(col_name, attr_path)] =
attr.value();
}
if (xpath_node.node().text().empty()) {
continue;
}
auto text_path = fmt::format(
"{}/text()", node_path);
this->ldh_xml_pairs[std::make_pair(col_name, text_path)] =
trim(xpath_node.node().text().get());
}
}
break;
}
default:
break;
}
}
retval = true;
}
return retval;
}
int log_data_helper::get_line_bounds(size_t &line_index_out,
size_t &line_end_index_out) const
{
int retval = 0;
line_end_index_out = 0;
do {
const char *line_end;
line_index_out = line_end_index_out;
line_end = (const char *)memchr(
this->ldh_msg.get_data() + line_index_out + 1,
'\n',
this->ldh_msg.length() - line_index_out - 1);
if (line_end != nullptr) {
line_end_index_out = line_end - this->ldh_msg.get_data();
} else {
line_end_index_out = std::string::npos;
}
retval += 1;
} while (retval <= this->ldh_y_offset);
if (line_end_index_out == std::string::npos) {
line_end_index_out = this->ldh_msg.length();
}
return retval;
}
std::string
log_data_helper::format_json_getter(const intern_string_t field, int index)
{
auto_mem<char, sqlite3_free> qname;
auto_mem<char, sqlite3_free> jget;
std::string retval;
qname = sql_quote_ident(field.get());
jget = sqlite3_mprintf("jget(%s,%Q)", qname.in(),
this->ldh_json_pairs[field][index].wt_ptr.c_str());
retval = std::string(jget);
return retval;
}

@ -44,6 +44,7 @@
#include "yajlpp/json_ptr.hh"
#include "base/lnav_log.hh"
#include "sql_util.hh"
#include "xml_util.hh"
class log_data_helper
{
@ -54,117 +55,15 @@ public:
};
void clear() {
this->ldh_file = nullptr;
this->ldh_msg.disown();
this->ldh_parser.reset();
this->ldh_scanner.reset();
this->ldh_namer.reset();
this->ldh_json_pairs.clear();
this->ldh_line_attrs.clear();
};
void clear();
bool parse_line(vis_line_t line, bool allow_middle = false) {
return this->parse_line(this->ldh_log_source.at(line), allow_middle);
}
bool parse_line(content_line_t line, bool allow_middle = false) {
logfile::iterator ll;
bool retval = false;
this->ldh_source_line = this->ldh_line_index = line;
this->ldh_file = this->ldh_log_source.find(this->ldh_line_index);
ll = this->ldh_file->begin() + this->ldh_line_index;
this->ldh_y_offset = 0;
while (allow_middle && ll->is_continued()) {
--ll;
this->ldh_y_offset += 1;
}
this->ldh_line = ll;
if (!ll->is_message()) {
this->ldh_parser.reset();
this->ldh_scanner.reset();
this->ldh_namer.reset();
this->ldh_json_pairs.clear();
this->ldh_line_attrs.clear();
}
else {
auto format = this->ldh_file->get_format();
struct line_range body;
auto& sa = this->ldh_line_attrs;
this->ldh_line_attrs.clear();
this->ldh_line_values.clear();
this->ldh_file->read_full_message(ll, this->ldh_msg);
format->annotate(this->ldh_line_index, this->ldh_msg, sa, this->ldh_line_values);
body = find_string_attr_range(sa, &SA_BODY);
if (body.lr_start == -1) {
body.lr_start = this->ldh_msg.length();
body.lr_end = this->ldh_msg.length();
}
this->ldh_scanner = std::make_unique<data_scanner>(
this->ldh_msg, body.lr_start, body.lr_end);
this->ldh_parser = std::make_unique<data_parser>(this->ldh_scanner.get());
this->ldh_msg_format.clear();
this->ldh_parser->dp_msg_format = &this->ldh_msg_format;
this->ldh_parser->parse();
this->ldh_namer = std::make_unique<column_namer>();
this->ldh_json_pairs.clear();
bool parse_line(content_line_t line, bool allow_middle = false);
for (const auto& lv : this->ldh_line_values) {
this->ldh_namer->cn_builtin_names.emplace_back(lv.lv_meta.lvm_name.get());
}
for (auto & ldh_line_value : this->ldh_line_values) {
switch (ldh_line_value.lv_meta.lvm_kind) {
case value_kind_t::VALUE_JSON: {
json_ptr_walk jpw;
if (jpw.parse(ldh_line_value.lv_sbr.get_data(), ldh_line_value.lv_sbr.length()) == yajl_status_ok &&
jpw.complete_parse() == yajl_status_ok) {
this->ldh_json_pairs[ldh_line_value.lv_meta.lvm_name] = jpw.jpw_values;
}
break;
}
default:
break;
}
}
retval = true;
}
return retval;
};
int get_line_bounds(size_t &line_index_out, size_t &line_end_index_out) const {
int retval = 0;
line_end_index_out = 0;
do {
const char *line_end;
line_index_out = line_end_index_out;
line_end = (const char *)memchr(
this->ldh_msg.get_data() + line_index_out + 1,
'\n',
this->ldh_msg.length() - line_index_out - 1);
if (line_end != nullptr) {
line_end_index_out = line_end - this->ldh_msg.get_data();
} else {
line_end_index_out = std::string::npos;
}
retval += 1;
} while (retval <= this->ldh_y_offset);
if (line_end_index_out == std::string::npos) {
line_end_index_out = this->ldh_msg.length();
}
return retval;
};
int get_line_bounds(size_t &line_index_out, size_t &line_end_index_out) const;
int get_value_line(const logline_value &lv) const {
return std::count(this->ldh_msg.get_data(),
@ -172,18 +71,7 @@ public:
'\n');
};
std::string format_json_getter(const intern_string_t field, int index) {
auto_mem<char, sqlite3_free> qname;
auto_mem<char, sqlite3_free> jget;
std::string retval;
qname = sql_quote_ident(field.get());
jget = sqlite3_mprintf("jget(%s,%Q)", qname.in(),
this->ldh_json_pairs[field][index].wt_ptr.c_str());
retval = std::string(jget);
return retval;
};
std::string format_json_getter(const intern_string_t field, int index);
logfile_sub_source &ldh_log_source;
content_line_t ldh_source_line;
@ -198,6 +86,7 @@ public:
string_attrs_t ldh_line_attrs;
std::vector<logline_value> ldh_line_values;
std::map<const intern_string_t, json_ptr_walk::walk_list_t> ldh_json_pairs;
std::map<std::pair<const intern_string_t, std::string>, std::string> ldh_xml_pairs;
std::string ldh_msg_format;
};

@ -111,6 +111,7 @@ logline_value::logline_value(logline_value_meta lvm, shared_buffer_ref &sbr,
switch (this->lv_meta.lvm_kind) {
case value_kind_t::VALUE_JSON:
case value_kind_t::VALUE_XML:
case value_kind_t::VALUE_STRUCT:
case value_kind_t::VALUE_TEXT:
case value_kind_t::VALUE_QUOTED:
@ -163,6 +164,7 @@ std::string logline_value::to_string() const
return "null";
case value_kind_t::VALUE_JSON:
case value_kind_t::VALUE_XML:
case value_kind_t::VALUE_STRUCT:
case value_kind_t::VALUE_TEXT:
case value_kind_t::VALUE_TIMESTAMP:

@ -105,6 +105,7 @@ enum class value_kind_t : int {
VALUE_QUOTED,
VALUE_W3C_QUOTED,
VALUE_TIMESTAMP,
VALUE_XML,
VALUE__MAX
};

@ -441,6 +441,7 @@ static const json_path_handler_base::enum_value_t KIND_ENUM[] = {
{"json", value_kind_t::VALUE_JSON},
{"struct", value_kind_t::VALUE_STRUCT},
{"quoted", value_kind_t::VALUE_QUOTED},
{"xml", value_kind_t::VALUE_XML},
json_path_handler_base::ENUM_TERMINATOR
};

@ -143,6 +143,7 @@ pair<int, unsigned int> log_vtab_impl::logline_value_to_sqlite_type(value_kind_t
case value_kind_t::VALUE_QUOTED:
case value_kind_t::VALUE_W3C_QUOTED:
case value_kind_t::VALUE_TIMESTAMP:
case value_kind_t::VALUE_XML:
type = SQLITE3_TEXT;
break;
case value_kind_t::VALUE_FLOAT:
@ -627,6 +628,7 @@ static int vt_column(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int col)
}
case value_kind_t::VALUE_STRUCT:
case value_kind_t::VALUE_TEXT:
case value_kind_t::VALUE_XML:
case value_kind_t::VALUE_TIMESTAMP: {
sqlite3_result_text(ctx,
lv_iter->text_value(),

@ -0,0 +1,81 @@
/**
* Copyright (c) 2021, 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.
*/
#include "config.h"
#include "fmtlib/fmt/format.h"
#include "xml_util.hh"
namespace lnav {
namespace pugixml {
std::string get_actual_path(const pugi::xml_node &node)
{
std::string retval;
auto curr = node;
while (curr) {
switch (curr.type()) {
case pugi::node_null:
break;
case pugi::node_pcdata:
retval += "text()";
break;
default: {
auto name = std::string(curr.name());
if (curr.previous_sibling(curr.name()) ||
curr.next_sibling(curr.name())) {
auto sibling = curr;
int index = 0;
while (sibling) {
index += 1;
sibling = sibling.previous_sibling(curr.name());
}
name = fmt::format("{}[{}]", name, index);
}
if (retval.empty()) {
retval = name;
} else {
retval = fmt::format("{}/{}", name, retval);
}
break;
}
}
curr = curr.parent();
}
return retval;
}
}
}

@ -0,0 +1,45 @@
/**
* Copyright (c) 2021, 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.
*/
#ifndef lnav_xml_util_hh
#define lnav_xml_util_hh
#include <string>
#include "pugixml/pugixml.hpp"
namespace lnav {
namespace pugixml {
std::string get_actual_path(const pugi::xml_node &node);
}
}
#endif

@ -35,6 +35,7 @@
#include "base/lnav_log.hh"
#include "pugixml/pugixml.hpp"
#include "sql_util.hh"
#include "xml_util.hh"
#include "vtab_module.hh"
#include "yajlpp/yajlpp.hh"
@ -85,48 +86,6 @@ void checkin_query(const std::string& query_str, pugi::xpath_query query)
QUERY_CACHE[query_str] = std::move(query);
}
static
std::string get_actual_path(const pugi::xml_node& node)
{
std::string retval;
auto curr = node;
while (curr) {
switch (curr.type()) {
case pugi::node_null:
break;
case pugi::node_pcdata:
retval += "text()";
break;
default: {
auto name = std::string(curr.name());
if (curr.previous_sibling(curr.name()) ||
curr.next_sibling(curr.name())) {
auto sibling = curr;
int index = 0;
while (sibling) {
index += 1;
sibling = sibling.previous_sibling(curr.name());
}
name += "[" + std::to_string(index) + "]";
}
if (retval.empty()) {
retval = name;
} else {
retval = name + std::string("/") + retval;
}
break;
}
}
curr = curr.parent();
}
return retval;
}
struct xpath_vtab {
static constexpr const char *NAME = "xpath";
static constexpr const char *CREATE_STMT = R"(
@ -218,7 +177,7 @@ CREATE TABLE xpath (
x_node = xpath_node.parent();
}
auto node_path = get_actual_path(x_node);
auto node_path = lnav::pugixml::get_actual_path(x_node);
if (x_attr) {
node_path += "/@" + std::string(x_attr.name());
}

@ -292,6 +292,7 @@ dist_noinst_DATA = \
vt52_curses_input.1 \
vt52_curses_output.0 \
vt52_curses_output.1 \
xpath_tui.0 \
formats/collision/format.json \
formats/customlevel/format.json \
formats/jsontest/format.json \

@ -35,7 +35,7 @@
"hidden": true
},
"msg_data": {
"kind": "string"
"kind": "xml"
}
},
"highlights": {

@ -9,7 +9,7 @@
<source>
x
</source>
<request>
<request id="1">
<name>
x
</name>
@ -22,7 +22,7 @@
<head>
x
</head>
<reply>
<reply id="2">
<status>
<result>OK</result>
</status>

@ -50,6 +50,7 @@ error:format.json:line 18
json
struct
quoted
xml
error:bad_regex_log.regex[std]:missing )
error:bad_regex_log.regex[std]:^(?<timestamp>\d+: (?<body>.*)$
error:bad_regex_log.regex[std]: ^

@ -18,3 +18,10 @@ for fn in ${srcdir}/tui-captures/*; do
;;
esac
done
run_test ./scripty -e ${srcdir}/xpath_tui.0 -- \
${lnav_test} -I ${test_dir} \
-c ':goto 2' \
${srcdir}/logfile_xml_msg.0
on_error_fail_with "xpath() fields are not working?"

@ -0,0 +1,571 @@
CSI Don't Send Mouse X & Y
CSI Dont Use Cell Motion Mouse Tracking
CSI Don't ...
CTRL Use alt charset
CTRL save cursor
CSI Use alternate screen buffer
CSI set scrolling region 1-24
S -1 ┋ ┋
A └ normal
CSI Reset Replace mode
CSI Application cursor keys
CTRL =
OSC Set window title: LOG
S -1 ┋ ┋
A └ normal, normal, normal
CSI Erase all
S 1 ┋ Thu Jun 06 1 :: :: LOG ┋
A └ fg(#c0c0c0), bg(#008080)
S 2 ┋ x┋
A ···············································································├ normal
A └┛ alt
A ················································································└ normal
S 3 ┋ x┋
A └┛ alt
A ················································································└ normal
S 4 ┋ x┋
A └┛ alt
A ················································································└ normal
S 5 ┋ x┋
A └┛ alt
A ················································································└ normal
S 6 ┋ x┋
A └┛ alt
A ················································································└ normal
S 7 ┋ x┋
A └┛ alt
A ················································································└ normal
S 8 ┋ x┋
A └┛ alt
A ················································································└ normal
S 9 ┋ x┋
A └┛ alt
A ················································································└ normal
S 10 ┋ x┋
A └┛ alt
A ················································································└ normal
S 11 ┋ x┋
A └┛ alt
A ················································································└ normal
S 12 ┋ x┋
A └┛ alt
A ················································································└ normal
S 13 ┋ x┋
A └┛ alt
A ················································································└ normal
S 14 ┋ x┋
A └┛ alt
A ················································································└ normal
S 15 ┋ x┋
A └┛ alt
A ················································································└ normal
S 16 ┋ x┋
A └┛ alt
A ················································································└ normal
S 17 ┋ lqqqq No log messages; Log Files: 0; Text Files: 1; Error rate: 0.00/min; Tix┋
A └----┛ alt │ │ │ │ │ │ │ │ ││
A ···································└ bold │ │ │ │ │ │ ││
A ·····································└ normal │ │ │ │ │ │ ││
A ···················································└ bold │ │ │ ││
A ·····················································└ normal │ │ │ ││
A ·······················································└ fg(#800000), bold ││
A ·································································└ normal ││
A ···································································└ bold ││
A ·······································································└ normal││
A └┛ alt
A ················································································└ normal
S 18 ┋ Files :: Text Filters :: Press q to exit ┋
A └ fg(#c0c0c0), bg(#000080), bold ││
A ·└ fg(#008080), bg(#000080), underline ││
A ··└ normal, fg(#c0c0c0), bg(#000080), bold ││
A ·······└ normal, fg(#c0c0c0), bg(#000080) ││
A ········└ fg(#000080), bg(#c0c0c0) ││
A ·········└ fg(#000000), bg(#c0c0c0), bold ││
A ··········└ fg(#800080), bg(#c0c0c0), underline ││
A ···········└ normal, fg(#000000), bg(#c0c0c0), bold ││
A ·······················└ normal, fg(#000000), bg(#c0c0c0) ││
A ······································································└ bold
A ·······································································└ normal, fg(#000000), bg(#c0c0c0)
S 19 ┋ ┋
S 20 ┋→ ` logfile_xml_msg.0 0.0 B — x┋
A ··├ fg(#008000), bg(#c0c0c0) │ │ │
A └┛ alt │ │ │ │
A ···└ fg(#000000), bg(#c0c0c0) │ │ │
A ························└ fg(#c0c0c0), bg(#c0c0c0) │
A ······························└ fg(#000000), bg(#c0c0c0), bold │
A ································└ normal, fg(#000000), bg(#c0c0c0) │
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 21 ┋ x┋
A ···············································································└ fg(#000000), bg(#c0c0c0)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 22 ┋ x┋
A ···············································································└ fg(#000000), bg(#c0c0c0)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 23 ┋ L0 0% ?:View Help ┋
A └ fg(#000000), bg(#c0c0c0)
S 22 ┋ ┋
A └ normal, normal
S 19 ┋ SPC: Hide ENTER: Jump To ┋
A ··└ fg(#000000), bg(#c0c0c0), bold
A ·····└ normal, fg(#000000), bg(#c0c0c0)
A ·············└ bold
A ··················└ normal, fg(#000000), bg(#c0c0c0)
S 20 ┋ 64.0 B 2020-12-10 06:56:41.061 — 2020-12-10 06:56:41. ┋
A ···························└ backspace │
A ··························└ fg(#c0c0c0), bg(#c0c0c0) │
A ······························└ fg(#000000), bg(#c0c0c0), bold │
A ································└ normal, fg(#000000), bg(#c0c0c0) │
A ···············································································└ carriage-return
S 22 ┋ ┋
A └ normal, normal
S 20 ┋ 628 ┋
A ·························└ fg(#c0c0c0), bg(#c0c0c0)
A ····························└ carriage-return
S 22 ┋ ┋
A └ normal, normal
OSC Set window title: /Users/stackt/github/lnav/test/logfile_xml_msg.0
S 1 ┋ logfile_xml_msg.0 ┋
A ·······························└ fg(#c0c0c0), bg(#008080)
S 1 ┋ xml_msg_log ┋
A ······································································└ carriage-return
S 2 ┋x x ┋
A ├ normal, bold
A └┛ alt│
A ·└ normal
A ······└ carriage-return
S 3 ┋x </head> ┋
A ├ bold ││
A └┛ alt ││
A ·└ normal││
A ·····└ bold
A ·········└ normal
A ··········└ carriage-return
S 4 ┋x <reply id="2"> ┋
A ├ bold ││ ││ ││
A └┛ alt ││ ││ ││
A ·└ normal││ ││ ││
A ····└ bold│ ││ ││
A ·········└ normal│
A ··········└ fg(#008080)
A ············└ normal
A ·············└ fg(#008000), bold
A ················└ normal
A ·················└ carriage-return
S 5 ┋x <status> ┋
A ├ bold│ ││
A └┛ alt│ ││
A ·└ normal ││
A ······└ bold││
A ············└ normal
A ·············└ carriage-return
S 6 ┋x <result>OK</result> ┋
A ├ bold ││ │ │ ││
A └┛ alt ││ │ │ ││
A ·└ normal │ │ ││
A ·······└ bold, normal ││
A ········└ bold│ │ ││
A ··············└ normal ││
A ···················└ bold││
A ·························└ normal
A ··························└ carriage-return
S 7 ┋x </status> ┋
A ├ bold │ ││
A └┛ alt │ ││
A ·└ normal ││
A ·······└ bold││
A ·············└ normal
A ··············└ carriage-return
S 8 ┋x <name> ┋
A ├ bold│ ││
A └┛ alt│ ││
A ·└ normal ││
A ······└ bold
A ··········└ normal
A ···········└ carriage-return
S 9 ┋x x ┋
A ├ bold ││
A └┛ alt ││
A ·└ normal
A ·······└ bold, normal
A ········└ carriage-return
S 10 ┋x </name> ┋
A ├ bold │ ││
A └┛ alt │ ││
A ·└ normal ││
A ·······└ bold
A ···········└ normal
A ············└ carriage-return
S 11 ┋x </reply> x┋
A ├ bold │ ││
A └┛ alt │ ││
A ·└ normal │ ││
A ·····└ bold ││
A ··········└ normal ││
A ···············································································└ fg(#000000), bg(#c0c0c0)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 12 ┋x <technical-track> x┋
A ├ fg(#000000), bg(#c0c0c0), normal, bold ││
A └┛ alt │ ││
A ·└ normal │ ││
A ····└ bold │ ││
A ···················└ normal ││
A ···············································································└ fg(#000000), bg(#c0c0c0)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 13 ┋x x x┋
A ├ fg(#000000), bg(#c0c0c0), normal, bold ││
A └┛ alt ││
A ·└ normal ││
A ···············································································└ fg(#000000), bg(#c0c0c0)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 14 ┋x </technical-track> x┋
A ├ fg(#000000), bg(#c0c0c0), normal, bold ││
A └┛ alt │ ││
A ·└ normal │ ││
A ·····└ bold │ ││
A ····················└ normal ││
A ···············································································└ fg(#000000), bg(#c0c0c0)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 15 ┋x</a-reply> x┋
A ├ fg(#000000), bg(#c0c0c0), normal, bold ││
A └┛ alt │ ││
A ·└ normal │ ││
A ···└ bold │ ││
A ··········└ normal ││
A ···············································································└ fg(#000000), bg(#c0c0c0)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 16 ┋ x┋
A ···············································································└ fg(#000000), bg(#c0c0c0)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 17 ┋ Last message: in the future; Files: 1; Error rate: 0.00/min; Time span:x┋
A ·······└ fg(#000000), bg(#c0c0c0), normal │ │ │ │ │ │ ││
A ·····················└ bold │ │ │ │ │ │ │ ││
A ··································└ normal │ │ │ │ │ │ ││
A ···········································└ bold │ │ │ ││
A ·············································└ normal │ │ │ ││
A ···············································└ fg(#800000), bold ││
A ·························································└ normal ││
A ···························································└ bold ││
A ·······························································└ normal ││
A ···············································································└ fg(#000000), bg(#c0c0c0)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 23 ┋ 22 10 ┋
A ··└ fg(#000000), bg(#c0c0c0)
A ·············└ carriage-return
S 22 ┋ ┋
A └ normal, normal
CSI Erase Below
S 1 ┋ Thu Jun 06 1 logfile_xml_msg.0:: xml_msg_log:: LOG ┋
A └ fg(#000000), bg(#c0c0c0) │││ │││
A ················································└ fg(#008080), bg(#c0c0c0)
A ·················································└ fg(#c0c0c0), bg(#008080)
A ··················································└ fg(#000000), bg(#008080)
A ······································································└ fg(#000080), bg(#008080)
A ·······································································└ fg(#008080), bg(#000080)
A ········································································└ fg(#c0c0c0), bg(#000080), bold
S 2 ┋ [2020-12-10 06:56:41,092] DEBUG [connect.client:69] Full request text: ┋
A ·└ normal │ │
A ··································└ bold │
A ················································└ normal
S 3 ┋ <?xml version='1.0' encoding='iso-8859-2'?> x┋
A ··└ bold ││ ││ ││ │ ││
A ······└ normal││ ││ ││ │ ││
A ·······└ fg(#008080)││ ││ │ ││
A ··············└ normal ││ │ ││
A ···············└ fg(#008000), bold │ ││
A ····················└ normal ││ │ ││
A ·····················└ fg(#008080) │ ││
A ·····························└ normal │ ││
A ······························└ fg(#008000), bold ││
A ··········································└ normal ││
A ···············································································└ fg(#000000), bg(#c0c0c0)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 4 ┋ <a-request> x┋
A ·└ fg(#000000), bg(#c0c0c0), normal ││
A ··└ bold │ ││
A ···········└ normal ││
A ···············································································└ fg(#000000), bg(#c0c0c0)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 5 ┋ <head> x┋
A ···└ fg(#000000), bg(#c0c0c0), normal ││
A ····└ bold ││
A ········└ normal ││
A ···············································································└ fg(#000000), bg(#c0c0c0)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 6 ┋ x x┋
A ·····└ fg(#000000), bg(#c0c0c0), normal ││
A ···············································································└ fg(#000000), bg(#c0c0c0)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 7 ┋ </head> x┋
A ···└ fg(#000000), bg(#c0c0c0), normal ││
A ·····└ bold ││
A ·········└ normal ││
A ···············································································└ fg(#000000), bg(#c0c0c0)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 8 ┋ <sourc x┋
A ···└ fg(#000000), bg(#c0c0c0), normal ││
A ····└ bold ││
A ···············································································└ normal, fg(#000000), bg(#c0c0c0)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 9 ┋ x x┋
A ·····└ fg(#000000), bg(#c0c0c0), normal ││
A ···············································································└ fg(#000000), bg(#c0c0c0)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 10 ┋ </sourc x┋
A ···└ fg(#000000), bg(#c0c0c0), normal ││
A ·····└ bold ││
A ···············································································└ normal, fg(#000000), bg(#c0c0c0)
A ················································································└ normal
A └┛ alt
A ················································································└ normal
S 11 ┋ request id="1"> ┋
A ····└ fg(#000000), bg(#c0c0c0), normal, bold
A ···········└ normal
A ············└ fg(#008080)
A ··············└ normal
A ···············└ fg(#008000), bold
A ··················└ normal
S 12 ┋ <name> ┋
A ······└ bold
A ··········└ normal
S 13 ┋ x ┋
S 14 ┋ </name> ┋
A ·······└ bold
A ···········└ normal
S 15 ┋ </request> x┋
A ·····└ bold │ ││
A ············└ normal ││
A └┛ alt
A ················································································└ normal
S 16 ┋x</a-request> x┋
A ├ bold │ ││
A └┛ alt │ ││
A ·└ normal │ ││
A ···└ bold │ ││
A ············└ normal ││
A └┛ alt
A ················································································└ normal
S 17 ┋x x┋
A ├ bold ││
A └┛ alt ││
A ·└ normal ││
A └┛ alt
A ················································································└ normal
S 18 ┋x[2020-12-10 06:56:41,099] DEBUG [m:85] Full reply text: x┋
A ├ bold ││ ││
A └┛ alt ││ ││
A ·└ normal ││ ││
A ··································└ bold ││
A ···································└ normal ││
A └┛ alt
A ················································································└ normal
S 19 ┋x<?xml version='1.0' encoding='iso-8859-2'?> x┋
A ├ bold││ ││ ││ ││ │ ││
A └┛ alt││ ││ ││ ││ │ ││
A ·└ normal ││ ││ ││ │ ││
A ··└ bold ││ ││ ││ │ ││
A ······└ normal││ ││ ││ │ ││
A ·······└ fg(#008080)││ ││ │ ││
A ··············└ normal ││ │ ││
A ···············└ fg(#008000), bold │ ││
A ····················└ normal ││ │ ││
A ·····················└ fg(#008080) │ ││
A ·····························└ normal │ ││
A ······························└ fg(#008000), bold ││
A ··········································└ normal ││
A └┛ alt
A ················································································└ normal
S 20 ┋x<a-reply> x┋
A ├ bold │ ││
A └┛ alt │ ││
A ·└ normal│ ││
A ··└ bold │ ││
A ·········└ normal ││
A └┛ alt
A ················································································└ normal
S 21 ┋x <head> x┋
A ├ bold │ ││
A └┛ alt │ ││
A ·└ normal ││
A ····└ bold ││
A ········└ normal ││
A └┛ alt
A ················································································└ normal
S 22 ┋ Files :: Text Filters :: Press TAB to edit ┋
A └ fg(#c0c0c0), bg(#008080) │ │
A ····································································└ bold
A ·······································································└ normal, fg(#c0c0c0), bg(#008080)
S 23 ┋ 61 ┋
A ···└ fg(#000000), bg(#c0c0c0)
A ··············└ carriage-return
S 24 ┋ ┋
A └ normal, normal
K 70
S 3 ┋ Received Time: 2020-12-10T06:56:41.092 -- in the future ┋
A ················└ bold │ │ │
A ·······································└ normal │
A ···········································└ bold │
A ························································└ carriage-return
S 4 ┋ Pattern: xml_msg_log/regex/std = ^\[(?<timestamp>\d{4}-\d{2}-\d{2} \d{2}:\d{2} ┋
A └ normal ││ │ │ │ │││││ │││││ │││││ │││││ ││││
A ··································└ fg(#008080), bold││││ │││││ │││││ │││││ ││││
A ···································└ normal │ │││││ │││││ │││││ │││││ ││││
A ·····································└ fg(#008000), bold│ │││││ │││││ │││││ ││││
A ········································└ normal │ │││││ │││││ │││││ │││││ ││││
A ··················································└ fg(#000080), bold │││││ ││││
A ····················································└ fg(#008000)││││ │││││ ││││
A ·····················································└ normal││ │││││ │││││ ││││
A ······················································└ fg(#008000), bold││ ││││
A ·······················································└ normal │││││ │││││ ││││
A ························································└ fg(#000080), bold ││││
A ··························································└ fg(#008000)││││ ││││
A ···························································└ normal││ │││││ ││││
A ····························································└ fg(#008000), bold│
A ·····························································└ normal │││││ ││││
A ······························································└ fg(#000080), bold
A ································································└ fg(#008000)│││
A ·································································└ normal││ ││││
A ··································································└ fg(#008000), bold
A ···································································└ normal ││││
A ····································································└ fg(#000080), bold
A ······································································└ fg(#008000)
A ·······································································└ normal│
A ········································································└ fg(#008000), bold
A ·········································································└ normal
A ··········································································└ fg(#000080), bold
A ············································································└ fg(#008000)
A ·············································································└ normal
A ··············································································└ fg(#008000), bold
A ···············································································└ carriage-return
S 5 ┋ Known message fields for table xml_msg_log: ┋
A └ normal │ ││
A ································└ bold ││
A ···········································└ normal
A ············································└ carriage-return
S 6 ┋ t timestamp = 2020-12-10 06:56:41,092 ┋
A └┛ alt │ │ │
A ···└ bold │ │ │
A ············└ normal │
A ···············└ bold │
A ···············································································└ carriage-return
S 7 ┋ t level = DEBUG ┋
A └ normal│ │ │
A └┛ alt │ │ │
A ···└ bold │ │
A ········└ normal │
A ···············└ bold │
A ···············································································└ carriage-return
S 8 ┋ t module = connect.client ┋
A └ normal │ │ │
A └┛ alt │ │ │
A ···└ bold│ │ │
A ·········└ normal │
A ···············└ bold │
A ···············································································└ carriage-return
S 9 ┋ t line = 69 ┋
A └ normal │ │ │
A └┛ alt │ │ │
A ···└ bold │ │ │
A ·············└ normal │
A ···············└ bold │
A ···············································································└ carriage-return
S 10 ┋ t body = Full request text: ┋
A └ normal │ │
A └┛ alt│ │ │
A ···└ bold │ │
A ·······└ normal│ │
A ···············└ bold │
A ···············································································└ carriage-return
S 11 ┋ t msg_data = <?xml version='1.0' encoding='iso-8859-2'?> <a-request> <head> ┋
A └ normal │ │ │
A └┛ alt │ │ │
A ···└ bold │ │ │
A ···········└ normal │
A ···············└ bold │
A ···············································································└ carriage-return
S 12 ┋ XML fields: ┋
A └ normal │
A ············└ carriage-return
S 13 ┋ t xpath('/a-request/head/text()', msg_data) = x ┋
A └┛ alt │
A ······└ bold │
A ···············································································└ carriage-return
S 14 ┋ t xpath('/a-request/request/@id', msg_data) = 1 ┋
A └ normal │
A └┛ alt │
A ······└ bold │
A ···············································································└ carriage-return
S 15 ┋ t xpath('/a-request/request/name/text()', msg_data) = x ┋
A └ normal │
A └┛ alt │
A ······└ bold │
A ···············································································└ carriage-return
S 16 ┋ t xpath('/a-request/source/text()', msg_data) = x ┋
A └ normal │
A └┛ alt │
A ······└ bold │
A ···············································································└ carriage-return
S 17 ┋ No discovered message fields ┋
A └ normal
S 18 ┋ <?xml version='1.0' encoding='iso-8859-2'?> ┋
A ··└ bold ││ ││ ││ │
A ······└ normal││ ││ ││ │
A ·······└ fg(#008080)││ ││ │
A ··············└ normal ││ │
A ···············└ fg(#008000), bold │
A ····················└ normal ││ │
A ·····················└ fg(#008080) │
A ·····························└ normal │
A ······························└ fg(#008000), bold
A ··········································└ normal
S 19 ┋ a-request> ┋
A ··└ bold │
A ···········└ normal
S 20 ┋ <head> ┋
A ····└ bold
A ········└ normal
S 21 ┋ x ┋
A ·········└ carriage-return
S 24 ┋ ┋
A └ normal
K 71
CSI Erase all
CSI Use normal screen buffer
CTRL restore cursor
S 24 ┋ ┋
A └ carriage-return
CSI Normal cursor keys
CTRL Normal keypad
Loading…
Cancel
Save