Measurements API

You can use the Measurements API to retrieve collected values stored in RRD or JRB files, in Newts, and in other supported time series databases.

Unless otherwise specified, all units of time are expressed in milliseconds.

GET (reading data)

Measurements API GET function
Resource Description

/measurements/{resourceid}/{attribute}

Retrieve the measurements for a single attribute.

This table shows all supported query string parameters and their default values:

Parameter Description Default

start

Timestamp. If > 0, the timestamp is relative to the UNIX epoch (January 1st 1970 00:00:00 AM).
If < 0, the timestamp is relative to the end option (for example, default value is 4 hours ago).

-14400000

end

Timestamp. If <= 0, the effective value is the current timestamp.

0

step

Requested time interval between rows. Actual step may differ.

300000

maxrows

When using the API to render a graph, this should be set to the graph’s pixel width.

0

aggregation

Consolidation function used (AVERAGE, MIN, MAX). The available options depend on the RRA definition.

AVERAGE

fallback-attribute

Secondary attribute that is queried if the primary attribute does not exist.

Blank

Step sizes

The step parameter behaves differently depending on the time series strategy that your Meridian instance uses.

When using persistence strategies based on RRD, the available step sizes are limited to those defined by the RRA when the file was created. The effective step size used is one that covers the requested period and is closest to the requested step size. For maximum accuracy, we recommend that you use a step size of 1.

When using Newts, you can set the step size to an arbitrary number; this is because the aggregation is performed at request time. To prevent large requests, Meridian limits the step size to a maximum of 5 minutes (the default collection rate). You can decrease this value by modifying org.opennms.newts.query.minimum_step.

cURL example

The following example demonstrates how you can use the GET function and its parameters with cURL.

This command retrieves CPU counter metrics for node 1, spanning the last two hours:

curl -u admin:admin "http://127.0.0.1:8980/opennms/rest/measurements/node%5B1%5D.nodeSnmp%5B%5D/CpuRawUser?start=-7200000&maxrows=30&aggregation=AVERAGE"

Its response resembles the following snippet:

<query-response end="1425588138256" start="1425580938256" step="300000">
  <columns>
    <values>159.5957271523179</values>
    <values>158.08531037527592</values>
    <values>158.45835584842285</values>
    ...
  </columns>
  <labels>CpuRawUser</labels>
  <metadata>
    <resources>
      ...
    </resources>
    <nodes>
      ...
    </nodes>
  </metadata>
  <timestamps>1425581100000</timestamps>
  <timestamps>1425581400000</timestamps>
  <timestamps>1425581700000</timestamps>
  ...
</query-response>

POST (reading data)

Measurements API POST function
Resource Description

/measurements

Retrieve the measurements for one or more attributes, possibly spanning multiple resources, with support for JEXL expressions.

In this case, we use a POST function instead of a GET to retrieve the measurements. This lets you perform complex queries that are difficult to express in a query string.

You cannot use these requests to update or create new metrics.

cURL example

The following example demonstrates how you can use the POST function with cURL.

This command retrieves the bits in and bits out metrics for a specified interface. Calculations are then performed on the bits out metric and only the derived values are returned:

curl -X POST  -H "Accept: application/json" -H "Content-Type: application/json" -u admin:admin  -d @report.json  http://127.0.0.1:8980/opennms/rest/measurements

The derived values are dumped into report.json, and resemble the following snippets:

report.json example
{
    "start": 1425563626316,
    "end": 1425585226316,
    "step": 10000,
    "maxrows": 1600,
    "source": [
        {
            "aggregation": "AVERAGE",
            "attribute": "ifHCInOctets",
            "label": "ifHCInOctets",
            "resourceId": "nodeSource[Servers:1424038123222].interfaceSnmp[eth0-04013f75f101]",
            "transient": "false" (1)
        },
        {
            "aggregation": "AVERAGE",
            "attribute": "ifHCOutOctets",
            "label": "ifHCOutOctets",
            "resourceId": "nodeSource[Servers:1424038123222].interfaceSnmp[eth0-04013f75f101]",
            "transient": "true" (2)
        }
    ],
    "expression": [
        {
            "label": "ifHCOutOctetsNeg",
            "value": "-1.0 * ifHCOutOctets",
            "transient": "false" (1)
        }
    ]
}
1 Indicates that the attribute will be included in the response.
2 Indicates that the attribute will not be included in the response; the query returns only the calculated expression result.
All attributes referenced in an expression query must be requested individually by setting their transient value to true or false, as appropriate. This ensures that the query response includes only the attributes that you want to enumerate.
Response example
{
    "step": 300000,
    "start": 1425563626316,
    "end": 1425585226316,
    "timestamps": [
        1425563700000,
        1425564000000,
        1425564300000,
        ...
    ],
    "labels": [
        "ifHCInOctets", (1)
        "ifHCOutOctetsNeg" (1)
    ],
    "columns": [
        {
            "values": [
                139.94817275747508,
                199.0062569213732,
                162.6264894795127,
                ...
            ]
        },
        {
            "values": [
                -151.66179401993355,
                -214.7415503875969,
                -184.9012624584718,
                ...
            ]
        }
    ],
    "metadata": {
        "resources": [
            {
                "id": "nodeSource[Servers:1424038123222].interfaceSnmp[eth0-04013f75f101]",
                "label": "eth0-04013f75f101",
                "name": "eth0-04013f75f101",
                "parent-id": "nodeSource[Servers:1424038123222]",
                "node-id": 1
            },
            {
                "id": "nodeSource[Servers:1424038123222].interfaceSnmp[eth0-04013f75f101]",
                "label": "eth0-04013f75f101",
                "name": "eth0-04013f75f101",
                "parent-id": "nodeSource[Servers:1424038123222]",
                "node-id": 1
            }
            ],
            "nodes": [
            {
                "id": 1,
                "label": "Test Server",
                "foreign-source": "Servers",
                "foreign-id": "1424038123222"
            }
        ]
    }
}
1 Attributes whose transient property is set to false in report.json.

Advanced expressions

The JEXL 2.1.x library is used to parse expression strings. This also lets you include Java objects and predefined functions in your expressions.

JEXL uses a context that Meridian pre-populates with the results of your query. Several constants and arrays are also predefined as references in the context:

Constant/Prefix Description

__inf

Double.POSITIVE_INFINITY

__neg_inf

Double.NEGATIVE_INFINITY

NaN

Double.NaN

__E

java.lang.Math.E

__PI

java.lang.Math.PI

__diff_time

Time span between the start and end of samples.

__step

Difference in time between subsequent values.

__i

Index into the samples array that the present calculation references.

__AttributeName (where AttributeName is the searched-for attribute)

This returns the complete double[] array of samples for AttributeName.

Meridian predefines a number of functions that you can use in expressions. They are referenced by namespace:function, and they all return a Java double value:

Function Description Example

jexl:evaluate("_formula"):

Passes a string to the JEXL engine to evaluate as if it were entered as a normal expression.
Like normal expressions, expressions evaluated through this function return a Java double value. This lets you reference and evaluate a formula that has been stored in Meridian as a string variable. Because of this, you can define and store a per-node and per-value correction formula that can normalize samples from different sample sources.

None

math:

References the java.lang.Math class.

math:cos(20)

strictmath:

References the java.lang.StrictMath class.

math:cos(20)

fn:

References the org.opennms.netmgt.measurements.impl.SampleArrayFunctions class. This contains several functions that can reference previous samples in the time series.

None

fn:arrayNaN("sampleName", n)

References sample N in the defined sample series and replaces the N samples before the start of the series with NaN.

fn:arrayNaN("x", 5)

fn:arrayZero("sampleName", n)

References sample N in the defined sample series and replaces the N samples before the start of the series with 0.

fn:arrayZero("x", 5)

fn:arrayFirst("sampleName", n)

References sample N in the defined sample series and replaces the N samples before the start of the series with the first sample.

fn:arrayFirst("x", 5)

fn:arrayStart("sampleName", n, constant)

References sample N in the defined sample series and replaces the N samples before the start of the series with a supplied constant.

fn:arrayStart("x", 5, 10)

With these additional expressions you can, for example, create a finite impulse response filter function such as y = a * f(n) + b * f(n-1) + c * f(n-2) using the following expression:

a * x + b * fn:arrayNaN("x", 1) + c * fn:arrayNaN("x", 2)

Here, a, b, and c are string constants, and x is a time series value.