Перейти к основному содержимому

Public API

Introduction

seq-db consists of 2 components - proxy and store:

This document describes seq-db ingestion API and seq-db search API

Bulk HTTP API

seq-db is compatible with Elasticsearch bulk API

/

Returns a hardcoded ES response that specifies the Elasticsearch version used. This feature allows the usage of seq-db as an Elasticsearch output for logstash, filebeat, and other log shippers.

Example request:

curl -X GET http://localhost:9002/

Example successful response:

{
"cluster_name": "seq-db",
"version": {
"number": "8.9.0"
}
}

/_bulk

Receives body, parses it to docs and metas and writes to stores via internal API.

Example request:

curl -X POST http://localhost:9002/_bulk -d '
{"index":""}
{"k8s_pod":"seq-proxy", "request_time": "5", "time": "2024-12-23T18:00:36.357Z"}
{"index":""}
{"k8s_pod":"seq-proxy", "request_time": "6"}
{"index":""}
{"k8s_pod":"seq-proxy", "request_time": "7"}
{"index":""}
{"k8s_pod":"seq-proxy", "request_time": "8"}
{"index":""}
{"k8s_pod":"seq-proxy", "request_time": "9"}
{"index":""}
{"k8s_pod":"seq-db", "request_time": "10"}
{"index":""}
{"k8s_pod":"seq-db", "request_time": "11"}
{"index":""}
{"k8s_pod":"seq-db", "request_time": "12"}
{"index":""}
{"k8s_pod":"seq-db", "request_time": "13"}
{"index":""}
{"k8s_pod":"seq-db", "request_time": "14"}
'

Example successful response:

{
"took": 11,
"errors": false,
"items": [
{ "create": { "status": 201 } },
{ "create": { "status": 201 } },
{ "create": { "status": 201 } },
{ "create": { "status": 201 } },
{ "create": { "status": 201 } },
{ "create": { "status": 201 } },
{ "create": { "status": 201 } },
{ "create": { "status": 201 } },
{ "create": { "status": 201 } },
{ "create": { "status": 201 } }
]
}

One can notice that index field is left empty. seq-db ignores data passed in this field, since it uses mapping for field indexing. You can find more information about mapping in relevant document

Example rate-limited response

There should not be more than consts.IngestorMaxInflightBulks requests at the same time (32 by default), otherwise request is rate-limited and seq-db will response with 429 status code.

Example error response

In case of error seq-db returns 500 status code and the error message. E.g. if we try to ingest corrupted json

curl -v -X POST http://localhost:9002/_bulk -d '
{"index":""}
{"k8s_pod":"seq-proxy", "request_time": "123}
'

We get

processing doc: unexpected end of string near `", "request_time": "123`
^

Search gRPC API

Document search method by request. Takes in query in seq-ql format and returns list of satisfying documents.

Example request:

grpcurl -plaintext -d '
{
"query": {
"from": "2020-01-01T00:00:00Z",
"to": "2030-01-01T00:00:00Z",
"query": "k8s_pod:seq-db"
},
"size": 2,
"with_total": true
}' localhost:9004 seqproxyapi.v1.SeqProxyApi/Search

Example successful response:

{
"total": "5",
"docs": [
{
"id": "0593adf493010000-d901eee224290dc6",
"data": "eyJrOHNfcG9kIjoic2VxLWRiIiwgInJlcXVlc3RfdGltZSI6ICIxMyJ9",
"time": "2024-12-23T18:00:36.357Z"
},
{
"id": "0593adf493010000-d9013865e424dba1",
"data": "eyJrOHNfcG9kIjoic2VxLWRiIiwgInJlcXVlc3RfdGltZSI6ICIxMSJ9",
"time": "2024-12-23T18:00:36.357Z"
}
],
"error": {
"code": "ERROR_CODE_NO"
}
}

data field contains original document in base64 format. If we try to decode it

echo 'eyJrOHNfcG9kIjoic2VxLWRiIiwgInJlcXVlc3RfdGltZSI6ICIxMyJ9' | base64 -d | jq

we get

{
"k8s_pod": "seq-db",
"request_time": "13"
}

/GetAggregation

Агрегации позволяют вычислять статистические значения (сумма, среднее, максимум, минимум, квантиль, уникальность, количество) по полям документов, соответствующим запросу.

Агрегации можно вызывать двумя способами:

  • через отдельный gRPC обработчик: GetAggregation
  • вместе с поиском и гистограммами: ComplexSearch

В примерах используется API GetAggregation, которая по структуре запроса и ответа совпадает с ComplexSearch.

Поддерживаемые функции агрегации:

  • AGG_FUNC_SUM — сумма значений поля
  • AGG_FUNC_AVG — среднее значение поля
  • AGG_FUNC_MIN — минимальное значение поля
  • AGG_FUNC_MAX — максимальное значение поля
  • AGG_FUNC_QUANTILE — вычисление квантилей для поля
  • AGG_FUNC_UNIQUE — вычисление уникальных значений поля
  • AGG_FUNC_COUNT — подсчёт количества документов по группе

Примеры агрегаций

Исходные документы:

{"service": "svc1", "latency": 100}
{"service": "svc1", "latency": 300}
{"service": "svc2", "latency": 400}
{"service": "svc2", "latency": 200}
{"service": "svc3", "latency": 500}
Вычисление SUM, AVG, MIN, MAX

Запрос:

{
"query": {
"from": "2000-01-01T00:00:00Z",
"to": "2077-01-01T00:00:00Z",
"query": "*"
},
"aggs": [
{
"field": "latency",
"func": "AGG_FUNC_SUM"
},
{
"field": "latency",
"func": "AGG_FUNC_AVG"
},
{
"field": "latency",
"func": "AGG_FUNC_MIN"
},
{
"field": "latency",
"func": "AGG_FUNC_MAX"
}
]
} | grpcurl -plaintext -d @ localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAggregation

Ответ:

{
"aggs": [
{
"buckets": [
{"value": 1500}
]
},
{
"buckets": [
{"value": 300}
]
},
{
"buckets": [
{"value": 100}
]
},
{
"buckets": [
{"value": 500}
]
}
]
}
Вычисление SUM, AVG, MIN, MAX c group_by

Запрос:

{
"query": {
"from": "2000-01-01T00:00:00Z",
"to": "2077-01-01T00:00:00Z",
"query": "*"
},
"aggs": [
{
"field": "latency",
"func": "AGG_FUNC_SUM",
"group_by": "service"
},
{
"field": "latency",
"func": "AGG_FUNC_AVG",
"group_by": "service"
},
{
"field": "latency",
"func": "AGG_FUNC_MIN",
"group_by": "service"
},
{
"field": "latency",
"func": "AGG_FUNC_MAX",
"group_by": "service"
}
]
} | grpcurl -plaintext -d @ localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAggregation

Ответ:

{
"aggs": [
{
"buckets": [
{"key": "svc2", "value": 600},
{"key": "svc3", "value": 500},
{"key": "svc1", "value": 400}
]
},
{
"buckets": [
{"key": "svc3", "value": 500},
{"key": "svc2", "value": 300},
{"key": "svc1", "value": 200}
]
},
{
"buckets": [
{"key": "svc1", "value": 100},
{"key": "svc2", "value": 200},
{"key": "svc3", "value": 500}
]
},
{
"buckets": [
{"key": "svc3", "value": 500},
{"key": "svc2", "value": 400},
{"key": "svc1", "value": 300}
]
}
]
}
QUANTILE

Функцию агрегации QUANTILE также можно применять с группировкой по полю, используя поле group_by.

Запрос:

{
"query": {
"from": "2000-01-01T00:00:00Z",
"to": "2077-01-01T00:00:00Z",
"query": "*"
},
"aggs": [
{
"field": "latency",
"func": "AGG_FUNC_QUANTILE",
"quantiles": [
0.5,
0.9
]
}
]
} | grpcurl -plaintext -d @ localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAggregation

Ответ:

{
"aggs": [
{
"buckets": [
{
"quantiles": [
300,
500
],
"value": 300
}
]
}
]
}
UNIQUE, COUNT

Для AGG_FUNC_UNIQUE, AGG_FUNC_COUNT поле field не требуется.

Запрос:

{
"query": {
"from": "2000-01-01T00:00:00Z",
"to": "2077-01-01T00:00:00Z",
"query": "*"
},
"aggs": [
{
"func": "AGG_FUNC_UNIQUE",
"group_by": "service"
},
{
"func": "AGG_FUNC_COUNT",
"group_by": "service"
}
]
} | grpcurl -plaintext -d @ localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAggregation

Ответ:

{
"aggs": [
{
"buckets": [
{"key": "svc1"},
{"key": "svc2"},
{"key": "svc3"}
]
},
{
"buckets": [
{"key": "svc1", "value": 2},
{"key": "svc2", "value": 2},
{"key": "svc3", "value": 1}
]
}
]
}

/GetHistogram

Method of getting histograms by query

Example request:

grpcurl -plaintext -d '
{
"query": {
"from": "2020-01-01T00:00:00Z",
"to": "2030-01-01T00:00:00Z"
},
"hist": {
"interval": "1ms"
}
}' localhost:9004 seqproxyapi.v1.SeqProxyApi/GetHistogram

Example successful response

{
"hist": {
"buckets": [
{
"docCount": "1",
"ts": "2024-12-23T18:00:36.357Z"
},
{
"docCount": "9",
"ts": "2024-12-23T18:23:41.349Z"
}
]
},
"error": {
"code": "ERROR_CODE_NO"
}
}

/ComplexSearch

Search request combining fetch of documents, aggregations and histograms

Example request:

grpcurl -plaintext -d '
{
"query": {
"from": "2020-01-01T00:00:00Z",
"to": "2030-01-01T00:00:00Z",
"query": "k8s_pod:seq-proxy"
},
"with_total": true,
"aggs": [
{
"group_by": "k8s_pod",
"field": "request_time",
"func": "AGG_FUNC_QUANTILE",
"quantiles": [
0.2,
0.8,
0.95
]
}
],
"hist": {
"interval": "1ms"
},
"order": 0
}' localhost:9004 seqproxyapi.v1.SeqProxyApi/ComplexSearch

Example successful response:

{
"total": "5",
"aggs": [
{
"buckets": [
{
"docCount": "6",
"key": "seq-proxy",
"value": 6,
"quantiles": [
6,
8,
9
]
}
]
}
],
"hist": {
"buckets": [
{
"docCount": "1",
"ts": "2024-12-23T18:00:36.357Z"
},
{
"docCount": "4",
"ts": "2024-12-23T18:23:41.349Z"
}
]
},
"error": {
"code": "ERROR_CODE_NO"
}
}

/Fetch

Method returning stream of documents by passed seq-id's

Example request:

grpcurl -plaintext -d '
{
"ids": [
"25b5c2f493010000-59024b2ba3fb9630",
"0593adf493010000-5902ee007dfb6547"
]
}' localhost:9004 seqproxyapi.v1.SeqProxyApi/Fetch

Example successful response:

{
"id": "25b5c2f493010000-59024b2ba3fb9630",
"data": "eyJrOHNfcG9kIjoic2VxLWRiIiwgInJlcXVlc3RfdGltZSI6ICIxMCJ9",
"time": "2024-12-23T18:23:41.349Z"
}
{
"id": "0593adf493010000-5902ee007dfb6547",
"data": "eyJrOHNfcG9kIjoic2VxLXByb3h5IiwgInJlcXVlc3RfdGltZSI6ICI1IiwgInRpbWUiOiAiMjAyNC0xMi0yM1QxODowMDozNi4zNTdaIn0=",
"time": "2024-12-23T18:00:36.357Z"
}

/Mapping

Method returning mapping seq-db working with

Example request:

grpcurl -plaintext localhost:9004 seqproxyapi.v1.SeqProxyApi/Mapping

Example successful response:

{
"data": "eyJrOHNfY29udGFpbmVyIjoia2V5d29yZCIsIms4c19uYW1lc3BhY2UiOiJrZXl3b3JkIiwiazhzX3BvZCI6ImtleXdvcmQiLCJtZXNzYWdlIjoidGV4dCIsIm1lc3NhZ2Uua2V5d29yZCI6ImtleXdvcmQiLCJyZXF1ZXN0IjoidGV4dCIsInJlcXVlc3RfdGltZSI6ImtleXdvcmQiLCJyZXF1ZXN0X3VyaSI6InBhdGgiLCJzb21lb2JqIjoib2JqZWN0Iiwic29tZW9iai5uZXN0ZWQiOiJrZXl3b3JkIiwic29tZW9iai5uZXN0ZWR0ZXh0IjoidGV4dCJ9"
}

decoding base64 results in:

{
"k8s_container": "keyword",
"k8s_namespace": "keyword",
"k8s_pod": "keyword",
"message": "text",
"message.keyword": "keyword",
"request": "text",
"request_time": "keyword",
"request_uri": "path",
"someobj": "object",
"someobj.nested": "keyword",
"someobj.nestedtext": "text"
}

/Status

Method returning detailed information about seq-db stores seq-db proxy working with

Example request:

grpcurl -plaintext localhost:9004 seqproxyapi.v1.SeqProxyApi/Status

Example successful response

{
"numberOfStores": 1,
"oldestStorageTime": "2024-12-23T18:23:37.622Z",
"stores": [
{
"host": "localhost:9234",
"values": {
"oldestTime": "2024-12-23T18:23:37.622Z"
}
}
]
}

/Export

Same method as a /Search, but streaming

Example request:

grpcurl -plaintext -d '
{
"query": {
"from": "2020-01-01T00:00:00Z",
"to": "2030-01-01T00:00:00Z",
"query": "k8s_pod:seq-db"
},
"size": 2,
}' localhost:9004 seqproxyapi.v1.SeqProxyApi/Export

Example successful response:

{
"doc": {
"id": "25b5c2f493010000-5902919c44e568be",
"data": "eyJrOHNfcG9kIjoic2VxLWRiIiwgInJlcXVlc3RfdGltZSI6ICIxMyJ9",
"time": "2024-12-23T18:23:41.349Z"
}
}
{
"doc": {
"id": "25b5c2f493010000-5902d3ff804c179d",
"data": "eyJrOHNfcG9kIjoic2VxLWRiIiwgInJlcXVlc3RfdGltZSI6ICIxMiJ9",
"time": "2024-12-23T18:23:41.349Z"
}
}