Spring Boot приложение на Java 17 для приёма пользовательских событий, хранения в PostgreSQL и расчёта простой аналитики. В проект встроена простая веб-панель, которая работает поверх тех же REST-эндпоинтов.
- Приём событий с произвольными метаданными.
- CRUD и фильтрация событий (по пользователю, типу, диапазону времени).
- Комбинирование фильтров в
GET /api/events. - Пагинация и сортировка через стандартный
Pageable. - Базовая аналитика: DAU и топ типов событий за период.
- Встроенный frontend для ручной отправки событий и просмотра аналитики.
- Наблюдаемость через Actuator + Prometheus/Grafana.
- Документация API через OpenAPI (springdoc).
- Java 17, Spring Boot 3.2.3
- Spring Web, Validation, Data JPA
- PostgreSQL + Flyway
- Micrometer + Prometheus + Grafana
- springdoc-openapi
- Testcontainers + JUnit 5 + Mockito
flowchart LR
User[Пользователь] --> UI[Встроенный Web UI]
Client[Клиент / Внешняя система] --> API[REST API]
UI --> API
API --> Service[Service Layer\nвалидация и бизнес-логика]
Service --> Repo[Repository Layer]
Repo --> DB[(PostgreSQL)]
Service --> Analytics[Analytics Module\nDAU и event-type stats]
Analytics --> DB
API --> Docs[OpenAPI / Swagger]
API --> Metrics[Actuator / Metrics]
Metrics --> Prometheus[Prometheus]
Prometheus --> Grafana[Grafana]
Подробности по слоям вынесены в Architecture/:
Architecture/API/readme.mdArchitecture/Service/readme.mdArchitecture/Data-Access/readme.mdArchitecture/Domain-Model/readme.mdArchitecture/DTO-Mapping/readme.mdArchitecture/Database-Migrations/readme.mdArchitecture/Configuration/readme.mdArchitecture/Observability/readme.mdArchitecture/Infrastructure/readme.mdArchitecture/Testing/readme.md
src/main/java/.../controller— REST APIsrc/main/java/.../config— конфигурация Spring/OpenAPIsrc/main/java/.../service— бизнес-логикаsrc/main/java/.../repository— JPA доступ к даннымsrc/main/java/.../model— JPA сущностиsrc/main/java/.../dto— DTOsrc/main/java/.../mapper— преобразования DTO <-> entitysrc/main/java/.../exception— обработка ошибокsrc/main/resources/db/migration— миграции Flywaysrc/main/resources/static— встроенный frontend (/)ops/docker-compose.yml— локальный docker composeops/docker/Dockerfile— Docker buildops/monitoring/prometheus.yml— конфигурация Prometheusops/qodana.yaml— конфигурация Qodana
Таблица events:
| Поле | Тип | Описание |
|---|---|---|
id |
BIGSERIAL | PK |
user_id |
TEXT | идентификатор пользователя |
event_type |
TEXT | тип события |
event_date |
TIMESTAMPTZ | время события |
metadata |
TEXT | метаданные (строка, обычно JSON) |
created_at |
TIMESTAMPTZ | время записи в БД |
Event в коде маппится на эти столбцы, а eventTime связан с event_date.
GET /api/events— список событий (пагинация).- Фильтры:
userId,eventType,from,to. - Фильтры можно комбинировать.
fromиtoдолжны передаваться вместе.- Пример пагинации:
?page=0&size=20&sort=eventTime,desc.
- Фильтры:
GET /api/events/{id}— получить событие по id.POST /api/events— создать событие.PUT /api/events/{id}— обновить событие (обновляютсяeventType,metadata,eventTime;userIdне меняется).DELETE /api/events/{id}— удалить событие.
Пример создания события:
curl -sS -X POST http://localhost:8080/api/events \
-H 'Content-Type: application/json' \
-d '{"userId":"u1","eventType":"click","eventTime":"2026-01-21T12:00:00Z","metadata":"{\"button\":\"buy\"}"}'GET /api/analytics/event-types?from=...&to=...— счётчики по типам событий.GET /api/analytics/dau?from=...&to=...— DAU за период.
В аналитике время считается как [from, to): from включительно, to исключительно.
Swagger UI доступен на стандартном пути springdoc (/swagger-ui.html, редирект на /swagger-ui/index.html), если настройки не переопределены.
После старта приложения главная страница / открывает простую панель:
- создание события;
- фильтрация списка событий;
- расчёт DAU и счётчиков по типам событий.
EventRequestDtoвалидируется через@Validи@NotBlank.- Ошибки возвращаются в формате
ApiError:
{
"status": 400,
"error": "BAD_REQUEST",
"message": "userId is required",
"path": "/api/events",
"timestamp": "2026-01-21T12:00:00Z"
}Исключения NotFoundException, BadRequestException и ошибки валидации диапазона времени маппятся в 404/400. Остальные — в 500.
В src/main/resources/application.yml источники БД ожидаются через переменные окружения:
SPRING_DATASOURCE_URLSPRING_DATASOURCE_USERNAMESPRING_DATASOURCE_PASSWORD
docker compose -f ops/docker-compose.yml up -d --buildПоднимаются сервисы:
app— порт8080db— PostgreSQL (хост-порт5433-> контейнер5432)prometheus— порт9090grafana— порт3000(логин/пароль:admin/admin)
Остановить:
docker compose -f ops/docker-compose.yml down -vТребования: JDK 17, Maven, внешняя PostgreSQL.
mvn spring-boot:runActuator включён, доступны эндпоинты:
/actuator/health/actuator/info/actuator/metrics/actuator/prometheus
Prometheus настраивается через ops/monitoring/prometheus.yml, Grafana доступна на http://localhost:3000.
Миграции лежат в src/main/resources/db/migration и применяются автоматически при старте приложения.
Формат имени: V<версия>__<описание>.sql.
- Unit:
EventServiceTest(Mockito). - Integration:
EventControllerIntegrationTest,AnalyticsControllerIntegrationTest(Testcontainers + Postgres).
Запуск:
mvn testДля интеграционных тестов нужен Docker.
Инфраструктурные и служебные конфиги вынесены из корня в ops/, чтобы корень проекта оставался компактным:
ops/docker-compose.ymlops/docker/Dockerfileops/monitoring/prometheus.ymlops/qodana.yaml