mirror of
https://github.com/zeek/zeek.git
synced 2025-10-05 08:08:19 +00:00
factor out ascii input/output.
First step - factored out everything the logging classes use ( so only output ). Moved the script-level configuration to logging/main, and made the individual writers just refer to it - no idea if this is good design. It works. But I am happy about opinions :) Next step - add support for input...
This commit is contained in:
parent
f62df0de82
commit
501328d61a
13 changed files with 194 additions and 297 deletions
|
@ -17,6 +17,23 @@ export {
|
||||||
## anything else.
|
## anything else.
|
||||||
const default_writer = WRITER_ASCII &redef;
|
const default_writer = WRITER_ASCII &redef;
|
||||||
|
|
||||||
|
## Default separator between fields for logwriters.
|
||||||
|
## Can be overwritten by individual writers.
|
||||||
|
const separator = "\t" &redef;
|
||||||
|
|
||||||
|
## Separator between set elements.
|
||||||
|
## Can be overwritten by individual writers.
|
||||||
|
const set_separator = "," &redef;
|
||||||
|
|
||||||
|
## String to use for empty fields. This should be different from
|
||||||
|
## *unset_field* to make the output non-ambigious.
|
||||||
|
## Can be overwritten by individual writers.
|
||||||
|
const empty_field = "(empty)" &redef;
|
||||||
|
|
||||||
|
## String to use for an unset &optional field.
|
||||||
|
## Can be overwritten by individual writers.
|
||||||
|
const unset_field = "-" &redef;
|
||||||
|
|
||||||
## Type defining the content of a logging stream.
|
## Type defining the content of a logging stream.
|
||||||
type Stream: record {
|
type Stream: record {
|
||||||
## A record type defining the log's columns.
|
## A record type defining the log's columns.
|
||||||
|
|
|
@ -25,17 +25,17 @@ export {
|
||||||
const meta_prefix = "#" &redef;
|
const meta_prefix = "#" &redef;
|
||||||
|
|
||||||
## Separator between fields.
|
## Separator between fields.
|
||||||
const separator = "\t" &redef;
|
const separator = Log::separator &redef;
|
||||||
|
|
||||||
## Separator between set elements.
|
## Separator between set elements.
|
||||||
const set_separator = "," &redef;
|
const set_separator = Log::set_separator &redef;
|
||||||
|
|
||||||
## String to use for empty fields. This should be different from
|
## String to use for empty fields. This should be different from
|
||||||
## *unset_field* to make the output non-ambigious.
|
## *unset_field* to make the output non-ambigious.
|
||||||
const empty_field = "(empty)" &redef;
|
const empty_field = Log::empty_field &redef;
|
||||||
|
|
||||||
## String to use for an unset &optional field.
|
## String to use for an unset &optional field.
|
||||||
const unset_field = "-" &redef;
|
const unset_field = Log::unset_field &redef;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Default function to postprocess a rotated ASCII log file. It moves the rotated
|
# Default function to postprocess a rotated ASCII log file. It moves the rotated
|
||||||
|
|
|
@ -2,12 +2,29 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "AsciiInputOutput.h"
|
||||||
|
#include "bro_inet_ntop.h"
|
||||||
|
|
||||||
bool AsciiInputOutput::ValToText(ODesc* desc, Value* val, const Field* field)
|
AsciiInputOutput::AsciiInputOutput(threading::MsgThread* t, const string & separator, const string & set_separator,
|
||||||
|
const string & empty_field, const string & unset_field)
|
||||||
|
{
|
||||||
|
thread = t;
|
||||||
|
this->separator = separator;
|
||||||
|
this->set_separator = set_separator;
|
||||||
|
this->empty_field = empty_field;
|
||||||
|
this->unset_field = unset_field;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AsciiInputOutput::~AsciiInputOutput()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AsciiInputOutput::ValToODesc(ODesc* desc, threading::Value* val, const threading::Field* field) const
|
||||||
{
|
{
|
||||||
if ( ! val->present )
|
if ( ! val->present )
|
||||||
{
|
{
|
||||||
desc->AddN(unset_field, unset_field_len);
|
desc->Add(unset_field);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,11 +80,11 @@ bool AsciiInputOutput::ValToText(ODesc* desc, Value* val, const Field* field)
|
||||||
|
|
||||||
if ( ! size )
|
if ( ! size )
|
||||||
{
|
{
|
||||||
desc->AddN(empty_field, empty_field_len);
|
desc->Add(empty_field);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( size == unset_field_len && memcmp(data, unset_field, size) == 0 )
|
if ( size == unset_field.size() && memcmp(data, unset_field.data(), size) == 0 )
|
||||||
{
|
{
|
||||||
// The value we'd write out would match exactly the
|
// The value we'd write out would match exactly the
|
||||||
// place-holder we use for unset optional fields. We
|
// place-holder we use for unset optional fields. We
|
||||||
|
@ -93,23 +110,23 @@ bool AsciiInputOutput::ValToText(ODesc* desc, Value* val, const Field* field)
|
||||||
{
|
{
|
||||||
if ( ! val->val.set_val.size )
|
if ( ! val->val.set_val.size )
|
||||||
{
|
{
|
||||||
desc->AddN(empty_field, empty_field_len);
|
desc->Add(empty_field);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
desc->AddEscapeSequence(set_separator, set_separator_len);
|
desc->AddEscapeSequence(set_separator);
|
||||||
for ( int j = 0; j < val->val.set_val.size; j++ )
|
for ( int j = 0; j < val->val.set_val.size; j++ )
|
||||||
{
|
{
|
||||||
if ( j > 0 )
|
if ( j > 0 )
|
||||||
desc->AddRaw(set_separator, set_separator_len);
|
desc->AddRaw(set_separator);
|
||||||
|
|
||||||
if ( ! DoWriteOne(desc, val->val.set_val.vals[j], field) )
|
if ( ! ValToODesc(desc, val->val.set_val.vals[j], field) )
|
||||||
{
|
{
|
||||||
desc->RemoveEscapeSequence(set_separator, set_separator_len);
|
desc->RemoveEscapeSequence(set_separator);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
desc->RemoveEscapeSequence(set_separator, set_separator_len);
|
desc->RemoveEscapeSequence(set_separator);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -118,32 +135,76 @@ bool AsciiInputOutput::ValToText(ODesc* desc, Value* val, const Field* field)
|
||||||
{
|
{
|
||||||
if ( ! val->val.vector_val.size )
|
if ( ! val->val.vector_val.size )
|
||||||
{
|
{
|
||||||
desc->AddN(empty_field, empty_field_len);
|
desc->Add(empty_field);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
desc->AddEscapeSequence(set_separator, set_separator_len);
|
desc->AddEscapeSequence(set_separator);
|
||||||
for ( int j = 0; j < val->val.vector_val.size; j++ )
|
for ( int j = 0; j < val->val.vector_val.size; j++ )
|
||||||
{
|
{
|
||||||
if ( j > 0 )
|
if ( j > 0 )
|
||||||
desc->AddRaw(set_separator, set_separator_len);
|
desc->AddRaw(set_separator);
|
||||||
|
|
||||||
if ( ! DoWriteOne(desc, val->val.vector_val.vals[j], field) )
|
if ( ! ValToODesc(desc, val->val.vector_val.vals[j], field) )
|
||||||
{
|
{
|
||||||
desc->RemoveEscapeSequence(set_separator, set_separator_len);
|
desc->RemoveEscapeSequence(set_separator);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
desc->RemoveEscapeSequence(set_separator, set_separator_len);
|
desc->RemoveEscapeSequence(set_separator);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Error(Fmt("unsupported field format %d for %s", val->type, field->name));
|
thread->Error(thread->Fmt("unsupported field format %d for %s", val->type, field->name));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string AsciiInputOutput::Render(const threading::Value::addr_t& addr)
|
||||||
|
{
|
||||||
|
if ( addr.family == IPv4 )
|
||||||
|
{
|
||||||
|
char s[INET_ADDRSTRLEN];
|
||||||
|
|
||||||
|
if ( ! bro_inet_ntop(AF_INET, &addr.in.in4, s, INET_ADDRSTRLEN) )
|
||||||
|
return "<bad IPv4 address conversion>";
|
||||||
|
else
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char s[INET6_ADDRSTRLEN];
|
||||||
|
|
||||||
|
if ( ! bro_inet_ntop(AF_INET6, &addr.in.in6, s, INET6_ADDRSTRLEN) )
|
||||||
|
return "<bad IPv6 address conversion>";
|
||||||
|
else
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string AsciiInputOutput::Render(const threading::Value::subnet_t& subnet)
|
||||||
|
{
|
||||||
|
char l[16];
|
||||||
|
|
||||||
|
if ( subnet.prefix.family == IPv4 )
|
||||||
|
modp_uitoa10(subnet.length - 96, l);
|
||||||
|
else
|
||||||
|
modp_uitoa10(subnet.length, l);
|
||||||
|
|
||||||
|
string s = Render(subnet.prefix) + "/" + l;
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
string AsciiInputOutput::Render(double d)
|
||||||
|
{
|
||||||
|
char buf[256];
|
||||||
|
modp_dtoa(d, buf, 6);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,54 @@
|
||||||
#ifndef AsciiInputOutput_h
|
#ifndef AsciiInputOutput_h
|
||||||
#define AsciiInputOutput_h
|
#define AsciiInputOutput_h
|
||||||
|
|
||||||
|
#include "Desc.h"
|
||||||
|
#include "threading/MsgThread.h"
|
||||||
|
|
||||||
class AsciiInputOutput {
|
class AsciiInputOutput {
|
||||||
public:
|
public:
|
||||||
|
AsciiInputOutput(threading::MsgThread*, const string & separator, const string & set_separator,
|
||||||
|
const string & empty_field, const string & unset_field);
|
||||||
|
~AsciiInputOutput();
|
||||||
|
|
||||||
|
|
||||||
// converts a threading value to the corresponding ascii representation
|
// converts a threading value to the corresponding ascii representation
|
||||||
// returns false & logs an error with reporter in case an error occurs
|
// returns false & logs an error with reporter in case an error occurs
|
||||||
bool ValToText(ODesc* desc, Value* val, const Field* field);
|
bool ValToODesc(ODesc* desc, threading::Value* val, const threading::Field* field) const;
|
||||||
|
|
||||||
|
/** Helper method to render an IP address as a string.
|
||||||
|
*
|
||||||
|
* @param addr The address.
|
||||||
|
*
|
||||||
|
* @return An ASCII representation of the address.
|
||||||
|
*/
|
||||||
|
static string Render(const threading::Value::addr_t& addr);
|
||||||
|
|
||||||
|
/** Helper method to render an subnet value as a string.
|
||||||
|
*
|
||||||
|
* @param addr The address.
|
||||||
|
*
|
||||||
|
* @return An ASCII representation of the address.
|
||||||
|
*/
|
||||||
|
static string Render(const threading::Value::subnet_t& subnet);
|
||||||
|
|
||||||
|
/** Helper method to render a double in Bro's standard precision.
|
||||||
|
*
|
||||||
|
* @param d The double.
|
||||||
|
*
|
||||||
|
* @return An ASCII representation of the double.
|
||||||
|
*/
|
||||||
|
static string Render(double d);
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
string separator;
|
||||||
|
string set_separator;
|
||||||
|
string empty_field;
|
||||||
|
string unset_field;
|
||||||
|
string meta_prefix;
|
||||||
|
|
||||||
|
threading::MsgThread* thread;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* AsciiInputOuput_h */
|
#endif /* AsciiInputOuput_h */
|
||||||
|
|
|
@ -284,6 +284,7 @@ set(bro_SRCS
|
||||||
Analyzer.cc
|
Analyzer.cc
|
||||||
Anon.cc
|
Anon.cc
|
||||||
ARP.cc
|
ARP.cc
|
||||||
|
AsciiInputOutput.cc
|
||||||
Attr.cc
|
Attr.cc
|
||||||
AYIYA.cc
|
AYIYA.cc
|
||||||
BackDoor.cc
|
BackDoor.cc
|
||||||
|
|
|
@ -118,6 +118,7 @@ public:
|
||||||
|
|
||||||
// Bypasses the escaping enabled via SetEscape().
|
// Bypasses the escaping enabled via SetEscape().
|
||||||
void AddRaw(const char* s, int len) { AddBytesRaw(s, len); }
|
void AddRaw(const char* s, int len) { AddBytesRaw(s, len); }
|
||||||
|
void AddRaw(const string &s) { AddBytesRaw(s.data(), s.size()); }
|
||||||
|
|
||||||
// Returns the description as a string.
|
// Returns the description as a string.
|
||||||
const char* Description() const { return (const char*) base; }
|
const char* Description() const { return (const char*) base; }
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// See the file "COPYING" in the main distribution directory for copyright.
|
// See the file "COPYING" in the main distribution directory for copyright.
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "bro_inet_ntop.h"
|
|
||||||
#include "threading/SerialTypes.h"
|
#include "threading/SerialTypes.h"
|
||||||
|
|
||||||
#include "Manager.h"
|
#include "Manager.h"
|
||||||
|
@ -328,46 +327,3 @@ bool WriterBackend::OnHeartbeat(double network_time, double current_time)
|
||||||
SendOut(new FlushWriteBufferMessage(frontend));
|
SendOut(new FlushWriteBufferMessage(frontend));
|
||||||
return DoHeartbeat(network_time, current_time);
|
return DoHeartbeat(network_time, current_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
string WriterBackend::Render(const threading::Value::addr_t& addr) const
|
|
||||||
{
|
|
||||||
if ( addr.family == IPv4 )
|
|
||||||
{
|
|
||||||
char s[INET_ADDRSTRLEN];
|
|
||||||
|
|
||||||
if ( ! bro_inet_ntop(AF_INET, &addr.in.in4, s, INET_ADDRSTRLEN) )
|
|
||||||
return "<bad IPv4 address conversion>";
|
|
||||||
else
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char s[INET6_ADDRSTRLEN];
|
|
||||||
|
|
||||||
if ( ! bro_inet_ntop(AF_INET6, &addr.in.in6, s, INET6_ADDRSTRLEN) )
|
|
||||||
return "<bad IPv6 address conversion>";
|
|
||||||
else
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
string WriterBackend::Render(const threading::Value::subnet_t& subnet) const
|
|
||||||
{
|
|
||||||
char l[16];
|
|
||||||
|
|
||||||
if ( subnet.prefix.family == IPv4 )
|
|
||||||
modp_uitoa10(subnet.length - 96, l);
|
|
||||||
else
|
|
||||||
modp_uitoa10(subnet.length, l);
|
|
||||||
|
|
||||||
string s = Render(subnet.prefix) + "/" + l;
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
string WriterBackend::Render(double d) const
|
|
||||||
{
|
|
||||||
char buf[256];
|
|
||||||
modp_dtoa(d, buf, 6);
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
|
@ -256,30 +256,6 @@ public:
|
||||||
*/
|
*/
|
||||||
bool FinishedRotation();
|
bool FinishedRotation();
|
||||||
|
|
||||||
/** Helper method to render an IP address as a string.
|
|
||||||
*
|
|
||||||
* @param addr The address.
|
|
||||||
*
|
|
||||||
* @return An ASCII representation of the address.
|
|
||||||
*/
|
|
||||||
string Render(const threading::Value::addr_t& addr) const;
|
|
||||||
|
|
||||||
/** Helper method to render an subnet value as a string.
|
|
||||||
*
|
|
||||||
* @param addr The address.
|
|
||||||
*
|
|
||||||
* @return An ASCII representation of the address.
|
|
||||||
*/
|
|
||||||
string Render(const threading::Value::subnet_t& subnet) const;
|
|
||||||
|
|
||||||
/** Helper method to render a double in Bro's standard precision.
|
|
||||||
*
|
|
||||||
* @param d The double.
|
|
||||||
*
|
|
||||||
* @return An ASCII representation of the double.
|
|
||||||
*/
|
|
||||||
string Render(double d) const;
|
|
||||||
|
|
||||||
// Overridden from MsgThread.
|
// Overridden from MsgThread.
|
||||||
virtual bool OnHeartbeat(double network_time, double current_time);
|
virtual bool OnHeartbeat(double network_time, double current_time);
|
||||||
virtual bool OnFinish(double network_time);
|
virtual bool OnFinish(double network_time);
|
||||||
|
|
|
@ -24,33 +24,35 @@ Ascii::Ascii(WriterFrontend* frontend) : WriterBackend(frontend)
|
||||||
output_to_stdout = BifConst::LogAscii::output_to_stdout;
|
output_to_stdout = BifConst::LogAscii::output_to_stdout;
|
||||||
include_meta = BifConst::LogAscii::include_meta;
|
include_meta = BifConst::LogAscii::include_meta;
|
||||||
|
|
||||||
separator_len = BifConst::LogAscii::separator->Len();
|
separator.assign(
|
||||||
separator = new char[separator_len];
|
(const char*) BifConst::LogAscii::separator->Bytes(),
|
||||||
memcpy(separator, BifConst::LogAscii::separator->Bytes(),
|
BifConst::LogAscii::separator->Len()
|
||||||
separator_len);
|
);
|
||||||
|
|
||||||
set_separator_len = BifConst::LogAscii::set_separator->Len();
|
set_separator.assign(
|
||||||
set_separator = new char[set_separator_len];
|
(const char*) BifConst::LogAscii::set_separator->Bytes(),
|
||||||
memcpy(set_separator, BifConst::LogAscii::set_separator->Bytes(),
|
BifConst::LogAscii::set_separator->Len()
|
||||||
set_separator_len);
|
);
|
||||||
|
|
||||||
empty_field_len = BifConst::LogAscii::empty_field->Len();
|
empty_field.assign(
|
||||||
empty_field = new char[empty_field_len];
|
(const char*) BifConst::LogAscii::empty_field->Bytes(),
|
||||||
memcpy(empty_field, BifConst::LogAscii::empty_field->Bytes(),
|
BifConst::LogAscii::empty_field->Len()
|
||||||
empty_field_len);
|
);
|
||||||
|
|
||||||
unset_field_len = BifConst::LogAscii::unset_field->Len();
|
unset_field.assign(
|
||||||
unset_field = new char[unset_field_len];
|
(const char*) BifConst::LogAscii::unset_field->Bytes(),
|
||||||
memcpy(unset_field, BifConst::LogAscii::unset_field->Bytes(),
|
BifConst::LogAscii::unset_field->Len()
|
||||||
unset_field_len);
|
);
|
||||||
|
|
||||||
meta_prefix_len = BifConst::LogAscii::meta_prefix->Len();
|
meta_prefix.assign(
|
||||||
meta_prefix = new char[meta_prefix_len];
|
(const char*) BifConst::LogAscii::meta_prefix->Bytes(),
|
||||||
memcpy(meta_prefix, BifConst::LogAscii::meta_prefix->Bytes(),
|
BifConst::LogAscii::meta_prefix->Len()
|
||||||
meta_prefix_len);
|
);
|
||||||
|
|
||||||
desc.EnableEscaping();
|
desc.EnableEscaping();
|
||||||
desc.AddEscapeSequence(separator, separator_len);
|
desc.AddEscapeSequence(separator);
|
||||||
|
|
||||||
|
io = new AsciiInputOutput(this, separator, set_separator, empty_field, unset_field);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ascii::~Ascii()
|
Ascii::~Ascii()
|
||||||
|
@ -61,17 +63,12 @@ Ascii::~Ascii()
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
delete [] separator;
|
delete io;
|
||||||
delete [] set_separator;
|
|
||||||
delete [] empty_field;
|
|
||||||
delete [] unset_field;
|
|
||||||
delete [] meta_prefix;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Ascii::WriteHeaderField(const string& key, const string& val)
|
bool Ascii::WriteHeaderField(const string& key, const string& val)
|
||||||
{
|
{
|
||||||
string str = string(meta_prefix, meta_prefix_len) +
|
string str = meta_prefix + key + separator + val + "\n";
|
||||||
key + string(separator, separator_len) + val + "\n";
|
|
||||||
|
|
||||||
return safe_write(fd, str.c_str(), str.length());
|
return safe_write(fd, str.c_str(), str.length());
|
||||||
}
|
}
|
||||||
|
@ -136,8 +133,8 @@ bool Ascii::DoInit(const WriterInfo& info, int num_fields, const Field* const *
|
||||||
{
|
{
|
||||||
if ( i > 0 )
|
if ( i > 0 )
|
||||||
{
|
{
|
||||||
names += string(separator, separator_len);
|
names += separator;
|
||||||
types += string(separator, separator_len);
|
types += separator;
|
||||||
}
|
}
|
||||||
|
|
||||||
names += string(fields[i]->name);
|
names += string(fields[i]->name);
|
||||||
|
@ -154,20 +151,17 @@ bool Ascii::DoInit(const WriterInfo& info, int num_fields, const Field* const *
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
string str = string(meta_prefix, meta_prefix_len)
|
string str = meta_prefix
|
||||||
+ "separator " // Always use space as separator here.
|
+ "separator " // Always use space as separator here.
|
||||||
+ get_escaped_string(string(separator, separator_len), false)
|
+ get_escaped_string(separator, false)
|
||||||
+ "\n";
|
+ "\n";
|
||||||
|
|
||||||
if ( ! safe_write(fd, str.c_str(), str.length()) )
|
if ( ! safe_write(fd, str.c_str(), str.length()) )
|
||||||
goto write_error;
|
goto write_error;
|
||||||
|
|
||||||
if ( ! (WriteHeaderField("set_separator", get_escaped_string(
|
if ( ! (WriteHeaderField("set_separator", get_escaped_string(set_separator, false)) &&
|
||||||
string(set_separator, set_separator_len), false)) &&
|
WriteHeaderField("empty_field", get_escaped_string(empty_field, false)) &&
|
||||||
WriteHeaderField("empty_field", get_escaped_string(
|
WriteHeaderField("unset_field", get_escaped_string(unset_field, false)) &&
|
||||||
string(empty_field, empty_field_len), false)) &&
|
|
||||||
WriteHeaderField("unset_field", get_escaped_string(
|
|
||||||
string(unset_field, unset_field_len), false)) &&
|
|
||||||
WriteHeaderField("path", get_escaped_string(path, false)) &&
|
WriteHeaderField("path", get_escaped_string(path, false)) &&
|
||||||
WriteHeaderField("open", Timestamp(0))) )
|
WriteHeaderField("open", Timestamp(0))) )
|
||||||
goto write_error;
|
goto write_error;
|
||||||
|
@ -205,151 +199,6 @@ bool Ascii::DoFinish(double network_time)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Ascii::DoWriteOne(ODesc* desc, Value* val, const Field* field)
|
|
||||||
{
|
|
||||||
if ( ! val->present )
|
|
||||||
{
|
|
||||||
desc->AddN(unset_field, unset_field_len);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ( val->type ) {
|
|
||||||
|
|
||||||
case TYPE_BOOL:
|
|
||||||
desc->Add(val->val.int_val ? "T" : "F");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TYPE_INT:
|
|
||||||
desc->Add(val->val.int_val);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TYPE_COUNT:
|
|
||||||
case TYPE_COUNTER:
|
|
||||||
desc->Add(val->val.uint_val);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TYPE_PORT:
|
|
||||||
desc->Add(val->val.port_val.port);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TYPE_SUBNET:
|
|
||||||
desc->Add(Render(val->val.subnet_val));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TYPE_ADDR:
|
|
||||||
desc->Add(Render(val->val.addr_val));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TYPE_DOUBLE:
|
|
||||||
// Rendering via Add() truncates trailing 0s after the
|
|
||||||
// decimal point. The difference with TIME/INTERVAL is mainly
|
|
||||||
// to keep the log format consistent.
|
|
||||||
desc->Add(val->val.double_val);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TYPE_INTERVAL:
|
|
||||||
case TYPE_TIME:
|
|
||||||
// Rendering via Render() keeps trailing 0s after the decimal
|
|
||||||
// point. The difference with DOUBLEis mainly to keep the log
|
|
||||||
// format consistent.
|
|
||||||
desc->Add(Render(val->val.double_val));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TYPE_ENUM:
|
|
||||||
case TYPE_STRING:
|
|
||||||
case TYPE_FILE:
|
|
||||||
case TYPE_FUNC:
|
|
||||||
{
|
|
||||||
int size = val->val.string_val.length;
|
|
||||||
const char* data = val->val.string_val.data;
|
|
||||||
|
|
||||||
if ( ! size )
|
|
||||||
{
|
|
||||||
desc->AddN(empty_field, empty_field_len);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( size == unset_field_len && memcmp(data, unset_field, size) == 0 )
|
|
||||||
{
|
|
||||||
// The value we'd write out would match exactly the
|
|
||||||
// place-holder we use for unset optional fields. We
|
|
||||||
// escape the first character so that the output
|
|
||||||
// won't be ambigious.
|
|
||||||
static const char hex_chars[] = "0123456789abcdef";
|
|
||||||
char hex[6] = "\\x00";
|
|
||||||
hex[2] = hex_chars[((*data) & 0xf0) >> 4];
|
|
||||||
hex[3] = hex_chars[(*data) & 0x0f];
|
|
||||||
desc->AddRaw(hex, 4);
|
|
||||||
|
|
||||||
++data;
|
|
||||||
--size;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( size )
|
|
||||||
desc->AddN(data, size);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case TYPE_TABLE:
|
|
||||||
{
|
|
||||||
if ( ! val->val.set_val.size )
|
|
||||||
{
|
|
||||||
desc->AddN(empty_field, empty_field_len);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
desc->AddEscapeSequence(set_separator, set_separator_len);
|
|
||||||
for ( int j = 0; j < val->val.set_val.size; j++ )
|
|
||||||
{
|
|
||||||
if ( j > 0 )
|
|
||||||
desc->AddRaw(set_separator, set_separator_len);
|
|
||||||
|
|
||||||
if ( ! DoWriteOne(desc, val->val.set_val.vals[j], field) )
|
|
||||||
{
|
|
||||||
desc->RemoveEscapeSequence(set_separator, set_separator_len);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
desc->RemoveEscapeSequence(set_separator, set_separator_len);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case TYPE_VECTOR:
|
|
||||||
{
|
|
||||||
if ( ! val->val.vector_val.size )
|
|
||||||
{
|
|
||||||
desc->AddN(empty_field, empty_field_len);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
desc->AddEscapeSequence(set_separator, set_separator_len);
|
|
||||||
for ( int j = 0; j < val->val.vector_val.size; j++ )
|
|
||||||
{
|
|
||||||
if ( j > 0 )
|
|
||||||
desc->AddRaw(set_separator, set_separator_len);
|
|
||||||
|
|
||||||
if ( ! DoWriteOne(desc, val->val.vector_val.vals[j], field) )
|
|
||||||
{
|
|
||||||
desc->RemoveEscapeSequence(set_separator, set_separator_len);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
desc->RemoveEscapeSequence(set_separator, set_separator_len);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
Error(Fmt("unsupported field format %d for %s", val->type, field->name));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Ascii::DoWrite(int num_fields, const Field* const * fields,
|
bool Ascii::DoWrite(int num_fields, const Field* const * fields,
|
||||||
Value** vals)
|
Value** vals)
|
||||||
{
|
{
|
||||||
|
@ -361,9 +210,9 @@ bool Ascii::DoWrite(int num_fields, const Field* const * fields,
|
||||||
for ( int i = 0; i < num_fields; i++ )
|
for ( int i = 0; i < num_fields; i++ )
|
||||||
{
|
{
|
||||||
if ( i > 0 )
|
if ( i > 0 )
|
||||||
desc.AddRaw(separator, separator_len);
|
desc.AddRaw(separator);
|
||||||
|
|
||||||
if ( ! DoWriteOne(&desc, vals[i], fields[i]) )
|
if ( ! io->ValToODesc(&desc, vals[i], fields[i]) )
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,7 +221,7 @@ bool Ascii::DoWrite(int num_fields, const Field* const * fields,
|
||||||
const char* bytes = (const char*)desc.Bytes();
|
const char* bytes = (const char*)desc.Bytes();
|
||||||
int len = desc.Len();
|
int len = desc.Len();
|
||||||
|
|
||||||
if ( strncmp(bytes, meta_prefix, meta_prefix_len) == 0 )
|
if ( strncmp(bytes, meta_prefix.data(), meta_prefix.size()) == 0 )
|
||||||
{
|
{
|
||||||
// It would so escape the first character.
|
// It would so escape the first character.
|
||||||
char buf[16];
|
char buf[16];
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#define LOGGING_WRITER_ASCII_H
|
#define LOGGING_WRITER_ASCII_H
|
||||||
|
|
||||||
#include "../WriterBackend.h"
|
#include "../WriterBackend.h"
|
||||||
|
#include "../../AsciiInputOutput.h"
|
||||||
|
|
||||||
namespace logging { namespace writer {
|
namespace logging { namespace writer {
|
||||||
|
|
||||||
|
@ -32,7 +33,6 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool IsSpecial(string path) { return path.find("/dev/") == 0; }
|
bool IsSpecial(string path) { return path.find("/dev/") == 0; }
|
||||||
bool DoWriteOne(ODesc* desc, threading::Value* val, const threading::Field* field);
|
|
||||||
bool WriteHeaderField(const string& key, const string& value);
|
bool WriteHeaderField(const string& key, const string& value);
|
||||||
void CloseFile(double t);
|
void CloseFile(double t);
|
||||||
string Timestamp(double t); // Uses current time if t is zero.
|
string Timestamp(double t); // Uses current time if t is zero.
|
||||||
|
@ -47,20 +47,13 @@ private:
|
||||||
bool include_meta;
|
bool include_meta;
|
||||||
bool only_single_header_row;
|
bool only_single_header_row;
|
||||||
|
|
||||||
char* separator;
|
string separator;
|
||||||
int separator_len;
|
string set_separator;
|
||||||
|
string empty_field;
|
||||||
|
string unset_field;
|
||||||
|
string meta_prefix;
|
||||||
|
|
||||||
char* set_separator;
|
AsciiInputOutput* io;
|
||||||
int set_separator_len;
|
|
||||||
|
|
||||||
char* empty_field;
|
|
||||||
int empty_field_len;
|
|
||||||
|
|
||||||
char* unset_field;
|
|
||||||
int unset_field_len;
|
|
||||||
|
|
||||||
char* meta_prefix;
|
|
||||||
int meta_prefix_len;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,10 +46,10 @@ std::string DataSeries::LogValueToString(threading::Value *val)
|
||||||
}
|
}
|
||||||
|
|
||||||
case TYPE_SUBNET:
|
case TYPE_SUBNET:
|
||||||
return Render(val->val.subnet_val);
|
return AsciiInputOutput::Render(val->val.subnet_val);
|
||||||
|
|
||||||
case TYPE_ADDR:
|
case TYPE_ADDR:
|
||||||
return Render(val->val.addr_val);
|
return AsciiInputOutput::Render(val->val.addr_val);
|
||||||
|
|
||||||
// Note: These two cases are relatively special. We need to convert
|
// Note: These two cases are relatively special. We need to convert
|
||||||
// these values into their integer equivalents to maximize precision.
|
// these values into their integer equivalents to maximize precision.
|
||||||
|
@ -69,10 +69,10 @@ std::string DataSeries::LogValueToString(threading::Value *val)
|
||||||
return ostr.str();
|
return ostr.str();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return Render(val->val.double_val);
|
return AsciiInputOutput::Render(val->val.double_val);
|
||||||
|
|
||||||
case TYPE_DOUBLE:
|
case TYPE_DOUBLE:
|
||||||
return Render(val->val.double_val);
|
return AsciiInputOutput::Render(val->val.double_val);
|
||||||
|
|
||||||
case TYPE_ENUM:
|
case TYPE_ENUM:
|
||||||
case TYPE_STRING:
|
case TYPE_STRING:
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "BroString.h"
|
#include "BroString.h"
|
||||||
#include "NetVar.h"
|
#include "NetVar.h"
|
||||||
#include "threading/SerialTypes.h"
|
#include "threading/SerialTypes.h"
|
||||||
|
#include "../../AsciiInputOutput.h"
|
||||||
|
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
#include <curl/easy.h>
|
#include <curl/easy.h>
|
||||||
|
@ -124,13 +125,13 @@ bool ElasticSearch::AddValueToBuffer(ODesc* b, Value* val)
|
||||||
|
|
||||||
case TYPE_SUBNET:
|
case TYPE_SUBNET:
|
||||||
b->AddRaw("\"", 1);
|
b->AddRaw("\"", 1);
|
||||||
b->Add(Render(val->val.subnet_val));
|
b->Add(AsciiInputOutput::Render(val->val.subnet_val));
|
||||||
b->AddRaw("\"", 1);
|
b->AddRaw("\"", 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TYPE_ADDR:
|
case TYPE_ADDR:
|
||||||
b->AddRaw("\"", 1);
|
b->AddRaw("\"", 1);
|
||||||
b->Add(Render(val->val.addr_val));
|
b->Add(AsciiInputOutput::Render(val->val.addr_val));
|
||||||
b->AddRaw("\"", 1);
|
b->AddRaw("\"", 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -400,7 +400,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A paremeterized OututMessage that stores a pointer to an argument object.
|
* A paremeterized OutputMessage that stores a pointer to an argument object.
|
||||||
* Normally, the objects will be used from the Process() callback.
|
* Normally, the objects will be used from the Process() callback.
|
||||||
*/
|
*/
|
||||||
template<typename O>
|
template<typename O>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue