2012-09-22 23:15:15 +00:00
|
|
|
/**
|
2013-05-03 06:02:03 +00:00
|
|
|
* Copyright (c) 2007-2012, Timothy Stack
|
|
|
|
*
|
|
|
|
* All rights reserved.
|
2013-05-28 04:35:00 +00:00
|
|
|
*
|
2013-05-03 06:02:03 +00:00
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions are met:
|
2013-05-28 04:35:00 +00:00
|
|
|
*
|
2013-05-03 06:02:03 +00:00
|
|
|
* * 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.
|
2013-05-28 04:35:00 +00:00
|
|
|
*
|
2013-05-03 06:02:03 +00:00
|
|
|
* 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.
|
|
|
|
*
|
2012-09-22 23:15:15 +00:00
|
|
|
* @file log_format.hh
|
|
|
|
*/
|
2009-09-14 01:07:32 +00:00
|
|
|
|
|
|
|
#ifndef __log_format_hh
|
|
|
|
#define __log_format_hh
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
#include <time.h>
|
2013-06-30 23:43:08 +00:00
|
|
|
#include <sys/time.h>
|
2012-07-13 16:26:47 +00:00
|
|
|
#include <stdint.h>
|
2013-06-01 04:13:26 +00:00
|
|
|
#define __STDC_FORMAT_MACROS
|
|
|
|
#include <inttypes.h>
|
2009-09-14 01:07:32 +00:00
|
|
|
#include <sys/types.h>
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
2009-10-14 19:42:58 +00:00
|
|
|
#include <memory>
|
2009-09-14 01:07:32 +00:00
|
|
|
|
2013-06-26 01:45:07 +00:00
|
|
|
#include "pcrepp.hh"
|
2013-06-30 23:43:08 +00:00
|
|
|
#include "lnav_util.hh"
|
2013-06-12 13:59:48 +00:00
|
|
|
#include "byte_array.hh"
|
2013-05-24 14:55:56 +00:00
|
|
|
#include "view_curses.hh"
|
|
|
|
|
2013-06-22 20:44:50 +00:00
|
|
|
class logfile_filter {
|
|
|
|
public:
|
|
|
|
typedef enum {
|
|
|
|
MAYBE,
|
|
|
|
INCLUDE,
|
|
|
|
EXCLUDE,
|
|
|
|
|
|
|
|
LFT__MAX,
|
|
|
|
|
|
|
|
LFT__MASK = (MAYBE|INCLUDE|EXCLUDE)
|
|
|
|
} type_t;
|
|
|
|
|
|
|
|
logfile_filter(type_t type, std::string id)
|
|
|
|
: lf_enabled(true),
|
|
|
|
lf_type(type),
|
|
|
|
lf_id(id) { };
|
|
|
|
virtual ~logfile_filter() { };
|
|
|
|
|
|
|
|
type_t get_type(void) const { return this->lf_type; };
|
|
|
|
std::string get_id(void) const { return this->lf_id; };
|
|
|
|
|
|
|
|
bool is_enabled(void) { return this->lf_enabled; };
|
|
|
|
void enable(void) { this->lf_enabled = true; };
|
|
|
|
void disable(void) { this->lf_enabled = false; };
|
|
|
|
|
|
|
|
virtual bool matches(std::string line) = 0;
|
|
|
|
|
|
|
|
virtual std::string to_command(void) = 0;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
bool lf_enabled;
|
|
|
|
type_t lf_type;
|
|
|
|
std::string lf_id;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef std::vector<logfile_filter *> filter_stack_t;
|
|
|
|
|
2009-09-14 01:07:32 +00:00
|
|
|
/**
|
|
|
|
* Metadata for a single line in a log file.
|
|
|
|
*/
|
|
|
|
class logline {
|
|
|
|
public:
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The logging level identifiers for a line(s).
|
|
|
|
*/
|
|
|
|
typedef enum {
|
2013-05-28 04:35:00 +00:00
|
|
|
LEVEL_UNKNOWN,
|
|
|
|
LEVEL_TRACE,
|
|
|
|
LEVEL_DEBUG,
|
|
|
|
LEVEL_INFO,
|
|
|
|
LEVEL_WARNING,
|
|
|
|
LEVEL_ERROR,
|
|
|
|
LEVEL_CRITICAL,
|
|
|
|
LEVEL_FATAL,
|
|
|
|
|
|
|
|
LEVEL__MAX,
|
|
|
|
|
|
|
|
LEVEL_MULTILINE = 0x40, /*< Start of a multiline entry. */
|
|
|
|
LEVEL_CONTINUED = 0x80, /*< Continuation of multiline entry. */
|
|
|
|
|
|
|
|
/** Mask of flags for the level field. */
|
|
|
|
LEVEL__FLAGS = (LEVEL_MULTILINE | LEVEL_CONTINUED)
|
2009-09-14 01:07:32 +00:00
|
|
|
} level_t;
|
|
|
|
|
|
|
|
static const char *level_names[LEVEL__MAX];
|
|
|
|
|
2013-06-04 13:53:25 +00:00
|
|
|
static level_t string2level(const char *levelstr, bool exact = false);
|
2009-09-14 01:07:32 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Construct a logline object with the given values.
|
|
|
|
*
|
|
|
|
* @param off The offset of the line in the file.
|
|
|
|
* @param t The timestamp for the line.
|
|
|
|
* @param millis The millisecond timestamp for the line.
|
|
|
|
* @param l The logging level.
|
|
|
|
*/
|
|
|
|
logline(off_t off,
|
2013-05-28 04:35:00 +00:00
|
|
|
time_t t,
|
|
|
|
uint16_t millis,
|
|
|
|
level_t l,
|
|
|
|
uint8_t m = 0)
|
|
|
|
: ll_offset(off),
|
|
|
|
ll_time(t),
|
|
|
|
ll_millis(millis),
|
|
|
|
ll_level(l),
|
2013-06-22 20:44:50 +00:00
|
|
|
ll_filter_state(logfile_filter::MAYBE)
|
2013-06-16 01:07:50 +00:00
|
|
|
{
|
2013-06-12 13:59:48 +00:00
|
|
|
memset(this->ll_schema, 0, sizeof(this->ll_schema));
|
|
|
|
};
|
2009-09-14 01:07:32 +00:00
|
|
|
|
2013-06-30 23:43:08 +00:00
|
|
|
logline(off_t off,
|
|
|
|
const struct timeval &tv,
|
|
|
|
level_t l,
|
|
|
|
uint8_t m = 0)
|
|
|
|
: ll_offset(off),
|
|
|
|
ll_level(l),
|
|
|
|
ll_filter_state(logfile_filter::MAYBE)
|
|
|
|
{
|
|
|
|
this->set_time(tv);
|
|
|
|
memset(this->ll_schema, 0, sizeof(this->ll_schema));
|
|
|
|
};
|
|
|
|
|
2009-09-14 01:07:32 +00:00
|
|
|
/** @return The offset of the line in the file. */
|
|
|
|
off_t get_offset() const { return this->ll_offset; };
|
|
|
|
|
|
|
|
/** @return The timestamp for the line. */
|
|
|
|
time_t get_time() const { return this->ll_time; };
|
|
|
|
|
|
|
|
void set_time(time_t t) { this->ll_time = t; };
|
|
|
|
|
|
|
|
/** @return The millisecond timestamp for the line. */
|
|
|
|
uint16_t get_millis() const { return this->ll_millis; };
|
|
|
|
|
2013-06-30 23:43:08 +00:00
|
|
|
void set_millis(uint16_t m) { this->ll_millis = m; };
|
|
|
|
|
|
|
|
struct timeval get_timeval() const {
|
|
|
|
struct timeval retval = { this->ll_time, this->ll_millis * 1000 };
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
};
|
|
|
|
|
|
|
|
void set_time(const struct timeval &tv) {
|
|
|
|
this->ll_time = tv.tv_sec;
|
|
|
|
this->ll_millis = tv.tv_usec / 1000;
|
|
|
|
};
|
2013-04-23 16:25:18 +00:00
|
|
|
|
2009-09-14 01:07:32 +00:00
|
|
|
void set_multiline(void) { this->ll_level |= LEVEL_MULTILINE; };
|
|
|
|
|
|
|
|
/** @param l The logging level. */
|
|
|
|
void set_level(level_t l) { this->ll_level = l; };
|
|
|
|
|
|
|
|
/** @return The logging level. */
|
|
|
|
level_t get_level() const { return (level_t)(this->ll_level & 0xff); };
|
|
|
|
|
2013-05-28 04:35:00 +00:00
|
|
|
const char *get_level_name() const
|
|
|
|
{
|
|
|
|
return level_names[this->ll_level & 0x0f];
|
2009-09-14 01:07:32 +00:00
|
|
|
};
|
2013-05-28 04:35:00 +00:00
|
|
|
|
2013-06-22 20:44:50 +00:00
|
|
|
uint8_t get_filter_generation(void) const {
|
|
|
|
return this->ll_filter_state >> 2;
|
|
|
|
};
|
|
|
|
|
|
|
|
logfile_filter::type_t get_filter_state(void) const {
|
|
|
|
return (logfile_filter::type_t)(this->ll_filter_state &
|
|
|
|
logfile_filter::LFT__MASK);
|
|
|
|
};
|
|
|
|
|
|
|
|
void set_filter_state(uint8_t generation, logfile_filter::type_t filter) {
|
|
|
|
this->ll_filter_state = (generation << 2) | filter;
|
|
|
|
};
|
2009-09-14 01:07:32 +00:00
|
|
|
|
2013-06-12 13:59:48 +00:00
|
|
|
/**
|
|
|
|
* @return True if there is a schema value set for this log line.
|
|
|
|
*/
|
2013-06-16 01:07:50 +00:00
|
|
|
bool has_schema(void) const
|
|
|
|
{
|
|
|
|
return this->ll_schema[0] != 0 ||
|
|
|
|
this->ll_schema[1] != 0 ||
|
|
|
|
this->ll_schema[2] != 0 ||
|
|
|
|
this->ll_schema[3] != 0;
|
2013-06-12 13:59:48 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the "schema" for this log line. The schema ID is used to match log
|
|
|
|
* lines that have a similar format when generating the logline table. The
|
|
|
|
* schema is set lazily so that startup is faster.
|
2013-06-16 01:07:50 +00:00
|
|
|
*
|
2013-06-12 13:59:48 +00:00
|
|
|
* @param ba The SHA-1 hash of the constant parts of this log line.
|
|
|
|
*/
|
2013-06-16 01:07:50 +00:00
|
|
|
void set_schema(const byte_array<20> &ba)
|
|
|
|
{
|
2013-06-12 13:59:48 +00:00
|
|
|
memcpy(this->ll_schema, ba.in(), sizeof(this->ll_schema));
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Perform a partial match of the given schema against this log line.
|
|
|
|
* Storing the full schema is not practical, so we just keep the first four
|
|
|
|
* bytes.
|
2013-06-16 01:07:50 +00:00
|
|
|
*
|
2013-06-12 13:59:48 +00:00
|
|
|
* @param ba The SHA-1 hash of the constant parts of a log line.
|
|
|
|
* @return True if the first four bytes of the given schema match the
|
|
|
|
* schema stored in this log line.
|
|
|
|
*/
|
2013-06-16 01:07:50 +00:00
|
|
|
bool match_schema(const byte_array<20> &ba) const
|
|
|
|
{
|
2013-06-12 13:59:48 +00:00
|
|
|
return memcmp(this->ll_schema, ba.in(), sizeof(this->ll_schema)) == 0;
|
|
|
|
}
|
|
|
|
|
2009-09-14 01:07:32 +00:00
|
|
|
/**
|
|
|
|
* Compare loglines based on their timestamp.
|
|
|
|
*/
|
|
|
|
bool operator<(const logline &rhs) const
|
|
|
|
{
|
2013-05-28 04:35:00 +00:00
|
|
|
return this->ll_time < rhs.ll_time ||
|
|
|
|
(this->ll_time == rhs.ll_time &&
|
|
|
|
this->ll_millis < rhs.ll_millis);
|
2009-09-14 01:07:32 +00:00
|
|
|
};
|
|
|
|
|
2013-04-17 16:27:12 +00:00
|
|
|
bool operator<(const time_t &rhs) const { return this->ll_time < rhs; };
|
2009-09-14 01:07:32 +00:00
|
|
|
|
|
|
|
private:
|
2013-05-28 04:35:00 +00:00
|
|
|
off_t ll_offset;
|
|
|
|
time_t ll_time;
|
|
|
|
uint16_t ll_millis;
|
|
|
|
uint8_t ll_level;
|
2013-06-22 20:44:50 +00:00
|
|
|
uint8_t ll_filter_state;
|
2013-06-12 13:59:48 +00:00
|
|
|
char ll_schema[4];
|
2009-09-14 01:07:32 +00:00
|
|
|
};
|
|
|
|
|
2013-05-24 14:55:56 +00:00
|
|
|
class logline_value {
|
|
|
|
public:
|
2013-05-28 04:35:00 +00:00
|
|
|
enum kind_t {
|
2013-06-29 13:22:24 +00:00
|
|
|
VALUE_UNKNOWN = -1,
|
2013-05-28 04:35:00 +00:00
|
|
|
VALUE_TEXT,
|
|
|
|
VALUE_INTEGER,
|
|
|
|
VALUE_FLOAT,
|
|
|
|
};
|
|
|
|
|
2013-06-29 13:22:24 +00:00
|
|
|
static kind_t string2kind(const char *kindstr);
|
|
|
|
|
2013-05-28 04:35:00 +00:00
|
|
|
logline_value(std::string name, int64_t i)
|
|
|
|
: lv_name(name), lv_kind(VALUE_INTEGER), lv_number(i) { };
|
|
|
|
logline_value(std::string name, double i)
|
|
|
|
: lv_name(name), lv_kind(VALUE_FLOAT), lv_number(i) { };
|
|
|
|
logline_value(std::string name, std::string s)
|
|
|
|
: lv_name(name), lv_kind(VALUE_TEXT), lv_string(s) { };
|
2013-06-29 13:22:24 +00:00
|
|
|
logline_value(std::string name, kind_t kind, std::string s, bool ident=false)
|
|
|
|
: lv_name(name), lv_kind(kind), lv_identifier(ident)
|
2013-05-28 04:35:00 +00:00
|
|
|
{
|
|
|
|
switch (kind) {
|
|
|
|
case VALUE_TEXT:
|
|
|
|
this->lv_string = s;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VALUE_INTEGER:
|
2013-06-01 04:13:26 +00:00
|
|
|
sscanf(s.c_str(), "%" PRId64 "", &this->lv_number.i);
|
2013-05-28 04:35:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case VALUE_FLOAT:
|
|
|
|
sscanf(s.c_str(), "%lf", &this->lv_number.d);
|
|
|
|
break;
|
2013-06-29 13:22:24 +00:00
|
|
|
|
|
|
|
case VALUE_UNKNOWN:
|
|
|
|
assert(0);
|
|
|
|
break;
|
2013-05-28 04:35:00 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const std::string to_string()
|
|
|
|
{
|
|
|
|
char buffer[128];
|
|
|
|
|
|
|
|
switch (this->lv_kind) {
|
|
|
|
case VALUE_TEXT:
|
|
|
|
return this->lv_string;
|
|
|
|
|
|
|
|
case VALUE_INTEGER:
|
2013-06-01 04:13:26 +00:00
|
|
|
snprintf(buffer, sizeof(buffer), "%" PRId64, this->lv_number.i);
|
2013-05-28 04:35:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case VALUE_FLOAT:
|
|
|
|
snprintf(buffer, sizeof(buffer), "%lf", this->lv_number.d);
|
|
|
|
break;
|
2013-06-29 13:22:24 +00:00
|
|
|
case VALUE_UNKNOWN:
|
|
|
|
assert(0);
|
|
|
|
break;
|
2013-05-28 04:35:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return std::string(buffer);
|
|
|
|
};
|
|
|
|
|
|
|
|
std::string lv_name;
|
|
|
|
kind_t lv_kind;
|
|
|
|
union value_u {
|
|
|
|
int64_t i;
|
|
|
|
double d;
|
|
|
|
|
|
|
|
value_u() : i(0) { };
|
|
|
|
value_u(int64_t i) : i(i) { };
|
|
|
|
value_u(double d) : d(d) { };
|
|
|
|
} lv_number;
|
|
|
|
std::string lv_string;
|
2013-06-29 13:22:24 +00:00
|
|
|
bool lv_identifier;
|
2013-05-24 14:55:56 +00:00
|
|
|
};
|
|
|
|
|
2013-06-29 13:22:24 +00:00
|
|
|
class log_vtab_impl;
|
|
|
|
|
2012-09-22 23:15:15 +00:00
|
|
|
/**
|
|
|
|
* Base class for implementations of log format parsers.
|
|
|
|
*/
|
2009-09-14 01:07:32 +00:00
|
|
|
class log_format {
|
|
|
|
public:
|
2013-05-28 04:35:00 +00:00
|
|
|
|
2012-09-22 23:15:15 +00:00
|
|
|
/**
|
|
|
|
* @return The collection of builtin log formats.
|
|
|
|
*/
|
2009-09-14 01:07:32 +00:00
|
|
|
static std::vector<log_format *> &get_root_formats(void);
|
|
|
|
|
2012-09-22 23:15:15 +00:00
|
|
|
/**
|
|
|
|
* Template used to register log formats during initialization.
|
|
|
|
*/
|
2013-05-28 04:35:00 +00:00
|
|
|
template<class T>
|
|
|
|
class register_root_format {
|
|
|
|
public:
|
|
|
|
register_root_format()
|
|
|
|
{
|
|
|
|
static T format;
|
2012-04-20 23:59:19 +00:00
|
|
|
|
2013-05-28 04:35:00 +00:00
|
|
|
log_format::lf_root_formats.push_back(&format);
|
|
|
|
};
|
2009-09-14 01:07:32 +00:00
|
|
|
};
|
|
|
|
|
2013-06-30 23:43:08 +00:00
|
|
|
log_format() : lf_fmt_lock(-1) {
|
2013-06-18 13:12:36 +00:00
|
|
|
};
|
2009-09-14 01:07:32 +00:00
|
|
|
virtual ~log_format() { };
|
|
|
|
|
2013-05-28 04:35:00 +00:00
|
|
|
virtual void clear(void)
|
|
|
|
{
|
|
|
|
this->lf_fmt_lock = -1;
|
2013-06-30 23:43:08 +00:00
|
|
|
this->lf_date_time.clear();
|
2009-09-14 01:07:32 +00:00
|
|
|
};
|
|
|
|
|
2012-09-22 23:15:15 +00:00
|
|
|
/**
|
|
|
|
* Get the name of this log format.
|
2013-05-28 04:35:00 +00:00
|
|
|
*
|
2012-09-22 23:15:15 +00:00
|
|
|
* @return The log format name.
|
|
|
|
*/
|
2013-06-29 13:22:24 +00:00
|
|
|
virtual std::string get_name(void) const = 0;
|
2009-09-14 01:07:32 +00:00
|
|
|
|
2012-09-22 23:15:15 +00:00
|
|
|
/**
|
|
|
|
* Scan a log line to see if it matches this log format.
|
|
|
|
*
|
|
|
|
* @param dst The vector of loglines that the formatter should append to
|
|
|
|
* if it detected a match.
|
|
|
|
* @param offset The offset in the file where this line is located.
|
|
|
|
* @param prefix The contents of the line.
|
|
|
|
* @param len The length of the prefix string.
|
|
|
|
*/
|
2013-05-28 04:35:00 +00:00
|
|
|
virtual bool scan(std::vector<logline> &dst,
|
|
|
|
off_t offset,
|
|
|
|
char *prefix,
|
|
|
|
int len) = 0;
|
2012-09-22 23:15:15 +00:00
|
|
|
|
2013-04-23 16:25:18 +00:00
|
|
|
/**
|
|
|
|
* Remove redundant data from the log line string.
|
2013-05-28 04:35:00 +00:00
|
|
|
*
|
2013-04-23 16:25:18 +00:00
|
|
|
* XXX We should probably also add some attributes to the line here, so we
|
|
|
|
* can highlight things like the date.
|
2013-05-28 04:35:00 +00:00
|
|
|
*
|
2013-04-23 16:25:18 +00:00
|
|
|
* @param line The log line to edit.
|
|
|
|
*/
|
2012-09-22 23:15:15 +00:00
|
|
|
virtual void scrub(std::string &line) { };
|
2013-05-24 14:55:56 +00:00
|
|
|
|
|
|
|
virtual void annotate(const std::string &line,
|
|
|
|
string_attrs_t &sa,
|
|
|
|
std::vector<logline_value> &values) const
|
|
|
|
{ };
|
2013-05-28 04:35:00 +00:00
|
|
|
|
2009-09-14 01:07:32 +00:00
|
|
|
virtual std::auto_ptr<log_format> specialized(void) = 0;
|
|
|
|
|
2013-06-29 13:22:24 +00:00
|
|
|
virtual log_vtab_impl *get_vtab_impl(void) const {
|
|
|
|
return NULL;
|
|
|
|
};
|
|
|
|
|
2013-06-30 23:43:08 +00:00
|
|
|
date_time_scanner lf_date_time;
|
|
|
|
int lf_fmt_lock;
|
2009-09-14 01:07:32 +00:00
|
|
|
protected:
|
|
|
|
static std::vector<log_format *> lf_root_formats;
|
|
|
|
|
2013-06-26 01:45:07 +00:00
|
|
|
const char *log_scanf(const char *line,
|
|
|
|
const char *fmt[],
|
|
|
|
int expected_matches,
|
|
|
|
const char *time_fmt[],
|
|
|
|
char *time_dest,
|
|
|
|
struct tm *tm_out,
|
2013-06-30 23:43:08 +00:00
|
|
|
struct timeval &tv_out,
|
2013-06-26 01:45:07 +00:00
|
|
|
...);
|
2009-09-14 01:07:32 +00:00
|
|
|
};
|
|
|
|
|
2013-06-26 01:45:07 +00:00
|
|
|
class external_log_format : public log_format {
|
|
|
|
|
|
|
|
public:
|
|
|
|
struct sample {
|
|
|
|
std::string s_line;
|
|
|
|
logline::level_t s_level;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct value_def {
|
2013-06-29 13:22:24 +00:00
|
|
|
value_def() :
|
|
|
|
vd_index(-1),
|
|
|
|
vd_kind(logline_value::VALUE_UNKNOWN),
|
|
|
|
vd_identifier(false) {
|
|
|
|
|
|
|
|
};
|
|
|
|
|
2013-06-26 01:45:07 +00:00
|
|
|
std::string vd_name;
|
2013-06-29 13:22:24 +00:00
|
|
|
int vd_index;
|
2013-06-26 01:45:07 +00:00
|
|
|
logline_value::kind_t vd_kind;
|
2013-06-29 13:22:24 +00:00
|
|
|
std::string vd_collate;
|
|
|
|
bool vd_identifier;
|
|
|
|
|
|
|
|
bool operator<(const value_def &rhs) const {
|
|
|
|
return this->vd_index < rhs.vd_index;
|
|
|
|
};
|
2013-06-26 01:45:07 +00:00
|
|
|
};
|
|
|
|
|
2013-06-29 18:00:34 +00:00
|
|
|
struct pattern {
|
|
|
|
pattern(const std::string &str) : p_string(str) { };
|
|
|
|
|
|
|
|
std::string p_string;
|
|
|
|
pcrepp *p_pcre;
|
|
|
|
std::vector<value_def> p_value_by_index;
|
|
|
|
};
|
|
|
|
|
2013-06-26 01:45:07 +00:00
|
|
|
struct level_pattern {
|
|
|
|
std::string lp_regex;
|
|
|
|
pcrepp *lp_pcre;
|
|
|
|
};
|
|
|
|
|
|
|
|
external_log_format(const std::string &name) : elf_name(name) { };
|
|
|
|
|
2013-06-29 13:22:24 +00:00
|
|
|
std::string get_name(void) const {
|
2013-06-26 01:45:07 +00:00
|
|
|
return this->elf_name;
|
|
|
|
};
|
|
|
|
|
|
|
|
bool scan(std::vector<logline> &dst,
|
|
|
|
off_t offset,
|
|
|
|
char *prefix,
|
2013-06-29 13:22:24 +00:00
|
|
|
int len);
|
2013-06-26 01:45:07 +00:00
|
|
|
|
|
|
|
void annotate(const std::string &line,
|
|
|
|
string_attrs_t &sa,
|
2013-06-29 13:22:24 +00:00
|
|
|
std::vector<logline_value> &values) const;
|
2013-06-26 01:45:07 +00:00
|
|
|
|
2013-06-29 18:00:34 +00:00
|
|
|
void build(std::vector<std::string> &errors);
|
2013-06-26 01:45:07 +00:00
|
|
|
|
|
|
|
std::auto_ptr<log_format> specialized() {
|
|
|
|
std::auto_ptr<log_format> retval((log_format *)
|
|
|
|
new external_log_format(*this));
|
|
|
|
|
2013-06-30 23:43:08 +00:00
|
|
|
retval->lf_fmt_lock = this->lf_fmt_lock;
|
|
|
|
retval->lf_date_time = this->lf_date_time;
|
2013-06-29 19:02:08 +00:00
|
|
|
|
2013-06-26 01:45:07 +00:00
|
|
|
return retval;
|
|
|
|
};
|
|
|
|
|
2013-06-29 13:22:24 +00:00
|
|
|
log_vtab_impl *get_vtab_impl(void) const;
|
|
|
|
|
2013-06-29 18:00:34 +00:00
|
|
|
std::vector<pattern> elf_patterns;
|
2013-06-26 01:45:07 +00:00
|
|
|
std::vector<sample> elf_samples;
|
2013-06-29 13:22:24 +00:00
|
|
|
std::map<std::string, value_def> elf_value_defs;
|
2013-06-26 01:45:07 +00:00
|
|
|
std::string elf_level_field;
|
|
|
|
std::map<logline::level_t, level_pattern> elf_level_patterns;
|
|
|
|
|
|
|
|
private:
|
|
|
|
const std::string elf_name;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
2009-09-14 01:07:32 +00:00
|
|
|
#endif
|