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:
parent
527150d6a0
commit
104b8736e8
@ -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
|
||||
|
@ -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
65
src/filter_observer.cc
Normal 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);
|
||||
}
|
||||
}
|
@ -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 {
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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" \
|
||||
|
Loading…
Reference in New Issue
Block a user