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

Публичное API

Введение

seq-db состоит из двух компонентов - proxy и store:

В этом документе описаны seq-db ingestion API и seq-db search API

Bulk HTTP API

seq-db совместима с Elasticsearch bulk API

/

Возвращает захардкоженный ответ, указывающий на версию используемого Elasticsearch. Это позволяет использовать seq-db в качестве Elasticsearch вывода для logstash, filebeat и других инструментов доставки логов.

Пример запроса:

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

Пример успешного ответа:

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

/_bulk

Принимает тело запроса, разбирает его на документы и метаданные, затем записывает в хранилища через внутренний API.

Пример запроса:

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"}
'

Пример успешного ответа:

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

Можно заметить, что в поле index нет данных: seq-db игнорирует это поле, потому что использует маппинг для индексации полей. Больше о маппинге и индексах можно прочитать в документации

Пример ответа при превышении лимита запросов:

Не должно быть более consts.IngestorMaxInflightBulks (по умолчанию 32) одновременных запросов, в противном случае
запрос будет ограничен по частоте, и seq-db ответит кодом ответа 429.

Пример ответа с ошибкой:

В случае ошибки, seq-db вернет код ответа 500 и сообщение об ошибке. Например, при попытке вставить некорректный json:

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

мы получим

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

Search gRPC API

Метод поиска документов. Принимает поисковый запрос в формате seq-ql и возвращает документы, удовлетворяющие поисковому запросу.

Пример запроса:

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

Пример успешного ответа:

{
"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 содержит оригинальный документ, закодированный в base64. Если декодировать его,

echo 'eyJrOHNfcG9kIjoic2VxLWRiIiwgInJlcXVlc3RfdGltZSI6ICIxMyJ9' | base64 -d | jq

то получится

{
"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

Запрос:

grpcurl -plaintext -d '
{
"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"
}
]
}' 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

Запрос:

grpcurl -plaintext -d '
{
"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"
}
]
}' 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.

Запрос:

grpcurl -plaintext -d '{
"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
]
}
]
}' localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAggregation

Ответ:

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

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

Запрос:

grpcurl -plaintext -d '{
"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"
}
]
}' 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}
]
}
]
}
COUNT (с указанием интервала)

Запрос:

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

Ответ:

{
"aggs": [
{
"buckets": [
{
"key": "svc1",
"value": 2,
"ts": "2025-08-17T11:46:00Z"
},
{
"key": "svc2",
"value": 2,
"ts": "2025-08-17T11:46:30Z"
},
{
"key": "svc3",
"value": 2,
"ts": "2025-08-17T11:47:00Z"
}
]
}
]
}

/GetHistogram

Метод построения гистограмм.

Пример запроса:

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

Пример успешного ответа:

{
"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

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

Пример запроса:

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

Пример успешного ответа:

{
"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

Возвращает поток документов по переданному в запросе списку seq-id

Пример запроса:

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

Пример успешного ответа:

{
"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

Возвращает используемый в seq-db маппинг.

Пример запроса:

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

Пример успешного ответа:

{
"data": "eyJrOHNfY29udGFpbmVyIjoia2V5d29yZCIsIms4c19uYW1lc3BhY2UiOiJrZXl3b3JkIiwiazhzX3BvZCI6ImtleXdvcmQiLCJtZXNzYWdlIjoidGV4dCIsIm1lc3NhZ2Uua2V5d29yZCI6ImtleXdvcmQiLCJyZXF1ZXN0IjoidGV4dCIsInJlcXVlc3RfdGltZSI6ImtleXdvcmQiLCJyZXF1ZXN0X3VyaSI6InBhdGgiLCJzb21lb2JqIjoib2JqZWN0Iiwic29tZW9iai5uZXN0ZWQiOiJrZXl3b3JkIiwic29tZW9iai5uZXN0ZWR0ZXh0IjoidGV4dCJ9"
}

после декодирования base64:

{
"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

Возвращает подробную информацию о всех seq-db store, используемых seq-db proxy

Пример запроса:

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

Пример успешного ответа:

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

/Export

То же самое, что и /Search, но потоковый

Пример запроса:

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

Пример успешного ответа:

{
"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"
}
}

Async search gRPC API

/StartAsyncSearch

Начать асинхронный поиск.

Возвращает идентификатор, с помощью которого можно получить результат выполнения поиска, отменить и удалить поиск.

Запрос похож на /ComplexSearch, но есть дополнительные поля: retention - определяет, как долго будут доступны данные поиска. И with_docs - определяет, будут ли найдены и сохранены идентификаторы документов, удовлетворяющих поисковому запросу. with_total будет автоматически установлен, если в запросе указан with_docs: true

Пример запроса:

grpcurl -plaintext -d '
{
"retention": "3600s",
"query": {
"from": "2025-07-01T05:20:00Z",
"to": "2025-09-01T05:21:00Z",
"query": "message:error | fields level, message"
},
"hist": {
"interval": "1ms"
},
"aggs": [
{
"group_by": "k8s_pod",
"field": "request_time",
"func": "AGG_FUNC_QUANTILE",
"quantiles": [
0.2,
0.8,
0.95
]
}
],
"with_docs": true
}' localhost:9004 seqproxyapi.v1.SeqProxyApi/StartAsyncSearch

Пример успешного ответа:

{
"search_id": "c28c97d1-117a-45dc-a0cf-d080f22b2a10"
}

/FetchAsyncSearchResult

Получить результат выполнения асинхронного поиска.

Возвращает результат выполнения, соответствующий поисковому запросу /StartAsyncSearch. Может быть возвращен результат частичного выполнения, если поиск еще не завершен. Поле status показывает текущий статус поиска. Возможные статусы: AsyncSearchStatusInProgress, AsyncSearchStatusDone, AsyncSearchStatusCanceled, AsyncSearchStatusError.

Пример запроса:

grpcurl -plaintext -d '
{
"search_id": "c28c97d1-117a-45dc-a0cf-d080f22b2a10",
"size": 2,
"offset": 0,
"order": 0
}' localhost:9004 seqproxyapi.v1.SeqProxyApi/FetchAsyncSearchResult

Пример успешного ответа:

{
"status": "AsyncSearchStatusDone",
"request": {
"retention": "3600s",
"query": {
"query": "message:peggy | fields level, message",
"from": "2025-08-01T05:20:00Z",
"to": "2025-09-01T05:21:00Z"
},
"hist": {
"interval": "1ms"
},
"aggs": [
{
"group_by": "k8s_pod",
"field": "request_time",
"func": "AGG_FUNC_QUANTILE",
"quantiles": [
0.2,
0.8,
0.95
]
}
],
"with_docs": true
},
"response": {
"total": 12,
"docs": [
{
"id": "c09e878998010000-9102a3cb83f156f2",
"data": {
"message": "some error",
"level": 3
},
"time": "2025-08-08T11:53:43.36Z"
},
{
"id": "c09e878998010000-91026cf9cf3386e3",
"data": {
"message": "error 2",
"level": 3
},
"time": "2025-08-08T11:53:43.36Z"
}
],
"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"
}
]
}
},
"progress": 1,
"disk_usage": "537",
"started_at": "2025-08-08T11:53:52.542336Z",
"expires_at": "2025-08-08T12:53:52.542336Z"
}

Поля response.docs и response.total будут сохранены и возвращены только если в запросе /StartAsyncSearch было указано with_docs: true

/GetAsyncSearchesList

Получить список асинхронных поисков.

Возвращает список асинхронных поисков, отфильтрованный в соответствии с полями запроса. Пустой запрос вернет все доступные поиски.

Пример запроса:

grpcurl -plaintext -d '
{
"status": null,
"size": 2,
"offset": 0,
"ids": ["c28c97d1-117a-45dc-a0cf-d080f22b2a10", "8e68d3d7-8e85-44a9-9b09-8de248a3b414"]
}' localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAsyncSearchesList

Пример успешного ответа:

{
"searches": [
{
"searchId": "c28c97d1-117a-45dc-a0cf-d080f22b2a10",
"status": "AsyncSearchStatusInProgress",
"request": {
"retention": "3600s",
"query": {
"query": "message:error | fields level, message",
"from": "2025-07-01T05:20:00Z",
"to": "2025-08-01T05:21:00Z"
},
"aggs": [],
"with_docs": true
},
"startedAt": "2025-08-08T11:49:20.707200Z",
"expiresAt": "2025-08-08T12:49:20.707200Z",
"progress": 0.89,
"diskUsage": "282"
},
{
"searchId": "8e68d3d7-8e85-44a9-9b09-8de248a3b414",
"status": "AsyncSearchStatusDone",
"request": {
"retention": "3600s",
"query": {
"query": "message:error",
"from": "2025-07-01T05:20:00Z",
"to": "2025-08-01T05:21:00Z"
},
"aggs": [],
"with_docs": false
},
"startedAt": "2025-08-08T11:48:49.488244Z",
"expiresAt": "2025-08-08T12:48:49.488244Z",
"progress": 1,
"diskUsage": "283"
}
]
}

/CancelAsyncSearch

Отменить асинхронный поиск.

Отменяет асинхронный поиск. Выполнение отмененного поиска будет остановлено. Нельзя отменить завершенный поиск.

Пример запроса:

grpcurl -plaintext -d '
{
"search_id": "c28c97d1-117a-45dc-a0cf-d080f22b2a10"
}' localhost:9004 seqproxyapi.v1.SeqProxyApi/CancelAsyncSearch

Пример успешного ответа:

{}

В случае успеха будет возвращен пустой ответ.

/DeleteAsyncSearch

Удалить асинхронный поиск.

Помечает поиск истекшим. Данные поиска будут удалены при следующей итерации обслуживания.

Пример запроса:

grpcurl -plaintext -d '
{
"search_id": "c28c97d1-117a-45dc-a0cf-d080f22b2a10"
}' localhost:9004 seqproxyapi.v1.SeqProxyApi/DeleteAsyncSearch

Пример успешного ответа:

{}

В случае успеха будет возвращен пустой ответ.