Documenting logging API.

This commit is contained in:
Robin Sommer 2012-02-01 07:16:24 -08:00
parent 1058e11ffb
commit 29fc56105d
8 changed files with 625 additions and 180 deletions

View file

@ -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.
bool Init(WriterFrontend* frontend, string path, int num_fields, const Field* const * fields);
/**
* 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;
const Field* const* fields) = 0;
// Called once per log entry to record.
virtual bool DoWrite(int num_fields, const Field* const * fields,
/**
* 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.
};