1
1
mirror of https://github.com/tstack/lnav.git synced 2024-09-11 13:05:51 +03:00

[vtab] fix for failed update to log_tags column and fix filtering with json logs

This commit is contained in:
Timothy Stack 2019-02-01 13:31:28 -08:00
parent 527150d6a0
commit 104b8736e8
11 changed files with 134 additions and 57 deletions

View File

@ -11,6 +11,7 @@ set(diag_STAT_SRCS
extension-functions.cc
field_overlay_source.cc
file_vtab.cc
filter_observer.cc
filter_status_source.cc
filter_sub_source.cc
fs-extension-functions.cc

View File

@ -286,6 +286,7 @@ libdiag_a_SOURCES = \
extension-functions.cc \
field_overlay_source.cc \
file_vtab.cc \
filter_observer.cc \
filter_status_source.cc \
filter_sub_source.cc \
fstat_vtab.cc \

65
src/filter_observer.cc Normal file
View File

@ -0,0 +1,65 @@
/**
* Copyright (c) 2019, 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 "filter_observer.hh"
void line_filter_observer::logline_new_line(const logfile &lf,
logfile::const_iterator ll,
shared_buffer_ref &sbr)
{
size_t offset = std::distance(lf.begin(), ll);
require(&lf == this->lfo_filter_state.tfs_logfile.get());
this->lfo_filter_state.resize(lf.size());
if (this->lfo_filter_stack.empty()) {
return;
}
if (lf.get_format() != nullptr) {
lf.get_format()->get_subline(*ll, sbr);
}
for (auto &filter : this->lfo_filter_stack) {
if (filter->lf_deleted) {
continue;
}
if (offset >= this->lfo_filter_state.tfs_filter_count[filter->get_index()]) {
filter->add_line(this->lfo_filter_state, ll, sbr);
}
}
}
void line_filter_observer::logline_eof(const logfile &lf)
{
for (auto &iter : this->lfo_filter_stack) {
iter->end_of_message(this->lfo_filter_state);
}
}

View File

@ -42,38 +42,15 @@ public:
};
void logline_restart(const logfile &lf) {
void logline_restart(const logfile &lf, size_t rollback_size) {
for (auto &filter : this->lfo_filter_stack) {
filter->revert_to_last(this->lfo_filter_state);
filter->revert_to_last(this->lfo_filter_state, rollback_size);
}
};
void logline_new_line(const logfile &lf, logfile::const_iterator ll, shared_buffer_ref &sbr) {
size_t offset = std::distance(lf.begin(), ll);
void logline_new_line(const logfile &lf, logfile::const_iterator ll, shared_buffer_ref &sbr);;
require(&lf == this->lfo_filter_state.tfs_logfile.get());
this->lfo_filter_state.resize(lf.size());
if (!this->lfo_filter_stack.empty()) {
if (lf.get_format() != nullptr) {
lf.get_format()->get_subline(*ll, sbr);
}
for (auto &filter : this->lfo_filter_stack) {
if (filter->lf_deleted) {
continue;
}
if (offset >= this->lfo_filter_state.tfs_filter_count[filter->get_index()]) {
filter->add_line(this->lfo_filter_state, ll, sbr);
}
}
}
};
void logline_eof(const logfile &lf) {
for (auto &iter : this->lfo_filter_stack) {
iter->end_of_message(this->lfo_filter_state);
}
};
void logline_eof(const logfile &lf);;
bool excluded(uint32_t filter_in_mask, uint32_t filter_out_mask,
size_t offset) const {

View File

@ -456,8 +456,8 @@ void load_config(const vector<string> &extra_paths, vector<string> &errors)
errors);
}
for (auto pair : lnav_config.lc_ui_keymaps) {
for (auto pair2 : pair.second.km_seq_to_cmd) {
for (const auto &pair : lnav_config.lc_ui_keymaps) {
for (const auto &pair2 : pair.second.km_seq_to_cmd) {
log_debug("foo %s %d", pair2.first.c_str(), pair2.second.size());
}
}

View File

@ -799,6 +799,32 @@ static int vt_update(sqlite3_vtab *tab,
const unsigned char *part_name = sqlite3_value_text(argv[2 + VT_COL_PARTITION]);
const unsigned char *log_comment = sqlite3_value_text(argv[2 + VT_COL_LOG_COMMENT]);
const unsigned char *log_tags = sqlite3_value_text(argv[2 + VT_COL_LOG_TAGS]);
bookmark_metadata tmp_bm;
if (log_tags) {
vector<string> errors;
yajlpp_parse_context ypc(log_vtab_data.lvd_source, tags_handler);
auto_mem<yajl_handle_t> handle(yajl_free);
handle = yajl_alloc(&ypc.ypc_callbacks, nullptr, &ypc);
ypc.ypc_userdata = &errors;
ypc.ypc_line_number = log_vtab_data.lvd_line_number;
ypc.with_handle(handle)
.with_error_reporter([](const yajlpp_parse_context &ypc,
lnav_log_level_t level,
const char *msg) {
vector<string> &errors = *((vector<string> *) ypc.ypc_userdata);
errors.emplace_back(msg);
})
.with_obj(tmp_bm);
ypc.parse(log_tags, strlen((const char *) log_tags));
ypc.complete_parse();
if (!errors.empty()) {
tab->zErrMsg = sqlite3_mprintf("%s",
join(errors.begin(), errors.end(), "\n").c_str());
return SQLITE_ERROR;
}
}
bookmark_vector<vis_line_t> &bv = vt->tc->get_bookmarks()[
&textview_curses::BM_META];
@ -825,29 +851,11 @@ static int vt_update(sqlite3_vtab *tab,
line_meta.bm_comment.clear();
}
if (log_tags) {
vector<string> errors;
yajlpp_parse_context ypc(log_vtab_data.lvd_source, tags_handler);
auto_mem<yajl_handle_t> handle(yajl_free);
line_meta.bm_tags.clear();
handle = yajl_alloc(&ypc.ypc_callbacks, nullptr, &ypc);
ypc.ypc_userdata = &errors;
ypc.ypc_line_number = log_vtab_data.lvd_line_number;
ypc.with_handle(handle)
.with_error_reporter([](const yajlpp_parse_context &ypc,
lnav_log_level_t level,
const char *msg) {
vector<string> &errors = *((vector<string> *) ypc.ypc_userdata);
errors.emplace_back(msg);
})
.with_obj(line_meta);
ypc.parse(log_tags, strlen((const char *) log_tags));
ypc.complete_parse();
if (!errors.empty()) {
tab->zErrMsg = sqlite3_mprintf("%s",
join(errors.begin(), errors.end(), "\n").c_str());
retval = SQLITE_ERROR;
for (const auto &tag : tmp_bm.bm_tags) {
line_meta.add_tag(tag);
}
for (const auto &tag : line_meta.bm_tags) {
bookmark_metadata::KNOWN_TAGS.insert(tag);
}

View File

@ -300,6 +300,7 @@ logfile::rebuild_result_t logfile::rebuild_index()
size_t begin_size = this->lf_index.size();
bool record_rusage = this->lf_index.size() == 1;
off_t begin_index_size = this->lf_index_size;
size_t rollback_size = 0;
if (record_rusage) {
getrusage(RUSAGE_SELF, &begin_rusage);
@ -314,8 +315,10 @@ logfile::rebuild_result_t logfile::rebuild_index()
*/
while (this->lf_index.back().get_sub_offset() != 0) {
this->lf_index.pop_back();
rollback_size += 1;
}
this->lf_index.pop_back();
rollback_size += 1;
this->lf_line_buffer.clear();
if (!this->lf_index.empty()) {
@ -335,7 +338,7 @@ logfile::rebuild_result_t logfile::rebuild_index()
}
last_off = off;
if (this->lf_logline_observer != NULL) {
this->lf_logline_observer->logline_restart(*this);
this->lf_logline_observer->logline_restart(*this, rollback_size);
}
bool sort_needed = this->lf_sort_needed;

View File

@ -441,7 +441,7 @@ class logline_observer {
public:
virtual ~logline_observer() { };
virtual void logline_restart(const logfile &lf) = 0;
virtual void logline_restart(const logfile &lf, size_t rollback_size) = 0;
virtual void logline_new_line(const logfile &lf, logfile::const_iterator ll, shared_buffer_ref &sbr) = 0;

View File

@ -129,7 +129,7 @@ public:
this->lf_enabled = value;
}
void revert_to_last(logfile_filter_state &lfs) {
void revert_to_last(logfile_filter_state &lfs, size_t rollback_size) {
this->lf_message_matched = this->lf_last_message_matched;
this->lf_lines_for_message = this->lf_last_lines_for_message;
@ -140,7 +140,9 @@ public:
lfs.tfs_mask[line_number] &= ~(((uint32_t) 1) << this->lf_index);
}
if (this->lf_lines_for_message > 0) {
this->lf_lines_for_message -= 1;
this->lf_lines_for_message -= rollback_size;
ensure(this->lf_lines_for_message >= 0);
}
if (this->lf_lines_for_message == 0) {
this->lf_message_matched = false;

View File

@ -47,7 +47,7 @@ yajl_gen_status json_path_handler_base::gen(yajlpp_gen_context &ygc, yajl_gen ha
this->jph_path_provider(ygc.ygc_obj_stack.top(), local_paths);
}
else {
local_paths.push_back(this->jph_path);
local_paths.emplace_back(this->jph_path);
}
if (this->jph_children) {
@ -125,7 +125,7 @@ void json_path_handler_base::possibilities(
this->jph_path_provider(root, local_paths);
}
else {
local_paths.push_back(this->jph_path);
local_paths.emplace_back(this->jph_path);
}
if (this->jph_children) {

View File

@ -85,7 +85,8 @@ log_line log_comment log_tags
EOF
run_test ${lnav_test} -n \
-c ";UPDATE access_log SET log_tags = json_array('#foo') WHERE log_line = 1" \
-c ";UPDATE access_log SET log_tags = json_array('#foo', '#foo') WHERE log_line = 1" \
-c ":save-session" \
${test_dir}/logfile_access_log.0
check_output "updating log_tags is not working?" <<EOF
@ -117,6 +118,25 @@ error:command-option:1:command-option:line 1
# <tag> -- A tag for the log line
EOF
run_test ${lnav_test} -n \
-c ";UPDATE access_log SET log_tags = json_array('foo') WHERE log_line = 1" \
-c ":save-session" \
${test_dir}/logfile_access_log.0
check_error_output "updating log_tags is not working?" <<EOF
error:command-option:1:Value does not match pattern: ^#[^\s]+$
EOF
run_test ${lnav_test} -n \
-c ":load-session" \
-c ";SELECT log_tags FROM access_log WHERE log_line = 1" \
${test_dir}/logfile_access_log.0
check_output "log_tags was updated?" <<EOF
log_tags
["#foo"]
EOF
run_test ${lnav_test} -n \
-c ":tag foo" \
-c ";UPDATE access_log SET log_tags = null" \