Skip to content

Counters Guide

Counters are sum or count queries that can be run on transactions and routing orders.

These queries can be scheduled using CRON expressions.

They can also be manually triggered from the user interface. Read the Counters user interface to learn how to synchronize a counter from the Platform 6 Portal.

The results of the queries, called counter’s value can be queried from monitoring tools (Grafana, Nagios, Centreon …) and used to draw graphs or to trigger alerts.

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 or routing orders
data partition When queries are run on Item, the Data partition to the user; usually TRANSACTION for documents like TransactionInfo
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 as in /TransactionInfo[FinalRecipient="BankOfAmerica"]

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 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 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 scheduling

Counters’s queries can be scheduled using CRON expressions.

Let’s take the example of a counter which 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"
}

With the user interface

Once the counter is created, you can manually recalculate it through the user interface.

If there are 24 failed routing orders, the counter’s value will be:

{
    "value": 24,
    "lastSyncDate": 1534853700107
}

(where lastSyncDate is the last calculation date).

You can try to recreate a failing routing order and check after calculation that the counter’s new value is 25.

However, you can’t spend your time clicking on the calculation button, especially if you have hundreds of counters.

With the Routes service

You can automate the calculation task thanks to the Routes service.

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:

camel.destroyAllRoutes()

In the script segment addRoutes, we’ll 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 our CRON scheduling section. It will explain the required format and show some examples.

Thus, if we decide to synchronise our 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 automatically be calculated every 10 seconds.

Remote access to counters values

For a remote access you must declare specific 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.

Enumerate all deployed counters

You need to define a script (ie. named 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")

You can now access to your route via the 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.

Access a counter’s value

You need to define a script (ie. named 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")

You can now access to your route via the 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.

Access a synchronized counter’s value

You need to define a script (ie. named 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")

You can now access to your route via the 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 the counter’s value.