All Products
Search
Document Center

Simple Log Service:Details of Metricstore-related HTTP API

Last Updated:Jan 22, 2025

Simple Log Service offers a suite of API operations for querying and writing metrics to Metricstores, all of which are compatible with the Prometheus protocol. This topic describes the usage of these API operations.

Overview

All interfaces provided by Prometheus are located under the /api/v1 directory. Metricstore-related API operations adhere to this convention. The complete URL format is https://{project}.{sls-endpoint}/prometheus/{project}/{metricstore}/api/v1/.

Variable

Required

Description

{sls-endpoint}

Yes

The Simple Log Service endpoint is the domain name used to access the service. The endpoint is associated with the region in which the project resides. For more information, see Service endpoint.

{project}

Yes

Project Name: A project is a resource management unit of Simple Log Service. It is the primary boundary for multi-user isolation and access control. For more information, see Manage projects.

{metricstore}

Yes

The Metricstore that is created. For more information, see Create a Metricstore.

Important

To use the related API operations, BasicAuth authentication is required. Set Username to your AccessKey ID and Password to your AccessKey secret. It is recommended to use the AccessKey pair of a RAM user with the necessary permissions for the specified project. For more information, see Configure permission assistant.

Additionally, the API operations support Security Token Service (STS) authentication. In this scenario, the Password in BasicAuth must follow the format {AccessKey secret}${STS token}. For more information, see What is STS.

API operations for metric queries

The Instant Queries API and Range Queries API are designed for metric retrieval.

Instant Queries API

The Instant Queries API allows you to retrieve metrics at a specific timestamp.

GET https://{project}.{sls-endpoint}/prometheus/{project}/{metricstore}/api/v1/query
POST https://{project}.{sls-endpoint}/prometheus/{project}/{metricstore}/api/v1/query

The table below details the parameters used in the statement above.

Variable

Required

Description

query

Yes

The specific PromQL statement. For more information, see PromQL syntax.

time

No

The point in time to query. The value is a UNIX timestamp that is accurate to the second. The default value is the current time.

timeout

No

The timeout period for a query. Unit: seconds.

1s, 2m, 3h, and 4d are supported. For example, timeout=10s. For more information, see Time durations.

lookback_delta

No

You can use this parameter to customize the value of the query.lookback-delta flag in Prometheus. The value is valid only for the current query. The value of this parameter must follow the usage of time durations. For example, lookback_delta=1m. For more information, see Time durations. This parameter specifies the maximum backtrack range when PromQL identifies specific points in time during calculation. The default value of 3m is used for the variable in Simple Log Service Metricstores.

  • Sample code

    curl -X GET 'https://haoqi-sls-metric-test.pub-cn-hangzhou.log.aliyuncs.com/prometheus/haoqi-sls-metric-test/prometheus-metrics/api/v1/query?query=up&time=1676700699' \
    -u username:password \
    -H 'Content-Type: application/x-www-form-urlencoded'
    
    # Set username and password to the Alibaba Cloud AccessKey.
  • Query results

    {
        "status": "success",
        "data": {
            "resultType": "vector",
            "result": [
                {
                    "metric": {
                        "__name__": "up",
                        "instance": "demo.promlabs.com:10001",
                        "job": "demo"
                    },
                    "value": [
                        1676700550.696,
                        "1"
                    ]
                },
                {
                    "metric": {
                        "__name__": "up",
                        "instance": "demo.promlabs.com:10000",
                        "job": "demo"
                    },
                    "value": [
                        1676700550.696,
                        "1"
                    ]
                }
            ]
        }
    }

Range Queries API

The Range Queries API enables you to retrieve metrics over a specified time range at multiple intervals.

GET https://{project}.{sls-endpoint}/prometheus/{project}/{metricstore}/api/v1/query_range
POST https://{project}.{sls-endpoint}/prometheus/{project}/{metricstore}/api/v1/query_range

The table below describes the parameters in the statement above.

Variable

Required

Description

query

Yes

The specific PromQL statement. For more information, see PromQL syntax.

start

No

The beginning of the time range to query. The value is a UNIX timestamp that is accurate to the second.

end

No

The end of the time range to query. The value is a UNIX timestamp that is accurate to the second.

step

No

The interval at which queries are performed. Unit: seconds.

1s, 2m, 3h, and 4d are supported. For example, step=2m. For more information, see Time durations.

timeout

No

The timeout period for a query. Unit: seconds.

1s, 2m, 3h, and 4d are supported. For example, timeout=10s. For more information, see Time durations.

lookback_delta

No

You can use this parameter to customize the value of the query.lookback-delta flag in Prometheus. The value is valid only for the current query. The value of this parameter must follow the usage of time durations. For example, lookback_delta=1m. For more information, see Time durations. This parameter specifies the maximum backtrack range when PromQL identifies specific points in time during calculation. The default value of 3m is used for the variable in Simple Log Service Metricstores.

  • Sample code

    The sample code below demonstrates how to query metrics from 2023-02-18 14:09:59 to 2023-02-18 14:16:39 at 60-second intervals.

    curl -X GET 'https://haoqi-sls-metric-test.pub-cn-hangzhou.log.aliyuncs.com/prometheus/haoqi-sls-metric-test/prometheus-metrics/api/v1/query_range?query=up&start=1676700599&end=1676700999&step=60s' \
    -u username:password \
    -H 'Content-Type: application/x-www-form-urlencoded'
    
    # Set username and password to the Alibaba Cloud AccessKey.
  • Query results

    {
      "status": "success",
      "data": {
        "resultType": "matrix",
        "result": [
          {
            "metric": {
              "__name__": "up",
              "instance": "demo.promlabs.com:10000",
              "job": "demo"
            },
            "values": [
              [
                1676700599,
                "1"
              ],
              [
                1676700659,
                "1"
              ],
              [
                1676700719,
                "0"
              ],
              [
                1676700779,
                "0"
              ],
              [
                1676700839,
                "1"
              ],
              [
                1676700899,
                "0"
              ],
              [
                1676700959,
                "1"
              ]
            ]
          },
          {
            "metric": {
              "__name__": "up",
              "instance": "demo.promlabs.com:10001",
              "job": "demo"
            },
            "values": [
              [
                1676700599,
                "1"
              ],
              [
                1676700659,
                "1"
              ],
              [
                1676700719,
                "0"
              ],
              [
                1676700779,
                "0"
              ],
              [
                1676700839,
                "1"
              ],
              [
                1676700899,
                "1"
              ],
              [
                1676700959,
                "1"
              ]
            ]
          }
        ]
      }
    }

API operations for metadata queries

Simple Log Service also facilitates metadata queries, such as retrieving label names and values, in line with Prometheus's Querying metadata API operations. These queries can fetch all metrics and label names, but not timestamps or numeric values.

Query Series API

The Query Series API retrieves all metric names and label-value pairs that match specified criteria within a given timeframe.

GET https://{project}.{sls-endpoint}/prometheus/{project}/{metricstore}/api/v1/series
POST https://{project}.{sls-endpoint}/prometheus/{project}/{metricstore}/api/v1/series

The table below describes the parameters used in the statement above.

Variable

Required

Description

match[]

Yes

Filter conditions. For example, match[]=up{instance="demo.*"}.

You can specify one or more conditions.

start

No

The beginning of the time range to query. The value is a UNIX timestamp that is accurate to the second.

The default value is 5 minutes before the current time.

end

No

The end of the time range to query. The value is a UNIX timestamp that is accurate to the second.

The default value is the current time.

Important

If both the start and end parameters are customized, the API operation can query only the data that is generated within 5 minutes before the end time. That is, the API operation queries the data that is generated within the (end - 5 minute, end) time range.

  • Configuration example

    curl -g -X GET 'https://haoqi-sls-metric-test.pub-cn-hangzhou.log.aliyuncs.com/prometheus/haoqi-sls-metric-test/prometheus-metrics/api/v1/series?match[]=up{instance="demo.promlabs.com:10000"}&match[]=go_sched_latencies_seconds_bucket&start=1676700599&end=1676700999' \
    -u username:password \
    -H 'Content-Type: application/x-www-form-urlencoded'
    
    # Set username and password to the Alibaba Cloud AccessKey.
  • Query results

    {
        "status": "success",
        "data": [
            {
                "__name__": "go_gc_duration_seconds_count",
                "instance": "demo.promlabs.com:10000",
                "job": "demo"
            },
            {
                "__name__": "go_gc_duration_seconds_count",
                "instance": "demo.promlabs.com:10001",
                "job": "demo"
            },
            {
                "__name__": "up",
                "instance": "demo.promlabs.com:10000",
                "job": "demo"
            }
        ]
    }

Query Label Names API

The Query Label Names API retrieves all label names that satisfy specific conditions within a given timeframe.

GET https://{project}.{sls-endpoint}/prometheus/{project}/{metricstore}/api/v1/labels
POST https://{project}.{sls-endpoint}/prometheus/{project}/{metricstore}/api/v1/labels

The table below details the parameters in the statement above.

Variable

Required

Description

match[]

Yes

Filter conditions. For example, match[]=up{instance="demo.*"}.

You can specify zero or more conditions.

start

No

The beginning of the time range to query. The value is a UNIX timestamp that is accurate to the second.

The default value is 5 minutes before the current time.

end

No

The end of the time range to query. The value is a UNIX timestamp that is accurate to the second.

The default value is the current time.

Important

If both the start and end parameters are customized, the API operation can query only the data that is generated within 5 minutes before the end time. That is, the API operation queries the data that is generated within the (end - 5 minute, end) time range.

  • Configuration example

    The sample code below shows how to query label names for all metrics within a specified period:

    curl -X GET 'https://haoqi-sls-metric-test.pub-cn-hangzhou.log.aliyuncs.com/prometheus/haoqi-sls-metric-test/prometheus-metrics/api/v1/labels?start=1676700599&end=1676700999' \
    -u username:password \
    -H 'Content-Type: application/x-www-form-urlencoded'
    
    # Set username and password to the Alibaba Cloud AccessKey.
  • Query results

    {
        "status": "success",
        "data": [
            "code",
            "instance",
            "job",
            "le",
            "method",
            "mode",
            "path",
            "quantile",
            "status",
            "type",
            "version",
            "__name__"
        ]
    }

Query Label Values API

The Query Label Values API retrieves all values for a specific label name that meet certain criteria within a given timeframe.

Important

You must replace <label_name> with the actual label name in the API operation's URL.

GET https://{project}.{sls-endpoint}/prometheus/{project}/{metricstore}/api/v1/label/<label_name>/values

The table below describes the parameters used in the statement above.

Variable

Required

Description

match[]

Yes

Filter conditions. For example, match[]=up{instance="demo.*"}.

You can specify one or more conditions.

start

No

The beginning of the time range to query. The value is a UNIX timestamp that is accurate to the second.

The default value is 5 minutes before the current time.

end

No

The end of the time range to query. The value is a UNIX timestamp that is accurate to the second.

The default value is the current time.

Important

If both the start and end parameters are customized, the API operation can query only the data that is generated within 5 minutes before the end time. That is, the API operation queries the data that is generated within the (end - 5 minute, end) time range.

  • Configuration example

    The sample code below illustrates how to query all values for the instance label of the up metric within a specified period:

    curl -X GET 'https://haoqi-sls-metric-test.pub-cn-hangzhou.log.aliyuncs.com/prometheus/haoqi-sls-metric-test/prometheus-metrics/api/v1/label/instance/values?match[]=up&start=1676700599&end=1676700999' \
    -u username:password \
    -H 'Content-Type: application/x-www-form-urlencoded'
    
    # Set username and password to the Alibaba Cloud AccessKey.
  • Query results

    {
        "status": "success",
        "data": [
            "demo.promlabs.com:10000",
            "demo.promlabs.com:10001",
            "demo.promlabs.com:10002"
        ]
    }

Data write API

By configuring the remote_write parameter in a Prometheus process's configuration file, you can direct metrics to Metricstores. For more details, see Collect Prometheus monitoring data using the remote write protocol. Metricstores are also compatible with Prometheus's remote write protocol, allowing you to use the remote_write API operation over HTTP to write data directly to Metricstores without a Prometheus process.

The remote_write API operation parses metrics and writes the parsed data to backend storage.

POST https://{project}.{sls-endpoint}/prometheus/{project}/{metricstore}/api/v1/write

The following code provides an example:

import (
	"bytes"
	"flag"
	"fmt"
	"github.com/gogo/protobuf/proto"
	"github.com/golang/snappy"
	"github.com/prometheus/prometheus/prompb"
	"io/ioutil"
	"net/http"
	"time"
)

func MockRemoteWrite() {
	project := flag.String("project", "xxxx", "")
	metricStore := flag.String("metricstore", "xxxx", "")
	endpoint := flag.String("endpoint", "xxxx", "")
	akId := flag.String("akid", "xxxx", "") // The AccessKey ID.
	akKey := flag.String("aksecret", "xxxx", "")
	flag.Parse()

	Url := fmt.Sprintf("https://%s.%s/prometheus/%s/%s/api/v1/write", *project, *endpoint, *project, *metricStore)
	timestamp := time.Now().UnixNano()
	timeSeries := []prompb.TimeSeries{
		{
			Labels: []prompb.Label{
				{Name: "__name__", Value: "test_metric"},
				{Name: "app", Value: "HOST"},
				{Name: "device", Value: "vda"},
			},
			Samples: []prompb.Sample{
				{Timestamp: timestamp / 1000000, Value: 100},
				{Timestamp: timestamp/1000000 + 10000, Value: 200},
				{Timestamp: timestamp/1000000 + 20000, Value: 400},
				{Timestamp: timestamp/1000000 + 30000, Value: 300},
			},
		},
		{
			Labels: []prompb.Label{
				{Name: "__name__", Value: "test_metric"},
				{Name: "app", Value: "HOST"},
				{Name: "device", Value: "vda"},
				{Name: "uid", Value: "123456"},
			},
			Samples: []prompb.Sample{
				{Timestamp: timestamp / 1000000, Value: 100},
				{Timestamp: timestamp/1000000 + 10000, Value: 200},
				{Timestamp: timestamp/1000000 + 20000, Value: 400},
				{Timestamp: timestamp/1000000 + 30000, Value: 600},
			},
		},
	}
	data, _ := proto.Marshal(&prompb.WriteRequest{Timeseries: timeSeries})
	bufBody := snappy.Encode(nil, data)
	rwR, err := http.NewRequest("POST", Url, ioutil.NopCloser(bytes.NewReader(bufBody)))
	rwR.Header.Add("Content-Encoding", "snappy")
	rwR.Header.Set("Content-Type", "application/x-protobuf")
	rwR.SetBasicAuth(*akId, *akKey) // The information that is used for basic authentication.
	if err != nil {
		fmt.Println(err.Error())
		return
	}

	start := time.Now().UnixNano() / 1000000 //ms
	do, err := client.Do(rwR)
	end := time.Now().UnixNano() / 1000000 // ms
	if err != nil {
		panic(err)
	}
	status, result := parseResp(do)

	fmt.Println("status:", status, "result:", result, "duration:", end-start)
}

func parseResp(resp *http.Response) (status, data string) {
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body) // Specifies that all content in the request body must be read.
	if err != nil {
		panic(err)
	}
	return resp.Status, string(body)
}

SDK examples

Call a query API operation over HTTP

import (
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"
)

const separator = "#"

func http_main() {

	project := flag.String("project", "xxxx", "")
	metricStore := flag.String("metricstore", "xxxx", "")
	endpoint := flag.String("endpoint", "xxxx", "")
	akId := flag.String("akid", "xxxx", "")
	akKey := flag.String("aksecret", "xxxx", "")
	query := flag.String("query", "avg(up)", "")
	queryType := flag.String("type", "values", "range or query or labels or values or series")
	matches := flag.String("match", "up", "") // Concatenate multiple parameters of the match[] method by using number signs (#).
	labelName := flag.String("label", "instance", "")
	step := flag.String("step", "1m", "")
	fromtime := flag.String("from", "2023-02-15T00:00:00Z", "time 2006-01-02T15:04:05Z07:00")
	totime := flag.String("to", "2023-02-15T00:15:00Z", "time 2006-01-02T15:04:05Z07:00")

	flag.Parse()

	timeFrom, err := time.Parse(time.RFC3339, *fromtime)
	if err != nil {
		panic(err)
	}
	timeTo, err := time.Parse(time.RFC3339, *totime)
	if err != nil {
		panic(err)
	}

	// URL:https://{project}.{sls-enpoint}/prometheus/{project}/{metricstore}
	prometheusEndpoint := fmt.Sprintf("https://%s/prometheus/%s/%s", *project+"."+*endpoint, *project, *metricStore)

	var uri string
	urlVal := url.Values{}
	urlVal.Add("start", strconv.FormatInt(timeFrom.Unix(), 10))
	urlVal.Add("end", strconv.FormatInt(timeTo.Unix(), 10))

	switch *queryType {
	case "range":
		urlVal.Add("query", *query)
		urlVal.Add("step", *step)
		uri = fmt.Sprintf("%s/api/v1/query_range?%v", prometheusEndpoint, urlVal.Encode())
	case "query":
		urlVal.Add("query", *query)
		urlVal.Add("time", strconv.FormatInt(timeTo.Unix(), 10))
		uri = fmt.Sprintf("%s/api/v1/query?%v", prometheusEndpoint, urlVal.Encode())
	case "labels":
		extractAddMatches(*matches, urlVal)
		uri = fmt.Sprintf("%s/api/v1/labels?%v", prometheusEndpoint, urlVal.Encode())
	case "values":
		extractAddMatches(*matches, urlVal)
		uri = fmt.Sprintf("%s/api/v1/label/%s/values?%v", prometheusEndpoint, *labelName, urlVal.Encode())
	case "series":
		extractAddMatches(*matches, urlVal)
		uri = fmt.Sprintf("%s/api/v1/series?%v", prometheusEndpoint, urlVal.Encode())
	}

	req, _ := http.NewRequest(http.MethodGet, uri, nil)
	req.SetBasicAuth(*akId, *akKey)

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	buf, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()
	if err != nil {
		panic(err)
	}

	fmt.Println(string(buf))

}

func extractAddMatches(matches string, uVal url.Values) {
	splits := strings.Split(matches, separator)
	for _, match := range splits {
		uVal.Add("match[]", match)
	}
}

Call a query API operation by using an SDK for Prometheus

This example is based on the Prometheus client_golang v1.14.0.

import (
	"context"
	"flag"
	"fmt"
	"github.com/prometheus/client_golang/api"
	v1 "github.com/prometheus/client_golang/api/prometheus/v1"
	"net"
	"net/http"
	"net/url"
	"time"
)

func main() {
	project := flag.String("project", "xxxx", "")
	metricStore := flag.String("metricstore", "xxxx", "")
	endpoint := flag.String("endpoint", "xxxx", "")
	akId := flag.String("akid", "xxxx", "")
	akKey := flag.String("aksecret", "xxxx", "")
	flag.Parse()

	// URL:https://{project}.{sls-enpoint}/prometheus/{project}/{metricstore}
	prometheusEndpoint := fmt.Sprintf("https://%s.%s/prometheus/%s/%s", *project, *endpoint, *project, *metricStore)

	client, err := api.NewClient(api.Config{
		Address: prometheusEndpoint,
		RoundTripper: &http.Transport{
			// set basic auth
			Proxy: func(req *http.Request) (*url.URL, error) {
				req.SetBasicAuth(*akId, *akKey)
				return nil, nil
			},
			DialContext: (&net.Dialer{
				Timeout:   60 * time.Second,
				KeepAlive: 60 * time.Second,
			}).DialContext,
			TLSHandshakeTimeout: 10 * time.Second,
		},
	})
	if err != nil {
		panic(err)
	}

	v1api := v1.NewAPI(client)
	ctx, _ := context.WithTimeout(context.Background(), 60*time.Second)
	r := v1.Range{
		Start: time.Now().Add(-15 * time.Minute),
		End:   time.Now(),
		Step:  time.Minute,
	}
	// query range
	result, warnings, err := v1api.QueryRange(ctx, "avg(up)", r)
	if err != nil {
		panic(err)
	}
	if len(warnings) > 0 {
		fmt.Printf("Warnings: %v %v\n", warnings, result)
	}
	fmt.Println(result)

	// query
	result, warnings, err = v1api.Query(ctx, "avg(up)", time.Now())
	if err != nil {
		panic(err)
	}
	if len(warnings) > 0 {
		fmt.Printf("Warnings: %v %v\n", warnings, result)
	}
	fmt.Println(result)

	// series
	series, warnings, err := v1api.Series(ctx, []string{"up"}, time.Now().Add(-15*time.Minute), time.Now())
	if err != nil {
		panic(err)
	}
	if len(warnings) > 0 {
		fmt.Printf("Warnings: %v %v\n", warnings, result)
	}
	fmt.Println(series)

	// labels
	names, warnings, err := v1api.LabelNames(ctx, []string{"up"}, time.Now().Add(-15*time.Minute), time.Now())
	if err != nil {
		panic(err)
	}
	if len(warnings) > 0 {
		fmt.Printf("Warnings: %v %v\n", warnings, result)
	}
	fmt.Println(names)

	// labelValues
	values, warnings, err := v1api.LabelValues(ctx, "instance", []string{"up"}, time.Now().Add(-15*time.Minute), time.Now())
	if err != nil {
		panic(err)
	}
	if len(warnings) > 0 {
		fmt.Printf("Warnings: %v %v\n", warnings, result)
	}
	fmt.Println(values)
}

Response structure

The code snippet below shows the structure of responses for query API operations and the data write API operation:

{
  "status": "success" | "error",
  "data": <data>,

  // The following code is returned if an error occurs in a query:
  "errorType": "<string>",
  "error": "<string>",
  
	// The following warning information is returned if the query results are incomplete:
  "warnings": ["<string>"]
}

Error handling

Common errors can be managed according to the descriptions below:

Authentication failure

  • If you receive the information below, authentication has failed. Ensure you provide a valid AccessKey pair.

    {
        "status": "error",
        "code": "401",
        "errorType": "unauthorized",
        "error": "get query instance error: {\n    \"httpCode\": 401,\n    \"errorCode\": \"Unauthorized\",\n    \"errorMessage\": \"AccessKeyId not found: xxxx\",\n    \"requestID\": \"xxxx\"\n}"
    }
  • If you receive the information below, the IP address is not whitelisted in the VPC CIDR block. Add the IP address to the whitelist.

    {
        "status": "error",
        "code": "401",
        "errorType": "unauthorized",
        "error": "get query instance error: {\n    \"httpCode\": 401,\n    \"errorCode\": \"Unauthorized\",\n    \"errorMessage\": \"AccessKeyId not found: xxxx\",\n    \"requestID\": \"xxxx\"\n}"
    }

Invalid PromQL statement

If you receive the information below, the PromQL statement is invalid. Modify the query statement in the query parameter accordingly.

--> /api/v1/query_range?query=up[2m]&start=1676700599&end=1676700999&step=60s
{
    "status": "error",
    "errorType": "bad_data",
    "error": "invalid expression type \"range vector\" for range query, must be Scalar or instant Vector"
}

Timeout error

If you receive the information below, a timeout has occurred. Increase the timeout parameter value.

{
    "status": "error",
    "errorType": "timeout",
    "error": "query timed out in expression evaluation"
}

Incomplete query results

If you receive the message below, the query results are incomplete. Try narrowing the query time range and querying again.

{
    "status": "success",
    "data": {
        "resultType": "matrix",
        "result": [
            {
                "metric": {},
                "values": [
                    [
                        1673798460,
                        "11111111"
                    ],
                    [
                        1673799060,
                        "22222222"
                    ],
                    [
                        1673799660,
                        "33333333"
                    ]
                ]
            }
        ]
    },
    "warnings": [
        "Request to Sls partial incompleted, incomplete task count : 11, total : 108"
    ]
}