Skip Headers
Oracle® Communications Operations Monitor User's Guide
Release 3.3.80

E57622-01
Go to Documentation Home
Home
Go to Table of Contents
Contents
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
PDF · Mobi · ePub

9 Implementing Apps

Apps provide an easy way to extend Oracle Communications Operations Monitor with analytical capabilities that are not present in the user interface. Apps can query information from Operations Monitor, process this information, and store results in an output table.

Structure of an App

A valid Operations Monitor extension app consists of a Python 2.7 module and of an app specification file, that declares the parameters of the app and the schema of the app's result table. The Python module file and the app specification file must be packed into a ZIP archive, containing no other files and no directories. Such a ZIP archive can be uploaded to Operations Monitor as described in "Apps".

Further requirements for the app module and the app specification file apply. The app module must contain a run function with the following signature:

run (facade, params)

Parameters:

  • facade

    An instance of libpalladion.scripting.Facade which provides access to the Apps API.

  • params

    A dict instance which represents the parameters supplied to the app.

This function is called by Operations Monitor when the app is executed from the web interface or via remote procedure calls.

The app specification file must be an XML file which complies with the Operations Monitor app-specification DTD cited below:

<!DOCTYPE script [
<!ELEMENT script (param-spec?,result-schema?)>
<!ATTLIST script xmlns CDATA #FIXED "http://iptego.de/palladion/script-spec">
<!ATTLIST script name CDATA #REQUIRED>
<!ATTLIST script description CDATA #IMPLIED>
<!ATTLIST script result-type (custom|calls) #REQUIRED>
  
<!ELEMENT param-spec (param+)>
  
<!ELEMENT param EMPTY>
<!ATTLIST param name CDATA #REQUIRED>
<!ATTLIST param label CDATA #REQUIRED>
<!ATTLIST param type (string|datetime|numeric) #REQUIRED>
<!ATTLIST param required CDATA #IMPLIED>
<!ATTLIST param default CDATA #IMPLIED>
  
<!ELEMENT result-schema (column+,primary-key?,unique-key*)>
  
<!ELEMENT column EMPTY>
<!ATTLIST column name CDATA #REQUIRED>
<!ATTLIST column type CDATA #REQUIRED>
<!ATTLIST column null (true|false) #IMPLIED>
<!ATTLIST column auto-increment (true|false) #IMPLIED>
<!ATTLIST column default CDATA #IMPLIED>
  
<!ELEMENT primary-key EMPTY>
<!ATTLIST primary-key columns NMTOKENS #REQUIRED>
  
<!ELEMENT unique-key EMPTY>
<!ATTLIST unique-key name CDATA #REQUIRED>
<!ATTLIST unique-key columns NMTOKENS #REQUIRED>
]>
  

The top-level script element is used to configure some important properties of an app. Its name attribute specifies a name for the app which is displayed in the Available Apps table. The description attribute can contain a longer description for the app. Most importantly, the result-type attribute specifies what kind of result table the app will have. It can be either custom, in which case you must specify the result table in the result-schema element, or calls, in which case the result table is fixed as a calls table.

The param-spec element is a container for parameter specifications declared by the param element. Parameter specifications are used by the web interface to generate the right kind of parameter entry dialog when an app is started. The name attribute of the param element specifies the name of the parameter, that is passed to the app. The label attribute specifies a label that is displayed in the parameter entry dialog. The type attribute specifies how the parameter entry is rendered in the parameter entry dialog. The required attribute decides whether the parameter must be entered or can be left blank. The default attribute specifies a default value, that is filled into the parameter entry.

The result-schema element is used to specify a schema for the result table of the app. This is required when the result-type attribute of the main script element is set to custom. The contents of the result-schema element are translated into an SQL CREATE TABLE statement. You can specify columns in the result table, as well as a primary key and multiple unique keys. The column element specifies a column. The name attribute gives the name of the column. The type attribute specifies the type of the column. It can contain any of the data type specifications valid in MySQL. For more information, see the Create Table Syntax in the MySQL 5.0 Reference Manual:

http://dev.mysql.com/doc/refman/5.0/en/create-table.html

The null attribute decides whether the column is nullable or not. The auto-increment attribute specifies whether the column can be filled via auto increment on insert. The default attribute gives a default value for the column. The primary-key element declares a primary key for the result table. Its columns attribute is a list of columns that make up the primary key. The unique-key element declares a unique key in the result table. Its name attribute gives the name for the unique key. Its columns attribute is a list of columns that make up the unique key.

Apps API

class libpalladion.scripting.Call (facade)

This class represents a call in Operations Monitor. For general information on how Operations Monitor handles calls, see"Calls".

Table 9-1 describes the fields for the Call class.

Table 9-1 Call Class Fields

Field Description

callid: STRING

ID of the call.

nlegs: INTEGER

The number of legs this call consists of.

state_msg: STRING

A string describing the call state. One of 'Unauthorized', 'Proceeding', 'Ringing', 'Established', 'Finished', 'Timed out', 'Error', 'Failed', 'Closed by CleanBye', 'Not found', 'Moved', 'Off-line', 'Busy', 'Canceled'.

state_details: STRING

An additional description of the call state.

setup_start_ts: DATETIME

A timestamp specifying when the call was initiated.

setup_time: INTEGER

The time, in milliseconds, needed for the call to reach the 'Established' state. Only available if state_msg equals 'Established'.

call_time: INTEGER

The duration of the call in milliseconds, that is the time the call was in the 'Established' state. Only available if state_msg equals 'Finished'.

code: INTEGER

The final response code of the INVITE transaction associated with this call.

src_user: STRING

The user creating the call. This is usually taken from the From header field of the first call leg.

src_ua: STRING

The user agent string for the caller.

src_codecs: STRING

The comma separated list of codecs proposed in the SDP body by the UAC, usually in the INVITE message.

On each re-INVITE from inside the dialog, this field is updated to the last proposed list of codecs. This is useful for detecting T.38 calls, for example

src_initial_codecs: STRING

The comma separated list of codecs proposed in the SDP body by the UAC, usually in the first INVITE message. This field is not updated at re-INVITES.

dst_user: STRING

The user to which the call is addressed. This is usually taken from the To header field of the first call leg.

dst_ua: STRING

The user agent string for the callee.

dst_codecs: STRING

The comma separated list of codecs proposed in the SDP body by the UAS.

On each re-INVITE from inside the dialog, this field is updated to the last proposed list of codecs.

dst_initial_codecs: STRING

The comma separated list of codecs proposed in the SDP body by the UAS, usually in the first INVITE message. This field is not updated at re-INVITES

term_devs: STRING

A comma separated list of device IDs for devices that this call has an inbound leg to.

init_devs: STRING

A comma separated list of device IDs for devices that this call has an outbound leg from.

ingress_devs: STRING

A comma separated list of devices that are ingress devices for this call.

egress_devs: STRING

A comma separated list of devices that are ingress devices for this call.

MOSlqe_avg: FLOAT

Average MOSlqe value for all relevant streams in the call.

MOSlqe_min: FLOAT

Minimum MOSlqe of all stream chunks associated with the call.

getLegs ()

Query legs that belong to this call. Note that this method works only for calls that are in the permanent history (that is, finished for more than 15-20 seconds).

Return type: QueryIterator over Leg instances.

getMessages (filter=[])

Query all SIP messages, that belong to this call. Note that this method works only for calls that are in the permanent history (that is, finished for more than 15-20 seconds).

Return type: QueryIterator over Message instances.

getOneWayAudio (filter=[], keys={}, orderBy=[])

Query all voice quality information, that belong to this call.

Return type: integer

Values:

  • 0: no audio.

  • 1: there is a media leg with audio only in one direction.

  • 2: all media legs with two way audio.

getRawMessages (filter=[])

Query all raw signaling messages, that belong to this call. Note that this method works only for calls that are in the permanent history (that is, finished for more than 15-20 seconds).

Parameters

  • filter - A filter specification to be applied to the queried RawMessage instances.

Return type: QueryIterator over RawMessage instances.

getVoiceQuality (filter=[], keys={}, orderBy=[])

Query all voice quality information, that belong to this call.

Parameters

  • filter - A filter specification to be applied to the queried VoiceQuality instances.

  • keys - Keys that the queried VoiceQuality instances must match.

  • orderBy - Ordering specification.

Return type: QueryIterator over VoiceQuality instances.

getVoiceQualityChunks (filter=[], keys={}, orderBy=[])

Query all voice quality information, that belong to this call.

Parameters

  • filter - A filter specification to be applied to the queried Chunk instances.

  • keys - Keys that the queried Chunk instances must match.

  • orderBy - Ordering specification.

Return type: QueryIterator over Chunk instances.


class libpalladion.scripting.Leg (facade)

The Leg class represents a leg found by Operations Monitor. A leg is the portion of a call that happens between two given devices. Table 9-2 describes the fields for the Leg class.

Table 9-2 Leg Class Fields

Field Description

id: INTEGER

Corresponds to the Call.id attribute of the associated call.

state: INTEGER

A numeric representation of the call state.

state_msg: STRING

A string describing the call state. One of 'Unauthorized', 'Proceeding', 'Ringing', 'Established', 'Finished', 'Timed out', 'Error', 'Failed','Closed by CleanBye', 'Not found', 'Moved', 'Off-line', 'Busy', 'Canceled'.

state_details: STRING

An additional description of the call state.

setup_start_ts: INTEGER

Timestamp in seconds of the first message in this leg.

setup_time: INTEGER

The time in milliseconds that the leg took to reach the 'Established' state. Only available, if state_msg equals 'Established'.

call_time: INTEGER

The time in milliseconds that the leg was in the 'Established' state. Only available, if state_msg equals 'Finished'.

code: INTEGER

The final response code in this leg.

src_user: STRING

The identifier of the caller.

src_uri: STRING

The URI of the caller.

src_ip: STRING

The IP address of the caller.

src_mac: STRING

The hardware address of the caller.

src_port: INTEGER

The port the caller is listening on.

src_ua: STRING

The user agent string of the caller.

dst_user: STRING

The identifier of the callee.

dst_uri: STRING

The URI of the callee.

dst_ip: STRING

The IP address of the callee.

dst_mac: STRING

The hardware address of the callee.

dst_port: INTEGER

The port the callee is listening on.

dst_ua: STRING

The user agent string of the callee.

ruri: STRING

The request URI.

callid: STRING

The value of the Call-ID header.

from_tag: STRING

The value of the tag parameter of the From header.

to_tag: STRING

The value of the tag parameter of the To header.

getMessages (filter=[])

Query all SIP messages, that belong to this leg.

Parameters

  • filter - A filter specification to be applied to the queried Message instances.

Return type: QueryIterator over Message instances.

getRawMessages (filter=[])

Query all raw signaling messages, that belong to this leg.

Parameters

  • filter - A filter specification to be applied to the queried Message instances.

Return type: QueryIterator over RawMessage instances.


class libpalladion.scripting.RegistrationEvent (facade)

This class represents registration events found by Operations Monitor. For a general description of registration events in Operations Monitor, see "Registrations".

Table 9-3 describes the fields for the Registration Event class.

Table 9-3 Registration Event Class Fields

Field Description

id: INTEGER

A unique ID for this registration event.

ts: DATETIME

The timestamp of this registration event.

realms: INTEGER

The realms bit mask for this registration event.

type: INTEGER

The type of this registration event.

type_msg: STRING

An additional message associated with the type of registration event.

user: STRING

The identifier of the user that is associated with this registration event.

ip: STRING

The source IP address of this registration event.

dest_ip: STRING

The destination IP address of this registration event.

contacts: STRING

The content of the contact header of the REGISTER request.

code: INTEGER

The response code for this registration event.

dev_id: INTEGER

The unique identifier of the device that handled the registration event.

getMessages (filter=[])

Query all SIP messages, that belong to this registration event.

Parameters

  • filter - A filter specification to be applied to the queried Message instances.

Return type: QueryIterator over Message instances.

getRawMessages (filter=[])

Query all raw SIP messages, that belong to this registration event.

Parameters

  • filter - A filter specification to be applied to the queried RawMessage instances.

Return type: QueryIterator over RawMessage instances.


class libpalladion.scripting.Message(facade)

This class encapsulates a single SIP message. Table 9-4 describes the fields for the Message class.

Table 9-4 Message Class Fields

Field Description

ts: DATETIME

The timestamp, when the message was received by Operations Monitor.

request: BOOLEAN

True if the message is a request, False otherwise.

proto: STRING

Protocol used.

src_ip: STRING

Source IP address.

src_mac: STRING

Source MAC address.

dst_ip: STRING

Destination IP address.

dst_mac: STRING

Destination MAC address.

method: STRING

The request method of this message. Only present, if this is a request message.

ruri: STRING

The request URI of this message. Only present, if this is a request message.

code: INTEGER

The response code of this message. Only present, if this is a response message.

reason: STRING

The response reason of this message. Only present, if this is a response message.

headers: LIST

A list of (fieldname, field body) tuples, representing the headers of this message.

body: STRING

The message body.

getBody ()

Returns the body of the message.

Return type: str.

getHeaders ()

Returns a list of (fieldname, field body) tuples for all defined header fields. Field name and field body are both instances of str.

Return type: list of tuples.

getHeadersByName (name)

Returns a list of header field bodies for header fields where the field name equals the given name. A field body is an instance of str.

Parameters

  • name - Name to match header fields against.

Return type: list of str.

isRequest ()

Returns, whether this message is a request.

Return type: bool.


class libpalladion.scripting.RawMessage(facade)

This class encapsulates a raw signaling message. Table 9-5 describes the fields for the Raw Message class.

Table 9-5 Raw Message Class Fields

Field Description

ts: DATETIME

The timestamp, when the message was received by Operations Monitor.

h: DICT

A dictionary representing the PCAP header.

frame: STRING

The raw data.


class libpalladion.scripting.VoiceQuality(facade)

This class represents voice quality measurements for a call found by Operations Monitor, or reported by one of the User Agents from the call. A call can have more Voice Quality instances associated, one for each RTP stream.

It cannot be invoked directly. It is used for the return objects of the method getVoiceQuality for Call objects.

For more information on how Operations Monitor gathers voice quality data, see "Voice Quality".

Table 9-6 describes the fields for the Voice Quality class.

Table 9-6 Voice Quality Class Fields

Field Description

start_ts: DATETIME

The timestamp of the first measured RTP packet.

probe: STRING

IP address of the probe that received the data.

vlan: INTEGER

VLAN of the probe.

direction: STRING

The direction of the RTP stream that was measured. One of 'src2dst' or 'dst2src'.

dst_ip: STRING

The destination IP of the call.

dst_port: INTEGER

The destination port of the call.

src_ip: STRING

The source ip of the call.

src_port: INTEGER

The source port of the call.

start_ts: DATETIME

The timestamp of the call.

packets_received: INTEGER

The number of RTP packets received.

packets_lost_rate: INTEGER

Packet loss rate for the RTP stream.

forward: BOOLEAN

True if forward.

source: STRING

Source Device Name.

moscqe_avg: FLOAT

MOS average for voice quality.

jitter_total: FLOAT

Sum of the jitter value for each packet, in milliseconds.

jitter_max: FLOAT

Average jitter value for the RTP packets from the call.

latency: INTEGER

Latency as reported by the client's User Agent, when available.

r_factor: FLOAT

R-factor value for voice quality.

rtcp: OBJECT

If present, this optional object contains the following fields:

  • start_ts: DATETIME

    The timestamp of the first measured RTP packet.

  • end_ts: DATETIME

  • The timestamp of the last measured RTP packet.

  • jitter_max: FLOAT

    Maximum jitter value for a single packet, in milliseconds.

  • jitter_avg: FLOAT

    Average jitter value for the RTP packets from the call.

  • packets_lost: INTEGER

    Packets lost for the RTP stream.

  • source: STRING

    Source Device Name.


class libpalladion.scripting.Chunk(facade)

This class represents a single chunk of voice quality data.

It cannot be invoked directly. It is used for the return objects of the method getVoiceQualityChunks for Call objects.

For more information on how Operations Monitor gathers voice quality data, see "Voice Quality".

Table 9-7 describes the fields for the Chunk class.

Table 9-7 Chunk Class Fields

Field Description

start_ts: DATETIME

The timestamp of the first measured RTP packet.

end_ts: DATETIME

The timestamp of the last measured RTP packet.

received: INTEGER

The number of RTP packets received.

expected: INTEGER

The number of RTP packets expected.

codec: STRING

The codec used for this chunk.

pkt_delay_variation_us: DOUBLE

Variation on packet delay.

no_moscqe_reason: STRING

If there is no MOS data, its cause.


class libpalladion.scripting.Device(facade)

This class represents a platform device configured in Operations Monitor. For a general introduction on platform devices in Operations Monitor, see "Platform Devices".

Table 9-8 describes the fields for the Device class.

Table 9-8 Device Class Fields

Field Description

id: INTEGER

The unique numeric ID of the device.

type: STRING

The type of the device. One of 'SBC', 'PROXY','L2LB', 'GW', or 'TRUNK'.

name: STRING

The user visible name of the device.

description: STRING

A description for the device.

match_type: STRING

If the device is of type 'SBC', this value indicates how call matching is performed.

suffix: INTEGER

Some call matching types require a suffix parameter.

match_script: STRING

This attribute contains a script that specifies the call matching algorithm.

ipranges: STRING

The IP address ranges which are occupied by this device.

hw_addrs: STRING

The hardware addresses of this device.

up_since: DATETIME

A timestamp specifying the time since when the device is known to be running.

dtg: STRING

If the device is of type TRUNK and device identification via DTG/OTG URI parameters was configured, this attribute contains the value of the DTG request URI parameter to look for.

otg: STRING

If the device is of type TRUNK and device identification via DTG/OTG URI parameters was configured, this attribute contains the value of the OTG From URI parameter to look for.

getCreatedCalls (filter=[], keys={}, orderBy=[])

Query calls that are created by this device, that is, calls that have an outbound leg from this device and no inbound leg to this device. See Facade.query() for the meaning of the parameters.

Parameters

  • filter - A filter specification to be applied to the queried Call instances.

  • keys - Keys that the queried Call instances must match.

  • orderBy - An ordering specification.

Return type: QueryIterator over Call instances.

getRegistrationEvents (filter=[], keys={}, orderBy=[])

Query registration events that are handled by this device. See Facade.query() for the meaning of the parameters.

Parameters

  • filter - A filter specification to be applied to the queried RegistrationEvent instances.

  • keys - Keys that the queried RegistrationEvent instances must match.

  • orderBy - An ordering specification.

Return type: QueryIterator over RegistrationEvent instances.

getRelayedCalls (filter=[], keys={}, orderBy=[])

Query calls that are relayed by this device, that is calls that have an inbound leg to this device and an outbound leg from this device. See Facade.query() for the meaning of the parameters.

Parameters

  • filter - A filter specification to be applied to the queried Call instances.

  • keys - Keys that the queried Call instances must match.

  • orderBy - An ordering specification.

Return type: QueryIterator over Call instances.

getTerminatedCalls (filter=[], keys={}, orderBy=[])

Query calls that are terminated by this device, that is, calls that have an inbound leg to this device and no outbound leg from this device. See Facade.query() for the meaning of the parameters.

Parameters

  • filter - A filter specification to be applied to the queried Call instances.

  • keys - Keys that the queried Call instances must match.

  • orderBy - An ordering specification.

Return type: QueryIterator over Call instances.


class libpalladion.scripting.Counter(facade)

A Counter is an object in Operations Monitor that takes periodic measurements of a numeric property of the monitored platform. For a general introduction on counters, see "KPI/Metrics".

Table 9-9 describes the fields for the Counter class.

Table 9-9 Counter Class Fields

Field Description

id: INTEGER

A unique identifier for the counter.

name: STRING

The name of the counter.

maintype: INTEGER

The main type of the counter.

subtype: INTEGER

The sub type of the counter.

device: STRING

The device this counter belongs to. May be None.

p1: STRING

The first parameter for the counter.

p2: STRING

The second parameter for the counter.

p3: STRING

The third parameter for the counter.

sec: INTEGER

The last second measurement.

m_avg: FLOAT

The last minute average of measurements.

h_avg: FLOAT

The last hour average of measurements.

getHourValues (span, offset=0)

Query hour average values from the counter history. The returned query iterator yields a dict instance for each hour in the supplied time span. The yielded dict instances contain the keys avg, min, max and sum, with the obvious meanings. The time span is given by the parameters span and offset, where offset specifies the end point of the time span relative to the current time.

Parameters

  • span - The length of the queried time span in seconds.

  • offset - The offset of the queried time span from the current time, specified in seconds.

Return type: QueryIterator over dict instances.

getMinuteValues (span, offset=0)

Query minute average values from the counter history. The returned query iterator yields a dict instance for each minute in the supplied time span. The yielded dict instances contain the keys avg, min, max, and sum, with the obvious meanings. The time span is given by the parameters span and offset, where offset specifies the end point of the time span relative to the current time.

Parameters

  • span - The length of the queried time span in seconds.

  • offset - The offset of the queried time span from the current time, specified in seconds.

Return type: QueryIterator over dict instances.


class libpalladion.scripting.Alert(facade)

This class represents alerts raised by Operations Monitor. Table 9-10 describes the fields for the Alert class.

Table 9-10 Alert Class Fields

Field Description

ts: DATETIME

The time when this alert was raised.

type: STRING

The type of the alert raised.

subtype: STRING

The sub type of the alert raised.

new: BOOLEAN

Whether this alert is new or read.

message: STRING

The message issued when raising the alert.

details: STRING

Some details about the raised alert.

prio: INTEGER

The priority of the alert.


class libpalladion.scripting.RegisteredUser(facade)

This class represents a registered user. Table 9-11 describes the fields for the Registered User class.

Table 9-11 Registered User Class Fields

Field Description

identifier: STRING

Username of the registered user.


class libpalladion.scripting.QueryIterator(facade,query_handle, cls=None)

Instances of this class can be used to iterate over query result sets. You cannot instantiate a QueryIterator directly, but various query methods in this API return QueryIterator instances.

Instances conform to the Python iterator protocol and can be used in 'for item in iterable:' constructs. You can also use the next() method directly to retrieve one result at a time. QueryIterator instances also provide a close() method, which frees resources tied by the query. Once close() has been called, iteration stops. close() is called automatically when all references to a QueryIterator instance are gone.

Table 9-3 describes the fields for the Query Iterator class.

Table 9-12 Query Iterator Class Fields

Field Description

close()

Free the resources tied up by the query.

next()

Return the next item in the query result set.

Return type: Depends on the type of query.


Using the Apps API Examples

The following app searches the Operations Monitor database for calls which have a given Call-ID header and have been set up between two given points in time:

from libpalladion.scripting.Model import Call, Leg
  
def run(facade, args):
  
    # Get input parameters
    start_ts = args.get("start_ts")
    end_ts = args.get("end_ts")
    callid = args.get("callid")
  
    callid = callid.strip()
  
    for call in facade.getCalls(
          filter=[Call.setup_start_ts >= start_ts, Call.setup_start_ts <= end_ts]
        ):
        # search for the specific callid in all the call legs
        # the callid of each call leg might be different
        for leg in call.getLegs():
             if leg.callid == callid:
                 facade.addResult(
                    {"id": call.id},
                    on_duplicate_key='ignore'
                 )
  

This app has to be packaged with an app specification file, which should specify the type of the result table (calls in this case), and the names and types of the parameters callid, start_ts, and end_ts. The following specification file achieves this:

<?xml version="1.0" encoding="utf-8"?>
<script xmlns="http://iptego.de/palladion/script-spec"
   name="Call-Id Search"
   description="This script will find all the calls with a given Call-ID value"
   result-type="calls">
   <param-spec>
     <param name="start_ts" label="Started after" type="datetime" required="yes"/>
     <param name="end_ts" label="Started before" type="datetime" required="yes"/>
     <param name="callid" label="Call-Id" type="string" required="yes"/>
   </param-spec>
</script>
  

Note, that the parameters specified as datetime are passed as the standard Python datetime type. If the result-type of an app is specified as calls, it has a result table with one integer column, ID. When displaying the results table of such an app in the user interface, a join with the calls table is performed. In the example above, the call to facade.addResult has to be surrounded by try ... except because there can be multiple libpalladion.scripting.Leg objects, with the same ID attribute. This is because a call can have multiple legs. Adding the same ID twice to the calls result table results in a duplicate key error.

In the next example we look at an app that requires a custom result table. We will see how this custom result table can be specified in the app specification file. The app calculates a statistics of which user agents use which codecs how often. Again the source data for the app is restricted to calls that were set up between two given points in time.

from libpalladion.scripting.Model import Call
  
def run(facade, args):
    start_ts = args.get("start_ts")
    end_ts = args.get("end_ts")
  
    stats = {}
    filter = [Call.setup_start_ts > start_ts, Call.setup_start_ts <= end_ts]
    for call in facade.getCalls(filter=filter):
        ua = call.src_ua
        if ua is not None:
            codecs = call.src_codecs
            if (ua, codecs) not in stats:
                stats[(ua, codecs)] = 0
            stats[(ua, codecs)] += 1
  
    for ((ua, codecs), count) in stats.items():
         facade.addResult({'ua': ua, 'codecs': codecs, 'count': count})
  

The facade.addResult call on the last line makes the assumption that the result table has the columns ua, codecs, and count. So this schema has to be specified in the script specification file.

<?xml version="1.0" encoding="utf-8"?>
<script xmlns="http://iptego.de/palladion/script-spec"
    name="Statistics of which user agent uses which codecs"
    description="This app calculates a statistic of which user agents use which codecs"
    result-type="custom">
    <param-spec>
        <param name="start_ts" label="Start time" type="datetime" required="yes"/>
        <param name="end_ts" label="End time" type="datetime" required="yes"/>
    </param-spec>
    <result-schema>
        <column name="ua" type="VARCHAR(255)" null="false"/>
        <column name="codecs" type="VARCHAR(255)" null="false"/>
        <column name="count" type="INT(11)" null="false" default="1"/>
        <primary-key columns="ua codecs"/>
    </result-schema>
</script>

Note:

Starting with Operations Monitor 3.0 release, the apps need to be signed by Oracle before uploading to the web interface.

Remote App Procedure Calls

Remote app procedure calls provide programmatic access to the app functionality of Operations Monitor. It is possible to invoke apps installed on Operations Monitor and get their results via a simple HTTP GET interface. For more information, see "Apps" and "Implementing Apps".

Apps are possibly long running processes. Therefore invoking an app and retrieving the results of an app run have been split into two separate steps.

Invoking an App

Invoking an app is done by an HTTP GET request to the URL /scripts/run/app_name on the Operations Monitor host, where app_name is to be replaced by the identifier of an app. Note, that you can lookup the identifier of an app in the Id column of that app's entry in the Available Apps table. The parameters of the app have to be encoded as URL parameters into the GET request URL. For more information on the Apps table, see "Apps".

If invoking the app succeeds, an app run is created, and the GET request returns the numeric run ID for the app run in the response body. This run ID can later be used to retrieve the results of the app run.

There are two possible failure cases when invoking an app. First, the given app name could be invalid. In this case Operations Monitor responds with an HTTP '404 Not found' error code. Secondly, the parameters given in the request could be invalid when a required parameter is missing or a given parameter cannot be parsed. In this case Operations Monitor responds with an 'HTTP 400 Bad request' error code.

A note regarding parameter encoding is required here: Datetime values have to be encoded in a special way to make Operations Monitor recognize them. Operations Monitor expects datetime values to be in the format YYYY-mm-dd HH:MM:SS, where the 4-digit string YYYY gives the year, mm gives the month, dd gives the day, HH gives the hour, MM gives the minute, and SS gives the second.

Retrieving the Results of an App Run

Retrieving the results of an app run is done by an HTTP GET request to the URL /scripts/get/run_id on the Operations Monitor host, where run_id is a numeric run ID. Run IDs are returned when invoking an app. They can also be looked up in the Id column of the App runs table. For more information, see "Apps".

There are three possible outcomes of this request. First, if the run ID given is invalid an HTTP '404 Not found' error code is returned. Secondly, if the run ID is valid but the app run is not yet finished, an HTTP '202 Accepted' status code is returned. In this case the body of the response contains the string 202 Accepted. The third case is when the run ID is valid and the app run is finished already. In this case an HTTP '200 OK' status code is returned, and the body of the response contains the app run result table in CSV format.