Skip Headers
Oracle® Communications Services Gatekeeper Platform Development Studio Developer's Guide
Release 5.0

Part Number E16619-02
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
View PDF

9 Annotations, EDRs, Alarms, and CDRs

The following section describe aspects and generation of EDRs, alarms, CDRs, and statistics:

About Aspects and Annotations

Aspects allow developers to manage cross-cutting concerns in their code in a straight forward and coherent way. Aspects in Oracle Communications Services Gatekeeper (pointcuts, advice, etc.) are written in the AspectJ 1.5.3 annotation style. There is already support for editing annotations in many modern IDEs, and aspects are simply set up as annotated classes.

How Aspects are Applied

All aspects are applied at build time by weaving the byte code of previously complied Java packages. Minimal reflection is used at runtime to make aspect based decisions.

Different aspect types are applicable to different Oracle Communications Services Gatekeeper modules. In general there are two categories of aspects:

Traffic aspects are subdivided into two categories:

Only statistics aspects are always applied because they are used to calculate usage costs. Traffic aspects are applied to North and South boundaries of a plug-in as well as to the internal processing of the plug-in.

Annotations are used to control the aspects that are not always applied for each plug-in. These annotations are defined as part of the functional areas that a given set of aspect implements. They allow the plug-in to communicate with the aspects as well as to customize their behavior.

Context Aspect

The Context aspect is woven at compile time, using PluginSouth as a marker.

While requests coming from the north interface have a valid context (with attributes like Service provider account ID, application Account ID, and so on) any events triggered by the network and entering a plug-in's south interface do not have a valid context.

The Context aspect solves this problem by rebuilding the context as soon as a south interface method is invoked: after this aspect is executed, a valid context will be available for any subsequent usages, such as the EDR aspect. All methods inside a class implementing the interface PluginSouth are woven by the Context aspect.

The Context aspect requires the following in order to correctly weave the south interface methods and be able to rebuild the context:

The following rules apply for methods in classes that implement PluginNorth:

The following rule applies for methods in classes that implement PluginSouth:

The ways of doing this are plug-in-specific, but normally a network triggered request is tied to an application instance in a store that is managed by the plug-in. The store used for context mapping may be a local cache or a cluster wide store, depending on whether responses are known to always arrive on the same plug-in instance, or if they can arrive at a plug-in on another server in the cluster.

Example:

  1. An application sends a request to the network and an ID for this request is either supplied by the network or generated by the plug-in. At this point the originator of the requests, the application instance, is known since the request originated from an application.

  2. The plug-in puts the application instance ID and the ID for the request into a store.

  3. At a later stage, when a response to the original requests arrives at the plug-in, the method resolveAppInstanceGroupId() is called by aspects.

  4. In this method, the plug-in must perform a lookup in the store of the application instance related to that request and return the application instance ID to the aspect.

  5. The aspect authenticates the application instance with the container and puts the application instance ID in the RequestContext.

  6. The method in the plug-in receives the request from the network and the RequestContext contains the application instance ID.

In the example below the method deliver(...) is a request from the underlying network. The destinationAddress is annotated to be available to the aspect that handles network-triggered requests associated with this request, represented by constant C.

NotificationHandler handles the store for notifications and supplies all necessary parameters to the store.

Example 9-1 Application initiated request

protected static final String C = "destinationAddress";
@Edr
  public void deliver(String data,
                      @ContextKey(EdrConstants.FIELD_DESTINATION_ADDRESS)
                      @MapperInfo(C) String destinationAddress,
                      @ContextKey(EdrConstants.FIELD_ORIGINATING_ADDRESS) String originatingAddress,
                      String nwTransactionId)
    throws Exception {

    notificationHandler.deliver(data, destinationAddress, originatingAddress, nwTransactionId);

  }

When a network triggered event occurs, the aspect calls resolveApplicationInstanceGroup(...) in PluginSouth and the plug-in looks up the application instance using any argument available in ContextMapperInfo that can help the plug-in to resolve this ID from ContextMapperInfo, using info.getArgument(C). The application instance ID is returned to the aspect and the execution flow continues in the plug-in, with a RequestContext that contains the application instance ID, session ID and so on.

Example 9-2 Rebuilding RequestContext

protected static final String C = "destinationAddress";
public String resolveAppInstanceGroupdId(ContextMapperInfo info) {

    String destinationAddress = (String) info.getArgument(C);
    NotificationData notificationData = null;
    try {
      notificationData = StoreHelper.getInstance().getNotificationData(destinationAddress);
    } catch (StorageException e) {
       return null;
    }

    if (notificationData == null) {
      return null;
    }

    return notificationData.getAppInstanceGroupId();
  }

Below are the steps you have to take to make your plug-in compliant with the Context aspect:

EDR Generation

EDRs are generated in the two following ways:

EDRs should be generated at the plug-in boundaries (north and south), using the @Edr annotation to ensure that the boundaries are covered. Additional Edrs can be added elsewhere in the plug-in if needed: for example for CDRs.

For extensions, the EDR ID should be in the range 500 000 to 999 999.

EDRs are generated automatically by an aspect in the following locations in the plug-in:

Table 9-1 Manual annotation for EDRs

Trigger When Modifiers restrictions What is woven

method

before executing

public method only

only in methods annotated with @Edr

method

after executing

public method only

only in methods annotated with @Edr

method-call

before calling

any method

only for method call to a class implementing the PluginNorthCallback interface (EJB callback)

method-call

after calling

any method

only for method call to a class implementing the PluginNorthCallback interface (EJB callback)

exception

after throwing

any method

any exception thrown except in methods annotated with @NoEdr


The following values are always available in an EDR when it is generated from an aspect:

Exception Scenarios

Exceptions are automatically woven by the aspect.

Some limitations apply:

  • The aspect will catch only exceptions that are thrown by a plug-in method.

  • The aspect will not catch an exception that is thrown by a library and caught by the plug-in.

  • If the same exception is re-thrown several times, the aspect will only trigger an EDR once, for the first instance of the exception.

Figure 9-1 illustrates typical scenarios when a library (or core service) throws an exception in the plug-in.

Figure 9-1 Exception scenarios

Surrounding text describes Figure 9-1 .

Scenario 1:

The plug-in method in Stage 2 simply catches the exception but does not re-throw it or throw another exception. Since it just consume the exception, the aspect will not trigger an EDR.

Scenario 2:

The plug-in method in Stage 2 lets the exception A propagate (or re-throws exception A).

In this case, the aspect triggers an EDR after the method in stage 2. Since the same exception A (the same exception instance object) is propagated (or re-thrown), only the first method triggers an EDR.

Scenario 3:

This scenario is almost identical to scenario 2 except that the method in stage 1 is not throwing the exception A but another exception, named B. In this case, because B is not the same instance as A, the aspect will trigger another EDR after the method in stage 1.

Adding Data to the RequestContext

In addition to the default values, an EDR also contains all the values put into the RequestContext using the putEdr() method.

Example 9-3 Example to add values to and EDR using RequestContex

...
RequestContext ctx = RequestContextManager.getCurrent();
// this value will be part of any EDRs generated in the current request
ctx.putEdr("address", "tel:1234"); 
// this value will NOT be part of any EDRs since ctx.put(...) is used
ctx.put("foo", "bar");
...

Note:

Common key names are defined in the class com.bea.wlcp.wlng.api.edr.EdrConstants.

Using translators

When a parameter is a more complex object, it is possible to specify a translator that will take care of extracting the relevant information from this parameter.

The annotation is @ContextTranslate.

For example, the following method declares:

  • The first (and only) parameter should be translated using the specified translator ACContextTranslator

  • The returned object should also be translated using the specified translator ACContextTranslator

Example 9-4 Using a translator

...
  @Edr
  public @ContextTranslate(ACContextTranslator.class) PlayTextMessageResponse playTextMessage(@ContextTranslate(ACContextTranslator.class) PlayTextMessage parameters) {
    ...
    return response;
  }
  ...

The Translator is a class implementing the ContextTranslator interface.

Example 9-5 Example of a Translator

public class ACContextTranslator implements ContextTranslator {
    public void translate(Object param, ContextInfo info) {
      if(param instanceof PlayTextMessage) {
        PlayTextMessage msg = (PlayTextMessage) param;
        info.put("address", msg.getAddress().toString());
      } else if(param instanceof PlayTextMessageResponse) {
        PlayTextMessageResponse response = (PlayTextMessageResponse) param;
        info.put("correlator", response.getResult());
      } ...
    }
  }

The ContextTranslator class specified in the @ContextTranslate annotation is automatically instantiated by the aspect when needed. It is however possible to explicitly register it using the ContextTranslatorManager.

Example 9-6 Example of registering a context translator

ContextTranslatorManager.register(ACContextTranslator.class.getName(), new ACContextTranslator());

Table 9-2 is a summary of annotations to use.

Table 9-2 Annotations

Name Type Description

@ContextKey

Annotation

Specifies that an argument must be put into the current RequestContext under the name provided in this annotation

@ContextTranslate

Annotation

Same as @ContextKey but for complex argument that need to be translated using a translator (implementing the ContextTranslator interface).

ContextTranslator

Interface

Interface used by static translators to translate complex object.


Trigger an EDR programmatically

Oracle Communications Services Gatekeeper triggers EDRs automatically in all plug-ins where aspects have been applied. It is also possible to trigger EDRs explicitly. In this case, you will have to manually create and trigger the EDR by following these steps:

  1. Create an EdrData object

  2. Trigger the EDR using the EdrService instance

Below is an example of triggering an EDR from inside a plug-in.

Example 9-7 Trigger an EDR programmatically

public class SamplePlugin {
   // Get the EdrDataHelper like a logger
   private static final EdrDataHelper helper = EdrDataHelper.getHelper(SamplePlugin.class);

   public void doSomething() {
      ...
      // Create a new EdrData using the EdrDataHelper class to allow 
      // Services Gatekeeper to automatically populate some fields
      EdrData data = helper.createData();
      // Since we are creating the EdrData manually, 
      // we have to provide the mandatory fields.
      // Note that the EdrDataHelper will provide most of them
      data.setValue(EdrConstants.FIELD_SOURCE, EdrConstants.VALUE_SOURCE_METHOD);
      data.setValue(EdrConstants.FIELD_METHOD_NAME, "doSomething");
      // Log the EDR
      EdrServiceFactory.getService().logEdr(data);
      ...
   }
}

EDR Content

Table 9-3 describes the content of an EDR. It shows which values are mandatory, who is responsible for providing these values, and other information.

Legends:

  • A: Automatically provided by Oracle Communications Services Gatekeeper

  • H: Provided if the EdrDataHelper createData API is used to create the EdrData (which is the recommended way)

  • M: Provided manually in the EdrData

  • X: Provided in the EDR descriptor.

  • C: Custom filter. Use the <attribute> element to specify a custom filter.

    Note:

    EDRs triggered by aspects will have all the mandatory fields provided by the aspect.

Table 9-3 EDR content

Name Description Filter tag name

EdrId

To get the ID, use getIdentifier() in EdrConfigDescriptor.

This value is provided in the EDR descriptor.

Provider INSIDE plug-in: X

Provider OUTSIDE plug-in: X

Mandatory: Yes

C

ServiceName

The name (or type) of the service.

Fields in EdrConstants: FIELD_SERVICE_NAME

Provider INSIDE plug-in: H

Provider OUTSIDE plug-in: M

Mandatory: Yes

C

ServerName

The name of the Oracle Communications Services Gatekeeper server.

Fields in EdrConstants: FIELD_SERVER_NAME

Provider INSIDE plug-in: H

Provider OUTSIDE plug-in: H

Mandatory: Yes

C

Timestamp

The time at which the EDR was triggered (in ms since midnight, January 1, 1970 UTC)

Fields in EdrConstants: FIELD_TIMESTAMP

Provider INSIDE plug-in: A

Provider OUTSIDE plug-in: A

Mandatory: Yes

C

ContainerTransactionId

The WebLogic Server transaction ID, if available.

Fields in EdrConstants: FIELD_CONTAINER_TRANSACTION_ID

Provider INSIDE plug-in: H

Provider OUTSIDE plug-in: H

Mandatory: No

C

Class

Name of the class that triggered the EDR.

Fields in EdrConstants: FIELD_CLASS_NAME

Provider INSIDE plug-in: H

Provider OUTSIDE plug-in: H

Mandatory: Yes

<class>

Method

Name of the method that triggered the EDR.

Provider INSIDE plug-in: M

Provider OUTSIDE plug-in: M

Mandatory: Yes

<name> inside <method> or <method> inside <exception>

Source

Indicates the type of source that triggered the EDR.

Fields in EdrConstants: FIELD_SOURCE

Values in EdrConstants: VALUE_SOURCE_METHOD, VALUE_SOURCE_EXCEPTION

Provider INSIDE plug-in: M

Provider OUTSIDE plug-in: M

Mandatory: Yes

<method> or <exception>

Direction

Direction of the request.

Fields in EdrConstants: FIELD_DIRECTION

Values in EdrConstants:VALUE_DIRECTION_SOUTH, VALUE_DIRECTION_NORTH

Provider INSIDE plug-in: M

Provider OUTSIDE plug-in: M

Mandatory: No

<direction>

Position

Position of the EDR relative to the method that triggered the EDR.

Fields in EdrConstants: FIELD_POSITION

Values in EdrConstants: VALUE_POSITION_BEFORE, VALUE_POSITION_AFTER

Provider INSIDE plug-in: M

Provider OUTSIDE plug-in: M

Mandatory: No

<position>

Interface

Interface where the EDR is triggered.

Fields in EdrConstants: FIELD_INTERFACE

Values in EdrConstants: VALUE_INTERFACE_NORTH, VALUE_INTERFACE_SOUTH, VALUE_INTERFACE_OTHER

Provider INSIDE plug-in: M

Provider OUTSIDE plug-in: M

Mandatory: No

<interface>

Exception

Name of the exception that triggered the EDR.

Fields in EdrConstants: FIELD_EXCEPTION_NAME

Provider INSIDE plug-in: M

Provider OUTSIDE plug-in: M

Mandatory: No

<name> inside <exception>

SessionId

Session ID.

Fields in EdrConstants: FIELD_SESSION_ID

Provider INSIDE plug-in: H

Provider OUTSIDE plug-in: M

Mandatory: No

C

ServiceProviderId

Service provider account ID.

Fields in EdrConstants: FIELD_SP_ACCOUNT_ID

Provider INSIDE plug-in: H

Provider OUTSIDE plug-in: M

Mandatory: No

C

ApplicationId

Application account ID.

Fields in EdrConstants: FIELD_APP_ACCOUNT_ID

Provider INSIDE plug-in: H

Provider OUTSIDE plug-in: M

Mandatory: No

C

AppInstanceGroupId

Application instance ID.

Fields in EdrConstants: FIELD_APP_INSTANCE_GROUP_ID

Provider INSIDE plug-in: H

Provider OUTSIDE plug-in: M

Mandatory: No.

C

OrigAddress

The originating address with scheme included (for example “tel:1234”).

Fields in EdrConstants: FIELD_ORIGINATING_ADDRESS

Provider INSIDE plug-in: M

Provider OUTSIDE plug-in: M

Mandatory: No

C

DestAddress

The destination address(es) with scheme included (For example “tel:1234”). See "Using send lists".

Fields in EdrConstants: FIELD_DESTINATION_ADDRESS

Provider INSIDE plug-in: M

Provider OUTSIDE plug-in: M

Mandatory: No

C

<custom>

Any additional information put into the current RequestContext using the putEdr() API will end up in the EDR.

Fields in EdrConstants: -

Provider INSIDE plug-in: -

Provider OUTSIDE plug-in: -

Mandatory: No

C


Using send lists

If more than one address needs to be stored in the DestAddress field, use the following pattern. Both patterns described below can be used.

Example 9-8 Pattern to store one single or multiple addresses in field destination directly on EdrData.

EdrData data = ...;
// If there is only one address
data.setValue(EdrConstants.FIELD_DESTINATION_ADDRESS, address);
// If there are multiple addresses
data.setValues(EdrConstants.FIELD_DESTINATION_ADDRESS, addresses);

If you are using the current RequestContext object, simply store a List of addresses. The EdrDataHelper will automatically take care of converting this to a List of Strings in the EdrData.

Example 9-9 Pattern to store one single or multiple addresses in field destination using RequestContext.

RequestContext ctx = RequestContextManager.getCurrent();
// If there is only one address
ctx.putEdr(EdrConstants.FIELD_DESTINATION_ADDRESS, address);
// If there are multiple addresses
URI[] addresses = ...;
ctx.putEdr(EdrConstants.FIELD_DESTINATION_ADDRESS, Arrays.asList(addresses));

RequestContext and EDR

Figure 9-2 shows how and where information for the EDR is added to the RequestContext and how it finally ends up in the additional info column of the alarm and CDR databases.

Figure 9-2 RequestContext and EDR

Surrounding text describes Figure 9-2 .

There are 3 ways of putting information in the RequestContext that will end up in the EDR (more precisely in the EdrData object):

  • Using the putEdr() API of the RequestContext

  • Using the @ContextKey or @ContextTranslate annotation. In the case of the @ContextTranslate annotation, the information that will end up in the RequestContext will be what is put into the ContextInfo object.

  • Any information put in the RequestContext parameter of the PluginSouth.prepareRequestContext() method.

When an EDR is created, the EdrDataHelper (which is the recommended way to create the EDR) will populate the EdrData with all the key/value pairs found in the RequestContext.

When the EdrService writes the alarm or CDR additional information content into the database, it will use all the EdrData key/value pairs EXCEPT a set of well-known keys that are either not relevant or already included in other columns of the database, see "Alarm content" and "CDR content".

Categorizing EDRs

Only one type of EDR exists: alarms and CDRs are subsets of this EDR type. In order to categorize the flow of EDRs as either pure EDRS, alarms or CDRs, the EDR service uses 3 descriptors:

These XML descriptors can be manipulated using the EDR Configuration Pane as described in Managing and Configuring EDRs, CDRs and Alarms in the System Administrator's Guide. File representations of these must be included in edrjmslistener.jar if you are using external EDR listeners.

The EDR descriptor

Each descriptor contains a list of EDR descriptors that define an EDR as a pure-EDR, as an alarm or as a CDR.

Table 9-4 EDR descriptors.

Descriptor Descriptor Description

EDR

<edr...>

Defines which EDRs are pure EDRs

Alarm

<alarm...>

Defines which EDRs are alarms

CDR

<cdr...>

Defines which EDRs are CDRs


The descriptor is composed of two parts:

  • The <filter> element: this is the filter

  • The <data> element: this part is used to attach additional data with the EDR if it is matched by the <filter> part

Table 9-5 describes the elements allowed in the <filter> part:

Table 9-5 Elements allowed in <filter> part of an EDR descriptor.

Source Filter Min occurs Max occurs Description

<method>

N/A

0

unbounded

Filter EDR triggered by a method

<method>

<name>

0

unbounded

Name of the method that triggered the EDR

<method>

<class>

0

unbounded

Name of the class that triggered the EDR

<method>

<direction>

0

2

Direction of the request

<method>

<interface>

0

3

Interface where the EDR has been triggered

<method>

<position>

0

2

Position relative to the method that triggered the EDR

<exception>

N/A

0

unbounded

Filter EDR triggered by an exception

<exception>

<name>

0

unbounded

Name of the exception that triggered the EDR

<exception>

<class>

0

unbounded

Name of the class where the exception was thrown

<exception>

<method>

0

unbounded

Name of the method where the exception was thrown

<exception>

<direction>

0

2

Direction of the request

<exception>

<interface>

0

3

Interface where the EDR has been triggered

<exception>

<position>

0

2

Position relative to the method that triggered the EDR

<attribute>

N/A

0

unbounded

Filter EDR by looking at custom attribute

<attribute>

<key>

1

1

Name of the key

<attribute>

<value>

1

1

Value


Table 9-5 describes the values allowed for each element of the <filter> part:

Table 9-6 Values allowed in each element of the <filter> part.

Source Filter Allowed values Comment

<method>

<name>

“returntype nameofmethod([args])”

Method name. The arguments can be omitted with the parenthesis. See "Special characters" below.

<method>

<class>

“fullnameofclass”

Fully qualified class name. See "Special characters" below.

<method>

<direction>

“south”, “north”

N/A

<method>

<interface>

“north”, “south”, “other”

N/A

<method>

<position>

“before”, “after”

N/A

<exception>

<name>

“fullnameofexceptionclass”

Fully qualified exception class name. See "Special characters" below.

<exception>

<class>

“fullnameofclass”

Fully qualified class name where the exception was triggered. See "Special characters" below.

<exception>

<method>

“returntype nameofmethod([args])”

Method name. The arguments can be omitted with the parenthesis See "Special characters" below.

<exception>

<direction>

“south”, “north”

N/A

<exception>

<interface>

“north”, “south”, “other”

N/A

<exception>

<position>

“before”, “after”

N/A

<attribute>

<key>

“astring”

N/A

<attribute>

<value>

“astring”

N/A


Special characters

The filter uses special characters to indicate more precisely how to match certain values.

Using * at the end of a method, class or exception name matches all names that match the string specified prior to the * (that is, what the string starts with).

Note:

The use of any of these characters disables the caching of the filter containing them. To avoid a performance hit, using the other way of matching is strongly encouraged.

Table 9-7 Example filters

To match on Use the filter

All sendInfoRes methods with one argument of type int.

<method>

<name>void sendInfoRes(int)</name>

...

</method>

All methods starting with sendInfoRes regardless of the arguments.

<method>

<name>void sendInfoRes</name>

...

</method>

All methods starting with void sendInfo.

<method>

<name>void sendInfo*</name>

...

</method>

All class names beginning with com.bea.wlcp.wlng.plugin

<method>

<class>com.bea.wlcp.wlng.plugin*</class>

...

</method>


Values provided

The exact value in these fields depends on who triggered the EDR. If the aspect triggered the EDR, then the name of the method (with return type and parameters) or the fully qualified name of the class/exception is indicated. If the EDR is manually triggered from the code, it is up to the implementer to decide what name to use. Here are some examples of fully qualified method/class names as specified by the aspect:

Example methods:

SendSmsResponse sendSms(SendSms)
void receivedMobileOriginatedSMS(NotificationInfo, boolean, SmsMessageState, String, SmsNotificationRemote)
TpAppMultiPartyCallBack reportNotification(TpMultiPartyCallIdentifier, TpCallLegIdentifier[], TpCallNotificationInfo, int)

Example Class:

com.bea.wlcp.wlng.plugin.sms.smpp.SMPPManagedPluginImpl

Boolean semantic of the filters

Figure 9-3 shows briefly how the filter works:

  • The EdrConfigSource elements are the following: <method>, <exception> or <attribute>. They are combined using OR.

  • The filter elements of each EdrConfigSource are combined using AND. However, if the same filter is available more than once (e.g. multiple class names), it is combined with OR.

Figure 9-3 Filter mechanism

Surrounding text describes Figure 9-3 .

Example filters

Example 1: filter

Example 9-10 categorizes EDRs as pure EDRs with an id of 1000 when the following conditions are met:

  • The class where the method triggered the EDR is com.bea.wlcp.wlng.plugin.AudioCallPlugin or any subclass of it.

  • AND the request is southbound (direction = south)

  • AND the interface where the EDR was trigger is north

  • AND the EDR has been triggered after the method has been executed (position = after)

Example 9-10 Example 1: filter

<edr id="1000" description="...">
    <filter>
      <method>
        <class>com.bea.wlcp.wlng.plugin.AudioCallPlugin</class>
        <direction>south</direction>
        <interface>north</interface>
        <position>after</position>
      </method>      
    </filter>
  </edr>

Example 2: Alarm filter

Example 9-11 categorizes EDRs as alarms when the following conditions are met:

  • The exception is the com.bea.wlcp.wlng.plugin.PluginException class or a subclass of it.

  • OR the name of the exception starts with org.csapi.*. Since “'*” is used, the matching will not be performed using the class hierarchy but only using a pure string matching.

The alarms descriptor has a <alarm-group> element that is used to group alarms by service/source: this group id and each individual alarm id is used to generate the OID of SNMP traps.

Example 9-11 Example 2: filter

<alarm-group id="104" name="parlayX" description="Parlay X alarms">>
<alarm id="1000" severity="minor" description="Parlay X exception">
    <filter>
      <exception>
        <name>com.bea.wlcp.wlng.plugin.PluginException</name>
        <name>org.csapi*</name>
      </exception>
    </filter>
  </alarm>
</alarm-group>

Example 3: Alarm filter

Example 9-12 categorizes EDRs as alarms when the following conditions are met:

  • The exception is the class com.bea.wlcp.wlng.plugin.PluginException or a subclass of it

  • OR the name of the exception starts with “org.csapi”. String matching in used.

  • AND the exception was triggered in a class whose name starts with com.bea.wlcp.wlng.plugin

  • AND the request is northbound (direction = north) when the exception was triggered

If the filter determines that the EDR is an alarm, the following attributes are available to the alarm listener. They are defined in the <data> part.

  • identifier = 123

  • source = wlng_nt1

Example 9-12 Example 3: filter

<alarm id="1000" severity="minor" description="Parlay X exception">
    <filter>
      <exception>
        <name>com.bea.wlcp.wlng.plugin.PluginException</name>
        <name>org.csapi*</name>
        <class>com.bea.wlcp.wlng.plugin*</class>
        <direction>north</direction>
      </exception>
    </filter>
    <data>
      <attribute key="identifier" value="123"/>
      <attribute key="source" value="wlng_nt1"/>
    </data>
  </alarm>

Example 4: filter

Example 9-13 (for example purposes only) categorizes EDRs as pure EDRs with the id 1002 when the following conditions are met:

  • The name of the method that triggered the EDR starts with “void play” AND the class is com.bea.wlcp.wlng.plugin.AudioCallPluginNorth or a subclass of it AND the EDR was triggered after executing this method.

  • OR the name of the method that triggered the EDR is “String getMessageStatus” AND the class is 'com.bea.wlcp.wlng.plugin.AudioCallPluginNorth' or a subclass of it AND the EDR was triggered before executing this method.

  • OR the name of the exception that triggered the EDR starts with com.bea.wlcp.wlng.bar AND the exception was triggered in a plug-in north interface

  • OR the name of the exception that triggered the EDR starts with com.bea.wlcp.wlng.plugin.exceptionA AND the exception was triggered in a class whose name starts with com.bea.wlcp.wlng.plugin.classD AND the exception was triggered in a method whose name starts with void com.bea.wlcp.wlng.plugin.methodA AND the exception was triggered in a plugin north interface

  • OR the EDR contains an attribute with key attribute_a and value value_a

  • OR the EDR contains an attribute with key attribute_b and value value_b

Example 9-13 Example 4: filter

<edr id="1002">
    <filter>
      <method>
        <name>void play*</name>
        <class>com.bea.wlcp.wlng.plugin.AudioCallPluginNorth</class>
        <position>after</position>
      </method>
      <method>
        <name>String getMessageStatus</name>
        <class>com.bea.wlcp.wlng.plugin.AudioCallPluginNorth</class>
        <position>before</position>
      </method>
      <exception>
        <name>com.bea.wlcp.wlng.bar*</name>
        <interface>north</interface>
      </exception>
      <exception>
        <name>com.bea.wlcp.wlng.plugin.exceptionA</name>
        <class>com.bea.wlcp.wlng.plugin.classD</class>
        <method>void com.bea.wlcp.wlng.plugin.methodA</method>
        <interface>north</interface>
      </exception>
      <attribute key="attribute_a" value="value_a"/>
      <attribute key="attribute_b" value="value_b"/>
    </filter>
  </edr>

Example 5: filter with corresponding code for manually triggering a matching EDR

Example 9-14 shows a manually triggered EDR with its corresponding filter. The EDR is triggered using these lines.

Example 9-14 Example 5: Trigger the EDR

// Declare the EdrDataHelper for each class 
  private static final EdrDataHelper helper = EdrDataHelper.getHelper(MyClass.class);

  public void myMethodName() {
    ...
    // Create a new EdrData. Use the EdrDataHelper class to allow Services Gatekeeper to automatically populate some fields
    EdrData data = helper.createData();
        
    // Because we are creating the EdrData manually, we have to provide the mandatory fields 
    data.setValue(EdrConstants.FIELD_SOURCE, EdrConstants.VALUE_SOURCE_METHOD);
    data.setValue(EdrConstants.FIELD_METHOD_NAME, "myMethodName");
    data.setValue("myKey", "myValue");
  
    // Log the EDR
    EdrServiceFactory.getService().logEdr(data);
    ...
  }

This EDR can be filtered using Example 9-15 (note the various ways of identifying this EDR):

Example 9-15 Example: Filter 5

<edr id="1003">
    <filter>
      <!-- Match both method name and class name -->
      <method>
        <name>myMethodName</name>
        <class>com.bea.wlcp.wlng.myClassName</class>
      </method>
      <!-- OR match only the method name (looser than matching also the class name) -->
      <method>
        <name>myMethodName</name>
      </method>
      <!-- OR match only the classname (looser than matching also the method name) -->
      <method>
        <class>com.bea.wlcp.wlng.myClassName</class>
      </method>
      <!-- OR match only the custom attribute -->
      <attribute key="myKey" value="myValue"/>
    </filter>
  </edr>

Checklist for EDR generation

Below is a list of steps to take to make your plug-in able to use aspect EDRs:

Frequently Asked Questions about EDRs and EDR filters

Question: Is it possible to specify both exception and method name in the filter section?

Example 9-16 Example: method name and exception in a filter.

<filter>
      <method>
        <name>internalSendSms</name>
      </method>
      <exception>
        <name>com.bea.wlcp.wlng.plugin.sms.smpp.TooManyAddressesException</name>
      </exception>
    </filter>

Answer

Yes, make sure that the <method> element is before the <exception> element. Otherwise the XSD will complain.

Q: Is it possible to specify multiple method names?

Answer

Yes.

Q: In some places I have methods re-throwing an exception. Is it possible to have only one of the methods generate the EDR and map that edr to an alarm?

Re-throwing an exception

myMethodA()throws MyException{
  myMethodB();
}

myMethodB()throws MyException{
  myMethodC();
}

myMethodC()throws MyException{
  ...
  //on error
 throw new MyException(“Exception text..”);
}

Answer

In this case, only the first exception will be caught by aspects. Or more precisely, they will all be caught by aspects but will only trigger an EDR for the first one, but not for the re-thrown ones (if they are the same, of course). So you don't need to use the @NoEdr annotation for myMethodA and myMethodB.

Q: Will aspects detect the following exception?

Example exception

try{
      throw new ReceiverConnectionFailureException(message);
    }catch(ReceiverConnectionFailureException connfail){
      //EDR-ALARM-MAPPING
    }

Answer

This exception will not be detected by aspects. If you need to generate an EDR you will have to either manually create an EDR or call a method throwing an exception.

Q: Will EDRs for exceptions also work for private methods?

Answer

Yes, EDRs can work for any method.

Q: Will exceptions be disabled with the @NoEdr annotation?

Answer

Yes, with the @NoEdr annotation you will not get any EDRs, not even for exceptions.

Q: How can data from the current context be included in an alarm?

For example, can an alarm be generated in a request with more than 12 destination addresses? How can information about how many addresses were included in the request be added to the alarm

It is possible to specify some info in the alarm descriptor with something like

<data>
      <attribute key="source" value="thesource"/>
</data>

Can something be put in the RequestContext using the putEdr method and then get it into the alarm in some way?

Answer

Yes, add custom information by putting this information into the current RequestContext, as show below.

RequestContext ctx = RequestContextManager.getCurrent();
ctx.putEdr("address", "tel:1234"); 

This value is part of any EDRs generated in the current request.

The information will be available in the database in the additional_info column. Make sure you are putting in only relevant information.

Q: Is it possible to specify classname in the filtering section?

Answer

Yes, use the <class> element inside <method> or <exception> in the filter.

<filter>
      <exception>
        <class>com.y.y.z.MyClass</class>
        <name>com.x.y.z.MyException</name>
      </exception>
</filter>

Alarm generation

An alarm is a subset of an EDR. To generate an alarm, generate an EDR, either using one generated in aspects or programmatically, and define the ID and the descriptor of the alarm in the alarm descriptor.

The alarm ID, severity, description and other kind of attributes are defined in the alarm descriptor, see "The EDR descriptor". For extensions, the alarm ID should be in the 500 000 to 999 999 range.

Note:

The alarm filter that provides the first match in the alarm descriptor is used for triggering the alarm.

There are two ways to trigger an alarm:

Trigger an alarm programmatically

Trigger an EDR as described in "EDR Content". Then specify in the alarm descriptor the corresponding alarms.

Example 9-17 Example code to trigger an alarm

private static final EdrDataHelper helper = EdrDataHelper.getHelper(MyClass.class);
...
EdrData data = helper.createData();
data.setValue(EdrConstants.FIELD_SOURCE, EdrConstants.VALUE_SOURCE_METHOD);
data.setValue(EdrConstants.FIELD_METHOD_NAME, "com.bea.wlcp.wlng.myMethod");
data.setValue("myAdditionalInformation", ...);
EdrServiceFactory.getService().logEdr(data);
...

The corresponding entry in the alarm descriptor that matches this EDR is shown below.

Example 9-18 Alarm descriptor

<alarm id="2006"
         severity="major"
         description="Sample alarm">
    <filter>
      <method>
        <name>com.bea.wlcp.wlng.myMethod</name>
        <class>com.bea.wlcp.wlng.myClass</class>
      </method>
    </filter>
  </alarm>

Alarm content

Table 9-8 shows a list of the information provided in alarms.

Table 9-8 Alarm information for alarm listeners, also stored in DB

Field Comment

alarm_id

Unique ID for the alarm.

Automatically provided by the EdrService.

source

Service name emitting the alarm.

Automatically provided by the EdrService.

timestamp

Timestamp in milliseconds since midnight, January 1, 1970 UTC.

Automatically provided by the EdrService.

severity

Severity level.

Defined in the alarm. descriptor.

identifier

The alarm identifier.

Defined in the alarm descriptor.

The column in the database will always contain the identifier defined in the alarm descriptor.

alarm_info

The alarm information or description.

Defined in the alarm descriptor.

additional_info

Automatically provided by the EdrService.

Not valid for backwards compatible alarm listeners.

Each entry is formatted as:

key=value\n

Similar to the Java properties file.

All the custom key/value pairs found in the EdrData except these are present (EdrConstants if not specified):

  • FIELD_TIMESTAMP

  • FIELD_SERVICE_NAME

  • FIELD_CLASS_NAME

  • FIELD_METHOD_NAME

  • FIELD_SOURCE

  • FIELD_DIRECTION

  • FIELD_POSITION

  • FIELD_INTERFACE

  • FIELD_EXCEPTION_NAME

  • FIELD_ORIGINATING_ADDRESS

  • FIELD_DESTINATION_ADDRESS

  • FIELD_CONTAINER_TRANSACTION_ID

  • FIELD_CORRELATOR

  • FIELD_SESSION_ID

  • FIELD_SERVER_NAME

  • ExternalInvocatorFactory.SERVICE_CORRELATION_ID

  • FIELD_BC_EDR_ID

  • FIELD_BC_EDR_ID_3

  • FIELD_BC_ALARM_IDENTIFIER

  • FIELD_BC_ALARM_INFO


CDR generation

A CDR is a subset of an EDR. To generate a CDR, generate an EDR and define the ID of the EDR in the CDR descriptor.

Triggering a CDR

There are two ways to trigger a CDR:

  • Use an existing EDR that is generated in the plug-in and add its description to the CDR descriptor.

  • Programmatically trigger an EDR and add its description to the CDR descriptor.

Trigger a CDR programmatically

If none of the existing EDRs is appropriate for a CDR, you can programmatically trigger an EDR that will become a CDR. See the section, "Trigger an EDR programmatically" for information on how to create and trigger an EDR. Specify in the CDR descriptor the description necessary for this EDR to be considered a CDR.

Example 9-19 Example, triggering a CDR

private static final EdrDataHelper helper = EdrDataHelper.getHelper(MyClass.class);
...
EdrData data = helper .createData();
data.setValue(EdrConstants.FIELD_SOURCE, EdrConstants.VALUE_SOURCE_METHOD);
data.setValue(EdrConstants.FIELD_METHOD_NAME, "com.bea.wlcp.wlng.myEndOfRequestMethod");
// Fill the required fields for a CDR
data.setValue(EdrConstants.FIELD_CDR_START_OF_USAGE, ...);
...
EdrServiceFactory.getService().logEdr(data);
...

The description, in the CDR descriptor, that matches this EDR is shown in Example 9-20.

Example 9-20 Filter to match the EDR

<cdr>
    <filter>
      <method>
        <name>com.bea.wlcp.wlng.myEndOfRequestMethod</name>
        <class>com.bea.wlcp.wlng.myClass</class>
      </method>
    </filter>
</cdr>

CDR content

In addition to the EDR fields, there are specific fields used only for CDRs. They are listed in Table 9-5.

Table 9-9 Fields in EdrConstants specific for CDRs.

Field in EdrConstants Comment

FIELD_CDR_SESSION_ID

Session ID

FIELD_CDR_START_OF_USAGE

Start Time

FIELD_CDR_CONNECT_TIME

Connect Time

FIELD_CDR_END_OF_USAGE

End Time

FIELD_CDR_DURATION_OF_USAGE

Duration

FIELD_CDR_AMOUNT_OF_USAGE

Amount

FIELD_CDR_ORIGINATING_PARTY

Originating Party

FIELD_CDR_DESTINATION_PARTY

Same pattern applies as for send lists, see "Using send lists".

FIELD_CDR_CHARGING_INFO

Charging Information


The structure of the CDR content is aligned toward the 3GPP Charging Applications specifications. As a result the database schema has been changed to accommodate these ends and to facilitate future extensions.

Legends:

  • NU: Not used

  • NC: New column in DB

  • RC: Renamed column in DB

Table 9-10 Content in database

Field Comment DB

transaction_id

Unique id for the CDR.

Provided automatically by the EDR service.

x

service_name

name of the service

Provided automatically by the EDR service.

x

service_provider

the service provider account ID

Provided automatically by the EDR service.

x

application_id

the application account ID (was user_id in 2.2)

RC

application_instance_grp_id

the application instance ID.

NC

container_transaction_id

id of the current user transaction

Provided automatically by the EDR service.

NC

server_name

name of the server that generated the CDR.

Provided automatically by the EDR service.

NC

timestamp

in ms since midnight, January 1, 1970 UTC

NC

service_correlation_id

Service Correlation ID.

Provided automatically by the EDR service.

NC

charging_session_id

Id that correlates requests that belong to one charging session as defined by the plug-in. Was 'session_id' in 2.2.

Plug-in specific. Plug-in needs to put the value into the RequestContext of the request that will trigger the CDR.

x

start_of_usage

The date and time the service capability module started to use services in the network (in ms since midnight, January 1, 1970 UTC)

Plug-in specific. Plug-in needs to put the value into the RequestContext of the request that will trigger the CDR.

x

connect_time

The date and time the destination party responded (in ms since midnight, January 1, 1970 UTC). Used for call control only.

Plug-in specific. Plug-in needs to put the value into the RequestContext of the request that will trigger the CDR.

x

end_of_usage

The date and time the service capability module stopped using services in the network (in ms since midnight, January 1, 1970 UTC).

Plug-in specific. Plug-in needs to put the value into the RequestContext of the request that will trigger the CDR

x

duration_of_usage

The total time the service capability module used the network services (in ms)

Plug-in specific. Plug-in needs to put the value into the RequestContext of the request that will trigger the CDR

x

amount_of_usage

Plug-in specific. Plug-in needs to put the value into the RequestContext of the request that will trigger the CDR.

x

originating_party

The originating party address with scheme included (e.g. “tel:1234”)

Plug-in specific. Plug-in needs to put the value into the RequestContext of the request that will trigger the CDR.

x

destination_party

the originating party address with scheme included (e.g. “tel:1234”). Additional addresses are stored in the additional_info field.

x

charging_info

The charging service code from the application.

Plug-in specific. Plug-in needs to put the value into the RequestContext of the request that will trigger the CDR.

x

additional_info

Additional information provided by the plug-in

x

revenue_share_percentage

Not used.

NU

party_to_charge

Not used.

NU

slee_instance

Not used.

NU

network_transaction_id

Not used.

NU

network_plugin_id

Not used.

NU

transaction_part_number

Not used.

NU

completion_status

Not used.

NU


Additional_info column

The EDR populates the additional_info column of the DB with all the custom key/value pairs found in the EdrData except the ones listed below.

Excluded keys (EdrConstants if not specified):

  • FIELD_SERVICE_NAME

  • FIELD_APP_INSTANCE_GROUP_ID

  • FIELD_SP_ACCOUNT_ID

  • FIELD_CONTAINER_TRANSACTION_ID

  • FIELD_SERVER_NAME

  • FIELD_TIMESTAMP

  • ExternalInvocatorFactory.SERVICE_CORRELATION_ID

  • FIELD_CDR_SESSION_ID

  • FIELD_CDR_START_OF_USAGE

  • FIELD_CDR_CONNECT_TIME

  • FIELD_CDR_END_OF_USAGE

  • FIELD_CDR_DURATION_OF_USAGE

  • FIELD_CDR_AMOUNT_OF_USAGE

  • FIELD_CDR_ORIGINATING_PARTY

  • FIELD_CDR_DESTINATION_PARTY

  • FIELD_CDR_CHARGING_INFO

  • FIELD_CLASS_NAME

  • FIELD_METHOD_NAME

  • FIELD_SOURCE

  • FIELD_DIRECTION

  • FIELD_POSITION

  • FIELD_INTERFACE

  • FIELD_EXCEPTION_NAME

  • FIELD_ORIGINATING_ADDRESS

  • FIELD_DESTINATION_ADDRESS

  • FIELD_CORRELATOR

  • FIELD_APP_ACCOUNT_ID

  • FIELD_SESSION_ID

  • FIELD_BC_EDR_ID

  • FIELD_BC_EDR_ID_3

  • FIELD_BC_ALARM_IDENTIFIER

  • FIELD_BC_ALARM_INFO

Two keys not present in the EdrData are added to additional_info.

Table 9-11 Keys not present in EdrData, but added in additional_info

Key Description

destinationParty

If a send list is specified as the destination party, the first address will be written in the destination_party field of the DB and the remainder of the list will be written under this key name

oldInfo

Any backwards compatible additional info is available


The format of the additional_info field is formatted as:

key=value\n

similar to the Java properties file.

Out-of-the box (OOTB) CDR support

It is difficult to come up with a CDR generation scheme that fulfills the requirements of all customers. Oracle Communications Services Gatekeeper generates a default set of CDRs which can be customized by re-configuring the CDR descriptor.

The guiding principle for deciding when to generate CDRs is:

  • Generate a CDR when you are 100% sure that you have completely handled the service request

In other words, after the last method, in a potential sequence of method calls, returns.

For network-triggered requests this means that you should a trigger a CDR at the south interface after the method has returned back to the network. For application-triggered requests generate a CDR at the north interface after the method has returned to the Network Tier SLSB.