mirror of
https://github.com/zeek/zeek.git
synced 2025-10-04 15:48:19 +00:00
Documenting logging API.
This commit is contained in:
parent
1058e11ffb
commit
29fc56105d
8 changed files with 625 additions and 180 deletions
|
@ -1279,7 +1279,7 @@ Value** Manager::RecordToFilterVals(Stream* stream, Filter* filter,
|
|||
}
|
||||
|
||||
WriterFrontend* Manager::CreateWriter(EnumVal* id, EnumVal* writer, string path,
|
||||
int num_fields, Field** fields)
|
||||
int num_fields, const Field* const* fields)
|
||||
{
|
||||
Stream* stream = FindStream(id);
|
||||
|
||||
|
|
|
@ -15,32 +15,63 @@ class RotationTimer;
|
|||
|
||||
namespace logging {
|
||||
|
||||
// Description of a log field.
|
||||
/**
|
||||
* Definition of a log file, i.e., one column of a log stream.
|
||||
*/
|
||||
struct Field {
|
||||
string name;
|
||||
TypeTag type;
|
||||
// inner type of sets
|
||||
TypeTag subtype;
|
||||
string name; //! Name of the field.
|
||||
TypeTag type; //! Type of the field.
|
||||
TypeTag subtype; //! Inner type for sets.
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
Field() { subtype = TYPE_VOID; }
|
||||
|
||||
/**
|
||||
* Copy constructor.
|
||||
*/
|
||||
Field(const Field& other)
|
||||
: name(other.name), type(other.type), subtype(other.subtype) { }
|
||||
|
||||
// (Un-)serialize.
|
||||
/**
|
||||
* Unserializes a field.
|
||||
*
|
||||
* @param fmt The serialization format to use. The format handles
|
||||
* low-level I/O.
|
||||
*
|
||||
* @return False if an error occured.
|
||||
*/
|
||||
bool Read(SerializationFormat* fmt);
|
||||
|
||||
/**
|
||||
* Serializes a field.
|
||||
*
|
||||
* @param fmt The serialization format to use. The format handles
|
||||
* low-level I/O.
|
||||
*
|
||||
* @return False if an error occured.
|
||||
*/
|
||||
bool Write(SerializationFormat* fmt) const;
|
||||
};
|
||||
|
||||
// Values as logged by a writer.
|
||||
/**
|
||||
* Definition of a log value, i.e., a entry logged by a stream.
|
||||
*
|
||||
* This struct essentialy represents a serialization of a Val instance (for
|
||||
* those Vals supported).
|
||||
*/
|
||||
struct Value {
|
||||
TypeTag type;
|
||||
bool present; // False for unset fields.
|
||||
TypeTag type; //! The type of the value.
|
||||
bool present; //! False for optional record fields that are not set.
|
||||
|
||||
// The following union is a subset of BroValUnion, including only the
|
||||
// types we can log directly.
|
||||
struct set_t { bro_int_t size; Value** vals; };
|
||||
typedef set_t vec_t;
|
||||
|
||||
/**
|
||||
* This union is a subset of BroValUnion, including only the types we
|
||||
* can log directly. See IsCompatibleType().
|
||||
*/
|
||||
union _val {
|
||||
bro_int_t int_val;
|
||||
bro_uint_t uint_val;
|
||||
|
@ -52,42 +83,173 @@ struct Value {
|
|||
vec_t vector_val;
|
||||
} val;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* arg_type: The type of the value.
|
||||
*
|
||||
* arg_present: False if the value represents an optional record field
|
||||
* that is not set.
|
||||
*/
|
||||
Value(TypeTag arg_type = TYPE_ERROR, bool arg_present = true)
|
||||
: type(arg_type), present(arg_present) {}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
~Value();
|
||||
|
||||
// (Un-)serialize.
|
||||
/**
|
||||
* Unserializes a value.
|
||||
*
|
||||
* @param fmt The serialization format to use. The format handles low-level I/O.
|
||||
*
|
||||
* @return False if an error occured.
|
||||
*/
|
||||
bool Read(SerializationFormat* fmt);
|
||||
|
||||
/**
|
||||
* Serializes a value.
|
||||
*
|
||||
* @param fmt The serialization format to use. The format handles
|
||||
* low-level I/O.
|
||||
*
|
||||
* @return False if an error occured.
|
||||
*/
|
||||
bool Write(SerializationFormat* fmt) const;
|
||||
|
||||
// Returns true if the type can be logged the framework. If
|
||||
// `atomic_only` is true, will not permit composite types.
|
||||
/**
|
||||
* Returns true if the type can be represented by a Value. If
|
||||
* `atomic_only` is true, will not permit composite types.
|
||||
*/
|
||||
static bool IsCompatibleType(BroType* t, bool atomic_only=false);
|
||||
|
||||
private:
|
||||
Value(const Value& other) { }
|
||||
Value(const Value& other) { } // Disabled.
|
||||
};
|
||||
|
||||
class WriterBackend;
|
||||
class WriterFrontend;
|
||||
class RotationFinishedMessage;
|
||||
|
||||
/**
|
||||
* Singleton class for managing log streams.
|
||||
*/
|
||||
class Manager {
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
Manager();
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
~Manager();
|
||||
|
||||
// These correspond to the BiFs visible on the scripting layer. The
|
||||
// actual BiFs just forward here.
|
||||
/**
|
||||
* Creates a new log stream.
|
||||
*
|
||||
* @param id The enum value corresponding the log stream.
|
||||
*
|
||||
* @param stream A record of script type \c Log::Stream.
|
||||
*
|
||||
* This method corresponds directly to the internal BiF defined in
|
||||
* logging.bif, which just forwards here.
|
||||
*/
|
||||
bool CreateStream(EnumVal* id, RecordVal* stream);
|
||||
|
||||
/**
|
||||
* Enables a log log stream.
|
||||
*
|
||||
* @param id The enum value corresponding the log stream.
|
||||
*
|
||||
* This method corresponds directly to the internal BiF defined in
|
||||
* logging.bif, which just forwards here.
|
||||
*/
|
||||
bool EnableStream(EnumVal* id);
|
||||
|
||||
/**
|
||||
* Disables a log stream.
|
||||
*
|
||||
* @param id The enum value corresponding the log stream.
|
||||
*
|
||||
* This methods corresponds directly to the internal BiF defined in
|
||||
* logging.bif, which just forwards here.
|
||||
*/
|
||||
bool DisableStream(EnumVal* id);
|
||||
|
||||
/**
|
||||
* Adds a filter to a log stream.
|
||||
*
|
||||
* @param id The enum value corresponding the log stream.
|
||||
*
|
||||
* @param filter A record of script type \c Log::Filter.
|
||||
*
|
||||
* This methods corresponds directly to the internal BiF defined in
|
||||
* logging.bif, which just forwards here.
|
||||
*/
|
||||
bool AddFilter(EnumVal* id, RecordVal* filter);
|
||||
|
||||
/**
|
||||
* Removes a filter from a log stream.
|
||||
*
|
||||
* @param id The enum value corresponding the log stream.
|
||||
*
|
||||
* @param name The name of the filter to remove.
|
||||
*
|
||||
* This methods corresponds directly to the internal BiF defined in
|
||||
* logging.bif, which just forwards here.
|
||||
*/
|
||||
bool RemoveFilter(EnumVal* id, StringVal* name);
|
||||
|
||||
/**
|
||||
* Removes a filter from a log stream.
|
||||
*
|
||||
* @param id The enum value corresponding the log stream.
|
||||
*
|
||||
* @param name The name of the filter to remove.
|
||||
*
|
||||
* This methods corresponds directly to the internal BiF defined in
|
||||
* logging.bif, which just forwards here.
|
||||
*/
|
||||
bool RemoveFilter(EnumVal* id, string name);
|
||||
|
||||
/**
|
||||
* Write a record to a log stream.
|
||||
*
|
||||
* @param id The enum value corresponding the log stream.
|
||||
*
|
||||
* @param colums A record of the type defined for the stream's
|
||||
* columns.
|
||||
*
|
||||
* This methods corresponds directly to the internal BiF defined in
|
||||
* logging.bif, which just forwards here.
|
||||
*/
|
||||
bool Write(EnumVal* id, RecordVal* columns);
|
||||
bool SetBuf(EnumVal* id, bool enabled); // Adjusts all writers.
|
||||
bool Flush(EnumVal* id); // Flushes all writers..
|
||||
|
||||
/**
|
||||
* Sets log streams buffering state. This adjusts all associated
|
||||
* writers to the new state.
|
||||
*
|
||||
* @param id The enum value corresponding the log stream.
|
||||
*
|
||||
* @param enabled False to disable buffering (default is enabled).
|
||||
*
|
||||
* This methods corresponds directly to the internal BiF defined in
|
||||
* logging.bif, which just forwards here.
|
||||
*/
|
||||
bool SetBuf(EnumVal* id, bool enabled);
|
||||
|
||||
/**
|
||||
* Flushes a log stream. This flushed all associated writers.
|
||||
*
|
||||
* @param id The enum value corresponding the log stream.
|
||||
*
|
||||
* This methods corresponds directly to the internal BiF defined in
|
||||
* logging.bif, which just forwards here.
|
||||
*/
|
||||
bool Flush(EnumVal* id);
|
||||
|
||||
protected:
|
||||
friend class WriterFrontend;
|
||||
|
@ -103,7 +265,7 @@ protected:
|
|||
|
||||
// Takes ownership of fields.
|
||||
WriterFrontend* CreateWriter(EnumVal* id, EnumVal* writer, string path,
|
||||
int num_fields, Field** fields);
|
||||
int num_fields, const Field* const* fields);
|
||||
|
||||
// Takes ownership of values..
|
||||
bool Write(EnumVal* id, EnumVal* writer, string path,
|
||||
|
@ -112,8 +274,6 @@ protected:
|
|||
// Announces all instantiated writers to peer.
|
||||
void SendAllWritersTo(RemoteSerializer::PeerID peer);
|
||||
|
||||
//// Functions safe to use by writers.
|
||||
|
||||
// Signals that a file has been rotated.
|
||||
bool FinishedRotation(WriterFrontend* writer, string new_name, string old_name,
|
||||
double open, double close, bool terminating);
|
||||
|
|
|
@ -40,6 +40,15 @@ public:
|
|||
virtual bool Process() { Object()->FlushWriteBuffer(); return true; }
|
||||
};
|
||||
|
||||
class DisableMessage : public threading::OutputMessage<WriterFrontend>
|
||||
{
|
||||
public:
|
||||
DisableMessage(WriterFrontend* writer)
|
||||
: threading::OutputMessage<WriterFrontend>("Disable", writer) {}
|
||||
|
||||
virtual bool Process() { Object()->SetDisable(); return true; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// Backend methods.
|
||||
|
@ -86,6 +95,11 @@ bool WriterBackend::FinishedRotation(string new_name, string old_name,
|
|||
return true;
|
||||
}
|
||||
|
||||
void WriterBackend::DisableFrontend()
|
||||
{
|
||||
SendOut(new DisableMessage(frontend));
|
||||
}
|
||||
|
||||
bool WriterBackend::Init(WriterFrontend* arg_frontend, string arg_path, int arg_num_fields,
|
||||
const Field* const* arg_fields)
|
||||
{
|
||||
|
@ -95,7 +109,10 @@ bool WriterBackend::Init(WriterFrontend* arg_frontend, string arg_path, int arg_
|
|||
fields = arg_fields;
|
||||
|
||||
if ( ! DoInit(arg_path, arg_num_fields, arg_fields) )
|
||||
{
|
||||
DisableFrontend();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -114,6 +131,7 @@ bool WriterBackend::Write(int arg_num_fields, int num_writes, Value*** vals)
|
|||
#endif
|
||||
|
||||
DeleteVals(num_writes, vals);
|
||||
DisableFrontend();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -129,6 +147,7 @@ bool WriterBackend::Write(int arg_num_fields, int num_writes, Value*** vals)
|
|||
vals[j][i]->type, fields[i]->type);
|
||||
Debug(DBG_LOGGING, msg);
|
||||
|
||||
DisableFrontend();
|
||||
DeleteVals(num_writes, vals);
|
||||
return false;
|
||||
}
|
||||
|
@ -148,6 +167,9 @@ bool WriterBackend::Write(int arg_num_fields, int num_writes, Value*** vals)
|
|||
|
||||
DeleteVals(num_writes, vals);
|
||||
|
||||
if ( ! success )
|
||||
DisableFrontend();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
@ -159,23 +181,47 @@ bool WriterBackend::SetBuf(bool enabled)
|
|||
|
||||
buffering = enabled;
|
||||
|
||||
return DoSetBuf(enabled);
|
||||
if ( ! DoSetBuf(enabled) )
|
||||
{
|
||||
DisableFrontend();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriterBackend::Rotate(string rotated_path, double open,
|
||||
double close, bool terminating)
|
||||
{
|
||||
return DoRotate(rotated_path, open, close, terminating);
|
||||
if ( ! DoRotate(rotated_path, open, close, terminating) )
|
||||
{
|
||||
DisableFrontend();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriterBackend::Flush()
|
||||
{
|
||||
return DoFlush();
|
||||
if ( ! DoFlush() )
|
||||
{
|
||||
DisableFrontend();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriterBackend::Finish()
|
||||
{
|
||||
return DoFinish();
|
||||
if ( ! DoFlush() )
|
||||
{
|
||||
DisableFrontend();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriterBackend::DoHeartbeat(double network_time, double current_time)
|
||||
|
|
|
@ -11,180 +11,291 @@
|
|||
|
||||
namespace logging {
|
||||
|
||||
// The backend runs in its own thread, separate from the main process.
|
||||
/**
|
||||
* Base class for writer implementation. When the logging::Manager creates a
|
||||
* new logging filter, it instantiates a WriterFrontend. That then in turn
|
||||
* creates a WriterBackend of the right type. The frontend then forwards
|
||||
* message over the backend as its methods are called.
|
||||
*
|
||||
* All of this methods must be called only from the corresponding child
|
||||
* thread (the constructor is the one exception.)
|
||||
*/
|
||||
class WriterBackend : public threading::MsgThread
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param name A descriptive name for writer's type (e.g., \c Ascii).
|
||||
*/
|
||||
WriterBackend(const string& name);
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~WriterBackend();
|
||||
|
||||
// One-time initialization of the writer to define the logged fields.
|
||||
//
|
||||
// "frontend" is the frontend writer that created this backend. The
|
||||
// *only* purpose of this value is to be passed back via messages as
|
||||
// a argument to callbacks. One must not otherwise access the
|
||||
// frontend, it's running in a different thread.
|
||||
//
|
||||
// Interpretation of "path" is left to the writer, and will be
|
||||
// corresponding the value configured on the script-level.
|
||||
//
|
||||
// Returns false if an error occured, in which case the writer must
|
||||
// not be used further.
|
||||
//
|
||||
// The new instance takes ownership of "fields", and will delete them
|
||||
// when done.
|
||||
/**
|
||||
* One-time initialization of the writer to define the logged fields.
|
||||
*
|
||||
* @param frontend The frontend writer that created this backend. The
|
||||
* *only* purpose of this value is to be passed back via messages as
|
||||
* a argument to callbacks. One must not otherwise access the
|
||||
* frontend, it's running in a different thread.
|
||||
*
|
||||
* @param path A string left to the interpretation of the writer
|
||||
* implementation; it corresponds to the value configured on the
|
||||
* script-level for the logging filter.
|
||||
*
|
||||
* @param num_fields The number of log fields for the stream.
|
||||
*
|
||||
* @param fields An array of size \a num_fields with the log fields.
|
||||
* The methods takes ownership of the array.
|
||||
*
|
||||
* @return False if an error occured.
|
||||
*/
|
||||
bool Init(WriterFrontend* frontend, string path, int num_fields, const Field* const* fields);
|
||||
|
||||
// Writes one log entry. The method takes ownership of "vals" and
|
||||
// will return immediately after queueing the write request, which is
|
||||
// potentially before output has actually been written out.
|
||||
//
|
||||
// num_fields and the types of the Values must match what was passed
|
||||
// to Init().
|
||||
//
|
||||
// Returns false if an error occured, in which case the writer must
|
||||
// not be used any further.
|
||||
/**
|
||||
* Writes one log entry.
|
||||
*
|
||||
* @param num_fields: The number of log fields for this stream. The
|
||||
* value must match what was passed to Init().
|
||||
*
|
||||
* @param An array of size \a num_fields with the log values. Their
|
||||
* types musst match with the field passed to Init(). The method
|
||||
* takes ownership of \a vals..
|
||||
*
|
||||
* Returns false if an error occured, in which case the writer must
|
||||
* not be used any further.
|
||||
*
|
||||
* @return False if an error occured.
|
||||
*/
|
||||
bool Write(int num_fields, int num_writes, Value*** vals);
|
||||
|
||||
// Sets the buffering status for the writer, if the writer supports
|
||||
// that. (If not, it will be ignored).
|
||||
/**
|
||||
* Sets the buffering status for the writer, assuming the writer
|
||||
* supports that. (If not, it will be ignored).
|
||||
*
|
||||
* @param enabled False if buffering is to be disabled (by default
|
||||
* it's on).
|
||||
*
|
||||
* @return False if an error occured.
|
||||
*/
|
||||
bool SetBuf(bool enabled);
|
||||
|
||||
// Flushes any currently buffered output, if the writer supports
|
||||
// that. (If not, it will be ignored).
|
||||
/**
|
||||
* Flushes any currently buffered output, assuming the writer
|
||||
* supports that. (If not, it will be ignored).
|
||||
*
|
||||
* @return False if an error occured.
|
||||
*/
|
||||
bool Flush();
|
||||
|
||||
// Triggers rotation, if the writer supports that. (If not, it will
|
||||
// be ignored).
|
||||
/**
|
||||
* Triggers rotation, if the writer supports that. (If not, it will
|
||||
* be ignored).
|
||||
*
|
||||
* @return False if an error occured.
|
||||
*/
|
||||
bool Rotate(string rotated_path, double open, double close, bool terminating);
|
||||
|
||||
// Finishes writing to this logger regularly. Must not be called if
|
||||
// an error has been indicated earlier. After calling this, no
|
||||
// further writing must be performed.
|
||||
/**
|
||||
* Finishes writing to this logger in a regularl fashion. Must not be
|
||||
* called if an error has been indicated earlier. After calling this,
|
||||
* no further writing must be performed.
|
||||
*
|
||||
* @return False if an error occured.
|
||||
*/
|
||||
bool Finish();
|
||||
|
||||
//// Thread-safe methods that may be called from the writer
|
||||
//// implementation.
|
||||
/**
|
||||
* Disables the frontend that has instantiated this backend. Once
|
||||
* disabled,the frontend will not send any further message over.
|
||||
*/
|
||||
void DisableFrontend();
|
||||
|
||||
// The following methods return the information as passed to Init().
|
||||
/**
|
||||
* Returns the log path as passed into the constructor.
|
||||
*/
|
||||
const string Path() const { return path; }
|
||||
|
||||
/**
|
||||
* Returns the number of log fields as passed into the constructor.
|
||||
*/
|
||||
int NumFields() const { return num_fields; }
|
||||
|
||||
/**
|
||||
* Returns the log fields as passed into the constructor.
|
||||
*/
|
||||
const Field* const * Fields() const { return fields; }
|
||||
|
||||
// Returns the current buffering state.
|
||||
/**
|
||||
* Returns the current buffering state.
|
||||
*
|
||||
* @return True if buffering is enabled.
|
||||
*/
|
||||
bool IsBuf() { return buffering; }
|
||||
|
||||
// Signals to the log manager that a file has been rotated.
|
||||
//
|
||||
// writer: The frontend writer that triggered the rotation. This must
|
||||
// be the value passed into DoRotate().
|
||||
//
|
||||
// new_name: The filename of the rotated file. old_name: The filename
|
||||
// of the origina file.
|
||||
//
|
||||
// open/close: The timestamps when the original file was opened and
|
||||
// closed, respectively.
|
||||
//
|
||||
// terminating: True if rotation request occured due to the main Bro
|
||||
// process shutting down.
|
||||
/**
|
||||
* Signals that a file has been rotated. This must be called by a
|
||||
* writer's implementation of DoRotate() once rotation has finished.
|
||||
*
|
||||
* Most of the parameters should be passed through from DoRotate().
|
||||
*
|
||||
* @param new_name The filename of the rotated file.
|
||||
*
|
||||
* @param old_name The filename of the original file.
|
||||
*
|
||||
* @param open: The timestamp when the original file was opened.
|
||||
*
|
||||
* @param close: The timestamp when the origina file was closed.
|
||||
*
|
||||
* @param terminating: True if the original rotation request occured
|
||||
* due to the main Bro process shutting down.
|
||||
*/
|
||||
bool FinishedRotation(string new_name, string old_name,
|
||||
double open, double close, bool terminating);
|
||||
|
||||
|
||||
protected:
|
||||
// Methods for writers to override. If any of these returs false, it
|
||||
// will be assumed that a fatal error has occured that prevents the
|
||||
// writer from further operation. It will then be disabled and
|
||||
// deleted. When returning false, the writer should also report the
|
||||
// error via Error(). Note that even if a writer does not support the
|
||||
// functionality for one these methods (like rotation), it must still
|
||||
// return true if that is not to be considered a fatal error.
|
||||
//
|
||||
// Called once for initialization of the writer.
|
||||
/**
|
||||
* Writer-specific intialization method.
|
||||
*
|
||||
* A writer implementation must override this method. If it returns
|
||||
* false, it will be assumed that a fatal error has occured that
|
||||
* prevents the writer from further operation; it will then be
|
||||
* disabled and eventually deleted. When returning false, an
|
||||
* implementation should also call Error() to indicate what happened.
|
||||
*/
|
||||
virtual bool DoInit(string path, int num_fields,
|
||||
const Field* const* fields) = 0;
|
||||
|
||||
// Called once per log entry to record.
|
||||
/**
|
||||
* Writer-specific output method implementing recording of fone log
|
||||
* entry.
|
||||
*
|
||||
* A writer implementation must override this method. If it returns
|
||||
* false, it will be assumed that a fatal error has occured that
|
||||
* prevents the writer from further operation; it will then be
|
||||
* disabled and eventually deleted. When returning false, an
|
||||
* implementation should also call Error() to indicate what happened.
|
||||
*/
|
||||
virtual bool DoWrite(int num_fields, const Field* const* fields,
|
||||
Value** vals) = 0;
|
||||
|
||||
// Called when the buffering status for this writer is changed. If
|
||||
// buffering is disabled, the writer should attempt to write out
|
||||
// information as quickly as possible even if doing so may have a
|
||||
// performance impact. If enabled (which is the default), it may
|
||||
// buffer data as helpful and write it out later in a way optimized
|
||||
// for performance. The current buffering state can be queried via
|
||||
// IsBuf().
|
||||
//
|
||||
// A writer may ignore buffering changes if it doesn't fit with its
|
||||
// semantics (but must still return true in that case).
|
||||
/**
|
||||
* Writer-specific method implementing a change of fthe buffering
|
||||
* state. If buffering is disabled, the writer should attempt to
|
||||
* write out information as quickly as possible even if doing so may
|
||||
* have a performance impact. If enabled (which is the default), it
|
||||
* may buffer data as helpful and write it out later in a way
|
||||
* optimized for performance. The current buffering state can be
|
||||
* queried via IsBuf().
|
||||
*
|
||||
* A writer implementation must override this method but it can just
|
||||
* ignore calls if buffering doesn't align with its semantics.
|
||||
*
|
||||
* If the method returns false, it will be assumed that a fatal error
|
||||
* has occured that prevents the writer from further operation; it
|
||||
* will then be disabled and eventually deleted. When returning
|
||||
* false, an implementation should also call Error() to indicate what
|
||||
* happened.
|
||||
*/
|
||||
virtual bool DoSetBuf(bool enabled) = 0;
|
||||
|
||||
// Called to flush any currently buffered output.
|
||||
//
|
||||
// A writer may ignore flush requests if it doesn't fit with its
|
||||
// semantics (but must still return true in that case).
|
||||
/**
|
||||
* Writer-specific method implementing flushing of its output.
|
||||
*
|
||||
* A writer implementation must override this method but it can just
|
||||
* ignore calls if flushing doesn't align with its semantics.
|
||||
*
|
||||
* If the method returns false, it will be assumed that a fatal error
|
||||
* has occured that prevents the writer from further operation; it
|
||||
* will then be disabled and eventually deleted. When returning
|
||||
* false, an implementation should also call Error() to indicate what
|
||||
* happened.
|
||||
*/
|
||||
virtual bool DoFlush() = 0;
|
||||
|
||||
// Called when a log output is to be rotated. Most directly this only
|
||||
// applies to writers writing into files, which should then close the
|
||||
// current file and open a new one. However, a writer may also
|
||||
// trigger other apppropiate actions if semantics are similar.
|
||||
//
|
||||
// Once rotation has finished, the implementation should call
|
||||
// RotationDone() to signal the log manager that potential
|
||||
// postprocessors can now run.
|
||||
//
|
||||
// "rotate_path" reflects the path to where the rotated output is to
|
||||
// be moved, with specifics depending on the writer. It should
|
||||
// generally be interpreted in a way consistent with that of "path"
|
||||
// as passed into DoInit(). As an example, for file-based output,
|
||||
// "rotate_path" could be the original filename extended with a
|
||||
// timestamp indicating the time of the rotation.
|
||||
//
|
||||
// "open" and "close" are the network time's when the *current* file
|
||||
// was opened and closed, respectively.
|
||||
//
|
||||
// "terminating" indicated whether the rotation request occurs due
|
||||
// the main Bro prcoess terminating (and not because we've reach a
|
||||
// regularly scheduled time for rotation).
|
||||
//
|
||||
// A writer may ignore rotation requests if it doesn't fit with its
|
||||
// semantics (but must still return true in that case).
|
||||
/**
|
||||
* Writer-specific method implementing log rotation. Most directly
|
||||
* this only applies to writers writing into files, which should then
|
||||
* close the current file and open a new one. However, a writer may
|
||||
* also trigger other apppropiate actions if semantics are similar. *
|
||||
* Once rotation has finished, the implementation must call
|
||||
* FinishedRotation() to signal the log manager that potential
|
||||
* postprocessors can now run.
|
||||
*
|
||||
* A writer implementation must override this method but it can just
|
||||
* ignore calls if flushing doesn't align with its semantics. It
|
||||
* still needs to call FinishedRotation() though.
|
||||
*
|
||||
* If the method returns false, it will be assumed that a fatal error
|
||||
* has occured that prevents the writer from further operation; it
|
||||
* will then be disabled and eventually deleted. When returning
|
||||
* false, an implementation should also call Error() to indicate what
|
||||
* happened.
|
||||
*
|
||||
* @param rotate_path Reflects the path to where the rotated output
|
||||
* is to be moved, with specifics depending on the writer. It should
|
||||
* generally be interpreted in a way consistent with that of \c path
|
||||
* as passed into DoInit(). As an example, for file-based output, \c
|
||||
* rotate_path could be the original filename extended with a
|
||||
* timestamp indicating the time of the rotation.
|
||||
*
|
||||
* @param open The network time when the *current* file was opened.
|
||||
*
|
||||
* @param close The network time when the *current* file was closed.
|
||||
*
|
||||
* @param terminating Indicates whether the rotation request occurs
|
||||
* due the main Bro prcoess terminating (and not because we've
|
||||
* reached a regularly scheduled time for rotation).
|
||||
*/
|
||||
virtual bool DoRotate(string rotated_path, double open, double close,
|
||||
bool terminating) = 0;
|
||||
|
||||
// Called once on termination. Not called when any of the other
|
||||
// methods has previously signaled an error, i.e., executing this
|
||||
// method signals a regular shutdown of the writer.
|
||||
/**
|
||||
* Writer-specific method implementing log output finalization at
|
||||
* termination. Not called when any of the other methods has
|
||||
* previously signaled an error, i.e., executing this method signals
|
||||
* a regular shutdown of the writer.
|
||||
*
|
||||
* A writer implementation must override this method but it can just
|
||||
* ignore calls if flushing doesn't align with its semantics.
|
||||
*
|
||||
* If the method returns false, it will be assumed that a fatal error
|
||||
* has occured that prevents the writer from further operation; it
|
||||
* will then be disabled and eventually deleted. When returning
|
||||
* false, an implementation should also call Error() to indicate what
|
||||
* happened.
|
||||
*/
|
||||
virtual bool DoFinish() = 0;
|
||||
|
||||
// Triggered by regular heartbeat messages from the main process.
|
||||
//
|
||||
// Note when overriding, you must call WriterBackend::DoHeartbeat().
|
||||
/**
|
||||
* Triggered by regular heartbeat messages from the main thread.
|
||||
*
|
||||
* This method can be overridden but once must call
|
||||
* WriterBackend::DoHeartbeat().
|
||||
*/
|
||||
virtual bool DoHeartbeat(double network_time, double current_time);
|
||||
|
||||
private:
|
||||
friend class Manager;
|
||||
|
||||
// When an error occurs, we call this method to set a flag marking
|
||||
// the writer as disabled. The Manager will check the flag later and
|
||||
// remove the writer.
|
||||
bool Disabled() { return disabled; }
|
||||
|
||||
// Deletes the values as passed into Write().
|
||||
/**
|
||||
* Deletes the values as passed into Write().
|
||||
*/
|
||||
void DeleteVals(int num_writes, Value*** vals);
|
||||
|
||||
// Frontend that instantiated us. This object must not be access from
|
||||
// this class, it's running in a different thread!
|
||||
WriterFrontend* frontend;
|
||||
string path;
|
||||
int num_fields;
|
||||
const Field* const * fields;
|
||||
bool buffering;
|
||||
bool disabled;
|
||||
|
||||
// For implementing Fmt().
|
||||
char* buf;
|
||||
unsigned int buf_len;
|
||||
string path; // Log path.
|
||||
int num_fields; // Number of log fields.
|
||||
const Field* const* fields; // Log fields.
|
||||
bool buffering; // True if buffering is enabled.
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
//
|
||||
// Bridge class between main process and writer threads.
|
||||
|
||||
#ifndef LOGGING_WRITERFRONTEND_H
|
||||
#define LOGGING_WRITERFRONTEND_H
|
||||
|
@ -13,57 +11,187 @@ namespace logging {
|
|||
|
||||
class WriterBackend;
|
||||
|
||||
/**
|
||||
* Bridge class between the logging::Manager and backend writer threads. The
|
||||
* Manager instantiates one \a WriterFrontend for each open logging filter.
|
||||
* Each frontend in turns instantiates a WriterBackend-derived class
|
||||
* internally that's specific to the particular output format. That backend
|
||||
* spawns a new thread, and it receives messages from the frontend that
|
||||
* correspond to method called by the manager.
|
||||
*
|
||||
*/
|
||||
class WriterFrontend {
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* type: The backend writer type, with the value corresponding to the
|
||||
* script-level \c Log::Writer enum (e.g., \a WRITER_ASCII). The
|
||||
* frontend will internally instantiate a WriterBackend of the
|
||||
* corresponding type.
|
||||
*
|
||||
* Frontends must only be instantiated by the main thread.
|
||||
*/
|
||||
WriterFrontend(bro_int_t type);
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*
|
||||
* Frontends must only be destroyed by the main thread.
|
||||
*/
|
||||
virtual ~WriterFrontend();
|
||||
|
||||
// Disables the writers and stop the backend thread.
|
||||
/**
|
||||
* Stops all output to this writer. Calling this methods disables all
|
||||
* message forwarding to the backend and stops the backend thread.
|
||||
*
|
||||
* This method must only be called from the main thread.
|
||||
*/
|
||||
void Stop();
|
||||
|
||||
// Interface methods to interact with the writer from the main thread
|
||||
// (and only from the main thread), typicalli from the log manager.
|
||||
// All these methods forward (via inter-thread messaging) to the
|
||||
// corresponding methods of an internally created WriterBackend. See
|
||||
// there for documentation.
|
||||
//
|
||||
// If any of these operations fails, the writer will be automatically
|
||||
// (but asynchronoulsy) disabled.
|
||||
|
||||
/**
|
||||
* Initializes the writer.
|
||||
*
|
||||
* This method generates a message to the backend writer and triggers
|
||||
* the corresponding message there. If the backend method fails, it
|
||||
* sends a message back that will asynchronously call Disable().
|
||||
*
|
||||
* See WriterBackend::Init() for arguments. The method takes
|
||||
* ownership of \a fields.
|
||||
*
|
||||
* This method must only be called from the main thread.
|
||||
*/
|
||||
void Init(string path, int num_fields, const Field* const* fields);
|
||||
|
||||
/**
|
||||
* Write out a record.
|
||||
*
|
||||
* This method generates a message to the backend writer and triggers
|
||||
* the corresponding message there. If the backend method fails, it
|
||||
* sends a message back that will asynchronously call Disable().
|
||||
*
|
||||
* As an optimization, if buffering is enabled (which is the default)
|
||||
* this method may buffer several writes and send them over to the
|
||||
* backend in bulk with a single message. An explicit bulk write of
|
||||
* all currently buffered data can be triggered with
|
||||
* FlushWriteBuffer(). The backend writer triggers this with a
|
||||
* message at every heartbeat.
|
||||
*
|
||||
* See WriterBackend::Writer() for arguments (except that this method
|
||||
* takes only a single record, not an array). The method takes
|
||||
* ownership of \a vals.
|
||||
*
|
||||
* This method must only be called from the main thread.
|
||||
*/
|
||||
void Write(int num_fields, Value** vals);
|
||||
|
||||
/**
|
||||
* Sets the buffering state.
|
||||
*
|
||||
* This method generates a message to the backend writer and triggers
|
||||
* the corresponding message there. If the backend method fails, it
|
||||
* sends a message back that will asynchronously call Disable().
|
||||
*
|
||||
* See WriterBackend::SetBuf() for arguments.
|
||||
*
|
||||
* This method must only be called from the main thread.
|
||||
*/
|
||||
void SetBuf(bool enabled);
|
||||
|
||||
/**
|
||||
* Flushes the output.
|
||||
*
|
||||
* This method generates a message to the backend writer and triggers
|
||||
* the corresponding message there. In addition, it also triggers
|
||||
* FlushWriteBuffer(). If the backend method fails, it sends a
|
||||
* message back that will asynchronously call Disable().
|
||||
*
|
||||
* This method must only be called from the main thread.
|
||||
*/
|
||||
void Flush();
|
||||
void FlushWriteBuffer();
|
||||
|
||||
/**
|
||||
* Triggers log rotation.
|
||||
*
|
||||
* This method generates a message to the backend writer and triggers
|
||||
* the corresponding message there. If the backend method fails, it
|
||||
* sends a message back that will asynchronously call Disable().
|
||||
*
|
||||
* See WriterBackend::Rotate() for arguments.
|
||||
*
|
||||
* This method must only be called from the main thread.
|
||||
*/
|
||||
void Rotate(string rotated_path, double open, double close, bool terminating);
|
||||
|
||||
/**
|
||||
* Finalizes writing to this tream.
|
||||
*
|
||||
* This method generates a message to the backend writer and triggers
|
||||
* the corresponding message there. If the backend method fails, it
|
||||
* sends a message back that will asynchronously call Disable().
|
||||
*
|
||||
* This method must only be called from the main thread.
|
||||
*/
|
||||
void Finish();
|
||||
|
||||
// Calling this disable the writer. All methods calls will be no-ops
|
||||
// from now on. The Manager will eventually remove disabled writers.
|
||||
/**
|
||||
* Explicitly triggers a transfer of all potentially buffered Write()
|
||||
* operations over to the backend.
|
||||
*
|
||||
* This method must only be called from the main thread.
|
||||
*/
|
||||
void FlushWriteBuffer();
|
||||
|
||||
/**
|
||||
* Disables the writer frontend. From now on, all method calls that
|
||||
* would normally send message over to the backend, turn into no-ops.
|
||||
* Note though that it does not stop the backend itself, use Stop()
|
||||
* to do thast as well (this method is primarily for use as callback
|
||||
* when the backend wants to disable the frontend).
|
||||
*
|
||||
* Disabled frontend will eventually be discarded by the
|
||||
* logging::Manager.
|
||||
*
|
||||
* This method must only be called from the main thread.
|
||||
*/
|
||||
void SetDisable() { disabled = true; }
|
||||
|
||||
/**
|
||||
* Returns true if the writer frontend has been disabled with SetDisable().
|
||||
*/
|
||||
bool Disabled() { return disabled; }
|
||||
|
||||
/**
|
||||
* Returns the log path as passed into the constructor.
|
||||
*/
|
||||
const string Path() const { return path; }
|
||||
|
||||
/**
|
||||
* Returns the number of log fields as passed into the constructor.
|
||||
*/
|
||||
int NumFields() const { return num_fields; }
|
||||
|
||||
/**
|
||||
* Returns the log fields as passed into the constructor.
|
||||
*/
|
||||
const Field* const * Fields() const { return fields; }
|
||||
|
||||
protected:
|
||||
friend class Manager;
|
||||
|
||||
WriterBackend* backend;
|
||||
bool disabled;
|
||||
bool initialized;
|
||||
bool buf;
|
||||
WriterBackend* backend; // The backend we have instanatiated.
|
||||
bool disabled; // True if disabled.
|
||||
bool initialized; // True if initialized.
|
||||
bool buf; // True if buffering is enabled (default).
|
||||
|
||||
string path;
|
||||
int num_fields;
|
||||
const Field* const * fields;
|
||||
string path; // The log path.
|
||||
int num_fields; // The number of log fields.
|
||||
const Field* const* fields; // The log fields.
|
||||
|
||||
// Buffer for bulk writes.
|
||||
static const int WRITER_BUFFER_SIZE = 50;
|
||||
|
||||
int write_buffer_pos;
|
||||
Value*** write_buffer;
|
||||
int write_buffer_pos; // Position of next write in buffer.
|
||||
Value*** write_buffer; // Buffer of size WRITER_BUFFER_SIZE.
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue