diff --git a/docs/en/10-public-api.md b/docs/en/10-public-api.md index 3c0361ab..315d5291 100644 --- a/docs/en/10-public-api.md +++ b/docs/en/10-public-api.md @@ -215,6 +215,7 @@ Sample documents: **Request:** ```sh +grpcurl -plaintext -d ' { "query": { "from": "2000-01-01T00:00:00Z", @@ -239,7 +240,7 @@ Sample documents: "func": "AGG_FUNC_MAX" } ] -} | grpcurl -plaintext -d @ localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAggregation +}' localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAggregation ``` **Response:** @@ -276,6 +277,7 @@ Sample documents: **Request:** ```sh +grpcurl -plaintext -d ' { "query": { "from": "2000-01-01T00:00:00Z", @@ -304,7 +306,7 @@ Sample documents: "group_by": "service" } ] -} | grpcurl -plaintext -d @ localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAggregation +}' localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAggregation ``` **Response:** @@ -351,6 +353,7 @@ Sample documents: **Request:** ```sh +grpcurl -plaintext -d ' { "query": { "from": "2000-01-01T00:00:00Z", @@ -367,7 +370,7 @@ Sample documents: ] } ] -} | grpcurl -plaintext -d @ localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAggregation +}' localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAggregation ``` **Response:** @@ -397,6 +400,7 @@ Sample documents: **Request:** ```sh +grpcurl -plaintext -d ' { "query": { "from": "2000-01-01T00:00:00Z", @@ -413,7 +417,7 @@ Sample documents: "group_by": "service" } ] -} | grpcurl -plaintext -d @ localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAggregation +}' localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAggregation ``` **Response:** @@ -444,6 +448,7 @@ Sample documents: **Request:** ```sh +grpcurl -plaintext -d ' { "query": { "from": "2000-01-01T00:00:00Z", @@ -457,7 +462,7 @@ Sample documents: "interval": "30s" } ] -} | grpcurl -plaintext -d @ localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAggregation +}' localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAggregation ``` **Response:** diff --git a/docs/en/14-aggregations.md b/docs/en/14-aggregations.md new file mode 100644 index 00000000..2826de99 --- /dev/null +++ b/docs/en/14-aggregations.md @@ -0,0 +1,188 @@ +--- +id: aggregations +--- + +# Aggregations + +seq-db support various types of aggregations: functional aggregations, histograms and timeseries. Each of the types +relies on the usage of the inverted-index, therefore to calculate aggregations for the fields, the field must be +indexed. + +## Function aggregations + +Aggregations allow the computation of statistical values over document fields that match the query. E.g. calculating +number of logs written by each service in the given interval, or all unique values of the field. + +seq-db supports various aggregation functions: + +- `AGG_FUNC_SUM` — sum of field values +- `AGG_FUNC_AVG` — average value of the field +- `AGG_FUNC_MIN` — minimum value of the field +- `AGG_FUNC_MAX` — maximum value of the field +- `AGG_FUNC_QUANTILE` — quantile value for the field +- `AGG_FUNC_UNIQUE` — computation of unique field values (not supported in timeseries) +- `AGG_FUNC_COUNT` — number of documents for each unique value of the field + +For the API of the functions, please refer to [public API](10-public-api.md#aggregation-examples) + +To better understand how aggregations work, let's illustrate examples with identical SQL queries. + +### Sum, average, minimum, maximum, quantile + +Calculation of the aforementioned aggregations requires: + +- `AGG_FUNC` which is one of `AGG_FUNC_SUM`, `AGG_FUNC_AVG`, `AGG_FUNC_MIN`, `AGG_FUNC_MAX`, `AGG_FUNC_QUANTILE`, +- `aggregate_by_field` - the field on which aggregation will be applied +- `group_by_field` - the field by which values will be grouped (used in not all aggregations) +- `filtering_query`- query to filter only relevant logs for the aggregation +- `quantile` - only for the `AGG_FUNC_QUANTILE` + +In general, this translates to the following SQL query: + +```sql +SELECT , AGG_FUNC() +FROM db +WHERE +GROUP BY +``` + +Translating to our API: + +```sh +grpcurl -plaintext -d ' +{ + "query": { + "from": "2000-01-01T00:00:00Z", + "to": "2077-01-01T00:00:00Z", + "query": "" + }, + "aggs": [ + { + "field": "", + "func": "AGG_FUNC", + "group_by": "" + } + ] +}' localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAggregation +``` + +Considering real-world example, we may want to calculate average response time for services having `response_time` +field, then we will write the following query: + +```sql +SELECT service, AVG(response_time) +FROM db +WHERE response_time:* -- meaning that `response_time` field exists in logs +GROUP BY service +``` + +Using our API: + +```sh +grpcurl -plaintext -d ' +{ + "query": { + "from": "2000-01-01T00:00:00Z", + "to": "2077-01-01T00:00:00Z", + "query": "response_time:*" + }, + "aggs": [ + { + "field": "response_time", + "func": "AGG_FUNC_AVG", + "group_by": "service" + } + ] +}' localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAggregation +``` + +### Count, unique + +Count and unique aggregations are very similar to the above examples, except for those aggregation there is no need to +have an additional `group_by_field`, since we are already grouping by `aggregate_by_field`. + +SQL query for the `AGG_FUNC_COUNT` aggregation: + +```sql +SELECT , COUNT (*) +FROM db +WHERE +GROUP BY +``` + +Translating to our API: + +```sh +grpcurl -plaintext -d ' +{ + "query": { + "from": "2000-01-01T00:00:00Z", + "to": "2077-01-01T00:00:00Z", + "query": "" + }, + "aggs": [ + { + "field": "", + "func": "AGG_FUNC_COUNT", + } + ] +}' localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAggregation +``` + +Considering real-world example, we may want to calculate number of logs for each logging level (`debug`, `info`, etc.) +for +the particular service, e.g. `seq-db`, then we can write the following query: + +```sql +SELECT level, COUNT(*) +FROM db +WHERE service:seq-db +GROUP BY level +``` + +Using our API: + +```sh +grpcurl -plaintext -d ' +{ + "query": { + "from": "2000-01-01T00:00:00Z", + "to": "2077-01-01T00:00:00Z", + "query": "service:seq-db" + }, + "aggs": [ + { + "field": "level", + "func": "AGG_FUNC_COUNT", + } + ] +}' localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAggregation +``` + +## Histograms + +Histograms allow users to visually interpret the distribution of logs satisfying given query. E.g. number of logs of the +particular service for the given interval of time. + +Histograms can be queried separately, using [GetHistogram](10-public-api.md#gethistogram) or with documents and +functional aggregations using [ComplexSearch](10-public-api.md#complexsearch). + +For the more detailed API and examples, please refer to [public API](10-public-api.md#gethistogram) + +## Timeseries + +Timeseries allow to calculate aggregations for intervals and visualize them. They are something in between histograms +and functional aggregations: they allow to simultaneously calculate multiple histograms for the given aggregate +functions. + +Consider the previous example of histograms, where we visualized number of logs over time only for one service at a +time. Using the power of timeseries, we can calculate number of logs for each service simultaneously, using the +`AGG_FUNC_COUNT` over `service` field. + +Another example of using timeseries is visualizing number of logs for each log-level over time. It may be exceptionally +useful, when there is a need to debug real-time problems. We can simply visualize number of logs for each level and find +unusual spikes and logs associated with them. + +Because timeseries are basically aggregations, they have the same API as aggregations, except a new `interval` field is +present to calculate number of buckets to calculate aggregation on. For the details, please refer +to [public API](10-public-api.md#aggregation-examples) diff --git a/docs/ru/10-public-api.md b/docs/ru/10-public-api.md index 536af8bd..b1a47982 100644 --- a/docs/ru/10-public-api.md +++ b/docs/ru/10-public-api.md @@ -215,6 +215,7 @@ echo 'eyJrOHNfcG9kIjoic2VxLWRiIiwgInJlcXVlc3RfdGltZSI6ICIxMyJ9' | base64 -d | jq **Запрос:** ```sh +grpcurl -plaintext -d ' { "query": { "from": "2000-01-01T00:00:00Z", @@ -239,7 +240,7 @@ echo 'eyJrOHNfcG9kIjoic2VxLWRiIiwgInJlcXVlc3RfdGltZSI6ICIxMyJ9' | base64 -d | jq "func": "AGG_FUNC_MAX" } ] -} | grpcurl -plaintext -d @ localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAggregation +}' localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAggregation ``` **Ответ:** @@ -276,6 +277,7 @@ echo 'eyJrOHNfcG9kIjoic2VxLWRiIiwgInJlcXVlc3RfdGltZSI6ICIxMyJ9' | base64 -d | jq **Запрос:** ```sh +grpcurl -plaintext -d ' { "query": { "from": "2000-01-01T00:00:00Z", @@ -304,7 +306,7 @@ echo 'eyJrOHNfcG9kIjoic2VxLWRiIiwgInJlcXVlc3RfdGltZSI6ICIxMyJ9' | base64 -d | jq "group_by": "service" } ] -} | grpcurl -plaintext -d @ localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAggregation +}' localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAggregation ``` **Ответ:** @@ -351,7 +353,7 @@ echo 'eyJrOHNfcG9kIjoic2VxLWRiIiwgInJlcXVlc3RfdGltZSI6ICIxMyJ9' | base64 -d | jq **Запрос:** ```sh -{ +grpcurl -plaintext -d '{ "query": { "from": "2000-01-01T00:00:00Z", "to": "2077-01-01T00:00:00Z", @@ -367,7 +369,7 @@ echo 'eyJrOHNfcG9kIjoic2VxLWRiIiwgInJlcXVlc3RfdGltZSI6ICIxMyJ9' | base64 -d | jq ] } ] -} | grpcurl -plaintext -d @ localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAggregation +}' localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAggregation ``` **Ответ:** @@ -397,7 +399,7 @@ echo 'eyJrOHNfcG9kIjoic2VxLWRiIiwgInJlcXVlc3RfdGltZSI6ICIxMyJ9' | base64 -d | jq **Запрос:** ```sh -{ +grpcurl -plaintext -d '{ "query": { "from": "2000-01-01T00:00:00Z", "to": "2077-01-01T00:00:00Z", @@ -413,7 +415,7 @@ echo 'eyJrOHNfcG9kIjoic2VxLWRiIiwgInJlcXVlc3RfdGltZSI6ICIxMyJ9' | base64 -d | jq "group_by": "service" } ] -} | grpcurl -plaintext -d @ localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAggregation +}' localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAggregation ``` **Ответ:** @@ -444,7 +446,7 @@ echo 'eyJrOHNfcG9kIjoic2VxLWRiIiwgInJlcXVlc3RfdGltZSI6ICIxMyJ9' | base64 -d | jq **Запрос:** ```sh -{ +grpcurl -plaintext -d '{ "query": { "from": "2000-01-01T00:00:00Z", "to": "2077-01-01T00:00:00Z", @@ -457,7 +459,7 @@ echo 'eyJrOHNfcG9kIjoic2VxLWRiIiwgInJlcXVlc3RfdGltZSI6ICIxMyJ9' | base64 -d | jq "interval": "30s" } ] -} | grpcurl -plaintext -d @ localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAggregation +}' localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAggregation ``` **Ответ:** diff --git a/docs/ru/14-aggregations.md b/docs/ru/14-aggregations.md new file mode 100644 index 00000000..daf5bd01 --- /dev/null +++ b/docs/ru/14-aggregations.md @@ -0,0 +1,187 @@ +--- +id: aggregations +--- + +# Агрегации + +seq-db поддерживает различные типы агрегаций: функциональные агрегации, гистограммы и таймсерии (временные ряды). Каждый +из этих типов опирается на использование обратного индекса, поэтому для вычисления агрегаций по полям поле должно быть +проиндексировано. + +## Функциональные агрегации + +Агрегации позволяют вычислять статистические значения по полям документов, соответствующих запросу. Например, вычисление +количества логов, записанных каждым сервисом в заданном интервале, или всех уникальных значений поля. + +seq-db поддерживает различные функции агрегации: + +- `AGG_FUNC_SUM` — сумма значений поля +- `AGG_FUNC_AVG` — среднее значение поля +- `AGG_FUNC_MIN` — минимальное значение поля +- `AGG_FUNC_MAX` — максимальное значение поля +- `AGG_FUNC_QUANTILE` — квантиль поля +- `AGG_FUNC_UNIQUE` — уникальные значения поля (не работает у таймсерий) +- `AGG_FUNC_COUNT` — количество документов для каждого уникального значения поля + +Для ознакомления с API функций обратитесь к [документации публичного API](10-public-api.md#примеры-агрегаций) + +Чтобы лучше понять, как работают агрегации, проиллюстрируем примеры с аналогичными SQL-запросами. + +### Sum, average, minimum, maximum, quantile + +Вычисление вышеупомянутых агрегаций требует: + +- `AGG_FUNC` - одна из функций `AGG_FUNC_SUM`, `AGG_FUNC_AVG`, `AGG_FUNC_MIN`, `AGG_FUNC_MAX`, `AGG_FUNC_QUANTILE`, +- `aggregate_by_field` - поле, к которому применяется агрегация +- `group_by_field` - поле, по которому группируются значения (используется не для всех агрегаций) +- `filtering_query`- запрос чтобы отфильтровать только интересующие нас логи +- `quantile` - только для `AGG_FUNC_QUANTILE` + +В общем случае это преобразуется в следующий SQL-запрос: + +```sql +SELECT , AGG_FUNC() +FROM db +WHERE +GROUP BY +``` + +Используя наш API: + +```sh +grpcurl -plaintext -d ' +{ + "query": { + "from": "2000-01-01T00:00:00Z", + "to": "2077-01-01T00:00:00Z", + "query": "" + }, + "aggs": [ + { + "field": "", + "func": "AGG_FUNC", + "group_by": "" + } + ] +}' localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAggregation +``` + +Рассматривая реальный пример, нам может потребоваться вычислить среднее время ответа для сервисов, имеющих поле +`response_time`. Тогда мы бы написали следующий запрос: + +```sql +SELECT service, AVG(response_time) +FROM db +WHERE response_time:* -- meaning that `response_time` field exists in logs +GROUP BY service +``` + +Используя наш API: + +```sh +grpcurl -plaintext -d ' +{ + "query": { + "from": "2000-01-01T00:00:00Z", + "to": "2077-01-01T00:00:00Z", + "query": "response_time:*" + }, + "aggs": [ + { + "field": "response_time", + "func": "AGG_FUNC_AVG", + "group_by": "service" + } + ] +}' localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAggregation +``` + +### Count, unique + +Агрегации Count и Unique очень похожи на приведенные выше примеры, за исключением того, что для этих агрегаций нет +необходимости в дополнительном `group_by_field`, поскольку мы уже группируем по `aggregate_by_field`. + +SQL-запрос для агрегации `AGG_FUNC_COUNT`: + +```sql +SELECT , COUNT (*) +FROM db +WHERE +GROUP BY +``` + +Используя наш API: + +```sh +grpcurl -plaintext -d ' +{ + "query": { + "from": "2000-01-01T00:00:00Z", + "to": "2077-01-01T00:00:00Z", + "query": "" + }, + "aggs": [ + { + "field": "", + "func": "AGG_FUNC_COUNT" + } + ] +}' localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAggregation +``` + +Рассматривая реальный пример, мы можем захотеть вычислить количество логов для каждого уровня логирования (`debug`, +`info` и т.д.) для определенного сервиса, например, `seq-db`. Тогда мы можем написать следующий запрос: + +```sql +SELECT level, COUNT(*) +FROM db +WHERE service:seq-db +GROUP BY level +``` + +Используя наш API: + +```sh +grpcurl -plaintext -d ' +{ + "query": { + "from": "2000-01-01T00:00:00Z", + "to": "2077-01-01T00:00:00Z", + "query": "service:seq-db" + }, + "aggs": [ + { + "field": "level", + "func": "AGG_FUNC_COUNT" + } + ] +}' localhost:9004 seqproxyapi.v1.SeqProxyApi/GetAggregation +``` + +## Гистограммы + +Гистограммы позволяют пользователям визуально интерпретировать распределение логов, удовлетворяющих заданному запросу. +Например, количество логов определенного сервиса за заданный интервал времени. + +Гистограммы можно запрашивать отдельно, используя [GetHistogram](10-public-api.md#gethistogram), или вместе с +документами и функциональными агрегациями, используя [ComplexSearch](10-public-api.md#complexsearch). + +Для более подробного ознакомления с API и примерами обратитесь к [публичному API](10-public-api.md). + +## Таймсерии + +Таймсерии позволяют вычислять агрегации для интервалов и визуализировать их. Они представляют собой нечто среднее +между гистограммами и функциональными агрегациями: они позволяют одновременно вычислять несколько гистограмм для +заданных функций агрегации. + +Рассмотрим предыдущий пример с гистограммами, где мы визуализировали количество логов во времени только для одного +сервиса за раз. Используя возможности таймсерий, мы можем одновременно вычислить количество логов для каждого сервиса, +используя `AGG_FUNC_COUNT` по полю `service`. + +Другой пример использования таймсерий — визуализация количества логов для каждого уровня логирования во времени. +Это может быть особенно полезно, когда необходимо отлаживать проблемы в реальном времени. Мы можем просто +визуализировать количество логов для каждого уровня и найти необычные всплески и связанные с ними логи. + +Поскольку временные ряды по сути являются агрегациями, они имеют тот же API, что и агрегации, за исключением того, что +присутствует новое поле interval для вычисления количества интервалов для расчета агрегации. Для получения подробной +информации обратитесь к [публичному API](10-public-api.md#count-с-указанием-интервала).