mirror of
https://github.com/tstack/lnav
synced 2024-11-01 21:40:34 +00:00
[sql] add a bookmark column to the log tables
This commit is contained in:
parent
7bcbd000ad
commit
10eb9617b1
3
NEWS
3
NEWS
@ -16,6 +16,9 @@ lnav v0.6.3:
|
|||||||
displayed can be tab-completed.
|
displayed can be tab-completed.
|
||||||
* The '-H' option was added so you can view the internal help text.
|
* The '-H' option was added so you can view the internal help text.
|
||||||
* Added the 'g/G' hotkeys to move to the top/bottom of the file.
|
* Added the 'g/G' hotkeys to move to the top/bottom of the file.
|
||||||
|
* Added a 'log_mark' column to the log tables that indicates whether or
|
||||||
|
not a log message is bookmarked. The field is writable, so you can
|
||||||
|
bookmark lines using an SQL UPDATE query.
|
||||||
|
|
||||||
Fixes:
|
Fixes:
|
||||||
* Performance improvements.
|
* Performance improvements.
|
||||||
|
@ -458,6 +458,8 @@ All log tables contain at least the following columns:
|
|||||||
log_idle_msecs The amount of time, in milliseconds, between the
|
log_idle_msecs The amount of time, in milliseconds, between the
|
||||||
current log message and the previous one.
|
current log message and the previous one.
|
||||||
log_level The log level (e.g. info, error, etc...).
|
log_level The log level (e.g. info, error, etc...).
|
||||||
|
log_mark The bookmark status for the line. This column
|
||||||
|
can be written to using an UPDATE query.
|
||||||
log_path The full path to the file.
|
log_path The full path to the file.
|
||||||
log_text The raw line of text. Note that this column is
|
log_text The raw line of text. Note that this column is
|
||||||
not included in the result of a 'select *', but
|
not included in the result of a 'select *', but
|
||||||
|
@ -1891,13 +1891,6 @@ static void handle_paging_key(int ch)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'x':
|
|
||||||
if (tc == &lnav_data.ld_views[LNV_LOG]) {
|
|
||||||
lnav_data.ld_log_source.toggle_user_mark(&BM_EXAMPLE,
|
|
||||||
vis_line_t(tc->get_top()));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'X':
|
case 'X':
|
||||||
execute_command("close");
|
execute_command("close");
|
||||||
break;
|
break;
|
||||||
|
@ -103,7 +103,7 @@ void ensure_dotlnav(void)
|
|||||||
path += "/*";
|
path += "/*";
|
||||||
if (glob(path.c_str(), GLOB_NOCHECK, NULL, gl.inout()) == 0) {
|
if (glob(path.c_str(), GLOB_NOCHECK, NULL, gl.inout()) == 0) {
|
||||||
for (int lpc = 0;
|
for (int lpc = 0;
|
||||||
lpc < (gl->gl_pathc - MAX_CRASH_LOG_COUNT);
|
lpc < ((int)gl->gl_pathc - MAX_CRASH_LOG_COUNT);
|
||||||
lpc++) {
|
lpc++) {
|
||||||
remove(gl->gl_pathv[lpc]);
|
remove(gl->gl_pathv[lpc]);
|
||||||
}
|
}
|
||||||
|
@ -119,11 +119,11 @@ public:
|
|||||||
|
|
||||||
LEVEL__MAX,
|
LEVEL__MAX,
|
||||||
|
|
||||||
LEVEL_MULTILINE = 0x40, /*< Start of a multiline entry. */
|
LEVEL_MARK = 0x40, /*< Bookmarked line. */
|
||||||
LEVEL_CONTINUED = 0x80, /*< Continuation of multiline entry. */
|
LEVEL_CONTINUED = 0x80, /*< Continuation of multiline entry. */
|
||||||
|
|
||||||
/** Mask of flags for the level field. */
|
/** Mask of flags for the level field. */
|
||||||
LEVEL__FLAGS = (LEVEL_MULTILINE | LEVEL_CONTINUED)
|
LEVEL__FLAGS = (LEVEL_MARK | LEVEL_CONTINUED)
|
||||||
} level_t;
|
} level_t;
|
||||||
|
|
||||||
static const char *level_names[LEVEL__MAX];
|
static const char *level_names[LEVEL__MAX];
|
||||||
@ -198,7 +198,16 @@ public:
|
|||||||
this->ll_millis = tv.tv_usec / 1000;
|
this->ll_millis = tv.tv_usec / 1000;
|
||||||
};
|
};
|
||||||
|
|
||||||
void set_multiline(void) { this->ll_level |= LEVEL_MULTILINE; };
|
void set_mark(bool val) {
|
||||||
|
if (val) {
|
||||||
|
this->ll_level |= LEVEL_MARK;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->ll_level &= ~LEVEL_MARK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
bool is_marked(void) const { return this->ll_level & LEVEL_MARK; };
|
||||||
|
|
||||||
/** @param l The logging level. */
|
/** @param l The logging level. */
|
||||||
void set_level(level_t l) { this->ll_level = l; };
|
void set_level(level_t l) { this->ll_level = l; };
|
||||||
|
@ -69,7 +69,8 @@ std::string log_vtab_impl::get_table_statement(void)
|
|||||||
<< " log_part text collate naturalnocase,\n"
|
<< " log_part text collate naturalnocase,\n"
|
||||||
<< " log_time datetime,\n"
|
<< " log_time datetime,\n"
|
||||||
<< " log_idle_msecs int,\n"
|
<< " log_idle_msecs int,\n"
|
||||||
<< " log_level text collate loglevel,\n";
|
<< " log_level text collate loglevel,\n"
|
||||||
|
<< " log_mark boolean,\n";
|
||||||
this->get_columns(cols);
|
this->get_columns(cols);
|
||||||
this->vi_column_count = cols.size();
|
this->vi_column_count = cols.size();
|
||||||
for (iter = cols.begin(); iter != cols.end(); iter++) {
|
for (iter = cols.begin(); iter != cols.end(); iter++) {
|
||||||
@ -328,6 +329,12 @@ static int vt_column(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int col)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case VT_COL_MARK:
|
||||||
|
{
|
||||||
|
sqlite3_result_int(ctx, ll->is_marked());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (col > (VT_COL_MAX + vt->vi->vi_column_count - 1)) {
|
if (col > (VT_COL_MAX + vt->vi->vi_column_count - 1)) {
|
||||||
int post_col_number = col -
|
int post_col_number = col -
|
||||||
@ -430,6 +437,27 @@ static int vt_best_index(sqlite3_vtab *tab, sqlite3_index_info *p_info)
|
|||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int vt_update(sqlite3_vtab *tab,
|
||||||
|
int argc,
|
||||||
|
sqlite3_value **argv,
|
||||||
|
sqlite_int64 *rowid)
|
||||||
|
{
|
||||||
|
vtab *vt = (vtab *)tab;
|
||||||
|
int retval = SQLITE_READONLY;
|
||||||
|
|
||||||
|
if (argc > 1 && sqlite3_value_type(argv[0]) != SQLITE_NULL &&
|
||||||
|
sqlite3_value_int64(argv[0]) == sqlite3_value_int64(argv[1])) {
|
||||||
|
int64_t rowid = sqlite3_value_int64(argv[0]) >> 8;
|
||||||
|
int val = sqlite3_value_int(argv[2 + VT_COL_MARK]);
|
||||||
|
|
||||||
|
vt->tc->set_user_mark(&textview_curses::BM_USER, vis_line_t(rowid), val);
|
||||||
|
|
||||||
|
retval = SQLITE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
static sqlite3_module vtab_module = {
|
static sqlite3_module vtab_module = {
|
||||||
0, /* iVersion */
|
0, /* iVersion */
|
||||||
vt_create, /* xCreate - create a vtable */
|
vt_create, /* xCreate - create a vtable */
|
||||||
@ -444,7 +472,7 @@ static sqlite3_module vtab_module = {
|
|||||||
vt_eof, /* xEof - inidicate end of result set*/
|
vt_eof, /* xEof - inidicate end of result set*/
|
||||||
vt_column, /* xColumn - read data */
|
vt_column, /* xColumn - read data */
|
||||||
vt_rowid, /* xRowid - read data */
|
vt_rowid, /* xRowid - read data */
|
||||||
NULL, /* xUpdate - write data */
|
vt_update, /* xUpdate - write data */
|
||||||
NULL, /* xBegin - begin transaction */
|
NULL, /* xBegin - begin transaction */
|
||||||
NULL, /* xSync - sync transaction */
|
NULL, /* xSync - sync transaction */
|
||||||
NULL, /* xCommit - commit transaction */
|
NULL, /* xCommit - commit transaction */
|
||||||
|
@ -45,6 +45,7 @@ enum {
|
|||||||
VT_COL_LOG_TIME,
|
VT_COL_LOG_TIME,
|
||||||
VT_COL_IDLE_MSECS,
|
VT_COL_IDLE_MSECS,
|
||||||
VT_COL_LEVEL,
|
VT_COL_LEVEL,
|
||||||
|
VT_COL_MARK,
|
||||||
VT_COL_MAX
|
VT_COL_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -113,6 +114,7 @@ public:
|
|||||||
virtual void get_foreign_keys(std::vector<std::string> &keys_inout)
|
virtual void get_foreign_keys(std::vector<std::string> &keys_inout)
|
||||||
{
|
{
|
||||||
keys_inout.push_back("log_line");
|
keys_inout.push_back("log_line");
|
||||||
|
keys_inout.push_back("log_mark");
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual void extract(logfile *lf,
|
virtual void extract(logfile *lf,
|
||||||
|
@ -206,7 +206,6 @@ void logfile::process_prefix(off_t offset, char *prefix, int len)
|
|||||||
* Assume this line is part of the previous one(s) and copy the
|
* Assume this line is part of the previous one(s) and copy the
|
||||||
* metadata over.
|
* metadata over.
|
||||||
*/
|
*/
|
||||||
ll.set_multiline();
|
|
||||||
last_time = ll.get_time();
|
last_time = ll.get_time();
|
||||||
last_millis = ll.get_millis();
|
last_millis = ll.get_millis();
|
||||||
if (this->lf_format.get() != NULL) {
|
if (this->lf_format.get() != NULL) {
|
||||||
|
@ -590,22 +590,28 @@ void logfile_sub_source::text_update_marks(vis_bookmarks &bm)
|
|||||||
content_line_t cl = this->lss_index[vl];
|
content_line_t cl = this->lss_index[vl];
|
||||||
logfile * lf;
|
logfile * lf;
|
||||||
|
|
||||||
|
lf = this->find(cl);
|
||||||
|
|
||||||
for (bookmarks<content_line_t>::type::iterator iter =
|
for (bookmarks<content_line_t>::type::iterator iter =
|
||||||
this->lss_user_marks.begin();
|
this->lss_user_marks.begin();
|
||||||
iter != this->lss_user_marks.end();
|
iter != this->lss_user_marks.end();
|
||||||
++iter) {
|
++iter) {
|
||||||
if (binary_search(iter->second.begin(), iter->second.end(), cl)) {
|
if (binary_search(iter->second.begin(), iter->second.end(), cl)) {
|
||||||
bm[iter->first].insert_once(vl);
|
bm[iter->first].insert_once(vl);
|
||||||
|
|
||||||
|
if (iter->first == &textview_curses::BM_USER) {
|
||||||
|
logfile::iterator ll = lf->begin() + cl;
|
||||||
|
|
||||||
|
ll->set_mark(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lf = this->find(cl);
|
|
||||||
|
|
||||||
if (lf != last_file) {
|
if (lf != last_file) {
|
||||||
bm[&BM_FILES].insert_once(vl);
|
bm[&BM_FILES].insert_once(vl);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ((*lf)[cl].get_level() & ~logline::LEVEL_MULTILINE) {
|
switch ((*lf)[cl].get_level() & ~logline::LEVEL_MARK) {
|
||||||
case logline::LEVEL_WARNING:
|
case logline::LEVEL_WARNING:
|
||||||
bm[&BM_WARNINGS].insert_once(vl);
|
bm[&BM_WARNINGS].insert_once(vl);
|
||||||
break;
|
break;
|
||||||
|
@ -154,6 +154,11 @@ public:
|
|||||||
content_line_t cl = this->lss_index[line];
|
content_line_t cl = this->lss_index[line];
|
||||||
std::vector<content_line_t>::iterator lb;
|
std::vector<content_line_t>::iterator lb;
|
||||||
|
|
||||||
|
if (bm == &textview_curses::BM_USER) {
|
||||||
|
logline *ll = this->find_line(cl);
|
||||||
|
|
||||||
|
ll->set_mark(added);
|
||||||
|
}
|
||||||
lb = std::lower_bound(this->lss_user_marks[bm].begin(),
|
lb = std::lower_bound(this->lss_user_marks[bm].begin(),
|
||||||
this->lss_user_marks[bm].end(),
|
this->lss_user_marks[bm].end(),
|
||||||
cl);
|
cl);
|
||||||
@ -171,6 +176,15 @@ public:
|
|||||||
|
|
||||||
void text_clear_marks(bookmark_type_t *bm)
|
void text_clear_marks(bookmark_type_t *bm)
|
||||||
{
|
{
|
||||||
|
std::vector<content_line_t>::iterator iter;
|
||||||
|
|
||||||
|
if (bm == &textview_curses::BM_USER) {
|
||||||
|
for (iter = this->lss_user_marks[bm].begin();
|
||||||
|
iter != this->lss_user_marks[bm].end();
|
||||||
|
++iter) {
|
||||||
|
this->find_line(*iter)->set_mark(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
this->lss_user_marks[bm].clear();
|
this->lss_user_marks[bm].clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -237,30 +251,6 @@ public:
|
|||||||
|
|
||||||
void text_update_marks(vis_bookmarks &bm);
|
void text_update_marks(vis_bookmarks &bm);
|
||||||
|
|
||||||
void toggle_user_mark(bookmark_type_t *bm,
|
|
||||||
vis_line_t start_line,
|
|
||||||
vis_line_t end_line = vis_line_t(-1))
|
|
||||||
{
|
|
||||||
if (end_line == -1) {
|
|
||||||
end_line = start_line;
|
|
||||||
}
|
|
||||||
if (start_line > end_line) {
|
|
||||||
std::swap(start_line, end_line);
|
|
||||||
}
|
|
||||||
for (vis_line_t curr_line = start_line; curr_line <= end_line;
|
|
||||||
++curr_line) {
|
|
||||||
bookmark_vector<content_line_t> &bv =
|
|
||||||
this->lss_user_marks[bm];
|
|
||||||
bookmark_vector<content_line_t>::iterator iter;
|
|
||||||
|
|
||||||
iter = bv.insert_once(this->at(curr_line));
|
|
||||||
if (iter == bv.end()) {}
|
|
||||||
else {
|
|
||||||
bv.erase(iter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void set_user_mark(bookmark_type_t *bm, content_line_t cl)
|
void set_user_mark(bookmark_type_t *bm, content_line_t cl)
|
||||||
{
|
{
|
||||||
this->lss_user_marks[bm].insert_once(cl);
|
this->lss_user_marks[bm].insert_once(cl);
|
||||||
|
@ -248,6 +248,24 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void set_user_mark(bookmark_type_t *bm, vis_line_t vl, bool marked) {
|
||||||
|
bookmark_vector<vis_line_t> &bv = this->tc_bookmarks[bm];
|
||||||
|
bookmark_vector<vis_line_t>::iterator iter;
|
||||||
|
|
||||||
|
if (marked) {
|
||||||
|
bv.insert_once(vl);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
iter = std::lower_bound(bv.begin(), bv.end(), vl);
|
||||||
|
if (iter != bv.end() && *iter == vl) {
|
||||||
|
bv.erase(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this->tc_sub_source != NULL) {
|
||||||
|
this->tc_sub_source->text_mark(bm, (int)vl, marked);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void set_sub_source(text_sub_source *src)
|
void set_sub_source(text_sub_source *src)
|
||||||
{
|
{
|
||||||
this->tc_sub_source = src;
|
this->tc_sub_source = src;
|
||||||
|
Loading…
Reference in New Issue
Block a user