VisiTelcoLog Guide : Logging for event aware applications

Logging for event aware applications
This chapter discuses how an event or notification service-based application (or any event aware application in general) can use VisiTelcoLog Service to log events. VisiTelcoLog Service is basically an event logger. Log, in this context, is an event channel that propagates events apart from logging the events to a persistent store.
There are four kinds of event-based log objects that an event-aware application can use:
The following table describes the VisiTelcoLog Service module and interface names and the features available for event and notification service-based applications.
In this chapter, the following topics will be explained:
Using log factories to obtain event based log objects.
Logging events on event based log objects.
Filtering events to be logged.
Using log factories
For an event aware application that wishes to log events, an event-based log is first bootstrapped using the log's factory. For example, a notification service-based application first resolves to NotifyLogFactory using the object name NotifyLogService, and then obtains a log of type NotifyLog. For other types of event-based applications, see the table above. This section explains the steps to be taken to obtain reference to an event-based log object.
The example code below first bootstraps to NotifyLogFactory using the object name NotifyLogService. It then attempts to find a NotifyLog log with ID equal to 100 from the factory. If it does not find NotifyLog it attempts to create one. The maximum size specified is 0 (zero). This means that no predefined limit is used; however, a predefined limit is recommended.
C++ example
The example code is located in the <install_dir>/examples/vbe/telcolog/primitive_cpp directory.
// get service reference
CORBA::Object_var service =
orb->resolve_initial_references("NotifyLogService");

DsNotifyLogAdmin::NotifyLogFactory_var factory =
DsNotifyLogAdmin::NotifyLogFactory::_narrow(service);

// find log with id 100
DsLogAdmin::LogId id = 100;
DsLogAdmin::Log_var log = factory->find_log(id);

// if log not created, create log
if( log.in() == NULL )
{
CORBA::ULongLong max_size = 4 * 1024 * 1024;
DsLogAdmin::CapacityAlarmThresholdList thresholds;
CosNotification::QoSProperties initial_qos;
CosNotification::AdminProperties initial_admin;

log = factory->create_with_id(id, DsLogAdmin::wrap,
max_size, thresholds, initial_qos, initial_admin);
}

DsNotifyLogAdmin::NotifyLog_var notify_log=
DsNotifyLogAdmin::NotifyLog::_narrow(log.in());
Java example
Example code is located in the <install_dir>/examples/vbe/telcolog/primitive_java directory.
// get service reference
org.omg.CORBA.Object service =
orb.resolve_initial_references("NotifyLogService");

org.omg.DsNotifyLogAdmin.NotifyLogFactory factory =
org.omg.DsNotifyLogAdmin.NotifyLogFactoryHelper.narrow(
service);

// find log with id 100
int id = 100;
org.omg.DsLogAdmin.Log log = factory.find_log(id);

// if log not created, create log
if( log == null )
{
long max_size = 4 * 1024 * 1024;
log = factory.create_with_id(id,
org.omg.DsLogAdmin.wrap.value, max_size, new short[0],
new org.omg.CosNotification.Property[0],
new org.omg.CosNotification.Property[0]);
}

org.omg.DsNotifyLogAdmin.NotifyLog notify_log =
org.omg.DsNotifyLogAdmin.NotifyLogHelper.narrow(log);
Logging events
Once the reference to the event-based log object is resolved, an event propagation (or forwarding) operation such as push or pull is used to propagate events. Since this channel object also has the characteristics of a log, it logs all the events that are propagated through it. Filters can also be attached to the log. See “Filtering events” for further details on how to selectively log events.
Furthermore, notification-based applications can use all the notification service features such as QoS framework, Event Filters, and others.
For further details on developing Notification Service supplier applications, see the Developing supplier and consumer applications section in the VisiBroker VisiNotify Guide.
VisiTelcoLog Service optimizes the event logging at the GIOP level.
On a log full condition, if the log full action is set to wrap, then the oldest events are over-written. If the log full action is set to halt, and if the log record expire time is specified, then all the expired events are over-written. Otherwise the following exceptions are thrown:
Insufficient space: If the log space is not sufficient for logging the event then a NO_RESOURCE system exception with LOGFULL minor code (1001) is thrown.
Off-duty log: If the log is off-duty then a NO_RESOURCE system exception with minor code LOGOFFDUTY (1000) is thrown.
Locked log: If the log is locked then a NO_PERMISSION system exception with minor code LOGLOCKED (1003) is thrown.
Disabled log: If the log is disabled, then TRANSIENT system exception with minor code equal to LOGDISABLED (1002) is thrown.
Note that if the supplier is using event batching the exceptions will not reach the supplier. See the “VisiBroker Event Buffering/Batch” section in the VisiBroker VisiNotify Guide for further details on event batching.
Also note that for the connected pull suppliers, the channel pulls the events and then logs those events. On a log full condition, the channel continually attempts to log until log space is available. There is no way the connected supplier application can know about this condition. Using the vbroker.dslog.waitForLogAvailable property a wait period can be specified for this loop. By default it is 20 seconds.
The following code sample shows a structured supplier logging TMN QoS Alarm event. The supplier application first obtains the default supplier admin from the log (as the log is also a channel in itself), and then after obtaining structured proxy push consumer, connects to it. It then creates a TMN QoS Alarm event and pushes the event through the log. When the event is pushed in the log, the log stores the event and then forwards the event based on the log's forwarding state.
C++ example
Example code is located in the <install_dir>/examples/vbe/telcolog/primitive_cpp directory.
// get default supplier admin object from the log
CosNotifyChannelAdmin::SupplierAdmin_var admin =
notify_log->default_supplier_admin();

CosNotifyChannelAdmin::ProxyID proxy_id;

// create a proxy consumer on the log
CosNotifyChannelAdmin::ProxyConsumer_var proxy =
admin->obtain_notification_push_consumer(
CosNotifyChannelAdmin::STRUCTURED_EVENT, proxy_id);

CosNotifyChannelAdmin::StructuredProxyPushConsumer_var
Consumer = CosNotifyChannelAdmin::
StructuredProxyPushConsumer::_narrow(proxy);

// connect to the proxy consumer
consumer->connect_structured_push_supplier(NULL);

// fill a structured event with TMN QoS Alarm event
TMN::Event event;
CosNotification::StructuredEvent structured;
TMN::QoSAlarmInfo qosalrm_info;
misc::forge_qosAlrmInfo(qosalrm_info);
event.name = (const char*) " TMN::Events::qosAlarm";
event.info <<= qosalrm_info;
misc::gathering(event, structured);

// push the structured event into log
consumer->push_structured_event(structured);
Java example
Example code is located in the <install_dir>/examples/vbe/telcolog/primitive_java directory.
// get default supplier admin object from the log
org.omg.CosNotifyChannelAdmin.SupplierAdmin admin
= notify_log.default_supplier_admin();

org.omg.CORBA.IntHolder proxy_id =
new org.omg.CORBA.IntHolder();

// create a proxy consumer on the log
org.omg.CosNotifyChannelAdmin.ProxyConsumer proxy =
admin.obtain_notification_push_consumer(
org.omg.CosNotifyChannelAdmin.ClientType.STRUCTURED_EVENT,
proxy_id);

org.omg.CosNotifyChannelAdmin.StructuredProxyPushConsumer
consumer =
org.omg.CosNotifyChannelAdmin.StructuredProxyPushConsumerHelper.narrow(
proxy);

// connect to the proxy consumer
consumer.connect_structured_push_supplier(null);

// fill a structured event with TMN QoS Alarm event
TMN.Event event = new TMN.Event();
org.omg.CosNotification.StructuredEvent structured =
new org.omg.CosNotification.StructuredEvent();
TMN.QoSAlarmInfo qosalrm_info = new TMN.QoSAlarmInfo();
event.header = new TMN.EventHeader();
event.info = orb.create_any();
Util.forge_event_header(event.header);
Util.forge_qosAlrmInfo(qosalrm_info);
event.name = "TMN::Events::qosAlarm";
TMN.QoSAlarmInfoHelper.insert(event.info,qosalrm_info);
Util.gathering(event, structured);

// push the structured event into log
consumer.push_structured_event(structured);
Forwarding logged events
The events that get pushed into a log or pulled by the log are forwarded to any down-stream consumers after the events are logged. Any consumer application can start consuming events that are propagated. See the Developing supplier and consumer applications section in the VisiBroker VisiNotify Guide for information on writing consumer applications.
By setting its forwarding state to off, the log object can be configured so that it does not forward logged events. The following code snippet shows how an application can disable forwarding on a NotifyLog object and check the current forwarding state of the log.
All the features of an event service and a notification service can be used for event propagation such as attaching filters, QoS, etc.
C++
notify_log->set_forwarding_state(DsLogAdmin::off);

DsLogAdmin::ForwardingState current_state =
notify_log->get_forwarding_state();
Java
notify_log.set_forwarding_state(
org.omg.DsLogAdmin.ForwardingState.off);

org.omg.DsLogAdmin::ForwardingState current_state =
notify_log.get_forwarding_state();
Filtering events
A filter set for a NotifyLog or a TypedNotifyLog can also filter events being logged to the log. The log uses the filter object defined by the notification service, CosNotifyFilter::Filter. See Setting the Quality of Service and Filters in the VisiBroker VisiNotify Guide for information about how to create a filter and how to write constraints.
Note that only one filter object can be associated with a log. By default, no filter objects are associated with the log and all events are logged. Also, whenever a set_filter() method is called the log will generate an AttributeValueChange event.
The following example shows how to create a filter, set a filter on the log, and get a filter from the log.
C++
// MAKE USE OF FILTERS
// STEP 1) Get default filter factory
CosNotifyFilter::FilterFactory_var ffact =
log->default_filter_factory();

// STEP 2) Create filter
CosNotifyFilter::Filter_var filter1;
filter1 = ffact->create_filter("EXTENDED_TCL");

// STEP 3) Create constraint
CosNotifyFilter::ConstraintExpSeq constr_seq1;
constr_seq1.length(1);
constr_seq1[0].constraint_expr = CORBA::string_dup(
"$type_name == 'TMN::Events::qosAlarm'"
);

// STEP 4) Add constraint to filter
filter1->add_constraints( constr_seq1 );

// STEP 5) Set filter on the log
log->set_filter( filter1 );

// STEP 6) Get the filter associated with the log
CosNotifyFilter::Filter_var filter2;
Filter2 = log->get_filter();
Java
//Make Use of Filters
//[1] Get a filter factory
org.omg.CosNotifyFilter.FilterFactory ffact =
channel.default_filter_factory();

//[2] Create a filter
org.omg.CosNotifyFilter.Filter filter = null;
filter = ffact.create_filter("EXTENDED_TCL");

//[3] Create a constraint
org.omg.CosNotifyFilter.ConstraintExp [] constraints =
new org.omg.CosNotifyFilter.ConstraintExp[1];
constraints [0] =
new org.omg.CosNotifyFilter.ConstraintExp();
constraints [0].constraint_expr =
new String ("$type_name == 'TMN::Events::qosAlarm'");

//[4] Add constraint to filter
org.omg.CosNotifyFilter.ConstraintInfo[] info = null;
info = filter.add_constraints(constraints);

//[5] Set filter on the log
log.set_filter (filter);

//[6] Get the filter associated with the log
org.omg.CosNotifyFilter.Filter filter2 = null;
filter2 = log.get_filter();