RM offers an enhanced mechanism for generating and reading log messages including backend hosts and managed devices.

Overview

Logs are objects, which contain useful information about the runtime behavior of a service or a bundle. In a log entry, bundle developers can put information concerning results from operations, exceptions, service references and other messages, but it is recommended to use it mainly for events and errors. Log levels indicate the type of these messages. They are also known as severity levels.

The RM Log Service extends the OSGi Log Service (org.osgi.service.log.LogService) adding options for creating log messages on the backend, which can be associated with the backend or with certain devices. The RM Log Service is published in the backend OSGi frameworks under the com.prosyst.mprm.backend.log.MPRMLogService interface. On managed devices, logs are generated with the OSGi Log Service which is a subject of the OSGi Service Platform Specification Release 4.

The RM Log Reader Service implements the OSGi Log Reader Service (org.osgi.service.log.LogReaderService). In a backend OSGi framework, the RM Log Reader Service is represented by the com.prosyst.mprm.admin.log.LogReader interface.

The RM Log Service and Log Reader Service are registered by the RM Backend Logs bundle (packages/system/log.jar).


Developers can use the lib/api/system-api.jar archive for development and compilation of applications using the RM log services.

Getting the Services

Log Service

The RM Log Service can be got and used by OSGi-compliant bundles running on a backend OSGi framework in the way defined by the OSGi Framework Specification.

Log Reader Service

There are two ways in which you can obtain and use the RM Log Reader Service:

  • From a remote access client (RAC) running remotely from the backend framework. The services are obtained remotely through the getService() method of the com.prosyst.mprm.rac.RemoteAccessClient class. The RAC class library is packed in the lib/rac/system-rac.jar JAR file. See the Remote Access to RM document for more information about using a remote access client.
  • Directly as a service in the context of a backend OSGi framework for applications created as OSGi-compliant bundles and running in the RM backend.

Using the RM Log Service

As it was said above, you can generate log messages on the backend with the RM Log Service (com.prosyst.mprm.backend.log.MPRMLogService).

Create log messages by using the service's log methods. If the message is associated with a specific device, then you should pass the ID of that device. If a message is related to the backend, you pass null as the deviceId log method parameter.

You can call the flush method to force storing persistently the available log information on the corresponding backend host.

The following listing contains an example, which writes a device-related log message each time when a device is added or removed.

Creating logs:

import com.prosyst.mprm.common.ManagementException;
import com.prosyst.mprm.backend.log.*;
import org.osgi.framework.*;
import com.prosyst.mprm.admin.devices.DeviceManager;
import com.prosyst.mprm.admin.devices.event.MPRMControlUnitListener;
import com.prosyst.mprm.admin.devices.event.ControlUnitEvent;
 
/** Example bundle which writes log messages each time a device is
* addded or removed.
*/
public class LogTester implements BundleActivator, MPRMControlUnitListener {
private MPRMLogService logService;
private ServiceReference logServRef;
 
private DeviceManager devManService;
private ServiceReference devManRef;
public void start(BundleContext bc) {
getLogService(bc);
getDeviceManagerService(bc);
}
public void stop(BundleContext bc) {
bc.ungetService(logServRef);
logServRef = null;
logService = null;
}
//Gets the RM Log Service
private void getLogService(BundleContext bc) {
logServRef = bc.getServiceReference(MPRMLogService.class.getName());
logService = (MPRMLogService) bc.getService(logServRef);
}
 
//Gets the DeviceManager service for adding a listener
//for device-related events.
private void getDeviceManagerService(BundleContext bc) {
devManRef = bc.getServiceReference(DeviceManager.class.getName());
if (devManRef != null) {
devManService = (DeviceManager) bc.getService(devManRef);
}
try {
devManService.registerControlUnitListener(null, this, null);
} catch (ManagementException exc) {
exc.printStackTrace();
}
}
 
// MPRMControlUnitListener method, which is called when there is a
// device-related event.
public void controlUnitEvent(ControlUnitEvent cue) {
System.out.println("Control Unit Event received: " + cue);
String devID = null;
String devType = cue.getDeviceType();
int eventType = cue.getEventType();
if (eventType == ControlUnitEvent.CONTROL_UNIT_ADDED) {
devID = cue.getDeviceId();
// Writes a log message saying that the device is added.
logService.log(MPRMLogService.LOG_INFO, devID, devType,
"*******device with ID " + devID + " is added******",
System.currentTimeMillis());
} else if (eventType == ControlUnitEvent.CONTROL_UNIT_REMOVED) {
devID = cue.getDeviceId();
// Writes a log message saying that the device is removed.
logService.log(MPRMLogService.LOG_INFO, devID, devType,
"*******Device with ID " + devID + " is removed******",
System.currentTimeMillis());
}
}
}


Using the RM Log Reader Service

The RM Log Reader Service (com.prosyst.mprm.admin.log.LogReader) adds an RM-specific methods to the OSGi Log Reader Service. The service provides log entries as com.prosyst.mprm.admin.log.LogEntry objects, which extend org.osgi.service.log.LogEntry adding methods for retrieving the ID of the host or the device the log is related to as well as the source bundle which has created the entry.

Reading Log Messages

The following methods of LogReader can be used for retrieving log messages:

  • To get all available logs including both backend-related and device-related, use the getLog method.

The fromTime and toTime parameters specify the time period for which we want to obtain log entries.

The level parameter indicates the least severe level of log messages (ERROR, WARNING, INFO or DEBUG constants of the OSGi Log Service). The getLog method returns messages with the specified level and messages with more severe levels. The least severe level is DEBUG and the most severe one - ERROR.

The source argument specifies the bundles from which log entries must come from. Each String element of the source argument is dedicated to a single source bundle and must be specified in the format {<bundle_symbolic_name>|<bundle name>}\<bundle_version>, e.g. "OSGi Device Manager\1.3.34".

The count argument limits the count of log entries to get from the RM Log Reader Service.

The getLog method returns an Enumeration of all logs satisfying the criteria set with the method's parameters.

  • To get backend-related logs, use the getSystemLog method. It has similar parameters as the getLog method, described above.
  • To get device-related logs, call the getDeviceLog method. Besides the level, fromTime and toTime, this method requires the ID and the type of the device to retrieve logs for.

Reading Device Log Files

You can use the getLogFileNames and getLogFile methods to access the requested log files of a given device.

Registering a Log Listener

To get notified of newly created messages, you can implement an org.osgi.service.log.LogListener and register it in the RM Log Reader Service with service's addLogListener method.

Log Reading Example

The following simple example creates a LogListener to receive and read newly logged messages.

Implementing a LogListener:

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
 
import org.osgi.service.log.LogListener;
import org.osgi.service.log.LogEntry;
 
/**
* Example bundle which registers as LogListener and prints every logged message
* on the console screen.
*/
public class LogListenerTest implements BundleActivator, LogListener {
 
private LogReaderTracker logTracker;
public void start(BundleContext bc) throws Exception {
logTracker = new LogReaderTracker(bc, this);
logTracker.open();
}
public void stop(BundleContext bc) throws Exception {
logTracker.close();
}
/**
* Invoked by LogReader service for every logged message.
*/
public void logged(LogEntry entry) {
System.out.println("Logged: " + entry);
 
com.prosyst.mprm.admin.log.LogEntry mprmLog =
(com.prosyst.mprm.admin.log.LogEntry)entry;
if (mprmLog.getDeviceId() != null) {
System.out.println("deviceId: " + mprmLog.getDeviceId());
}
}
}

The example uses the ServiceTracker utility to keep track of the Log Reader Service's registration and unregistration. It adds the above-created LogListener when the service becomes registered, and removes it when the service becomes unregistered.

Registering the LogListener in the RM Log Reader Service:

import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTracker;
import com.prosyst.mprm.admin.log.LogReader;
 
/**
* Utility class for accessing the LogReader service. It keeps track
* of the service's registration and unregistrations.
* It also adds the LogListenerTest as log service's listener when LogReader
* becomes available, and removes it when the service is becomes unregistered.
*/
public class LogReaderTracker extends ServiceTracker {
private LogListenerTest logListener;
private BundleContext bc;
LogReaderTracker(BundleContext _bc, LogListenerTest _logListener) {
super(_bc, LogReader.class.getName(), null);
logListener = _logListener;
bc = _bc;
}
/**
* This method is invoked by ServiceTracker when it gets the reference
* to the LogReader service. It adds the LogListenerTest object as log listener.
*/
public Object addingService(ServiceReference ref) {
LogReader service = (LogReader)bc.getService(ref);
service.addLogListener(logListener);
return service;
}
/**
* This method is invoked by ServiceTracker when the service is unregistering or the
* tracker object is closed. It removes the LogListenerTest object
* as log listener.
*/
public void removedService(ServiceReference ref, Object obj) {
((LogReader)obj).removeLogListener(logListener);
}
}