This guide provides information about Rhino Service Assurance Server (SAS) API — a Rhino API that enables you to send data from Rhino applications to Metaswitch SAS for diagnosing issues or analyzing data. It explains relevant SAS and Rhino SAS API concepts, describes the Rhino SAS API application development process, and provides instructions on implementing SAS tracing with the API in your code.
This guide assumes that you are a Rhino application developer who:
-
Is familiar with Rhino Telephony Application Server (TAS).
-
Is familiar with the Java programming language.
-
Is familiar with Rhino application development.
-
Has basic knowledge about Metaswitch SAS.
Notices
Copyright © 2024 Microsoft. All rights reserved
This manual is issued on a controlled basis to a specific person on the understanding that no part of the Metaswitch Networks product code or documentation (including this manual) will be copied or distributed without prior agreement in writing from Metaswitch Networks.
Metaswitch Networks reserves the right to, without notice, modify or revise all or part of this document and/or change product features or specifications and shall not be responsible for any loss, cost, or damage, including consequential damage, caused by reliance on these materials.
Metaswitch and the Metaswitch logo are trademarks of Metaswitch Networks. Other brands and products referenced herein are the trademarks or registered trademarks of their respective holders.
Introduction
This section gives an overview of Rhino SAS API, describes the conventions used in the guide, and lists the documents from which you can get more information related to Rhino SAS API.
In addition, it provides the contact information that you can use if you encounter any technical issues while developing Rhino applications with SAS tracing support.
Rhino SAS API overview
Metaswitch Service Assurance Server (SAS) is a platform for analyzing call processing data and diagnosing call processing issues in both fixed line and mobile networks. It offers a web-based user interface (UI) in which the detailed call processing information it received from other network elements is displayed. Through the UI, you can examine the detailed history of how each call was processed.
Rhino SAS API is an API that Rhino TAS provides. With the API, you can send data to SAS servers from within your Rhino application, such as a service or a resource adaptor. An application with SAS tracing capability allows support personnel to use SAS to analyze the calls that it processed and investigate the cause of any issue.
In terms of the API architecture, Rhino TAS provides a SAS facility, with which applications can send diagnostic data to configured SAS servers. From the SAS facility, you can create a trail, which is the primary interface for reporting data to SAS. Multiple related trails form a trace, which reflects a distinct occurrence of subscriber activity. The most common trace type is a call. Trails are composed of two message types: events and markers. An event is a structure for capturing call processing data to be sent, while a marker is a tag for identifying or associating trails.
For example, in an application you can define an event that captures certain processing data of a call. In your processing logic, you can assign a marker such as CALLING_DN_MARKER
to a trail or use a marker such as IMS_CHARGING_ID_MARKER
to associate multiple trails. Markers that identify a call enable SAS users to search for the call. Markers that associate trails enable the users to view the full call flow.
Conventions
The following table lists the conventions that this guide uses:
Convention | Description | Example |
---|---|---|
Monospaced font |
Sample code or inline code snippet. |
|
Italic font |
Document title. |
Rhino Extended APIs |
Angle bracket with italic font |
A value that you must specify appropriately. For example, for |
|
Square bracket with italic font |
A value that you can optionally specify. For example, for |
|
Technical support
If you encounter technical issues when implementing SAS tracing in your Rhino applications, first check Rhino SAS API documentation listed in the Related information section and see whether that can help you resolve the issue.
If you cannot resolve an issue with the help of the documentation, check whether your organization has a support agreement with Metaswitch. If it has, contact Metaswitch support team through one of the channels listed on the Metaswitch website.
Related information
This section lists the documents related to Rhino SAS API development. It also provides information about major Rhino products that already have SAS tracing implemented.
Rhino SAS API documentation
The following table lists Rhino SAS API related documents:
Document | Content related to SAS API |
---|---|
Rhino SAS API Development Guide (this document) |
Rhino SAS API introduction and instructions on developing SAS tracing functionalities with the API. |
Rhino Extensions API |
Reference information about the interfaces, classes, and enums included in the |
Rhino Extended APIs |
Introduction of the SAS facility, the Rhino interface for integrating applications with SAS. |
Rhino Administration and Deployment Guide |
Rhino management console commands for managing the SAS facility and resource bundles. |
In addition to these documents, you may need to use other Rhino TAS documents or SAS documents during your application development.
The SAS documents on the Metaswitch manuals site require logging in. For more information, contact your Metaswitch representative. |
Rhino applications with SAS tracing support
This section provides information about SAS tracing support in Rhino products.
The following products already have SAS tracing implemented:
-
Sentinel VoLTE service
-
Sentinel Express service
-
Sentinel IP-SM-GW service
-
IM-SSF service (call flow only)
-
Sh Cache Microservice
-
HTTP resource adaptor
-
Diameter resource adaptor
-
SIS EasySIP resource adaptor
-
REST API framework
|
For these products or product features, you don’t need to implement SAS tracing.
Application development
With Rhino SAS API, you can implement SAS tracing, which means capturing call processing data in your application and sending it to SAS.
For a development environment, you can manage all the development, deployment, and configuration tasks yourself. However, for a production environment, you may need the help of an administrator to handle tasks such as application deployment or Rhino SAS facility configuration. |
To implement SAS tracing for a component in your application, take the following steps:
-
Create a mini-bundle file — a
yaml
file that defines events. -
Add events to the mini-bundle.
In each event, you can define parameters for the data you want to send.
-
Generate a Java enums file from the mini-bundle.
The enums file contains the enums that represent the events in the mini-bundle and the data the events use.
-
In your code, add logic for capturing and sending data.
-
Create a bundle mapping file — a
yaml
file that defines a unique ID for each mini-bundle in your application.In the data sent to SAS, these IDs are added to the event IDs as prefixes so that SAS can differentiate events from different components within the deployed application.
-
Build your application and deploy it onto Rhino TAS.
-
Configure the SAS facility to connect to relevant SAS servers and then enable SAS tracing.
-
Export a resource bundle file from Rhino TAS.
The resource bundle file is a
yaml
file that contains event and enum definitions from the mini-bundles, with the event IDs prefixed with relevant IDs from the bundle mapping file. SAS uses information in the file to display events. -
Import the resource bundle file in SAS and test the data sent from your application.
Information about exporting the resource bundle file and configuring the SAS facility is in the Rhino Administration and Deployment Guide. |
The use of the resource bundle file enables Rhino TAS to send only event IDs and relevant parameter values to SAS. SAS reads the event summary information locally from the imported resource bundle file. This way, Rhino SAS API makes efficient use of the bandwidth between Rhino TAS and SAS.
Subsections provide detailed instructions on each step, with necessary code examples. For a complete code example that involves all the steps, check the example service source code of the HTTP Resource Adaptor. The HTTP Resource Adaptor Guide provides more information about the code.
Create a mini-bundle
A mini-bundle is a yaml
file in which you define events that you use in your processing logic and the enumerated values that the events use. For each component with SAS tracing support in your application, you usually create a separate mini-bundle.
From each mini-bundle file, you can generate a Java enums file that contains enums representing the events and the data that the events use. All the mini-bundle files in your application, together with the bundle mapping file, are used to generate a resource bundle file, which you will need to import in SAS.
By convention, the mini-bundle file is named sas-bundle.yaml
and located in a nested subdirectory under the resources/sas-bundles
directory of the corresponding module. The path to the mini-bundle file must match the Java package for the module. For example, if the package is com.abc.feature.xyz
, the path of the mini-bundle file should be resources/sas-bundles/com/abc/feature/xyz/
. You will need the path and name of the mini-bundle file when you generate the Java enum file from it.
The fields in a mini-bundle are as follows:
version: <file-version>
events:
<EVENT_NAME_1>:
...
<EVENT_NAME_N>:
...
enums:
<ENUM_NAME_1>:
...
<ENUM_NAME_N>:
...
The version field specifies the version of the mini-bundle. |
|
The events section contains event definitions. For more information, see Define events in a mini-bundle. |
|
The enums section contains definitions of the enums that the events use. |
Use enums for known sets of values in an event. For example, you can use enums to represent the reasons for a call diversion or the types of a timer. This can reduce the amount of data sent to SAS and therefore save network bandwidth and storage space, because for enums, you are sending integers rather than objects. |
For example, the following mini-bundle file contains the definition of the SETTING_TIMER
event and the TIMER_TYPES
enum that the event uses:
version: 1.0
events:
SETTING_TIMER:
level: 20
summary: 'Set {{ static_data[0] | enum: "TIMER_TYPES" }} timer for {{ static_data[1] }} seconds'
enums:
TIMER_TYPES:
1: 'No reply'
2: 'Forward to voicemail'
In this example, enum is a Liquid filter that SAS provides for getting the relevant value from the enumeration variable. For more information, see Predefined Liquid filters. |
To make sure that SAS uses the correct version of an event or enum, follow these guidelines when you update the mini-bundle for a new version of the application:
-
Increment the version number appropriately.
-
Don’t remove old events that you no longer need.
-
Don’t change the meaning or order of events or enum values.
Define events in a mini-bundle
In Rhino SAS API, an event is a structure for capturing call processing data to be sent to SAS. For example, if you want to send data to SAS to indicate that a call is being diverted, you can define an event called DIVERTING_CALL
, which has parameters to capture data such as the phone number to which the call is diverted.
By convention, events are defined in the mini-bundle file in the same module where they are used.
Event structure
The structure of an event is as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<EVENT_NAME>:
level: <event-level>
summary: <event-summary>
user_exp: <user-experience>
details: <call-details>
call_flow:
caption: <call-flow-caption>
data: <call-flow-data>
protocol: <call-flow-protocol>
call_leg: <call-leg>
direction: <call-flow-direction>
local_address: <call-flow-local-address>
remote_address: <call-flow-remote-address>
message: <protocol_message>
message_id: <call-flow-message-id>
call_info_id: <call-flow-call-info-id>
This structure contains these fields:
-
<EVENT_NAME>
: The name of the event. By convention, event names are capitalized. -
level
: The level of the event. For more information, see Event level. -
summary
: The summary of the event. SAS displays this information as the Event Summary of the event. -
user_exp
: The user experience information of the event. SAS displays this information in the User Experience view. -
details
: Detailed information about the event. SAS displays this information as the detailed text of the event in the Detailed Timeline view. -
call_flow
: The call flow information of the event. SAS displays this information in the Call Flow view.This field contains the following subfields (lines 7-16):
-
caption
: The text that SAS displays above the arrows in the ladder diagram for the event. -
data
: The protocol message data to add to the call flow diagram. -
protocol
: The protocol to which the message belongs. -
call_leg
: A string that identifies the call leg to which the message belongs. -
direction
: The direction of the call flow. -
local_address
: The local IP address and port that the message is sent from or received at. -
remote_address
: The remote IP address and port that the message is sent from or received at. -
message
: The protocol message data for display in the Message tab of the details panel of the call flow diagram. -
message_id
: The ID of the protocol message. -
call_info_id
: The ID of the "call info" marker that can be used to modify the event or supply additional information for it after it is logged.
-
If you send the same call flow events from multiple nodes, send them using the same fields to ensure correct association within SAS. Otherwise, SAS will display the events separately. |
For information about the SAS user interface, check the SAS documentation listed in Related information.
For each event, the level
and summary
fields are mandatory. If the call_flow
field is specified, the data
, protocol
, and direction
subfields are mandatory.
All text fields can contain parameterized text using the Liquid template language. For example, New target: {{ var_data[0] }}
.
|
SAS uses two types of predefined event variables: static_data
and var_data
. These variables are arrays.
-
The
static_data
variable contains an array of the static data associated with the event, with each element of the array being a 32-bit integer. -
The
var_data
variable contains an array of variable data associated with the event, with each element of the array being variable length data (typically a string).
In your event definition, you can use these variables to format the event data that SAS displays. For example, Attempts in the last minute: {{ static_data[0] }}
or User agent string: {{ var_data[0] }}
.
SAS assigns relevant values to these variables when it needs to display the event data that you send with the staticParam()
method or the varParam()
method. For more information about using these methods, see Create and send an API message.
In addition, SAS provides predefined Liquid filters that you can use in your event definition. For example, with the if_blank
filter, you can get the specified string if the input string is blank. For details about these filters, see Predefined Liquid filters.
Event level
The level of an event determines how SAS displays the event in its GUI.
You can assign one of the following levels to an event:
-
100: A high-level event that SAS displays in the User Experience view.
-
80: A user-friendly event that SAS displays in the Detailed Timeline view.
-
60: A protocol event where the protocol is of interest to the user. SAS displays events of this level in the protocol flows group.
-
40: An event that SAS displays in the Detailed events group.
-
20: A diagnostic event that SAS displays in the Engineering level events group. Events of this level are for application engineers.
Event example
The following event named INCOMING_MESSAGE
for reporting an HTTP message received contains the summary
, details
, level
, and call_flow
fields, in which the call_flow
field contains several subfields:
INCOMING_MESSAGE:
summary: 'Received HTTP {{ var_data[3] }} from {{ var_data[2] }}'
details: |
Received HTTP message from {{ var_data[2] }}:{{ static_data[1] }}
On {{ var_data[1] }}:{{ static_data[0] }}<sas:fixed-width-font>{{ var_data[0] }}</sas:fixed-width-font>
level: 60
call_flow:
caption: '{{ var_data[3] }}'
data: '{{ var_data[0] | binary }}'
protocol: HTTP
direction: in
local_address: '{{ var_data[1] }}:{{ static_data[0] }}'
remote_address: '{{ var_data[2] }}:{{ static_data[1] }}'
message_id: '{{ var_data[4] }}'
In this example, the binary
filter is used on the call flow data. For more information, see Predefined Liquid filters.
Generate an enums file
To use an event that you have defined in the mini-bundle in your data processing code, you must generate a Java enums file from the mini-bundle and then add the event to a trail with the relevant enum.
The Ant task for generating the enums file is generate-bundle-enums
, and the relevant Java class is provided in the client/lib/rhino-extensions-ant.jar
Rhino TAS library.
In Rhino TAS, if you check client/etc/rhino-extensions.xml
, you will find the task defined as follows:
<taskdef name="generate-bundle-enums" classname="com.opencloud.ant.sas.GenerateBundleEnumsTask">
<classpath refid="rhino-extensions-ant.classpath"/>
</taskdef>
You can add this task to your build script so that when the application is built, the enums files are automatically generated from the latest mini-bundle files.
To use the task in your build script, import rhino-extensions.xml
first. For example, you can import the file like this:
<import file="${client.home}/etc/rhino-extensions.xml"/>
After that, you can define a build target that calls the task, as illustrated below:
<target name="generate-sas-enums" depends="initiation">
<generate-bundle-enums destDir="${src}" dir="${basedir}/resources/sas-bundles" includes="*.yaml"/>
</target>
The attributes that you can set for the task are:
-
dir
: The base directory to search for the mini-bundle files. The default value isresources/sas-bundles
. -
destDir
: The output base directory where the task will save the generated enums files. The default value issrc
. -
eventsClassName
: The class name for the generated enum. The default value isSasEvent
. This attribute is optional.
The Java class for the task extends the Ant class MatchingTask , which makes attributes such as includes available. |
By convention, the script reads the mini-bundle files from the resources/sas-bundles
base directory and saves the generated enums files to the src
base directory. The name of the Java package determines the actual subdirectory paths. For example, for a package named com.abc.feature.xyz
, the path of the mini-bundle should be resources/sas-bundles/com/abc/feature/xyz/sas-bundle.yaml
, and the path of the generated enums file should be src/com/abc/feature/xyz/SasEvent.java
.
The following example shows a generated enum class:
public enum SasEvent implements SasEventEnum {
ANNOUNCE ( 0 ),
DIVERT ( 1 ),
ERROR ( 2 ),
;
SasEvent(int id) {
this.id = id;
}
@Override
public int id() {
return id;
}
private int id;
}
Once this file is generated, you can add relevant events to a trail in your code. For example, you can use the following code to add the ANNOUNCE
event:
EventMessage event = trail.event(SasEvent.ANNOUNCE);
For more information, see Create and send an API message.
Don’t edit the generated enums file. If you need an updated version of the file after changing the relevant mini-bundle, use the Ant task to generate it again. |
Create and send an API message
After adding events to the mini-bundle and generating the relevant Java enums file from it, you can start to add data sending logic in your code.
To send data, you need to create or get a trail
first. The SAS facility creates trails either explicitly, when a resource adaptor calls startTrail()
or implicitly, when a resource adaptor or service calls getOrCreateTrail()
with an activity reference. Trails typically last the lifetime of an activity. Multiple activities may share the same trail. For example, a database lookup in a call setup uses the trail of the SIP dialog or transaction.
You can use the methods provided by the
interface to create or get a trail. For example, the SasFacility
getTrail()
method enables you to get the trail attached to an activity.
When a SLEE event is delivered to a service, the invoking trail is available through an invoking trail accessor, which you can get by calling the getInvokingTrail()
method of the
class. The method returns the SAS trail attached to the activity context interface (ACI) on which the event was fired. On subsequent down calls that result in a new SLEE activity being created, the invoking trail is automatically attached to the new activity. This can save you from having to add code that explicitly gets a trail from the invoking ACI and attaches it to a new ACI. If necessary, you can call the InvokingTrailAccessor
setInvokingTrail(Trail)
or remove()
method to manually set or clear the invoking trail.
The following example code shows how to get the invoking trail from an invoking trail accessor:
Trail trail = InvokingTrailAccessor.getInvokingTrail();
Once you have a trail, you can use it to create API messages and send data to SAS.
With a trail, you can send two types of data:
-
Send event data by adding events that you defined in the mini-bundle to the trail.
-
Send marker data by adding predefined markers with appropriate values to the trail.
The objects and methods for creating and sending API messages are defined in the Java library rhino-extensions.jar . Make sure that you include this library in your class path. |
Send event data
Once you have a trail, you can use it to create an API message and send data with the message.
The following example code for call diversion illustrates the steps for sending data with events:
1
2
3
4
5
Trail trail = InvokingTrailAccessor.getInvokingTrail();
EventMessage event = trail.event(SasEvent.DIVERT_CALL);
event.staticParam(diversionTypeToSasType(diversionType));
event.varParam(newTarget);
event.report();
These steps are as follows:
-
Add an event to the trail with an event message object.
As shown in line 2, the
event()
method is used to add theDIVERT_CALL
event to the trail. -
Assign values to event parameters with an appropriate method.
As shown in lines 3 and 4, the
staticParam()
method and thevarParam()
method are respectively used to add the values. -
Send the data out with the
report()
method.As shown in line 5, the
report()
method of the event message object is used to send the data.
Once you are familiar with the process, you can combine the methods in the same statement. The example code above can also be written as follows:
InvokingTrailAccessor.getInvokingTrail()
.event(SasEvent.DIVERT_CALL)
.staticParam(diversionTypeToSasType(diversionType))
.varParam(newTarget)
.report();
Add an event to the trail
Once you get a trail, you can add an event that you defined in the mini-bundle to the trail.
Events can be added with the event()
method. In this method, you must use the Java enum generated from the mini-bundle to add the relevant event. For example, the following code uses the enum for the SETTING_TIMER
event to add the event to a trail:
EventMessage event = trail.event(SasEvent.SETTING_TIMER);
is an object type for sending event data to SAS. Each object can have parameters holding information with details about event specifics.EventMessage
Assign values to event parameters
After adding the event, you can use appropriate methods of the event message object to assign values to event parameters. For example, the following code assigns values to two parameters with the staticParam()
method, which assigns a value to a 32-bit fixed-length parameter:
event.staticParam(timerTypes.No_Reply);
event.staticParam(timerValue);
The number and type of the parameters that you assign to the event must match the number and type of the parameters that you define for the event in the mini-bundle. |
For information about the methods that you can use, see the Rhino Extension API document listed in the Related information section.
Send the data out
Once you have an event message object ready, you can use the report()
method to send the relevant data out.
The report() method is asynchronous, which means once it is called, the Rhino SAS facility enqueues the message for sending. Make sure the values of the parameters don’t change between their assignments and the actual sending of the data. |
Send marker data
To make the events and trails for a single call appear in a single trace and searchable, you can attach markers to trails.
Markers can associate trails. If you use the same value for an association marker, such as GENERIC_CORRELATOR_MARKER
, on multiple trails, SAS associates those trails to give its users a comprehensive view of the trace. Markers can also make trails searchable. If you add a value to a searchable marker, such as CALLING_DN_MARKER
, which is attached to a trail, SAS users can use that value to search for the trail once it is sent through.
A marker can serve multiple purposes. For example, you can use a marker to both search for a trail and associate multiple trails. |
The following code example illustrates the steps for adding an association marker and sending the data out:
1
2
3
4
MarkerMessage associationMarker = trail.marker(Markers.IMS_CHARGING_ID_MARKER);
associationMarker.traceScope();
associationMarker.varParam(icid);
associationMarker.report();
The following code example illustrates the steps for adding a searchable marker and sending the data out:
1
2
3
4
MarkerMessage searchableMarker = trail.marker(Markers.CALLING_DN_MARKER);
searchableMarker.noneScope();
searchableMarker.varParam(fromAddress);
searchableMarker.report();
As shown in these examples, sending marker data takes these steps:
-
Add a marker to the trail with a
object.MarkerMessage
As shown in line 1 of the examples, the
marker()
method is used to respectively add theIMS_CHARGING_ID_MARKER
marker and theCALLING_DN_MARKER
to the trails. -
Define the scope of the marker.
For association markers, you must define an appropriate scope. SAS only associates markers that have the same scope. A scope can be a branch of a call leg or a trace. In line 2 of the examples, the
traceScope()
method specifies that the scope of the marker is the trace, while thenoneScope()
method specifies that the marker isn’t an association marker. -
Add values to the marker.
To add the values, use the
staticParam()
method for static data and thevarParam()
method for variable data. As shown in line 3 of the examples, the values of theicid
and thefromAddress
variables are respectively added to theIMS_CHARGING_ID_MARKER
and theCALLING_DN_MARKER
markers. -
Send the marker out.
Once the marker message object is ready with appropriate marker, scope, and values, you can use the
report()
method of the object to send the marker data out.You can also use the
report()
method of the
object to send the data out. For example, in the first example, you can change the last line toTrail
trail.report(associationMarker)
.
For the best practices in using markers, see the Best practices sections.
Define bundle mappings
To let SAS distinguish the events reported from different modules that use separate mini-bundles, Rhino TAS allows you to use a bundle mapping file to define a unique prefix for the events in each mini-bundle. In the resource bundle file exported for SAS, Rhino TAS adds the prefixes to the IDs of the events from relevant mini-bundle files.
A bundle mapping file is a yaml
file, with all bundle mappings defined at the top level. The prefixes are 16 bits, that is, from 0 to 65535 (0xFFFF), and must be unique. You can define the prefixes in the integer or hexadecimal format. By convention, the hexadecimal format is used. For the packages, use fully qualified bundle names, such as com.abc.feature.xyz
.
For example, the following lines define the mappings for com.abc.feature.m
and com.abc.feature.n
:
com.abc.feature.m: 0x0001
com.abc.feature.n: 0x0002
After creating the bundle mapping file, use the setsasbundlemapping
Ant task to instruct Rhino to use the file.
As to the mappings in the bundle mapping file, you can add or remove them either by manually editing the file, or by using the Rhino management console commands. For example, you can use the setsasbundlemapping
command to add a mapping or use the removesasbundlemapping
command to remove a mapping.
To ensure consistency between deployments and upgrades, you generally need to create the bundle mapping file and assign bundle mappings manually. If you want Rhino TAS to automatically assign prefixes to unmapped bundles, set the assignbundlemappings
attribute in the install
Ant task to true
when you install the relevant deployable unit.
If no prefix is assigned for a mini-bundle, Rhino TAS doesn’t send the events in it. To check for any mini-bundles with missing prefix mappings, use the listunmappedsasbundles Rhino management console command. |
Create a deployment package
Upon finishing your application development, you will need to package the application and deploy it onto Rhino TAS, so that the application can run and send data to SAS.
When you create a SLEE component JAR file, make sure that you include the following files:
-
The mini-bundle files in your application.
Rhino TAS needs to read the event definitions from these mini-bundle files. In the JAR file, put the mini-bundle files in subdirectories under
META-INF/sas-bundles
, with the subdirectory structure matching the names of relevant Java packages. For example, if the mini-bundle is for a package namedcom.abc.feature.xyz
, its path in the JAR file should beMETA-INF/sas-bundles/com/abc/feature/xyz/sas-bundle.yaml
. -
The compiled Java enums files generated from relevant mini-bundle files.
Compile and package the enums files like other Java class files. For example, in the JAR file, the path of one of the enums file might be
com/abc/feature/xyz/SasEvent.class
.
Don’t include the bundle mapping file in the deployment package. Once the application is deployed, you can use the setsasbundlemapping
Ant task to install the bundle mapping file onto Rhino TAS.
After deploying the application and installing the relevant bundle mapping file, you can export a resource bundle file from Rhino TAS with the exportsasbundle
command. SAS uses information in the resource bundle file to format the data it receives from your application.
Test a Rhino SAS API application
To ensure your application correctly processes data, test it before putting it into production. For applications with SAS tracing support, in addition to local tests, you must check the data received by SAS and make sure relevant events are displayed as expected.
For the SAS tracing functionalities in your application, make sure that you test these items:
-
The mini-bundle file.
Review the event definitions and see whether there are any issues. If an event uses enums, make sure the relevant enums are defined in the
enums
section. -
The Java enums file.
Make sure a Java enums file is generated for each mini-bundle. If there are any errors in the mini-bundle file, you will see errors when you generate the enums file.
-
The bundle mapping file.
Make sure a bundle mapping file is in place for your application. Check the bundle mapping file and make sure a prefix has been defined for each Java package that has a mini-bundle. Check whether there are any prefix conflicts.
For deployed applications, use the listunmappedsasbundles command to identify missing prefixes.
To check the data that SAS receives from your application, take the following steps.
-
Create a deployment package and then deploy the application onto Rhino TAS.
-
Install the bundle mapping file onto Rhino TAS with the
setsasbundlemapping
Ant task. -
Configure the Rhino SAS facility to connect to relevant SAS servers.
-
Export a resource bundle file from Rhino TAS with the
exportsasbundle
command. -
Enable SAS tracing in Rhino TAS.
-
Import the resource bundle file in SAS.
The resource bundle file contains information about the events defined in your application. Once you import it in SAS, SAS can format the data it receives with relevant event information and then display complete event information through its user interface.
-
Check the events that SAS receives and make sure everything is as expected.
For example, you may want to check whether the set of events for a feature represents the data flow and the processing logic, because that can help SAS users better understand the situation and diagnose issues easily. For more information about the best practices like this, see Best practices.
For instructions on importing resource bundle files and checking events in SAS, see the SAS documentation listed in Rhino SAS API documentation.
Best practices
Once you are familiar with the Rhino SAS API application development process, you may want to search for best practices for improving your efficiency and productivity in application development.
This section and its subsections describe the best practices in using events, markers, associating trails, and handling object parameters. With these best practices, you can define your application logic efficiently and avoid making mistakes.
To use SAS for issue diagnostics, you can implement SAS tracing in resource adaptors and/or services. If SAS tracing isn’t provided in the resource adaptors that you use, add call flow events and markers in your service. Rhino SAS facility handles trails from both services and resource adaptors. |
Events
Well-defined events can make it easy for support personnel to investigate call processing issues, and well-used events can minimize the amount of data that your application sends, therefore saving the network bandwidth and the storage space that your application uses.
Follow these guidelines when you define or use events:
-
Assign appropriate event levels.
For details, see Event level.
-
Minimize event data for protocol events.
If a resource adaptor already sends a SAS event containing a protocol stack message, don’t send the same stack message in SAS events at the application layer. Doing that wastes the bandwidth and storage space and may also clutter the SAS trace with redundant information that reduces the clarity of the trace.
-
Be aware of event ordering.
Send SAS events inside a service before calling down to a resource adaptor to send a protocol message. This way the event you create will precede the resource adaptor’s SAS events and provide context and explanation for them.
-
Consider the entire narrative of the SAS trace.
The goal in sending SAS events is to record a concise, linear narrative of what happened and why, both in normal and abnormal flows. By ensuring a coherent SAS narrative as a whole on the SAS server, we can afford the SAS user a greater understanding of what went wrong in instances where the call flow is unexpected.
Markers
Well-used markers can make it easy for users to find the information they need and help to produce a coherent view of the call flow.
Follow these guidelines when you use markers:
-
Use an appropriate
marker
to record each party’s identity in at least one event in each trail.To SAS users, a trace is worthless if they cannot find it.
-
Assign at least one start marker and one end marker to a trace.
The start marker allows the trace to be found as part of a time-constrained search. The end marker ensures that SAS writes the trace to the disk in a timely manner.
-
Make a trace searchable even if there is no appropriate marker.
If there is no Call ID or SIP URL or anything else that is searchable associated with a trail, make something up and employ one of the existing searchable markers. If an end user identity looks like a directory number (DN), pretend it is a DN. and if it looks like a URL, pretend it is a URL. If there is a token, which would be known or discoverable, passed around, pretend it is a Call ID. Test and make sure that the pretense works, and then document that as a way of searching for the trace.
-
Associate trails in the same trace.
If there is a risk that two trails in a trace might not be associated, use at least one association marker with the same value and appropriate scope in both trails.
-
Don’t use DN or URI markers as association markers.
These markers aren’t unique to a particular trace and will result in incorrectly associating unrelated trails in a single trace. For example, if a subscriber makes two calls in quick succession and the DN marker is used for trail association, SAS will display the trails for these two calls in the same search result, which is incorrect.
For DN or URI markers, always use the
noneScope()
method to specify that they aren’t association markers.
Trail association and colocation
You can associate SAS trails that form part of the same call with the associate(Trail)
method. If the Rhino SAS facility is configured with multiple SAS servers, different trails may not use the same server.
Associating trails that use the same SAS server is more efficient, as you only need to send a trail association message to the one server informing it that the trails form part of the same trail group. If the trails being associated use different servers, a generic association marker gets sent to each SAS server with the UUID of the one trail. In that case, SAS needs to perform additional operations to associate the trails.
To colocate related trails on the same SAS server, use the startColocatedTrail(Trail)
method or the startAndAssociateTrail(Trail, Scope)
method. These methods create a new SAS trail using the same server as the given trail and, in the second case, automatically send a trail association message to the server.
Object parameter handling
You can use the following methods to pass data to a SAS EventMessage
object:
-
staticParam()
-
varParam()
orvarParams()
-
threadSafeParam()
Static parameters
The staticParam()
method allows a 32-bit integer value in the EventMessage
object to be sent to the SAS server. In the SAS mini-bundle, you can get the corresponding enum value and format SAS EventMessage
details with meaningful information.
Whenever possible, use staticParam()
instead of varParam()
, as the size of the resulting EventMessage
object is much smaller and therefore requires less memory, CPU usage, and network bandwidth. This is important because unlike most logging APIs that offer a log level hierarchy to modulate the log verbosity, SAS tracing sends every SAS event to the server regardless of the level specified in the SAS mini-bundle.
The cumulative effect of using varParam()
calls in place of staticParam()
calls can have a sizeable impact on system performance. Therefore, pack as much fixed data into the mini-bundle as is practical to minimize the amount of data to be sent to the server. Encoding data in an enum value and decoding it to text in the bundle helps ensure this and allows the application to scale efficiently.
Consider refactoring code to use staticParam()
if:
-
The
varParam()
method is used to send a string from a finite set of strings (typically for debugging). -
The
varParam()
method is used to format fixed strings with variable data.Either define these strings in full inside the mini-bundle or separate the constant text into the mini-bundle and divide the variable data into static parameters and variable-length parameters appropriately. If this becomes too complex, for example if you are passing differently formatted data at different locations in your code to a single event, consider using separate events.
The staticParam()
method allows parameters to be passed in as int
, Integer
, or EnumParameter
.
Variable-length parameters
If you cannot define the data being passed to SAS as an enum or the length of the data varies, use the varParam()
or the varParams()
method. These methods accept object parameters, allowing for flexibility in the data passed to the EventMessage
. The varParams()
method behaves similarly to varParam()
but allows two or three objects to be passed in as parameters. You can achieve the same result by chaining multiple varParam()
calls together.
The varParam()
method handles parameters passed to it differently depending on their types:
-
null
: Encodes as a zero-length byte array. -
byte[]
: Copies directly into the message. -
java.nio.ByteBuffer
: Unsupported. Coerces to a zero-length byte array. In this case, usethreadSafeParam(byte[])
instead. -
java.lang.String
: Encodes as UTF-8 and copies into the message. -
Any other type: Calls
Object#toString()
and then proceeds as forjava.lang.String
.
For the implementation of EncodeableParameter
, the method calls EncodeableParameter#encode(ByteBuffer)
and copies bytes written to stream into the message, while for the implementation of MarshalableParameter
, the method calls MarshalableParameter#marshal()
and copies the returned byte[]
into the message.
Don’t use the varParam()
method for parameters that implement EnumParameter
. It will automatically add the parameter as a static parameter, with a debug message logged. Use the staticParam(EnumParameter)
method for enum parameters instead.
Thread safety
Data passed as parameters is only copied or marshalled into the relevant EventMessage
object when the report()
method is invoked. Therefore, don’t modify the parameters passed to the EventMessage
object before invoking the report()
method.
Additionally, parameters passed using the threadSafeParam(byte[])
method will not be copied even after the report()
method is invoked. This means that if a value you want to pass as a parameter may be subsequently modified, and you already have defensively copied it, you should use the threadSafeParam(byte[])
method to put the defensive copy in the event. This allows the SAS API to be more efficient, by not making its own defensive copy when the report()
method is invoked.
Different from the above, the staticParam()
, varParam()
, and varParams()
methods convert the following types of parameters when they are added:
-
null
: Convert to an empty byte array. -
ByteBuffer
: Convert to an empty byte array. -
EnumParameter
: Convert to its integer value.
Check isEnabled()
on the trail object before marshalling. The isEnabled()
method returns a boolean value, which is true if SAS tracing is enabled on the SAS facility that the trail object was created from. By wrapping the code responsible for marshalling the object conditioned on the isEnabled()
method, you can achieve further reduction in memory and CPU usage.
Predefined Liquid filters
SAS provides predefined Liquid filters that you can use to further process the event data it receives. It runs the filters used in an event when it displays the event.
To display the data from your application, SAS assigns relevant values to the static_data or var_data variables, and then renders the Liquid template for the relevant event. For that reason, this section uses the Liquid terminology, instead of the Java terminology, for the description of the filters. |
This section lists the filters that you may need when you develop applications with Rhino SAS API.
To use the predefined filters, separate the input value and the filter with a |
symbol. Some filters can have additional parameters. To specify them, use a colon (:
) followed by a comma-separated list of parameters.
For example, the following template calls the foo
filter with three parameters, static_data[0]
, static_data[1]
, and static_data[2]
:
{{ static_data[0] | foo: static_data[1], static_data[2] }}
You can combine multiple filters. In that case, they are applied from left to right.
Filters for formatting static_data
Data that your application attached to an event using the staticParam()
method is available to the Liquid templates in the mini-bundle in the static_data
array variable. Without any filters, SAS renders this variable as an unsigned decimal string, or as an empty string if the value is absent.
To format static_data
in other forms, use the following filters:
Filter name | Description | Parameters |
---|---|---|
|
Treats an integer as a Boolean value and then converts the value to a string. If the integer is For example, the expression |
|
|
Gets a value stored in an enumeration variable defined for an event in the mini-bundle. |
|
|
Formats the input integer as a 32-bit float value. |
|
|
Returns the text description for an integer HTTP status code. For example, the expression |
|
|
Formats the input integer as a signed integer with optional radix (for example, 10 for decimal) parameter. |
|
|
Formats the input integer as an unsigned one with optional radix (for example, 10 for decimal) parameter. |
|
Filters for formatting var_data
Data that your application attaches to an event using the varParam()
method is available to the Liquid templates in the mini-bundle in the var_data
array variable. Without any filters, SAS casts the value as UTF-8 encoded text and displays it as such. If the variable value is not valid UTF-8 encoded text, SAS renders it as Invalid UTF-8 String
. If the value is absent, SAS renders it as an empty string.
When a Java String is passed to the varParam() method, the corresponding var_data is UTF-8 encoded. |
Filters for formatting UTF-8 var_data
To format var_data
that is UTF-8 encoded in other forms, use the following filters:
Filter name | Description | Parameters |
---|---|---|
|
Appends an object to another and returns a concatenated string if the first object is present. Otherwise returns an empty string. |
|
|
Appends the specified port number to the input IPv4 address/hostname or IPv6 address. For an IPv6 address, the filter adds brackets. Consider the following example:
If the value of |
|
|
Converts the given JSON object to a well-formatted string. You can use this filter in combination with the
|
|
|
Returns the specified string if the input value is absent. Otherwise returns the input value. |
|
|
Returns the specified string if the input value is blank. Otherwise returns the input value. Consider the following example:
In this example, if the value of the |
|
|
Prepends an object to another and returns a concatenated string if the first object is present. Otherwise returns an empty string. Consider the following example:
If the variable |
|
|
Converts a string into a JSON object. For example, after getting the
You can print the entire JSON structure with this code:
Or print a field with this code:
|
|
Filters for formatting other var_data
To format var_data
that is not UTF-8 encoded, use the following filters. For example, you may need one of these filters when you pass the contents of a binary encoded message in a byte
array to the varParam()
method.
These filters need to access the raw data form of the input. Don’t use them after other filters because all filters output UTF-8 strings that don’t have a raw data form. |
Filter name | Description | Parameters | ||
---|---|---|---|---|
|
Converts the input, which may include binary data, into a hexadecimal string. |
|
||
|
Interprets the input non UTF-8 data as valid UTF-8 data so that the data can be further processed. Use this filter when SAS needs to process the results of a template render as binary. For example, the variable for the
|
|
||
|
Formats a string as Diameter details. |
|
||
|
Formats a string as a Diameter summary |
|
||
|
Formats a string as SIP details. |
|
||
|
Formats a string as a SIP summary. |
|
||
|
Formats the input string as a directory number. |
|
||
|
Dump a byte string as a hexadecimal string. Returns |
|
||
|
Formats the input data by displaying it as a hex dump, with corresponding printable ASCII characters alongside. Use this filter to display blobs of binary data for which a decoder isn’t available. |
|
||
|
Formats the input string’s byte sequence as an IP address. The filter interprets four bytes as an IPv4 address and 16 bytes as an IPv6 address. |
|