[format] allow leading slash in field names

Fixes #852
This commit is contained in:
Timothy Stack 2021-04-16 14:47:47 -07:00
parent 70c07da5c5
commit 3741985ee3
4 changed files with 21 additions and 8 deletions

View File

@ -101,10 +101,18 @@ should be another object with the following fields:
[ { "field": "ts" }, " ", { "field": "msg" } ] [ { "field": "ts" }, " ", { "field": "msg" } ]
:field: The name of the message field that should be inserted at this :field: The name or `JSON-Pointer <https://tools.ietf.org/html/rfc6901>`_
point in the message. The special "__timestamp__" field name can be of the message field that should be inserted at this point in the
used to insert a human-readable timestamp. The "__level__" field can message. The special :code:`__timestamp__` field name can be used to
be used to insert the level name as defined by lnav. insert a human-readable timestamp. The :code:`__level__` field can be
used to insert the level name as defined by lnav.
.. tip::
Use a JSON-Pointer to reference nested fields. For example, to include
a "procname" property that is nested in a "details" object, you would
write the field reference as :code:`/details/procname`.
:min-width: The minimum width for the field. If the value for the field :min-width: The minimum width for the field. If the value for the field
in a given log message is shorter, padding will be added as needed to in a given log message is shorter, padding will be added as needed to
meet the minimum-width requirement. (v0.8.2+) meet the minimum-width requirement. (v0.8.2+)

View File

@ -1881,6 +1881,9 @@ void external_log_format::build(std::vector<std::string> &errors) {
static const intern_string_t level_field = intern_string::lookup("__level__"); static const intern_string_t level_field = intern_string::lookup("__level__");
json_format_element &jfe = *iter; json_format_element &jfe = *iter;
if (startswith(jfe.jfe_value.get(), "/")) {
jfe.jfe_value = intern_string::lookup(jfe.jfe_value.get() + 1);
}
if (!jfe.jfe_ts_format.empty()) { if (!jfe.jfe_ts_format.empty()) {
if (!jfe.jfe_value.empty() && jfe.jfe_value != ts) { if (!jfe.jfe_value.empty() && jfe.jfe_value != ts) {
log_warning("%s:line-format[%d]:ignoring field '%s' since " log_warning("%s:line-format[%d]:ignoring field '%s' since "

View File

@ -216,8 +216,10 @@ static int read_format_int(yajlpp_parse_context *ypc, long long val)
static int read_format_field(yajlpp_parse_context *ypc, const unsigned char *str, size_t len) static int read_format_field(yajlpp_parse_context *ypc, const unsigned char *str, size_t len)
{ {
auto elf = (external_log_format *) ypc->ypc_obj_stack.top(); auto elf = (external_log_format *) ypc->ypc_obj_stack.top();
string value = string((const char *)str, len); auto leading_slash = len > 0 && str[0] == '/';
string field_name = ypc->get_path_fragment(1); auto value = string((const char *) (leading_slash ? str + 1 : str),
leading_slash ? len - 1 : len);
auto field_name = ypc->get_path_fragment(1);
if (field_name == "file-pattern") { if (field_name == "file-pattern") {
elf->elf_file_pattern = value; elf->elf_file_pattern = value;

View File

@ -7,11 +7,11 @@
"line-format" : [ "line-format" : [
{ "field" : "ts" }, { "field" : "ts" },
" ", " ",
{ "field" : "@fields/lvl" }, { "field" : "/@fields/lvl" },
" ", " ",
{ "field" : "@fields/msg" } { "field" : "@fields/msg" }
], ],
"level-field" : "@fields/lvl", "level-field" : "/@fields/lvl",
"timestamp-field": "ts", "timestamp-field": "ts",
"body-field" : "@fields/msg", "body-field" : "@fields/msg",
"value" : { "value" : {