mirror of
https://github.com/zeek/zeek.git
synced 2025-10-04 23:58:20 +00:00
Extending the log writer DoInit() API.
We now pass in a Info struct that contains: - the path name (as before) - the rotation interval - the log_rotate_base_time in seconds - a table of key/value pairs with further configuration options. To fill the table, log filters have a new field "config: table[string] of strings". This gives a way to pass arbitrary values from script-land to writers. Interpretation is left up to the writer. Also splits calc_next_rotate() into two functions, one of which is thread-safe and can be used with the log_rotate_base_time value from DoInit(). Includes also updates to the None writer: - It gets its own script writers/none.bro. - New bool option LogNone::debug to enable debug output. It then prints out all the values passed to DoInit(). That's used by a btest test to ensure the new DoInit() values are right. - Fixed a bug that prevented Bro from terminating.. (scripts.base.frameworks.logging.rotate-custom currently fails. Haven't yet investigated why.)
This commit is contained in:
parent
b38d1e1ec2
commit
19eea409c3
16 changed files with 231 additions and 23 deletions
|
@ -51,6 +51,7 @@ struct Manager::Filter {
|
|||
string path;
|
||||
Val* path_val;
|
||||
EnumVal* writer;
|
||||
TableVal* config;
|
||||
bool local;
|
||||
bool remote;
|
||||
double interval;
|
||||
|
@ -519,6 +520,7 @@ bool Manager::AddFilter(EnumVal* id, RecordVal* fval)
|
|||
Val* log_remote = fval->LookupWithDefault(rtype->FieldOffset("log_remote"));
|
||||
Val* interv = fval->LookupWithDefault(rtype->FieldOffset("interv"));
|
||||
Val* postprocessor = fval->LookupWithDefault(rtype->FieldOffset("postprocessor"));
|
||||
Val* config = fval->LookupWithDefault(rtype->FieldOffset("config"));
|
||||
|
||||
Filter* filter = new Filter;
|
||||
filter->name = name->AsString()->CheckString();
|
||||
|
@ -530,6 +532,7 @@ bool Manager::AddFilter(EnumVal* id, RecordVal* fval)
|
|||
filter->remote = log_remote->AsBool();
|
||||
filter->interval = interv->AsInterval();
|
||||
filter->postprocessor = postprocessor ? postprocessor->AsFunc() : 0;
|
||||
filter->config = config->Ref()->AsTableVal();
|
||||
|
||||
Unref(name);
|
||||
Unref(pred);
|
||||
|
@ -538,6 +541,7 @@ bool Manager::AddFilter(EnumVal* id, RecordVal* fval)
|
|||
Unref(log_remote);
|
||||
Unref(interv);
|
||||
Unref(postprocessor);
|
||||
Unref(config);
|
||||
|
||||
// Build the list of fields that the filter wants included, including
|
||||
// potentially rolling out fields.
|
||||
|
@ -768,6 +772,22 @@ bool Manager::Write(EnumVal* id, RecordVal* columns)
|
|||
WriterBackend::WriterInfo info;
|
||||
info.path = path;
|
||||
|
||||
HashKey* k;
|
||||
IterCookie* c = filter->config->AsTable()->InitForIteration();
|
||||
|
||||
TableEntryVal* v;
|
||||
while ( (v = filter->config->AsTable()->NextEntry(k, c)) )
|
||||
{
|
||||
ListVal* index = filter->config->RecoverIndex(k);
|
||||
string key = index->Index(0)->AsString()->CheckString();
|
||||
string value = v->Value()->AsString()->CheckString();
|
||||
info.config.insert(std::make_pair(key, value));
|
||||
Unref(index);
|
||||
delete k;
|
||||
}
|
||||
|
||||
// CreateWriter() will set the other fields in info.
|
||||
|
||||
writer = CreateWriter(stream->id, filter->writer,
|
||||
info, filter->num_fields,
|
||||
arg_fields, filter->local, filter->remote);
|
||||
|
@ -777,7 +797,6 @@ bool Manager::Write(EnumVal* id, RecordVal* columns)
|
|||
Unref(columns);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Alright, can do the write now.
|
||||
|
@ -977,8 +996,6 @@ WriterFrontend* Manager::CreateWriter(EnumVal* id, EnumVal* writer, const Writer
|
|||
WriterFrontend* writer_obj = new WriterFrontend(id, writer, local, remote);
|
||||
assert(writer_obj);
|
||||
|
||||
writer_obj->Init(info, num_fields, fields);
|
||||
|
||||
WriterInfo* winfo = new WriterInfo;
|
||||
winfo->type = writer->Ref()->AsEnumVal();
|
||||
winfo->writer = writer_obj;
|
||||
|
@ -1020,6 +1037,16 @@ WriterFrontend* Manager::CreateWriter(EnumVal* id, EnumVal* writer, const Writer
|
|||
Stream::WriterMap::value_type(Stream::WriterPathPair(writer->AsEnum(), info.path),
|
||||
winfo));
|
||||
|
||||
// Still need to set the WriterInfo's rotation parameters, which we
|
||||
// computed above.
|
||||
const char* base_time = log_rotate_base_time ?
|
||||
log_rotate_base_time->AsString()->CheckString() : 0;
|
||||
|
||||
winfo->info.rotation_interval = winfo->interval;
|
||||
winfo->info.rotation_base = parse_rotate_base_time(base_time);
|
||||
|
||||
writer_obj->Init(winfo->info, num_fields, fields);
|
||||
|
||||
return writer_obj;
|
||||
}
|
||||
|
||||
|
@ -1223,8 +1250,9 @@ void Manager::InstallRotationTimer(WriterInfo* winfo)
|
|||
const char* base_time = log_rotate_base_time ?
|
||||
log_rotate_base_time->AsString()->CheckString() : 0;
|
||||
|
||||
double base = parse_rotate_base_time(base_time);
|
||||
double delta_t =
|
||||
calc_next_rotate(rotation_interval, base_time);
|
||||
calc_next_rotate(network_time, rotation_interval, base);
|
||||
|
||||
winfo->rotation_timer =
|
||||
new RotationTimer(network_time + delta_t, winfo, true);
|
||||
|
|
|
@ -63,12 +63,48 @@ using namespace logging;
|
|||
|
||||
bool WriterBackend::WriterInfo::Read(SerializationFormat* fmt)
|
||||
{
|
||||
return fmt->Read(&path, "path");
|
||||
int size;
|
||||
|
||||
if ( ! (fmt->Read(&path, "path") &&
|
||||
fmt->Read(&rotation_base, "rotation_base") &&
|
||||
fmt->Read(&rotation_interval, "rotation_interval") &&
|
||||
fmt->Read(&size, "config_size")) )
|
||||
return false;
|
||||
|
||||
config.clear();
|
||||
|
||||
while ( size )
|
||||
{
|
||||
string value;
|
||||
string key;
|
||||
|
||||
if ( ! (fmt->Read(&value, "config-value") && fmt->Read(&value, "config-key")) )
|
||||
return false;
|
||||
|
||||
config.insert(std::make_pair(value, key));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool WriterBackend::WriterInfo::Write(SerializationFormat* fmt) const
|
||||
{
|
||||
return fmt->Write(path, "path");
|
||||
int size = config.size();
|
||||
|
||||
if ( ! (fmt->Write(path, "path") &&
|
||||
fmt->Write(rotation_base, "rotation_base") &&
|
||||
fmt->Write(rotation_interval, "rotation_interval") &&
|
||||
fmt->Write(size, "config_size")) )
|
||||
return false;
|
||||
|
||||
for ( config_map::const_iterator i = config.begin(); i != config.end(); ++i )
|
||||
{
|
||||
if ( ! (fmt->Write(i->first, "config-value") && fmt->Write(i->second, "config-key")) )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
WriterBackend::WriterBackend(WriterFrontend* arg_frontend) : MsgThread()
|
||||
|
|
|
@ -48,6 +48,8 @@ public:
|
|||
*/
|
||||
struct WriterInfo
|
||||
{
|
||||
typedef std::map<string, string> config_map;
|
||||
|
||||
/**
|
||||
* A string left to the interpretation of the writer
|
||||
* implementation; it corresponds to the value configured on
|
||||
|
@ -55,6 +57,22 @@ public:
|
|||
*/
|
||||
string path;
|
||||
|
||||
/**
|
||||
* The rotation interval as configured for this writer.
|
||||
*/
|
||||
double rotation_interval;
|
||||
|
||||
/**
|
||||
* The parsed value of log_rotate_base_time in seconds.
|
||||
*/
|
||||
double rotation_base;
|
||||
|
||||
/**
|
||||
* A map of key/value pairs corresponding to the relevant
|
||||
* filter's "config" table.
|
||||
*/
|
||||
std::map<string, string> config;
|
||||
|
||||
private:
|
||||
friend class ::RemoteSerializer;
|
||||
|
||||
|
|
|
@ -1,9 +1,36 @@
|
|||
|
||||
#include "None.h"
|
||||
#include "NetVar.h"
|
||||
|
||||
using namespace logging;
|
||||
using namespace writer;
|
||||
|
||||
bool None::DoInit(const WriterInfo& info, int num_fields,
|
||||
const threading::Field* const * fields)
|
||||
{
|
||||
if ( BifConst::LogNone::debug )
|
||||
{
|
||||
std::cout << "[logging::writer::None]" << std::endl;
|
||||
std::cout << " path=" << info.path << std::endl;
|
||||
std::cout << " rotation_interval=" << info.rotation_interval << std::endl;
|
||||
std::cout << " rotation_base=" << info.rotation_base << std::endl;
|
||||
|
||||
for ( std::map<string,string>::const_iterator i = info.config.begin(); i != info.config.end(); i++ )
|
||||
std::cout << " config[" << i->first << "] = " << i->second << std::endl;
|
||||
|
||||
for ( int i = 0; i < num_fields; i++ )
|
||||
{
|
||||
const threading::Field* field = fields[i];
|
||||
std::cout << " field " << field->name << ": "
|
||||
<< type_name(field->type) << std::endl;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool None::DoRotate(string rotated_path, double open, double close, bool terminating)
|
||||
{
|
||||
if ( ! FinishedRotation(string("/dev/null"), Info().path, open, close, terminating))
|
||||
|
|
|
@ -19,7 +19,7 @@ public:
|
|||
|
||||
protected:
|
||||
virtual bool DoInit(const WriterInfo& info, int num_fields,
|
||||
const threading::Field* const * fields) { return true; }
|
||||
const threading::Field* const * fields);
|
||||
|
||||
virtual bool DoWrite(int num_fields, const threading::Field* const* fields,
|
||||
threading::Value** vals) { return true; }
|
||||
|
@ -27,7 +27,7 @@ protected:
|
|||
virtual bool DoRotate(string rotated_path, double open,
|
||||
double close, bool terminating);
|
||||
virtual bool DoFlush() { return true; }
|
||||
virtual bool DoFinish() { return true; }
|
||||
virtual bool DoFinish() { WriterBackend::DoFinish(); return true; }
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue