All Products
Search
Document Center

Simple Log Service:MetricStore HTTP API details

Last Updated:Dec 06, 2025

Simple Log Service provides multiple APIs to query time series metrics or write metric data to a MetricStore. These APIs are compatible with the open source Prometheus protocol. This topic describes these APIs in detail.

Overview

The APIs provided by Prometheus are located in the /api/v1/ directory. The MetricStore APIs follow the same convention. The complete URL is https://{project}.{sls-endpoint}/prometheus/{project}/{metricstore}/api/v1/.

Variable

Required

Description

{sls-endpoint}

Yes

The endpoint of Simple Log Service. The endpoint is the domain name used to access the service. The endpoint varies by the region where the project is located. For more information, see Endpoints.

{project}

Yes

Project Name: A Project is the 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 you created. For more information, see Create a MetricStore.

Important

When you call the APIs, you must use BasicAuth authentication. Set Username to your AccessKey ID and Password to your AccessKey secret. We recommend that you use the AccessKey of a Resource Access Management (RAM) user. You must grant the RAM user the permissions to query the specified project. For more information, see Configure a permission assistant.

The APIs also support Security Token Service (STS) authentication. In this case, the Password for BasicAuth is in the format {AccessKey Secret}${STS Token}. For more information, see What is STS?.

Time series metric query APIs

The time series metric query APIs include the Instant Queries API and the Range Queries API.

Instant Queries API

You can use the Instant Queries API to query metric data at a specific point in time.

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

The following table describes the parameters.

Variable

Required

Description

query

Yes

The Prometheus Query Language (PromQL) statement. For more information, see PromQL syntax.

time

No

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

timeout

No

The query execution timeout period, in seconds.

Formats such as 1s, 2m, 3h, and 4d are also supported. For example, timeout=10s. For more information, see Time Durations.

lookback_delta

No

Customizes the `query.lookback-delta` flag in Prometheus for the current query only. The value must follow the Time Durations format. For example, `lookback_delta=1m`. For more information, see Time Durations. This parameter specifies the maximum lookback interval for finding data points in PromQL calculations. The default value in an SLS Metricstore is `3m`.

  • Example

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

You can use the Range Queries API to query metric data at multiple points in time within a specified time range.

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 following table describes the parameters.

Variable

Required

Description

query

Yes

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

start

No

The start time of the query. The value is a UNIX timestamp, accurate to the second.

end

No

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

step

No

The interval between query executions, in seconds.

Formats such as 1s, 2m, 3h, and 4d are also supported. For example, `step=2m`. For more information, see Time Durations.

timeout

No

The query execution timeout period, in seconds.

Formats such as 1s, 2m, 3h, and 4d are also supported. For example, timeout=10s. For more information, see Time Durations.

lookback_delta

No

Customizes the `query.lookback-delta` flag in Prometheus for the current query only. The value must follow the Time Durations format. For example, `lookback_delta=1m`. For more information, see Time Durations. This parameter specifies the maximum lookback interval for finding data points in PromQL calculations. The default value in an SLS Metricstore is `3m`.

  • Example

    This example queries metric data from 14:09:59 on 2023-02-18 to 14:16:39 on 2023-02-18 with a step of 60 s.

    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 your 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"
              ]
            ]
          }
        ]
      }
    }

Metadata query APIs

Simple Log Service also supports querying metadata, such as labels and label values. The SLS metadata query APIs are compatible with the Querying metadata APIs in Prometheus. You can use these APIs to retrieve all metrics, labels, and label values within a specific time period. The response does not include timestamps or numeric values.

Query Series API

You can use the Query Series API to query all metric names and their corresponding label-value pairs that match specific conditions within a specified time period.

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

The following table describes the parameters.

Variable

Required

Description

match[]

Yes

The filter condition. Example: match[]=up{instance="demo.*"}.

You can set one or more values.

start

No

The start time of the query. The value is a UNIX timestamp, accurate to the second.

The default value is 5 minutes before the current time.

end

No

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

The default value is the current time.

Important

If you specify custom values for both the start and end parameters, the API only supports querying data within the 5 minutes before the end time. The query range is `(end - 5 minutes, end)`.

  • 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 your Alibaba Cloud AccessKey.
  • 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

You can use this API to query all label names that match specific conditions within a specified time period.

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

The following table describes the parameters.

Variable

Required

Description

match[]

Yes

The filter condition. For example, `match[]=up{instance="demo.*"}`.

You can specify zero, one, or more values.

start

No

The start time of the query range. The value is a UNIX timestamp, accurate to the second.

The default value is 5 minutes before the current time.

end

No

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

The default value is the current time.

Important

If you specify custom values for both the start and end parameters, the API only supports querying data within the 5 minutes before the end time. The query range is `(end - 5 minutes, end)`.

  • Example

    This example queries the label names of all metrics within a specified time 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 your Alibaba Cloud AccessKey.
  • Query results

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

Query Label Values API

You can use the Query Label Values API to query all label values for a specific label name that match specific conditions within a specified time period.

Important

In the API URL, replace <label_name> with a specific label name.

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

The following table describes the parameters.

Variable

Required

Description

match[]

Yes

The filter condition. For example, `match[]=up{instance="demo.*"}`.

You can specify one or more values.

start

No

The start time of the query. The value is a UNIX timestamp, accurate to the second.

The default value is 5 minutes before the current time.

end

No

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

The default value is the current time.

Important

If you specify custom values for both the start and end parameters, the API only supports querying data within the 5 minutes before the end time. The query range is `(end - 5 minutes, end)`.

  • Example

    This example queries all label values for the instance label of the up metric within a specified time 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 your Alibaba Cloud AccessKey.
  • Query results

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

Data write API

You can ingest time series data into a MetricStore by configuring the `remote_write` parameter in the configuration file of a Prometheus process. For more information, see Ingest Prometheus monitoring data using the remote write protocol. Because MetricStore is compatible with the Prometheus remote write protocol, you can also write data to a MetricStore by directly calling the `remote_write` API over HTTP without using a Prometheus process.

MetricStore provides the following API, which is compatible with the remote write protocol. This API parses time series data and writes the data to backend storage.

Important

If time series data is written to an SLS MetricStore using the remote write protocol, SLS uses `MetricName` and `Labels` as the hash key by default. This routes time series data from different time series to specific shards to improve data locality in 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", "") // AccessKey information.
	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) // Set the basic auth information.
	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) // The body content must be read completely.
	if err != nil {
		panic(err)
	}
	return resp.Status, string(body)
}

SDK examples

Access the query API 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", "") // Use the # symbol to concatenate multiple match[] parameters.
	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-endpoint}/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)
	}
}

Access the query API using the Prometheus SDK

This example is based on 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-endpoint}/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 response structure for the query and write APIs is as follows:

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

  // The following two items are returned when an error occurs during query analysis.
  "errorType": "<string>",
  "error": "<string>",
  
	// A warning message is returned, usually for an incomplete query.
  "warnings": ["<string>"]
}

Error handling

This section describes common errors and their solutions.

Authentication failed

  • If the following information is returned, authentication has failed. Check and modify your AccessKey.

    {
        "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 the following information is returned, the source IP address is not in the VPC CIDR block whitelist. Add the IP address to the VPC CIDR block 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}"
    }

Error in the PromQL statement

If the following information is returned, the PromQL statement contains an error. Modify the query statement in the query parameter.

--> /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 the following information is returned, a timeout error occurred. Increase the value of the timeout parameter.

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

Incomplete query

If the following information is returned, the query is incomplete. We recommend that you narrow the query time range and try 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"
    ]
}