Counters

The counters service allows managing Sum or Count queries that can be run on transactions, routing orders, logs or table data. The results of these queries are called counter values.

Counters can be leveraged to display KPIs in home pages, or be queried from monitoring tools (Grafana, Nagios, Centreon …) and used to draw graphs or to trigger alerts.

The synchronization or refresh of counters can be performed from the Portal user interface or scheduled using cron expressions.

Read the page about the Counters user interface to learn more about how to handle counters via P6 Portal.

Counter’s parameters

A counter consists of several attributes.

Parameter Description
name The name of the counter
description The multi-language description of the counter
target Determines if the query is going to be run on transactions, logs, table data or routing orders
type Determines if the counter’s value is calculated by running a Sum or Count query
query An XPath (XML Path Language) expression

XPath expressions

Validation

Valid XPath expressions are tightly coupled to the XML capabilities of the underlying database:

  • PostgreSQL supports XPath 1.0 expressions

Root elements

Routing order XPaths should always start with /routingOrder.

Transaction XPaths should start with a slash followed by the transaction type name, for example /TransactionInfo

Date & time variable expansions

To facilitate writing XPaths relative to time, two variable expansions are provided for date and time.


Date

The ${DATE} variable will be expanded to a timestamp:

  • The format of the timestamp is specified by the p6.service.counters.date.format configuration and defaults to yyyyMMdd'T'HH:mm:ss.S z.
  • The timezone short form (CST, CDT, etc…) is specified by the p6.service.counters.date.timezone configuration and defaults to the server time zone.

Time

The ${TIME} variable will be expanded to an epoch (the number of milliseconds since January 1st, 1970).


Calculations can be performed on DATE and TIME using the following syntax: ${[DATE|TIME]([+|-]\d+[s|m|h|d|M|y])*} where:

  • s: seconds
  • m: minutes
  • h: hours
  • d: days
  • M: months
  • y: years

Examples

Assuming the current date/time is May 13th, 2013 at 11:34:57.12 CEST which is an epoch of 1368437697012 ms.

XPath Expanded
TransactionInfo[DateCreated<"${DATE-15d}"][Status="SENT"] TransactionInfo[DateCreated<"20130428T11:34:57.12 CEST"][Status="SENT"]
TransactionInfo[DateSent>"${DATE-2d+1h}"][Status="SENT"] TransactionInfo[DateSent>"20130511T12:34:57.12 CEST"][Status="SENT"]
TransactionInfo[DateCreated<"${DATE-15d}"][DateSent>"${TIME-2d+1h}"][Status="SENT"] TransactionInfo[DateCreated<"20130428T11:34:57.12 CEST"][DateSent>"1368268497012"][Status="SENT"]

Counters synchronization

Once the counter is created, you will want to show its value - so you will need to ‘synchronize’ it (i.e. calculate or refresh its value).

Let’s take the example of a counter that counts the number of failed routing orders.
The counter‘s properties will look like:

{
    "appKey": "",
    "name": "Count_FailedRoutingOrders",
    "description": { "EN": "Number Of Failed Routing Orders" },
    "query": "/routingOrder",
    "target": "FailedRoutingOrder",
    "type": "COUNT"
}
If there are 24 failed routing orders, the counter‘s value will be:

{
    "value": 24,
    "lastSyncDate": 1534853700107
}
(where lastSyncDate is the last calculation date).

Synch counters via the Portal

Counters can be synchronized via the Portal user interface, as explained on this section of the Counters UI page.

Synch counters via a route

You can automate the synchronization or refresh of counters leveraging the Routes service and cron expressions:

Go to the Routes service user interface and create a new route deployment script.
Choose a name (eg: Count_FailedRoutingOrders), a description, select the type Scheduler and the template BaseRoute.groovy.

In the script segment destroyRoutes, enter the following line:

p6.camel.destroyAllRoutes()

In the script segment addRoutes, you can define the route using the Camel component Quartz2.

The purpose of the route will be to ask the Counters service to calculate the counter which id is Count_FailedRoutingOrders at a period determined by a cron expression.

For any counter, the route will look like this:

from("quartz2://platform6/p6route_${COUNTER_ID}?cron=${CRON_EXPRESSION}")
    .to('p6cmb://counters?platform6.request.action=synchronize&id=${COUNTER_ID}')
    .routeId('${ROUTE_ID}')

The parameters are:

  • COUNTER_ID: the counter‘s identifier
  • CRON_EXPRESSION: the cron expression
  • USER_EMAIL_ADDRESS: the email address of the user scheduling the counter (eg: admin@amalto.com)
  • ROUTE_ID: it can be anything that you want, but it must be unique. We suggest you also use the counter‘s id

For some information about cron expressions, have a look at the Cron Scheduling section. It will explain the required format and show some examples.

Thus, if we decide to synchronize the Count_FailedRoutingOrders counter every 10 seconds, the route will look like as follow:

from("quartz2://platform6/p6route_Count_FailedRoutingOrders?cron=0/10+*+*+*+*+?")
    .to('p6cmb://counters?platform6.request.action=synchronize&id=Count_FailedRoutingOrders')
    .routeId('Count_FailedRoutingOrders')

Enable the route deployment script and save it.

Finally, start the route deployment script. As long as the job is running, the counter will be automatically calculated every 10 seconds.

Remote access to counters

Remote access to counters require the creation of specific scripts and routes.

Authentication

All Platform 6 RESTful services are guarded with basic authentication. The username/passwords used are those defined using the Platform 6 user administration.

List counters

In order to list all the counters available on your instance, you first need to define a script (say ‘CounterList’):

p6.pipeline.put("body", p6.counter.list())

And then define the corresponding route:

rest("/public/counters")
    .get("/list")    
    .to("p6cmb://scripts?platform6.request.action=execute&id=CounterList")
    .id("CounterList")

Once done, you will have access your route via the following URL:

http://<hostname>:8080/p6/public/counters/list

Where:

  • <hostname>: the host running the Platform 6 instance.

The response is text/plain and contains a list of all deployed counters in a JSON text format.

Retrieve a counter’s value

In order to remotely retrieve a counter‘s value, you first need to define a script (say ‘CounterDetail’):

p6.pipeline.put("body", p6.counter.get(p6.pipeline.get("counter")))

And then define the corresponding route:

rest("/public/counters")
    .get("/detail/?counter={counter}")
    .to("p6cmb://scripts?platform6.request.action=execute&id=CounterDetail&counter={counter}")
    .id("CounterDetail")

Once done, you will have access to your route via the following URL:

http://<hostname>:8080/p6/public/counters/detail?counter=<countername>

Where:

  • <hostname>: the host running the Platform 6 instance
  • <countername>: the name of the counter to query

Warning

If a counter’s name contains spaces then the URL will require this name to be escaped.

The response is text/plain and contains the detail of the counter in a JSON text format.

Synchronize a counter and retrieve its value

In order to remotely synchronize a counter and retrieve its value, you will first need to define a script (say ‘CounterSync’):

p6.pipeline.put("body", p6.counter.synchronize(p6.pipeline.get("counter")))

And then define the corresponding route:

rest("/public/counters")
    .get("/sync/?counter={counter}")
    .to("p6cmb://scripts?platform6.request.action=execute&id=CounterSync&counter={counter}")
    .id("CounterSync")

Once done, you will have access to your route via the following URL:

http://<hostname>:8080/p6/public/counters/sync?counter=<countername>

Where:

  • <hostname>: the host running the Platform 6 instance
  • <countername>: the name of the counter to query

Warning

If a counter’s name contains spaces then the URL will require this name to be escaped.

The response is text/plain and contains the counter‘s value.