Репозиторий для трека «Сервер сбора метрик и алертинга».
- Iter7. Пакет encoding. Сериализация и десериализация данных.
- Отправлять с агента метрики в формате json на новый маршрут
/update
- Реализовать на сервере новый маршрут
/update
который будет принимать json с метрикой и парсить его в структуру. - Получать значение метрик с помощью
POST /value
, в ответе такой же json только с заполненными значениями. - Проверить тесты.
- Отправлять с агента метрики в формате json на новый маршрут
- Iter8. Пакет compress. Сжатие данных.
- Агент передавать данные в формате gzip (добавить Content-Encoding: gzip в заголовок запроса и сжать данные).
- Сервер опционально принимать запросы в сжатом формате (при наличии соответствующего HTTP-заголовка Content-Encoding).
- Отдавать сжатый ответ клиенту, который поддерживает обработку сжатых ответов (с HTTP-заголовком Accept-Encoding).
- Iter9. Пакет os. Операции с файлами.
- Доработайте код сервера, чтобы он мог с заданной периодичностью сохранять текущие значения метрик на диск в указанный файл, а на старте — опционально загружать сохранённые ранее значения. При штатном завершении сервера все накопленные данные должны сохраняться.
- Флаг
-i
, переменная окружения STORE_INTERVAL — интервал времени в секундах, по истечении которого текущие показания сервера сохраняются на диск (по умолчанию 300 секунд, значение 0 делает запись синхронной). - Флаг
-f
, переменная окружения FILE_STORAGE_PATH — полное имя файла, куда сохраняются текущие значения (по умолчанию /tmp/metrics-db.json, пустое значение отключает функцию записи на диск). - Флаг
-r
, переменная окружения RESTORE — булево значение (true/false), определяющее, загружать или нет ранее сохранённые значения из указанного файла при старте сервера (по умолчанию true).
- Iter10. Пакет database/sql. Взаимодействие с базами данных SQL.
- Добавьте на сервер функциональность подключения к базе данных. В качестве СУБД используйте PostgreSQL не ниже 10 версии.
- Строка с адресом подключения к БД должна получаться из переменной окружения DATABASE_DSN или флага командной строки -d.
- Добавьте в сервер хендлер GET /ping, который при запросе проверяет соединение с базой данных. При успешной проверке хендлер должен вернуть HTTP-статус 200 OK, при неуспешной — 500 Internal Server Error.
- Iter11. Пакет database/sql. Взаимодействие с базами данных SQL.
- Перепишите сервер для сбора метрик таким образом, чтобы СУБД PostgreSQL стала хранилищем метрик вместо текущей реализации.
- Iter12. Пакет database/sql. Взаимодействие с базами данных SQL.
- Сервер: Добавьте новый хендлер POST /updates/, принимающий в теле запроса множество метрик в формате: []Metrics (списка метрик).
- Агент: Научите агент работать с использованием нового API (отправлять метрики батчами).
- Iter13. Добавьте обработку
retriable
-ошибок.- Агент не сумел с первой попытки выгрузить данные на сервер из-за временной невозможности установить соединение с сервером.
- При обращении к PostgreSQL cервер получил ошибку транспорта (из категории Class 08 — Connection Exception)
- Ошибка доступа к файлу, который был заблокирован другим процессом.
- Три повтора (всего 4 попытки). Интервалы между повторами должны увеличиваться: 1s, 3s, 5s.
- Использование golang-migrate для миграции таблички сервера
- Makefile для запуска миграций, сервера и агента.
- Iter14. Подпись передаваемых данных по алгоритму SHA256. Посчитать hash от всего тела запроса и разместить его в HTTP-заголовке HashSHA256.
- Агент:
- Добавьте поддержку аргумента через флаг
-k=<КЛЮЧ>
и переменную окруженияKEY=<КЛЮЧ>
. - При наличии ключа агент должен вычислять хеш и передавать в HTTP-заголовке запроса с именем
HashSHA256
.
- Добавьте поддержку аргумента через флаг
- Сервер:
- Добавьте поддержку аргумента через флаг
-k=<КЛЮЧ>
и переменную окруженияKEY=<КЛЮЧ
>. - При наличии ключа (хэша) во время обработки запроса сервер должен проверять соответствие полученного и вычисленного хеша.
- При несовпадении сервер должен отбрасывать полученные данные и возвращать
http.StatusBadRequest
. - При наличии ключа на этапе формирования ответа сервер должен вычислять хеш и передавать его в HTTP-заголовке ответа с именем HashSHA256.
- Добавьте поддержку аргумента через флаг
- Агент:
- Iter15. Паттерны многопоточности.
- Агент: Добавить флаг -l=<ЗНАЧЕНИЕ> и переменную окружения RATE_LIMIT.
- Агент: Перепланируйте архитектуру агента таким образом, чтобы сбор метрик (опрос runtime) и их отправка осуществлялись в разных горутинах. При этом количество одновременно исходящих запросов на сервер нужно ограничивать «сверху» (паттерн worker pool).
- Агент: Добавьте ещё одну горутину, которая будет использовать пакет gopsutil и собирать дополнительные метрики
- TotalMemory,
- FreeMemory,
- CPUutilization1 (по числу CPU, определяемому во время исполнения)
- Iter16. Бенчмарки и профилирование.
- Добавить бенчмарки, измеряющие скорость выполнения важнейших компонентов вашей системы.
- Сохранить профиль потребления памяти и времени выполнения для каждого компонента.
- Исправить неэффективные места в коде.
- Сохранить профиль после исправлений и сравнить с предыдущим:
pprof -top -diff_base=profiles/base.pprof profiles/result.pprof
- Внимание: к концу текущего спринта покрытие вашего кода тестами должно быть не менее 40%.
- Iter17. Форматирование кода.
- Отформатируйте свой проект с помощью gofmt или goimports. Убедитесь, что все файлы проекта прошли форматирование.
- Iter18. Документация.
- Добавьте к основным экспортированным методам и переменным (хендлерам, публичным структурам и интерфейсам) в вашем проекте документацию в формате godoc.
- Добавьте примеры работы с эндпоинтами практического трека в формате example_test.go.
- Покрытие вашего кода тестами на данный момент должно быть не менее 40%.
- Iter19. Статический анализ.
- Создайте свой multichecker (под названием staticlint, в директории
cmd/staticlint
), состоящий из:- стандартных статических анализаторов пакета golang.org/x/tools/go/analysis/passes;
- всех анализаторов класса SA пакета staticcheck.io;
- не менее одного анализатора остальных классов пакета staticcheck.io;
- двух или более любых публичных анализаторов на ваш выбор.
- Напишите и добавьте в multichecker собственный анализатор, запрещающий использовать прямой вызов os.Exit в функции main пакета main.
- Добавьте документацию в формате godoc, подробно опишите в ней механизм запуска multichecker, а также каждый анализатор и его назначение.
- Покрытие вашего кода тестами к концу спринта должно быть не менее 55%.
- Создайте свой multichecker (под названием staticlint, в директории
- Iter20. Флаги сборки и компиляции.
-
Добавьте в пакеты
cmd/agent
иcmd/server
глобальные переменные:var BuildVersion string var BuildDate string var BuildCommit string
-
При старте приложения выводите в stdout сообщение в следующем формате:
Build version: <buildVersion> (или "N/A" при отсутствии значения) Build date: <buildDate> (или "N/A" при отсутствии значения) Build commit: <buildCommit> (или "N/A" при отсутствии значения)
-
Покрытие вашего кода тестами к концу спринта должно быть не менее 55%.
-
- Iter21. Добавление ассиметричного шифрования.
- Добавьте в агент и сервер поддержку асимметричного шифрования.
- Для агента: с помощью флага -crypto-key или переменной окружения CRYPTO_KEY передайте путь до файла с публичным ключом.
- Для сервера: с помощью флага -crypto-key или переменной окружения CRYPTO_KEY передайте путь до файла с приватным ключом.
- Шифруйте сообщения от агента к серверу с помощью ключей.
- Добавьте в агент и сервер поддержку асимметричного шифрования.
- Iter22. Конфигурация в формате JSON.
- Добавьте возможность конфигурации сервера и агента с помощью файла в формате JSON. Нужно поддержать все действующие опции приложения.
- Имя файла конфигурации должно задаваться через флаг -c/-config или переменную окружения CONFIG.
- Значения из файла конфигурации должны иметь меньший приоритет, чем флаги или переменные окружения.
- Iter23. Обработка сигналов.
- Агент должен штатно завершаться по сигналам: syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT.
- Сервер должен штатно завершаться по сигналам: syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT.
- Данные, которые находятся в процессе обработки на момент получения сигнала, должны быть успешно переданы агентом на сервер, а сервер должен успешно сохранить все несохранённые данные.
- К концу спринта покрытие тестами не менее 70%.
Пример:
{
"address": "localhost:8080", // аналог переменной окружения ADDRESS или флага -a
"restore": true, // аналог переменной окружения RESTORE или флага -r
"store_interval": "1s", // аналог переменной окружения STORE_INTERVAL или флага -i
"store_file": "/path/to/file.db", // аналог переменной окружения STORE_FILE или -f
"database_dsn": "", // аналог переменной окружения DATABASE_DSN или флага -d
"crypto_key": "/path/to/key.pem" // аналог переменной окружения CRYPTO_KEY или флага -crypto-key
}
Пример:
{
"address": "localhost:8080", // аналог переменной окружения ADDRESS или флага -a
"report_interval": "1s", // аналог переменной окружения REPORT_INTERVAL или флага -r
"poll_interval": "1s", // аналог переменной окружения POLL_INTERVAL или флага -p
"crypto_key": "/path/to/key.pem" // аналог переменной окружения CRYPTO_KEY или флага -crypto-key
}
Чтобы иметь возможность получать обновления автотестов и других частей шаблона, выполните команду:
git remote add -m main template https://github.com/Yandex-Practicum/go-musthave-metrics-tpl.git
Для обновления кода автотестов выполните команду:
git fetch template && git checkout template/main .github
Затем добавьте полученные изменения в свой репозиторий.
Для успешного запуска автотестов называйте ветки iter<number>
, где <number>
— порядковый номер инкремента. Например,
в ветке с названием iter4
запустятся автотесты для инкрементов с первого по четвёртый.
При мёрже ветки с инкрементом в основную ветку main
будут запускаться все автотесты.
Подробнее про локальный и автоматический запуск читайте в README автотестов.
# бинарник для MacOS (intel)
wget https://github.com/Yandex-Practicum/go-autotests/releases/download/v0.10.6/metricstest-darwin-amd64
chmod +x metricstest-darwin-amd64
# запуск тестов
./metricstest-darwin-amd64 -test.v -binary-path=bin/server -agent-binary-path=bin/agent -source-path . > test.log
# запуск конкретной итерации
./metricstest-darwin-amd64 -test.v -test.run=^TestIteration7$ -binary-path=bin/server -agent-binary-path=bin/agent -source-path . | tee test.log
# запуск конкретной итерации с -server-port=8080
./metricstest-darwin-amd64 -test.v -test.run=^TestIteration8$ -server-port=8080 -binary-path=bin/server -agent-binary-path=bin/agent -source-path . | tee test.log
# проверка iter12
./metricstest-darwin-amd64 -test.v -test.run=^TestIteration12$ -server-port=8080 -binary-path=bin/server -agent-binary-path=bin/agent -database-dsn=postgres://metrics:password@localhost:5432/metrics -source-path . | tee test.log
# проверка iter13
./metricstest-darwin-amd64 -test.v -test.run=^TestIteration13$ -server-port=8080 -binary-path=bin/server -agent-binary-path=bin/agent -database-dsn=postgres://metrics:password@localhost:5432/metrics -source-path . | tee iter13.log
# проверка iter14
./metricstest-darwin-amd64 -test.v -test.run=^TestIteration14$ -server-port=8080 -binary-path=bin/server -agent-binary-path=bin/agent -database-dsn=postgres://metrics:password@localhost:5432/metrics -source-path . | tee iter13.log
# запуск сервера с postgres
go run . -d postgres://metrics:password@localhost:5432/metrics
clear && golangci-lint run
В Linux однократно:
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
go install golang.org/x/tools/cmd/goimports@latest
go install github.com/segmentio/golines@latest
go install honnef.co/go/tools/cmd/staticcheck@latest
Пример:
go run -ldflags "-X main.BuildVersion=v1.0.1 -X 'main.BuildDate=$(date +'%Y/%m/%d %H:%M:%S')' -X main.BuildCommit=dev