Introduction
The REST API for the data historian is currently exposing the following enpoints:
-
/api/historian/v0 : The main API of the historian which currently only contains endpoints for importing and exporting data.
-
POST /api/historian/v0/import/csv: Un endpoint pour importer des measures depuis des fichiers csv.
-
POST /api/historian/v0/import/json: An endpoint to import measures sent in the body of the request, in json format .
-
POST /api/historian/v0/export/csv: An endpoint to export measures in csv format.
-
GET /api/grafana/simplejson: The API to interact with Grafana using the "SimpleJson" datasource plugin.
-
POST /api/grafana/simplejson/query: Used to obtain historian measures from a query.
-
POST /api/grafana/simplejson/search: Get names of historian metrics.
-
POST /api/grafana/simplejson/annotations: Used to obtain the annotations stored in the historian.
-
POST /api/grafana/simplejson/tag-keys: Get the keys available to use the endpoint '/api/grafana/simplejson/tag-values'.
-
POST /api/grafana/simplejson/tag-values: Get the possible values for the specified key.
-
GET /api/grafana/v0: The API to interact with Grafana using the hurence "Hurence-Historian" datasource plugin.
-
POST /api/grafana/v0/query: Get the measures of the historian.
-
POST /api/grafana/v0/search: Get the name of the metrics stored in the historian.
-
POST /api/grafana/v0/search/values: Get the values for the specified key.
-
POST /api/grafana/v0/annotations: Get the annotations stored in the historian.
-
POST /api/grafana/v0/tag-keys: Get the keys available to use the endpoint '/api/grafana/v0/tag-values'.
-
POST /api/grafana/v0/tag-values: Get the possible values for the specified key.
The 'tag-keys' and 'tag-values' endpoints are only useful for Grafana.
Detailed descriptions of the API endpoints
Data injection
The following endpoints are used to inject data measures in the historian :
POST /api/historian/v0/import/csv
This request allows to inject data measures from CSV files. The format of the http request must be Content-Type: multipart/form-data;
| attribute | multivalued | description | mandatory | possible values | default value |
|---|---|---|---|---|---|
my_csv_file |
Yes |
the path of the csv files to import. Please note that each file is imported individually independently. In other words, listing several files or making a request per file is equivalent. The settings of the request are common to all the files listed in the request. The files must contain a header. |
Yes |
||
mapping.name |
No |
the name of the column that corresponds to "name". It is the main identifier of a metric. |
No |
must be a column name from the header of the attached csv files. |
"metric" |
mapping.value |
No |
the name of the column that corresponds to "value". It is the measure value. The values in this column must be numeric values. |
No |
must be a column name from the header of the attached csv files. |
"value" |
mapping.timestamp |
No |
The name of the header column which corresponds to "timestamp". It is the date of the measure. By default this column must contain an epoch timestamp in milliseconds (see format_date) |
No |
must be a column name from the header of the attached csv files. |
"timestamp" |
mapping.quality |
No |
The name of the header column which corresponds to "quality". It is the quality of the measure (quality is currently not stored in the historian - next release will provide quality) |
No |
must be a column name from the header of the attached csv files. |
"quality" |
mapping.tags |
Yes |
The names of the header columns to be considered as a tag. Tags are concepts that describe the metric in addition to its name ("name" column). All columns not entered in the mapping will be ignored during the injection. |
No |
must be a column name from the header of the attached csv files. |
|
format_date |
No |
The expected format for the values in the "timestamp" column. |
No |
Must be a value in: [MILLISECONDS_EPOCH,SECONDS_EPOCH,MICROSECONDS_EPOCH,NANOSECONDS_EPOCH] NANOSECONDS_EPOCH : the value must be the number of nanoseconds since January 1, 1970 UTC. MICROSECONDS_EPOCH : the value must be the number of microseconds since January 1, 1970 UTC. MILLISECONDS_EPOCH : the value must be the number of milliseconds since January 1, 1970 UTC. SECONDS_EPOCH : the value must be the number of seconds since January 1, 1970 UTC. Or another value, in this case this value must be a valid date format, for example "yyyy-mm-dd". |
"MILLISECONDS_EPOCH" |
timezone_date |
No |
the timezone for the dates in the csv. |
No |
must be a valid timezone. |
"UTC" |
group_by |
Yes |
This parameter is very important! If it is misused it is possible to corrupt already existing data. List all the fields that will be used to build the chunks here. By default we group the measures in chunk only according to their name. However, it is also possible to group according to the value of some tags. Be aware that this will impact the way the data will be retrieved later. For example if we inject data by grouping by "name" and the tag "factory". Then we can request the values for each factory by filtering on the correct value of the factory tag (see the API to request the measures). Only if thereafter someone injects other data without grouping by the tag "factory" then the data will find themselves mixed. |
No |
Accepted values are "name" (whatever the mapping, use "name" and not the name of the column in the csv). Otherwise the other accepted values are the column names added as a tag. |
"name" |
-
If there is a problem with the request we receive a 400 BAD_REQUEST response.
-
If everything went well we receive a 201 CREATED response:
| json path | type | description |
|---|---|---|
tags |
array |
the tags entered in the request. |
grouped_by |
array |
the fields that are used for the group by (completed in the request). |
report |
json object |
a report on the chunks that were injected. |
Example of a minimum curl command:
curl -X POST \
http://localhost:8080/historian-server/ingestion/csv \
-F 'my_csv_file=@path/de/mon/csv/file.csv'
Example of a minial csv file :
metric,timestamp,value
metric_1, 1, 1.2
metric_1, 2, 2
metric_1, 3, 3
Example of a curl command :
curl -X POST \
http://localhost:8080/historian-server/ingestion/csv \
-F 'my_csv_file=@path/de/mon/csv/file.csv' \
-F 'my_csv_file2=@path/de/mon/csv/file2.csv' \
-F mapping.name=metric_name_2 \
-F mapping.value=value_2 \
-F mapping.timestamp=timestamp \
-F mapping.quality=quality \
-F mapping.tags=sensor \
-F mapping.tags=code_install \
-F timestamp_unit=MILLISECONDS_EPOCH \
-F group_by=name \
-F group_by=tags.sensor \
-F format_date=yyyy-D-m HH:mm:ss.SSS \
-F timezone_date=UTC \
Example of a csv file :
metric_name_2,timestamp,value_2,quality,sensor,code_install
metric_1, 1970-1-1 00:00:00.001, 1.2 ,1.4,sensor_1,code_1
metric_1, 1970-1-1 00:00:00.002, 2 ,1.4,sensor_1,code_1
metric_1, 1970-1-1 00:00:00.003, 3 ,1.4,sensor_2,code_1
metric_2, 1970-1-1 00:00:00.004, 4 ,1.5,sensor_2,code_1
with the following request:
curl -X POST \
http://localhost:8080/historian-server/ingestion/csv \
-F 'my_csv_file=@path/de/mon/csv/file.csv' \
-F 'my_csv_file2=@path/de/mon/csv/file.csv' \
-F mapping.name=metric_name_2 \
-F mapping.value=value_2 \
-F mapping.timestamp=timestamp \
-F mapping.quality=quality \
-F mapping.tags=sensor \
-F mapping.tags=code_install \
-F timestamp_unit=MILLISECONDS_EPOCH \
-F group_by=name \
-F group_by=tags.sensor \
-F format_date=yyyy-D-m HH:mm:ss.SSS \
-F timezone_date=UTC \
and the following "file.csv":
metric_name_2,timestamp,value_2,quality,sensor,code_install
metric_1, 1970-1-1 00:00:00.001, 1.2 ,1.4,sensor_1,code_1
metric_1, 1970-1-1 00:00:00.002, 2 ,1.4,sensor_1,code_1
metric_1, 1970-1-1 00:00:00.003, 3 ,1.4,sensor_2,code_1
metric_2, 1970-1-1 00:00:00.004, 4 ,1.5,sensor_2,code_1
we get this respons back:
{
"tags": ["sensor", "code_install"],
"grouped_by": ["name", "sensor"],
"report" : [
{
"name": "metric_1",
"sensor": "sensor_1",
"number_of_points_injected": 4,
"number_of_point_failed": 0,
"number_of_chunk_created": 2
},
{
"name": "metric_1",
"sensor": "sensor_2",
"number_of_points_injected": 2,
"number_of_point_failed": 0,
"number_of_chunk_created": 2
},
{
"name": "metric_2",
"sensor": "sensor_2",
"number_of_points_injected": 2,
"number_of_point_failed": 0,
"number_of_chunk_created": 2
}
]
}
(we notice here that we used the same file twice)
POST /api/historian/v0/import/json
Allows you to inject measures into the historian from a request body in json format. The format of the expected request is a request with Content-Type: application / json;
Example of a request:
[
{
"name": "temp",
"measures": [
[100, 1.0],
[200, 1.2]
]
},
{
"name": "temp_2",
"measures": [
[100, 1.7],
[200, 1.9]
]
}
]
Example of a minimal request:
[
{
"name": "temp",
"measures": [
[100, 1.0]
]
}
]
The body of the expected request is a list of objects. Each object must be composed of the following attributes:
| json path | type | description | mandatory | /name | String |
|---|---|---|---|---|---|
The name of the metric for which we are going to inject the measures. |
Yes |
/measures |
Array d’array |
Points for creating a chunk with the metric name assigned to 'name'. The measures are to be completed in the form [[timestsamp<long>, value<double>],..,[timestsamp<long>, value<double>]]. |
Yes |
Example of a response
[
{
"target":"upper_75",
"datapoints":[
[622,1450754160000],
[365,1450754220000]
]
},
{
"target":"upper_90",
"datapoints":[
[861,1450754160000],
[767,1450754220000]
]
}
]
Data Exprt
POST /api/historian/v0/export/csv
Allows you to search for measures and export them to csv for the desired metrics.
This endpoint uses the same request as the endpoint query but it gives the response in csv.
Example of a response :
metric,value,date
temp_a,622.1,1477895624866
temp_a,-3.0,1477916224866
temp_a,365.0,1477917224866
temp_b,861.0,1477895624866
temp_b,767.0,1477917224866
Interactions with Grafana
The APIs below are used to interact with Grafana using certain data sources (a concept of Grafana). Depending on which plugin version you use(SimpleJson or the more recent Historian one), you will have to use the corresponding API.
Compatible API with the "SimpleJson" plugin
GET /api/grafana/simplejson
This endpoint returns a 200 'OK' response if the historian is working properly.
POST /api/grafana/simplejson/query
Used to search for measures for the desired metrics. Various parameters are available.
Example of a request:
{
"panelId": 1,
"range": {
"from": "2016-10-31T06:33:44.866Z",
"to": "2016-10-31T12:33:44.866Z",
"raw": {
"from": "now-6h",
"to": "now"
}
},
"rangeRaw": {
"from": "now-6h",
"to": "now"
},
"interval": "30s",
"intervalMs": 30000,
"targets": [
{ "target": "upper_50", "refId": "A", "type": "timeserie" },
{ "target": "upper_75", "refId": "B", "type": "timeserie" }
],
"adhocFilters": [{
"key": "City",
"operator": "=",
"value": "Berlin"
}],
"format": "json",
"maxDataPoints": 550
}
Example of a minimal request:
{
"targets": [
{ "target": "upper_50" }
]
}
| json path | type | description | mandatory | possible values | default value |
|---|---|---|---|---|---|
/targets |
array |
Allows you to enter the metrics for which you want to obtain measures. |
Yes |
||
/targets/target |
String |
The name of a metric for which we want to obtain measures. |
Yes (at least one metric must be listed) |
||
/range/from |
String |
The start date to search for measures. Only measures with a date greater than or equal to this date. |
No |
Must represent a date in the following format (UTC) : yyyy-MM-dd’T’HH:mm:ss.SSS |
January 1, 1970 (UTC) |
/range/to |
String |
The end date to search for measures. Only measures with a date less than or equal to this date. |
No |
Must represent a date in the following format (UTC): yyyy-MM-dd’T’HH:mm:ss.SSS |
The default is infinity |
/maxDataPoints |
long |
The maximum number of measures desired for each metric (Indeed the goal is to draw measures on a graph). If necessary the measures will be sampled with a default sampling algorithm. |
No |
positive |
1000 |
/adhocFilters |
String |
Used by Grafana |
No |
| The remaining parameters are parameters that are sent by Grafana but which are not currently used. |
Example of a response
[
{
"target":"upper_75",
"datapoints":[
[622,1450754160000],
[365,1450754220000]
]
},
{
"target":"upper_90",
"datapoints":[
[861,1450754160000],
[767,1450754220000]
]
}
]
POST /api/grafana/simplejson/search
Lets you search for the different metrics available.
Example of a response :
{ "target": "upper_50" }
| json path | type | description | mandatory | possible values | default value |
|---|---|---|---|---|---|
/target |
String |
Part of the name of the metric you are looking for. |
No |
| The body of the request is optional. |
Example of a response :
["upper_25","upper_50","upper_75","upper_90","upper_95"]
POST /api/grafana/simplejson/annotations
Lets you search for annotations.
Example of a request :
{
"range": {
"from": "2020-2-14T01:43:14.070Z",
"to": "2020-2-14T06:50:14.070Z"
},
"limit" : 100,
"tags": ["tag1", "tag2"],
"matchAny": false,
"type": "tags"
}
Example of the current response:
[
{
"annotation": "annotation",
"time": "time",
"title": "title",
"tags": "tags",
"text": "text"
}
]
| json path | type | description | mandatory | possible values | default value |
|---|---|---|---|---|---|
/range/from |
String |
The start date to search for annotations. Only annotations with a date greater than or equal to this date. |
No |
Must represent a date in the following format (UTC): * yyyy-MM-dd’T’HH: mm: ss.SSS * |
January 1, 1970 (UTC) |
/range/to |
String |
The end date to search for annotations. Only annotations with a date less than or equal to this date. |
No |
Must represent a date in the following format (UTC): * yyyy-MM-dd’T’HH: mm: ss.SSS * |
The default is infinity |
/limit |
Integer |
The maximum number of annotations to return |
No |
positive integer |
100 |
/tags |
Liste de string |
The name of the tags to filter the annotations. The behavior depends on the value of the _ / type_ field |
No |
[] (empty array) |
|
/matchAny |
Boolean |
If the type field is worth TAGS. If true the annotations must have at least one of the tags in the tags field otherwise the annotations must contain all the tags. |
No |
true |
|
/type |
String |
The type of request. If the value is "ALL", all annotations in the time range will be returned. If the type is "TAGS", the annotations must also contain tags (either all or at least one depending on the value of matchAny). |
No |
one value from [ALL, TAGS] |
ALL |
POST /api/grafana/simplejson/tag-keys
Used to find out the keys that can be used in the tag_values endpoint.
Example of a request:
{}
Example of a response:
[
{"type":"string","text":"City"},
{"type":"string","text":"Country"}
]
The values in "text" are the values usable as a key in the endpoint tag-values.
| json path | type | description | mandatory | possible values | default value |
|---|---|---|---|---|---|
/range/from |
String |
The start date to search for annotations. Only annotations with a date greater than or equal to this date. |
No |
Must represent a date in the following format (UTC): * yyyy-MM-dd’T’HH: mm: ss.SSS * |
January 1, 1970 (UTC) |
/range/to |
String |
The end date to search for annotations. Only annotations with a date less than or equal to this date. |
No |
Must represent a date in the following format (UTC): * yyyy-MM-dd’T’HH: mm: ss.SSS * |
The default is infinity |
/limit |
Integer |
The maximum number of annotations to return |
No |
positive integer |
100 |
/tags |
Liste de string |
The name of the tags to filter the annotations. The behavior depends on the value of the _ / type_ field |
No |
[] (empty array) |
|
/matchAny |
Boolean |
If the type field is worth TAGS. If true the annotations must have at least one of the tags in the tags field, otherwise the annotations must contain all the tags. |
No |
true |
|
/type |
String |
The type of request. If the value is "ALL", all annotations in the time range will be returned. If the type is "TAGS", the annotations must also contain tags (either all or at least one depending on the value of matchAny). |
No |
one value from [ALL, TAGS] |
ALL |
Compatible API with the "Hurence-Historian" plugin
POST /api/grafana/v0/query
Used to search for measures for the desired metrics. Various parameters are available.
Example of a request:
{
"from": "2016-10-31T06:33:44.866Z",
"to": "2020-10-31T12:33:44.866Z",
"names": ["metric_1"],
"format": "json",
"max_data_points": 30,
"tags": {
"sensor" : "sensor_1"
},
"sampling":{
"algorithm": "MIN",
"bucket_size" : 100
}
}
Example of a minimal request :
[
{
"name": "metric_1",
"datapoints": [
[
622,
1477895624866
],
[
-3,
1477916224866
],
[
365,
1477917224866
]
]
}
]
{ "tags": { "sensor" : "sensor_1" }, "sampling":{ "algorithm": "MIN", "bucket_size" : 100 } }
| json path | type | description | mandatory | possible values | default value |
|---|---|---|---|---|---|
/names |
array |
Allows you to enter the metrics for which you want to obtain measures. |
Yes |
||
from |
String |
The start date to search for measures. Only measures with a date greater than or equal to this date. |
No |
Must represent a date in the following format (UTC): * yyyy-MM-dd’T’HH: mm: ss.SSS * |
January 1, 1970 (UTC) |
to |
String |
The end date to search for measures. Only measures with a date less than or equal to this date. |
No |
Must represent a date in the following format (UTC): * yyyy-MM-dd’T’HH: mm: ss.SSS * |
The default is infinity |
/max_data_points |
long |
The maximum number of measures desired for each metric (Indeed the goal is to draw measures on a graph). If necessary the measures will be sampled with a default sampling algorithm. |
No |
positive |
1000 |
/sampling |
String |
An object which will contain the information of the parameters to be used for the sampling of the measures if the number of measures to return is greater than the maximum number of measures requested. |
No |
||
/sampling/algorithm |
String |
L’algorithme à utiliser pour l’échantillonnage |
No |
les valeurs possibles sont ["NONE", "AVERAGE", "FIRST", "MIN", "MAX"] |
AVERAGE (la moyenne des measures pour chaque bucket, le timestamp utilisé est celui du premier measure du bucket) |
/sampling/bucket_size |
Int |
The size of the buckets desired to sample the data. Please note this size can be changed by the server if this is incompatible with the maximum number of measures returned desired. |
No |
Automatically computed by the server in order to obtain at most the maximum number of measures. |
|
/tags |
String |
Allows you to obtain only the measures of the chunks which contain the filled tags. The tags must be indicated in the form of a key / value map. |
No |
no tags. |
Example of a response
[
{
"name":"upper_75",
"datapoints":[
[622,1450754160000],
[365,1450754220000]
]
},
{
"name":"upper_90",
"datapoints":[
[861,1450754160000],
[767,1450754220000]
]
}
]
POST /api/grafana/v0/search
Lets you search for the different metrics available.
Example of a request:
{
"name": "upper_50",
"limit": 5
}
| json path | type | description | mandatory | possible values | default value |
|---|---|---|---|---|---|
/name |
String |
Part of the name of the metric you are looking for. |
No |
||
/limit |
Int |
The maximum number of metric names to return. |
No |
| The body of the request is optional. |
Example of a response:
["upper_25","upper_50","upper_75","upper_90","upper_95"]
POST /api/grafana/v0/search/values
Allows you to search for the different values for the indicated key.
Example of a request:
{
"field": "name",
"query": "up",
"limit": 5
}
| json path | type | description | mandatory | possible values | default value |
|---|---|---|---|---|---|
/field |
String |
the searched key. |
Yes |
||
/query |
String |
Part of the name of the key you are looking for. |
Yes |
||
/limit |
Int |
The maximum number of metric names to return. |
No |
| The query and limit parameters of the query are optional. |
Example of a response:
["upper_25","upper_50","upper_75","upper_90","upper_95"]
POST /api/grafana/v0/annotations
Lets you search for annotations.
Example of a request:
{
"from": "2020-2-14T01:43:14.070Z",
"to": "2020-2-14T06:50:14.070Z",
"limit" : 100,
"tags": ["tag1", "tag2"],
"matchAny": false,
"type": "tags"
}
Example of a response in current release:
{
"annotations" : [
{
"time": 1581669794070,
"text": "annotation 7",
"tags": ["tag2","tag3"]
},
{
"time": 1581666194070,
"text": "annotation 6",
"tags": ["tag3","tag5"]
}
],
"total_hit" : 2
}
| json path | type | description | mandatory | possible values | default value |
|---|---|---|---|---|---|
/from |
String |
The start date to search for annotations. Only annotations with a date greater than or equal to this date. |
No |
Must represent a date in the following format (UTC): * yyyy-MM-dd’T’HH: mm: ss.SSS * |
January 1, 1970 (UTC) |
/to |
String |
The end date to search for annotations. Only annotations with a date less than or equal to this date. |
No |
Must represent a date in the following format (UTC): * yyyy-MM-dd’T’HH: mm: ss.SSS * |
The default is infinity |
/limit |
Integer |
The maximum number of annotations to return |
No |
positive integer |
100 |
/tags |
Liste de string |
The name of the tags to filter the annotations. The behavior depends on the value of the _ / type_ field |
No |
[] (empty array) |
|
/matchAny |
Boolean |
If the type field is equal to TAGS. If true the annotations must have at least one of the tags in the tags field otherwise the annotations must contain all the tags. |
No |
true |
|
/type |
String |
The type of request. If the value is "ALL", all annotations in the time range will be returned. If the type is "TAGS", the annotations must also contain tags (either all or at least one depending on the value of matchAny. |
No |
one value from [ALL, TAGS] |
ALL |
POST /api/grafana/v0/tag-keys
Used to find out the keys that can be used in the tag_values endpoint.
Example of a request:
{}
Example of a response:
[
{
"type": "string",
"text": "Algo"
},
{
"type": "int",
"text": "Bucket size"
}
]
The values in "text" are the values that can be used as a key in the endpoint tag-values.
POST /api/grafana/simplejson/tag-values
Lets you search for the different metrics available.
Example of a request:
{"key": "Algo"}
Example of a response:
[
{
"text": "NONE"
},
{
"text": "AVERAGE"
},
{
"text": "FIRST"
},
{
"text": "MIN"
},
{
"text": "MAX"
}
]
Here are the values available for the corresponding keys.