Skip to content

REST API server for storing arbitrary metrics (Data Warehouse)

License

Notifications You must be signed in to change notification settings

AnatoliyBr/dwh-service

Repository files navigation

Data Warehouse Service

Описание

REST API приложение для хранения произвольных метрик, способное принимать в себя данные, хранить и отдавать пользователю.

Функционал

Данное серверное (backend) приложение предоставляет API с форматом JSON для добавления сервисов, метрик и событий, а также получения данных по ключам событий за заданный интервал времени.

Под событием понимается получение списка метрик от одного сервиса.

Структура REST API

POST /services - добавление нового сервиса
GET /services - просмотр отслеживаемых сервисов

POST /metrics - добавление новой метрики
GET /metrics - просмотр используемых метрик

POST /events - добавление нового события
GET /events - получение данных по идентификатору сервиса и метрики за заданный интервал времени

Схема базы данных

Архитектура

Запуск и отладка

Все команды, используемые в процессе разработки и тестирования, фиксировались в Makefile.

Для запуска сервиса достаточно добавить .env файл в директорию с проектом и заполнить его данными из .env.example.

Чтобы поднять проект, необходимо выполнить две задачи из Makefile:

make compose-build
make compose-up

Примеры запросов

Добавление сервиса

Добавление нового сервиса:

curl --location --request POST http://localhost:8080/services \
--data-raw '{
    "slug": "TODO_APP",
    "details": "REST API application for managing task lists (todo lists)"
}'

Пример ответа:

{
    "service_id": 1,   
    "slug": "TODO_APP",
    "details": "REST API application for managing task lists (todo lists)"
}

Просмотр сервиса

Просмотр сервиса по идентификатору:

curl --location --request GET http://localhost:8080/services \
--data-raw '{
    "service_id": 1
}'

Пример ответа:

{
    "service_id": 1,
    "slug": "TODO_APP",
    "details": "REST API application for managing task lists (todo lists)"
}

Добавление метрики

Сервер поддерживает 6 типов: "INT", "FLOAT", "DURATION", "TIMESTAMP_WITH_TIMEZONE", "BOOL", "STRING".

Типа INT

Добавление новой метрики типа "INT":

curl --location --request POST http://localhost:8080/metrics \
--data-raw '{
    "slug": "INT_METRIC",
    "metric_type": "INT",
    "details": "Calculated in integers"
}'

Пример ответа:

{
    "metric_id": 1,
    "slug": "INT_METRIC",
    "metric_type": "INT",
    "details": "Calculated in integers"
}

Типа FLOAT

Добавление новой метрики типа "FLOAT":

curl --location --request POST http://localhost:8080/metrics \
--data-raw '{
    "slug": "FLOAT_METRIC",
    "metric_type": "FLOAT",
    "details": "Calculated in floating point numbers"
}'

Пример ответа:

{
    "metric_id": 2,
    "slug": "FLOAT_METRIC",
    "metric_type": "FLOAT",
    "details": "Calculated in floating point numbers"
}

Типа DURATION

Добавление новой метрики типа "DURATION":

curl --location --request POST http://localhost:8080/metrics \
--data-raw '{
    "slug": "DURATION_METRIC",
    "metric_type": "DURATION",
    "details": "Calculated by duration"
}'

Пример ответа:

{
    "metric_id": 3,
    "slug": "DURATION_METRIC",
    "metric_type": "DURATION",
    "details": "Calculated by duration"
}

Типа TIMESTAMP_WITH_TIMEZONE

Добавление новой метрики типа "TIMESTAMP_WITH_TIMEZONE":

curl --location --request POST http://localhost:8080/metrics \
--data-raw '{
    "slug": "TIMESTAMP_WITH_TIMEZONE_METRIC",
    "metric_type": "TIMESTAMP_WITH_TIMEZONE",
    "details": "Calculated by timestamps with timezone"
}'

Пример ответа:

{
    "metric_id": 4,
    "slug": "TIMESTAMP_WITH_TIMEZONE_METRIC",
    "metric_type": "TIMESTAMP_WITH_TIMEZONE",
    "details": "Calculated by timestamps with timezone"
}

Типа BOOL

Добавление новой метрики типа "BOOL":

curl --location --request POST http://localhost:8080/metrics \
--data-raw '{
    "slug": "BOOL_METRIC",
    "metric_type": "BOOL",
    "details": "Calculated by logical type"
}'

Пример ответа:

{
    "metric_id": 5,
    "slug": "BOOL_METRIC",
    "metric_type": "BOOL",
    "details": "Calculated by logical type"
}

Типа STRING

Добавление новой метрики типа "STRING":

curl --location --request POST http://localhost:8080/metrics \
--data-raw '{
    "slug": "STRING_METRIC",
    "metric_type": "STRING",
    "details": "Contains a message"
}'

Пример ответа:

{
    "metric_id": 6,
    "slug": "STRING_METRIC",
    "metric_type": "STRING",
    "details": "Contains a message"
}

Просмотр метрики

Просмотр метрики по идентификатору:

curl --location --request GET http://localhost:8080/metrics \
--data-raw '{
    "metric_id": 1
}'

Пример ответа:

{
    "metric_id": 1,
    "slug": "INT_METRIC",
    "metric_type": "INT",
    "details": "Calculated in integers"
}

Добавление события

Добавление нового события со списком метрик:

curl --location --request POST http://localhost:8080/events \
--data-raw '{
    "service_id": 1,
    "metrics": [
        {
            "metric_id": 1,
            "metric_value": 25
        },
        {
            "metric_id": 2,
            "metric_value": 36.6
        },
        {
            "metric_id": 3,
            "metric_value": "1h13m0.5s"
        },
        {
            "metric_id": 4,
            "metric_value": "2023-10-08T19:14:05Z"
        },
        {
            "metric_id": 5,
            "metric_value": true
        },
        {
            "metric_id": 6,
            "metric_value": "Suspicious activity"
        }
    ]
}'

Пример ответа:

{
    "event": {
        "event_id": 1,
        "time_stamp": "2023-10-08T20:44:59+03:00",
        "service_id": 1
    },
    "metrics": [
        {
            "metric_id": 1,
            "metric_value": 25
        },
        {
            "metric_id": 2,
            "metric_value": 36.6
        },
        {
            "metric_id": 3,
            "metric_value": "1h13m0.5s"
        },
        {
            "metric_id": 4,
            "metric_value": "2023-10-08T19:14:05Z"
        },
        {
            "metric_id": 5,
            "metric_value": true
        },
        {
            "metric_id": 6,
            "metric_value": "Suspicious activity"
        }
    ]
}

Получение данных

Получение данных по идентификатору сервиса и метрики за заданный интервал времени:

curl --location --request GET http://localhost:8080/events \
--data-raw '{
    "service_id": 1,
    "period": [
        "2023-10-06T10:00:00+03:00",
        "2023-10-09T10:00:00+03:00"
        ],
    "metric_id": 3
}'

Пример ответа:

{
    "request": {
        "service_id": 1,
        "period": [
            "2023-10-06T10:00:00+03:00",
            "2023-10-09T10:00:00+03:00"
        ],
        "metric_id": 3
    },
    "report": [
        {
            "time_stamp": "2023-10-08T20:41:37Z",
            "value": "3m10s"
        },
        {
            "time_stamp": "2023-10-08T20:42:02Z",
            "value": "1h3m9.9s"
        },
        {
            "time_stamp": "2023-10-08T20:42:19Z",
            "value": "33m35s"
        },
        {
            "time_stamp": "2023-10-08T20:42:36Z",
            "value": "13m2.1s"
        }
    ]
}

Решения

В ходе разработки были сомнения по тем или иным вопросам, которые были решены следующим образом:

  1. Как организовать хранение произвольных метрик, набор которых динамически меняется?
  • Первый вариант. При регистрации события записывать каждую метрику в отдельную строку (то есть одна строка = одна метрика). Схема простая, расширяемая, нормализованная, позволяет использовать реляционную БД типа PostgreSQL и хорошо справляется с добавлением новых метрик, но требует преобразования значений метрик разных типов в один (например, в строку).
  • Второй вариант. Каждой метрике сопоставлять столбец и использовать колоночную БД типа Cassandra. Схема позволяет эффективнее считывать информацию по ключам, но требует изменения схемы БД (добавления новой колонки) при добавлении каждой новой метрики в БД.

В данном проекте использовался первый вариант.

Releases

No releases published

Packages

No packages published

Languages