Ingesting Metrics with the Push Metrics REST API

Last updated on 16 November, 2023

You can use LogicMonitor Push Metrics REST API to programmatically ingest metrics for multiple instances associated with single or multiple resources and DataSource.

The Push Metrics REST API requires authorization using either the LMv1 API token or the Bearer token. For more information, see API Tokens and Bearer Token.

Request Information

The metric ingestion endpoint is used to push metrics of one or more instances associated with a DataSource and resource. Only one resource and DataSource is supported per request. If this is the first time metrics are being pushed to a resource, this request will result in a new DataSource and optionally a new resource (depending on parameters).

MethodPost
Base URLhttps://{ACCOUNTNAME}.logicmonitor.com/rest
Pathmetric/ingest
HeaderAuthorization: LMv1 token or Bearer token
Parameter(Optional)https://companyxyz.logicmonitor.com/rest/metric/ingest?create=trueIf create=true, a new resource will be created if there is no match for the provided resource IDs. The default value is “false”.
Content-Typeapplication/json
{
    “resourceName”: “<Resource name>”,  //Optional when create flag is not specified             
    “resourceDescription”: “<Resource description>”,
    “resourceIds” : {                      //Mandatory
        “key1” : “value1”,
        “key2” : “value2”,…             //Multi-values accepted
    },                                                                     
    “resourceProperties”: {
        “key1” : “value1”,
        “key2” : “value2”            //Multi-values accepted
     },
    “dataSourceId”: “<DataSource ID>”   //Either dataSourceId or dataSource mandatory
    “dataSource”: “<DataSource Name>”   //Either dataSourceId or dataSource mandatory
    “dataSourceDisplayName”: “<Display Name for the DataSource>”
    “dataSourceGroup”: “<DataSource Group name>”
    “instances”:[
        {
            “instanceName”: “<Instance Name>”,         //Mandatory
            “instanceDisplayName”: “<Instance display Name>”
            “instanceProperties”: {
                “key1” : “value1”,
                “key2” : “value2”
        },
            “dataPoints”:
            [
                {
                    “dataPointName”: “<Datapoint Name>”,        //Mandatory
                    “dataPointDescription”: “<Datapoint Description>”,
                    “dataPointType”: “<Datapoint Metric Type>”,
                    “dataPointDataType”: “<Datapoint Data Type>”,
“values”: { //Mandatory
“Epoch Timepstamp” : “Metric Value”
}
}
]
}
]
}

Use the following mandatory and optional fields in your request.

Field NameDescriptionTypeRequired?Validations
resourceNameResource unique name. Only considered when creating a new resource. StringRequired only if the create parameter is set to TRUE (create=true). FALSE is the default.– 255-character limit
– Must be unique
– Should not start or end with spaces, tabs, etc
– Should not contain line breaks
– Characters from A-Z, a-z, and 0-9 allowed as well as colons, hyphens, underscores and full stops
– No whitespace allowed
resourceDescriptionResource description. Only considered when creating a new resource.StringOptional. Defaults to “”.– 65535-character limit
resourceIdsAn array of existing resource properties are used to identify the resource. For more information on the types of properties that can be used, see Managing Resources that Ingest Push Metrics for information on the types of properties that can be used. If no resource is matched and the create parameter is set to TRUE, a new resource is created with these specified resource IDs set on it. If the system.displayname and/or system.hostname property is included as resource IDs, they will be used as host name and display name respectively in the resulting resource.
Note:  Resource IDs provided need not fully or partially match (Logical And, OR) for the existing resources.
JSON objectRequired– Takes input as key-value pairs in the form of property name and assigned value (For example, “system.displayname” : “mcentos”)
– Keys and values are strings
– All characters except , ; / * [ ] ? ‘ ” ` ## and newline are allowed
-Spaces allowed except at start or end
– Keys and values should not contain backslashes (\)Null key and value are not allowed
– Keys have 255-character limits; values have 24000-character limits
– Case insensitive
resourcePropertiesNew properties for resource. Updates to existing resource properties are not considered. Depending on the property name, we will convert these properties into system, auto, or custom properties.JSON objectOptional. Defaults to “”.– Takes input as key-value pairs in the form of property name and assigned value (Example: “version” : “5.0”)
– System properties are not allowed (For example, system.xxx)
– Auto properties are not allowed (For example, auto.xxx)
– Reserved properties are not allowed (For example, predef.xxx)
– Keys and values are stringsAll characters except , ; / * [ ] ? ‘ ” ` ## and newline are allowed
– Spaces allowed except at start or end
– Keys and values should not contain backslashes (\)
– Null key and value are not allowed
– Keys have 255-character limits; values have 24000-character limitsCase insensitive
dataSourceIdDataSource unique ID. Used only to match an existing DataSource. If no existing DataSource matches the provided ID, an error results.
If this field is used in combination with the dataSource field, both the ID and name provided must match a single DataSource or an error results.
IntegerEither dataSourceId or dataSource is mandatory.– 9-digit limit
– Only positive whole numbers allowed
dataSourceDataSource unique name. Used to match an existing DataSource. If no existing DataSource matches the name provided here, a new DataSource is created with this name.
If this field is used in combination with the dataSourceId field, both the ID and name provided must match a single DataSource or an error is returned.
StringEither dataSourceId or dataSource is mandatory.– 64-character limit
– Must be unique
– All characters except , ; / * [ ] ? ‘ ” ` ## and newline are allowed
– Spaces allowed except at start or end
– Hyphen allowed only at the end; hyphen must be used with at least one other character
dataSourceDisplayNameDataSource display name. Only considered when creating a new DataSource.StringOptional.
Defaults to dataSource.
– 64-character limit
– All characters except , ; / * [ ] ? ‘ ” ` ## and newline are allowed
– Spaces are allowed except at start or end
– Keys and values should not contain backslashes (\)
– Hyphen allowed only at the end; hyphen must be used with at least one other character
dataSourceGroupDataSource group name. Only considered when DataSource does not already belong to a group. Used to organize the DataSource within a DataSource group. If no existing DataSource group matches, a new group is created with this name and the DataSource is organized under the new group.StringOptional.
Defaults to “PushModules”.
– 128-character limit
– Only supports characters from A-Z, a-z, 0-9, colon, hyphen, underscore, and whitespace
– Values should not be null, empty, or having trailing spaces
instancesAn array of DataSource instances.JSON objectRequired
instanceNameInstance name. If no existing instance matches, a new instance is created with this name.StringRequired– 255-character limit
– All characters except , ; / * [ ] ? ‘ ” ` ## and newline are allowed
– Spaces allowed except at start or end
– Should not contain backslashes (\).
– Only supports characters from A-Z, a-z, 0-9, colon, hyphen, underscore, and full stop
– No whitespace allowed
instanceDisplayNameInstance display name. Only considered when creating a new instance.StringOptional. Defaults to {instanceName}.– 255-character limit
– All characters except , ; / * [ ] ? ‘ ” ` ## and newline are allowed
– Spaces allowed except at start or end
– Should not contain backslashes (\).*<?,;`\\n characters not allowed
instancePropertiesNew properties for instance. Updates to existing instance properties are not considered. Depending on the property name, we will convert these properties into system, auto, or custom properties.JSON objectOptional.
Defaults to “”.
– Takes input as key-value pairs in the form of property name and assigned value
– System properties are not allowed (For example, system.xxx)
– Auto properties are not allowed (For example, auto.xxx)
– Reserved properties are not allowed (For example, predef.xxx)
– Keys and values are stringsAll characters except , ; / * [ ] ? ‘ ” ` ## and newline are allowed
– Spaces allowed except at start or end
– Keys and values should not contain backslashes (\)
– Keys have 255-character limits; values have 24000-character limits
– Case insensitive
– Keys and values should not be null, empty, or having trailing spaces
dataPointNameDatapoint name. If no existing datapoint  matches for specified DataSource, a new datapoint is created with this name.StringRequired– 128-character limit
Characters from A-Z, a-z, and 0-9 only allowed
– Should not contain reserved keywords such as COS, SIN, etc.
dataPointDescriptionDatapoint description. Only considered when creating a new datapoint.StringOptional.
Defaults to {dataPointName}.
1024-character limit
dataPointTypeMetric type as a number in string format. Only considered when creating a new datapoint.StringOptional.
Defaults to “gauge”.
– Only values of  “counter”, “derive”, or “guage” accepted
– Case insensitive
dataPointAggregationTypeThe aggregation interval is for one minute.
The aggregation is calculated based on the aggregation type (sum/average/none/min/max) of the data occurring within a minute.
For more information, see
About the Push Metrics REST API.
StringOptional.
Defaults to “none”.
– Only values of “min”, “max”, “none”, “avg”, “sum”, or “percentile” accepted
– Case insensitive
percentileValueIf “percentile” is specified for dataPointAggregationType, this field is required for specifying the percent value to use.IntegerRequired when dataPointAggregationType is percentile– Any whole number percentage between 0-100.
Example: 99|95|90|70|50 (no default)
valuesAn array of datapoint values JSON objectRequired–Takes input as key-value pairs in the form of epoch time and datapoint value. Example: “1584902069” : “10″
-Only long type values accepted in keys
–Digits accepted in values or scientific notation Example:4.93e-2, 1.89502e202

Support for Ingesting Multiple Resources

The rest/v2/metric/ingest API allows the ingestion of multiple resources at a time in a single API call. The create and match type API parameters apply to all the multiple ingested resources. 

Multiple Resource Payload Ingestion

[
    {
        single resource payload
    },
    {
        single resource payload
    }
]

Multiple Resource Response

{
    "success": false,
    "message": "Some events were not accepted. See the 'errors' property for additional information.",
    "errors" : [
        {
            "code": <custom code>,
            "message": "The request has been accepted for processing, but the processing has not been completed.",
            "resourceIds": {
                "system.displayname": "test088"
            },
        },
        {
            "message": "Resource Name is mandatory.",
            "resourceIds": {
                "system.displayname": "test096"
        },
    }
}

Example of Ingesting Metrics using Push Metrics REST API

The following Python 3 example monitors CPU utilization.

#!/usr/bin/env python3
import time, os, sys
import hmac, hashlib, base64
import requests
import json
import psutil

#--------------------------------------
# Constants - Do not change
#--------------------------------------
resource_path = '/metric/ingest'
headers =  {
	   'Content-Type': 'application/json'
	  }

#---------------------------------------
# Change Values below as per your setup
#---------------------------------------
def get_params():
	# Account info
	# Your account name
	Company = "ABC"
	# User account Access Id for which it must have permissions to manage resources and manage LogicModules 
	AccessId = "6wDEvh73taGMPP43SSmF"
	AccessKey = 'Q)cfY2w8u[G97jkz5^P8{HT)g-uq[6+E8LL%Mb{^'

	url = "https://"+Company+".logicmonitor.com/rest"+ resource_path
	return url, AccessId, AccessKey


#--------------------------------------------
# Function to send metric data to LM Platform
#--------------------------------------------
def send_metrics(timestamp, body):
		url, AccessId, AccessKey  = get_params()
		req_var =  "POST" + str(timestamp) + body +resource_path;
		signature = base64.b64encode(bytes(hmac.new(
                            bytes(AccessKey, 'latin-1'),
                            bytes(req_var, 'latin-1'),
                            digestmod=hashlib.sha256
                        ).hexdigest(), 'latin-1')).decode('latin-1')
		auth = "LMv1 "+AccessId+ ":"+ signature+":"+str(timestamp)
		headers['Authorization'] =  auth
		try:
			response = requests.post(url, verify=True, headers=headers, data=body,  params={"create":'true'})
			if response.status_code != 202:
				print('Failed to send metric. Error:', response.status_code, response.text)
			else:
				print("SUCCESS :",response.text)
		except Exception as e:
			print("Unable to connect. Error: ", e)

#--------------------------------------------
# Prepare REST payload
#--------------------------------------------
def prepare_request_body(metric, timestamp, data_value):
	return json.dumps({
	    "resourceName": metric["device_name"],
	    "resourceIds": {
			"system.displayname": metric["device_name"],
			"system.ips": metric["device_ip"]
	    },
	    "dataSource": metric["data_source"],
	    "dataSourceDisplayName": metric["data_source"],
	    "instances": [
			{
				"instanceName": metric["instance"],
				"instanceDisplayName": metric["instance"],
				"instanceProperties": {
					"version": "1",
				},
				"dataPoints": [
					{
						"dataPointName": metric["data_point"],
						"dataPointType": "GAUGE",
						"dataPointAggregationType": "sum",
						"values": {
							str(timestamp//1000): data_value
						}
					},
		    	]
			},
	    ]
	}).replace("'", '"')


#------------------
#====  MAIN =======
#------------------
if __name__ == "__main__":
	my_metric = {}
	my_metric["device_name"] = os.uname()[1]
	my_metric["device_ip"] = "192.168.1.1"
	my_metric["data_source"] = "CPU"
	my_metric["instance"] = "cpu-1"
	my_metric["data_point"] = "cpu_utilization"
	while True:
		timestamp = int(time.time()*1000)
		data_value = psutil.cpu_percent()

		body = prepare_request_body(my_metric, timestamp, data_value)
		send_metrics(timestamp, body)
		time.sleep(10)

In This Article