diff --git a/backend/authik/src/main/kotlin/ru/ifmo/se/dating/authik/security/AuthikSecuredPaths.kt b/backend/authik/src/main/kotlin/ru/ifmo/se/dating/authik/security/AuthikSecuredPaths.kt index 47af4cd6..f5db5f3f 100644 --- a/backend/authik/src/main/kotlin/ru/ifmo/se/dating/authik/security/AuthikSecuredPaths.kt +++ b/backend/authik/src/main/kotlin/ru/ifmo/se/dating/authik/security/AuthikSecuredPaths.kt @@ -1,11 +1,19 @@ package ru.ifmo.se.dating.authik.security +import org.springframework.http.HttpMethod import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher import org.springframework.stereotype.Component -import ru.ifmo.se.dating.spring.security.auth.SpringSecuredPaths +import ru.ifmo.se.dating.spring.security.auth.And +import ru.ifmo.se.dating.spring.security.auth.Not import ru.ifmo.se.dating.spring.security.auth.Path +import ru.ifmo.se.dating.spring.security.auth.SpringSecuredPaths @Component class AuthikSecuredPaths : SpringSecuredPaths { - override val matcher: ServerWebExchangeMatcher = Path("") + override val matcher: ServerWebExchangeMatcher = And( + Path("/api/**"), + Not(Path("/api/auth/telegram/web-app", HttpMethod.GET)), + Not(Path("/api/monitoring/healthcheck", HttpMethod.PUT)), + Not(Path("/actuator/**", HttpMethod.GET)), + ) } diff --git a/backend/config/build.gradle.kts b/backend/config/build.gradle.kts index 90257949..86bd7768 100644 --- a/backend/config/build.gradle.kts +++ b/backend/config/build.gradle.kts @@ -3,13 +3,14 @@ plugins { } dependencies { - implementation(project(":starter-service-discovery")) - implementation(project(":starter-tls")) - implementation(libs.org.springframework.boot.spring.boot) implementation(libs.org.springframework.boot.spring.boot.starter.web) implementation(libs.org.springframework.cloud.spring.cloud.config.server) + implementation(project(":starter-monitoring")) + implementation(project(":starter-service-discovery")) + implementation(project(":starter-tls")) + testImplementation(libs.org.springframework.boot.spring.boot.starter.test) testImplementation(libs.junit.junit) testImplementation(libs.org.testcontainers.vault) diff --git a/backend/config/src/main/resources/application.yml b/backend/config/src/main/resources/application.yml index da096319..e3ac293c 100644 --- a/backend/config/src/main/resources/application.yml +++ b/backend/config/src/main/resources/application.yml @@ -1,6 +1,6 @@ spring: config: - import: application-service-discovery.yml,application-tls.yml + import: application-monitoring.yml,application-service-discovery.yml,application-tls.yml application: name: config profiles: diff --git a/backend/foundation/build.gradle.kts b/backend/foundation/build.gradle.kts index abd179a3..c6194022 100644 --- a/backend/foundation/build.gradle.kts +++ b/backend/foundation/build.gradle.kts @@ -5,6 +5,7 @@ plugins { } dependencies { + api(project(":starter-monitoring")) api(project(":starter-service-discovery")) api(project(":starter-tls")) diff --git a/backend/foundation/src/main/resources/application-foundation.yml b/backend/foundation/src/main/resources/application-foundation.yml index 4744934c..e2218da0 100644 --- a/backend/foundation/src/main/resources/application-foundation.yml +++ b/backend/foundation/src/main/resources/application-foundation.yml @@ -1,6 +1,6 @@ spring: config: - import: application-service-discovery.yml,application-tls.yml,optional:configserver:https://config.dating.se.ifmo.ru:8080 + import: application-monitoring.yml,application-service-discovery.yml,application-tls.yml,optional:configserver:https://config.dating.se.ifmo.ru:8080 cloud: config: uri: https://config.dating.se.ifmo.ru:8080 @@ -27,12 +27,3 @@ springdoc: swagger-ui: url: /openapi/api.yml path: /swagger-ui.html -logging: - level: - web: INFO - liquibase: WARN - r2dbc: DEBUG - group: - r2dbc: org.springframework.r2dbc,org.springframework.data.r2dbc,org.jooq.tools.LoggerListener - pattern: - console: "%clr(%d{yyyy-MM-dd'T'HH:mm:ss.SSS}){faint} %clr([%level]) %clr(%logger{36}){blue}: %msg%n" diff --git a/backend/gateway/build.gradle.kts b/backend/gateway/build.gradle.kts index 0f7c77c3..974ef7d3 100644 --- a/backend/gateway/build.gradle.kts +++ b/backend/gateway/build.gradle.kts @@ -3,6 +3,7 @@ plugins { } dependencies { + implementation(project(":starter-monitoring")) implementation(project(":starter-service-discovery")) implementation(project(":starter-tls")) diff --git a/backend/gateway/src/main/resources/application.yml b/backend/gateway/src/main/resources/application.yml index 00e1a29a..ecf18086 100644 --- a/backend/gateway/src/main/resources/application.yml +++ b/backend/gateway/src/main/resources/application.yml @@ -1,6 +1,6 @@ spring: config: - import: application-service-discovery.yml,application-tls.yml + import: application-monitoring.yml,application-service-discovery.yml,application-tls.yml application: name: gateway cloud: @@ -146,10 +146,3 @@ springdoc: url: openapi/matchmaker/api.yml - name: people url: openapi/people/api.yml -logging: - level: - gateway: WARN - group: - gateway: org.springframework.cloud.gateway.route - pattern: - console: "%clr(%d{yyyy-MM-dd'T'HH:mm:ss.SSS}){faint} %clr([%level]) %clr(%logger{36}){blue}: %msg%n" diff --git a/backend/gradle/libs.versions.toml b/backend/gradle/libs.versions.toml index e8d86bdb..fdb99c7c 100644 --- a/backend/gradle/libs.versions.toml +++ b/backend/gradle/libs.versions.toml @@ -24,6 +24,8 @@ commons-codec-commons-codec = "1.17.1" org-jetbrains-kotlinx-kotlinx-coroutines = "1.9.0" io-projectreactor-kotlin-reactor-kotlin-extensions = "1.2.3" +io-micrometer = "1.14.3" + io-projectreactor-reactor-test = "3.6.11" junit-junit = "4.13.2" org-testcontainers = "1.20.3" @@ -76,6 +78,8 @@ org-liquibase-liquibase-core = { module = "org.liquibase:liquibase-core", versio org-postgresql-postgresql = { module = "org.postgresql:postgresql", version.ref = "org-postgresql-postgresql" } org-postgresql-r2dbc-postgresql = { module = "org.postgresql:r2dbc-postgresql", version.ref = "org-postgresql-r2dbc-postgresql" } +io-micrometer-micrometer-registry-prometheus = { module = "io.micrometer:micrometer-registry-prometheus", version.ref = "io-micrometer" } + junit-junit = { module = "junit:junit", version.ref = "junit-junit" } org-testcontainers-postgresql = { module = "org.testcontainers:postgresql", version.ref = "org-testcontainers" } org-testcontainers-r2dbc = { module = "org.testcontainers:r2dbc", version.ref = "org-testcontainers" } diff --git a/backend/grafana/Dockerfile b/backend/grafana/Dockerfile new file mode 100644 index 00000000..74b3c03c --- /dev/null +++ b/backend/grafana/Dockerfile @@ -0,0 +1,3 @@ +FROM grafana/grafana + +ADD ./provisioning /etc/grafana/provisioning diff --git a/backend/grafana/provisioning/datasources/all.yml b/backend/grafana/provisioning/datasources/all.yml new file mode 100644 index 00000000..867a7545 --- /dev/null +++ b/backend/grafana/provisioning/datasources/all.yml @@ -0,0 +1,8 @@ +apiVersion: 1 +datasources: + - name: Prometheus + label: Prometheus + type: prometheus + access: proxy + url: http://${ITMO_DATING_PROMETHEUS_HOST}:9090 + isDefault: true diff --git a/backend/haproxy/config/haproxy.cfg b/backend/haproxy/config/haproxy.cfg index 296a56e6..7a234c36 100644 --- a/backend/haproxy/config/haproxy.cfg +++ b/backend/haproxy/config/haproxy.cfg @@ -18,12 +18,14 @@ defaults frontend internal bind :8445 ssl crt /usr/local/etc/haproxy/itmo-dating-backend.pem bind :8446 ssl crt /usr/local/etc/haproxy/itmo-dating-backend.pem + bind :8447 bind :8455 ssl crt /usr/local/etc/haproxy/itmo-dating-backend.pem bind :8456 ssl crt /usr/local/etc/haproxy/itmo-dating-backend.pem bind :8457 ssl crt /usr/local/etc/haproxy/itmo-dating-backend.pem use_backend vault if { dst_port 8445 } use_backend consul if { dst_port 8446 } + use_backend grafana if { dst_port 8447 } use_backend authik if { dst_port 8455 } use_backend matchmaker if { dst_port 8456 } use_backend people if { dst_port 8457 } @@ -36,6 +38,9 @@ backend consul option httpchk GET /ui server consul server.dc1.consul:8500 check init-addr last,libc,none +backend grafana + server grafana grafana.dating.se.ifmo.ru:3000 check init-addr last,libc,none + backend authik balance roundrobin option httpchk GET /actuator/health diff --git a/backend/matchmaker/src/main/kotlin/ru/ifmo/se/dating/matchmaker/security/MatchmakerSecuredPaths.kt b/backend/matchmaker/src/main/kotlin/ru/ifmo/se/dating/matchmaker/security/MatchmakerSecuredPaths.kt index 18df44fe..645352b2 100644 --- a/backend/matchmaker/src/main/kotlin/ru/ifmo/se/dating/matchmaker/security/MatchmakerSecuredPaths.kt +++ b/backend/matchmaker/src/main/kotlin/ru/ifmo/se/dating/matchmaker/security/MatchmakerSecuredPaths.kt @@ -15,5 +15,7 @@ class MatchmakerSecuredPaths : SpringSecuredPaths { Not(Path("/api/people/{person_id}", HttpMethod.PUT)), Not(Path("/api/monitoring/healthcheck", HttpMethod.GET)), Not(Path("/api/suggestions", HttpMethod.OPTIONS)), + Not(Path("/api/monitoring/healthcheck", HttpMethod.PUT)), + Not(Path("/actuator/**", HttpMethod.GET)), ) } diff --git a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/security/PeopleSecuredPaths.kt b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/security/PeopleSecuredPaths.kt index 15a45772..03737013 100644 --- a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/security/PeopleSecuredPaths.kt +++ b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/security/PeopleSecuredPaths.kt @@ -12,6 +12,7 @@ import ru.ifmo.se.dating.spring.security.auth.SpringSecuredPaths class PeopleSecuredPaths : SpringSecuredPaths { override val matcher: ServerWebExchangeMatcher = And( Path("/api/**"), - Not(Path("/api/monitoring/healthcheck", HttpMethod.GET)), + Not(Path("/api/monitoring/healthcheck", HttpMethod.PUT)), + Not(Path("/actuator/**", HttpMethod.GET)), ) } diff --git a/backend/prometheus/Dockerfile b/backend/prometheus/Dockerfile new file mode 100644 index 00000000..31e5f126 --- /dev/null +++ b/backend/prometheus/Dockerfile @@ -0,0 +1,9 @@ +FROM prom/prometheus:latest + +COPY ./prometheus.yml /etc/prometheus/prometheus.yml + +CMD [ \ + "--config.file=/etc/prometheus/prometheus.yml", \ + "--storage.tsdb.retention.size=500MB", \ + "--storage.tsdb.retention.time=3d" \ +] diff --git a/backend/prometheus/prometheus.yml b/backend/prometheus/prometheus.yml new file mode 100644 index 00000000..43ee500a --- /dev/null +++ b/backend/prometheus/prometheus.yml @@ -0,0 +1,67 @@ +global: + scrape_interval: 5s + +scrape_configs: + + - job_name: authik + metrics_path: /actuator/prometheus + dns_sd_configs: + - names: + - authik-0.dating.se.ifmo.ru + - authik-1.dating.se.ifmo.ru + type: A + port: 8080 + scheme: https + tls_config: + insecure_skip_verify: true + + - job_name: people + metrics_path: /actuator/prometheus + dns_sd_configs: + - names: + - people-0.dating.se.ifmo.ru + - people-1.dating.se.ifmo.ru + type: A + port: 8080 + scheme: https + tls_config: + insecure_skip_verify: true + + - job_name: matchmaker + metrics_path: /actuator/prometheus + dns_sd_configs: + - names: + - matchmaker-0.dating.se.ifmo.ru + - matchmaker-1.dating.se.ifmo.ru + type: A + port: 8080 + scheme: https + tls_config: + insecure_skip_verify: true + + - job_name: gateway + metrics_path: /actuator/prometheus + dns_sd_configs: + - names: + - gateway.dating.se.ifmo.ru + type: A + port: 8080 + scheme: https + tls_config: + insecure_skip_verify: true + + - job_name: object-storage + metrics_path: /minio/v2/metrics/cluster + dns_sd_configs: + - names: + - object-storage.dating.se.ifmo.ru + type: A + port: 9000 + scheme: http + + - job_name: postgres + dns_sd_configs: + - names: + - database-primary-exporter.dating.se.ifmo.ru + type: 'A' + port: 9187 diff --git a/backend/settings.gradle.kts b/backend/settings.gradle.kts index 08de02aa..853f7199 100644 --- a/backend/settings.gradle.kts +++ b/backend/settings.gradle.kts @@ -12,6 +12,7 @@ include( ":authik", ":matchmaker", ":people", + ":starter-monitoring", ":starter-service-discovery", ":starter-tls", ) diff --git a/backend/starter-monitoring/build.gradle.kts b/backend/starter-monitoring/build.gradle.kts new file mode 100644 index 00000000..3c8a9e51 --- /dev/null +++ b/backend/starter-monitoring/build.gradle.kts @@ -0,0 +1,11 @@ +plugins { + id("buildlogic.kotlin-library-conventions") + kotlin("plugin.spring") +} + +dependencies { + api(project(":starter-tls")) + + api(libs.org.springframework.boot.spring.boot.starter.actuator) + api(libs.io.micrometer.micrometer.registry.prometheus) +} diff --git a/backend/foundation/src/main/kotlin/ru/ifmo/se/dating/logging/Log.kt b/backend/starter-monitoring/src/main/kotlin/ru/ifmo/se/dating/logging/Log.kt similarity index 100% rename from backend/foundation/src/main/kotlin/ru/ifmo/se/dating/logging/Log.kt rename to backend/starter-monitoring/src/main/kotlin/ru/ifmo/se/dating/logging/Log.kt diff --git a/backend/foundation/src/main/kotlin/ru/ifmo/se/dating/logging/Slf4jLog.kt b/backend/starter-monitoring/src/main/kotlin/ru/ifmo/se/dating/logging/Slf4jLog.kt similarity index 100% rename from backend/foundation/src/main/kotlin/ru/ifmo/se/dating/logging/Slf4jLog.kt rename to backend/starter-monitoring/src/main/kotlin/ru/ifmo/se/dating/logging/Slf4jLog.kt diff --git a/backend/starter-monitoring/src/main/resources/application-monitoring.yml b/backend/starter-monitoring/src/main/resources/application-monitoring.yml new file mode 100644 index 00000000..dc777d03 --- /dev/null +++ b/backend/starter-monitoring/src/main/resources/application-monitoring.yml @@ -0,0 +1,29 @@ +spring: + config: + import: application-tls.yml +management: + endpoints: + web: + exposure: + include: health,prometheus + health: + diskspace: + enabled: false + metrics: + export: + prometheus: + enabled: true + distribution: + percentiles-histogram: + "[http.server.requests]": true +logging: + level: + web: INFO + liquibase: WARN + r2dbc: DEBUG + gateway: WARN + group: + r2dbc: org.springframework.r2dbc,org.springframework.data.r2dbc,org.jooq.tools.LoggerListener + gateway: org.springframework.cloud.gateway.route + pattern: + console: "%clr(%d{yyyy-MM-dd'T'HH:mm:ss.SSS}){faint} %clr([%level]) %clr(%logger{36}){blue}: %msg%n" diff --git a/backend/starter-service-discovery/build.gradle.kts b/backend/starter-service-discovery/build.gradle.kts index 812c0c41..a68bb280 100644 --- a/backend/starter-service-discovery/build.gradle.kts +++ b/backend/starter-service-discovery/build.gradle.kts @@ -5,8 +5,8 @@ plugins { dependencies { api(project(":starter-tls")) + api(project(":starter-monitoring")) - api(libs.org.springframework.boot.spring.boot.starter.actuator) api(libs.org.springframework.cloud.spring.cloud.starter.consul.discovery) api(libs.org.springframework.cloud.spring.cloud.starter.loadbalancer) } diff --git a/backend/starter-service-discovery/src/main/resources/application-service-discovery.yml b/backend/starter-service-discovery/src/main/resources/application-service-discovery.yml index 9116255d..bac24e34 100644 --- a/backend/starter-service-discovery/src/main/resources/application-service-discovery.yml +++ b/backend/starter-service-discovery/src/main/resources/application-service-discovery.yml @@ -1,6 +1,6 @@ spring: config: - import: application-tls.yml + import: application-tls.yml,application-monitoring.yml cloud: consul: scheme: https @@ -24,9 +24,3 @@ management: health: consul: enabled: true - diskspace: - enabled: false - endpoints: - web: - exposure: - include: health diff --git a/backend/starter-tls/build.gradle.kts b/backend/starter-tls/build.gradle.kts index 317a0e22..6c8a6f21 100644 --- a/backend/starter-tls/build.gradle.kts +++ b/backend/starter-tls/build.gradle.kts @@ -4,7 +4,7 @@ plugins { } dependencies { - api(libs.org.springframework.boot.spring.boot) + api(libs.org.springframework.spring.context) api(libs.org.springframework.spring.web) api(libs.org.springframework.spring.webflux) implementation("io.netty:netty-handler:4.1.117.Final") diff --git a/compose.yml b/compose.yml index aa147f7c..50fddb69 100644 --- a/compose.yml +++ b/compose.yml @@ -72,6 +72,7 @@ services: environment: MINIO_ROOT_USER: ${ITMO_DATING_MINIO_ROOT_USER?:err} MINIO_ROOT_PASSWORD: ${ITMO_DATING_MINIO_ROOT_PASSWORD?:err} + MINIO_PROMETHEUS_AUTH_TYPE: public volumes: - minio-data:/export tty: true @@ -96,6 +97,18 @@ services: timeout: 1s retries: 16 hostname: database-primary.dating.se.ifmo.ru + postgres-exporter: + image: quay.io/prometheuscommunity/postgres-exporter + command: '--no-collector.stat_bgwriter' + environment: + DATA_SOURCE_URI: database-primary.dating.se.ifmo.ru:5432/${ITMO_DATING_POSTGRES_DB?:err}?sslmode=disable + DATA_SOURCE_USER: ${ITMO_DATING_POSTGRES_USER?:err} + DATA_SOURCE_PASS: ${ITMO_DATING_POSTGRES_PASSWORD?:err} + tty: true + hostname: database-primary-exporter.dating.se.ifmo.ru + depends_on: + database: + condition: service_healthy gateway: image: ghcr.io/secs-dev/itmo-dating-gateway:latest build: @@ -143,9 +156,31 @@ services: ports: - "127.0.0.1:8445:8445" - "127.0.0.1:8446:8446" + - "127.0.0.1:8447:8447" - "127.0.0.1:8455:8455" - "127.0.0.1:8456:8456" - "127.0.0.1:8457:8457" + prometheus: + image: ghcr.io/secs-dev/itmo-dating-prometheus:latest + build: + context: ./backend/prometheus + user: root + volumes: + - prometheus-data:/prometheus + tty: true + hostname: prometheus.dating.se.ifmo.ru + grafana: + image: ghcr.io/secs-dev/itmo-dating-grafana:latest + build: + context: ./backend/grafana + environment: + GF_SECURITY_ADMIN_USER: ${ITMO_DATING_GRAFANA_ADMIN_USER?:err} + GF_SECURITY_ADMIN_PASSWORD: ${ITMO_DATING_GRAFANA_ADMIN_PASSWORD?:err} + ITMO_DATING_PROMETHEUS_HOST: prometheus.dating.se.ifmo.ru + volumes: + - grafana-data:/var/lib/grafana + tty: true + hostname: grafana.dating.se.ifmo.ru tg-miniapp: image: ghcr.io/secs-dev/itmo-dating-tg-miniapp:latest build: @@ -157,3 +192,5 @@ volumes: postgres-data: minio-data: consul-data: + prometheus-data: + grafana-data: