REST API приложение для хранения произвольных метрик, способное принимать в себя данные, хранить и отдавать пользователю.
Данное серверное (backend) приложение предоставляет API с форматом JSON для добавления сервисов, метрик и событий, а также получения данных по ключам событий за заданный интервал времени.
Под событием понимается получение списка метрик от одного сервиса.
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":
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":
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":
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":
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":
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":
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"
}
]
}
В ходе разработки были сомнения по тем или иным вопросам, которые были решены следующим образом:
- Как организовать хранение произвольных метрик, набор которых динамически меняется?
- Первый вариант. При регистрации события записывать каждую метрику в отдельную строку (то есть одна строка = одна метрика). Схема простая, расширяемая, нормализованная, позволяет использовать реляционную БД типа PostgreSQL и хорошо справляется с добавлением новых метрик, но требует преобразования значений метрик разных типов в один (например, в строку).
- Второй вариант. Каждой метрике сопоставлять столбец и использовать колоночную БД типа Cassandra. Схема позволяет эффективнее считывать информацию по ключам, но требует изменения схемы БД (добавления новой колонки) при добавлении каждой новой метрики в БД.
В данном проекте использовался первый вариант.