BDE 4.14.0 Production release
Loading...
Searching...
No Matches
ball_observer

Detailed Description

Outline

Purpose

Define a protocol for receiving and processing log records.

Classes

See also
ball_record, ball_loggermanager

Description

This component defines the base-level protocol, ball::Observer, for receiving and processing log records. Concrete types derived from this protocol, receive log records, and process them in a manner defined by the derived class author.

Usage

This example shows the definition and use of a simple concrete observer that writes three of the log record's fields, timestamp, process ID, and thread ID, to an ostream that is provided to the observer at construction. This (trivial) functionality suffices to demonstrate the requisite steps for having a working observer:

  1. Define a concrete class derived from ball::Observer.
  2. Implement the pure virtual publish method.
  3. Instantiate and use an object of the concrete type.

Note that the "publish attributes" object provided to the publish method indicates, among other properties, whether the log record to be published is a "solo" message or whether it is one of a sequence. In general, a useful observer object should incorporate the attributes information as part of the "publication" of the log record. In this example, the attributes information is used to generate an appropriate heading for each log record that is printed to the observer's ostream.

We first define the (derived) my_OstreamObserver class and implement its simple constructor inline (for convenience, directly within the derived-class definition):

// my_ostreamobserver.h
class my_OstreamObserver : public ball::Observer {
ostream& d_stream;
public:
my_OstreamObserver(ostream& stream) : d_stream(stream) { }
virtual ~my_OstreamObserver();
using Observer::publish; // avoid hiding base class method
virtual void publish(const ball::Record& record,
const ball::Context& context);
};
Definition ball_context.h:295
Definition ball_observer.h:235
virtual void publish(const Record &record, const Context &context)
Definition ball_record.h:178

Note, however, that we always implement a virtual destructor (non-inline) in the .cpp file (to indicate the unique location of the class's virtual table):

// my_ostreamobserver.cpp
// ...
my_OstreamObserver::~my_OstreamObserver() { }

We next implement the (virtual) publish method, which incorporates the "policy" of what it means for this observer to "publish" a log record. In this example, the policy is that three log record fields are written to an ostream, along with an appropriate heading, and the rest of the log record is ignored. Note that, in this implementation, the zero-based index attribute is incremented by one before it is written, which produces a more natural record count:

// my_ostreamobserver.cpp
// ...
my_OstreamObserver::~my_OstreamObserver() { }
void my_OstreamObserver::publish(const ball::Record& record,
const ball::Context& context)
{
using namespace std;
d_stream << endl; // skip a line
switch (context.transmissionCause()) {
case ball::Transmission::PASSTHROUGH: {
d_stream << "Single Pass-through Message:" << endl;
} break;
case ball::Transmission::TRIGGER_ALL: {
d_stream << "Remotely "; // no 'break'; concatenated output
}
case ball::Transmission::TRIGGER: {
d_stream << "Triggered Publication Sequence: Message "
<< context.recordIndex() + 1 // Account for 0-based
// index.
<< " of " << context.sequenceLength()
<< ':' << endl;
} break;
default: {
d_stream << "***ERROR*** Unknown Message Cause:" << endl;
return;
} break;
}
d_stream << "\tTimestamp: " << record.fixedFields().timestamp()
<< endl;
d_stream << "\tProcess ID: " << record.fixedFields().processID()
<< endl;
d_stream << "\tThread ID: " << record.fixedFields().threadID()
<< endl;
}
Transmission::Cause transmissionCause() const
Return the transmission cause attribute of this context object.
Definition ball_context.h:501
int recordIndex() const
Return the record index attribute of this context object.
Definition ball_context.h:507
int sequenceLength() const
Return the sequence length attribute of this context object.
Definition ball_context.h:513
const bdlt::Datetime & timestamp() const
Return the timestamp attribute of this record attributes object.
Definition ball_recordattributes.h:635
bsls::Types::Uint64 threadID() const
Return the threadID attribute of this record attributes object.
Definition ball_recordattributes.h:617
int processID() const
Return the processID attribute of this record attributes object.
Definition ball_recordattributes.h:605
RecordAttributes & fixedFields()
Return the modifiable fixed fields of this log record.
Definition ball_record.h:396
Definition bdldfp_decimal.h:5188

We now want to use the my_OstreamObserver object and its publish method; we illustrate this use in the body of the otherwise-unrealistic function recordPublisher, which generates the relevant fields of four dummy records. The first record is published singly (i.e., as a "Pass-through" record). Note that we call the observer's publish method with a ball::Context object appropriately initialized for a "Pass-through". The last three records are published as a sequence of "Triggered" records. Note that, in the sequenced output, the publish method is called with a zero-based index attribute; in this example, the publish implementation will print a natural-number message count equal to index + 1:

void recordPublisher()
{
my_OstreamObserver myObserver(bsl::cout);
ball::UserFields emptyList;
fixed.setTimestamp(now);
fixed.setProcessID(100);
fixed.setThreadID(0);
myObserver.publish(ball::Record(fixed, emptyList),
ball::Context(ball::Transmission::PASSTHROUGH,
0,
1));
const int NUM_MESSAGES = 3;
for (int n = 0; n < NUM_MESSAGES; ++n) {
fixed.setTimestamp(now);
fixed.setProcessID(201 + n);
fixed.setThreadID(31 + n);
myObserver.publish(ball::Record(fixed, emptyList),
ball::Context(ball::Transmission::TRIGGER,
n,
NUM_MESSAGES));
}
}
Definition ball_recordattributes.h:274
void setProcessID(int processID)
Definition ball_recordattributes.h:562
void setTimestamp(const bdlt::Datetime &timestamp)
Definition ball_recordattributes.h:580
void setThreadID(bsls::Types::Uint64 threadID)
Definition ball_recordattributes.h:574
Definition ball_userfields.h:136
Definition bdlt_datetime.h:331
static Datetime convertFromTimeT(bsl::time_t time)
Definition bdlt_epochutil.h:383

recordPublisher, when invoked, prints the following to stdout:

Single Pass-through Message:
Timestamp: 15JAN2004_23:12:59.000
Process ID: 100
Thread ID: 0
Triggered Publication Sequence: Message 1 of 3:
Timestamp: 15JAN2004_23:12:59.000
Process ID: 201
Thread ID: 31
Triggered Publication Sequence: Message 2 of 3:
Timestamp: 15JAN2004_23:12:59.000
Process ID: 202
Thread ID: 32
Triggered Publication Sequence: Message 3 of 3:
Timestamp: 15JAN2004_23:12:59.000
Process ID: 203
Thread ID: 33