diff --git a/backend/authik/src/main/kotlin/ru/ifmo/se/dating/authik/api/HttpAuthApi.kt b/backend/authik/src/main/kotlin/ru/ifmo/se/dating/authik/api/HttpAuthApi.kt index fb2e1f72..c863c8df 100644 --- a/backend/authik/src/main/kotlin/ru/ifmo/se/dating/authik/api/HttpAuthApi.kt +++ b/backend/authik/src/main/kotlin/ru/ifmo/se/dating/authik/api/HttpAuthApi.kt @@ -3,10 +3,10 @@ package ru.ifmo.se.dating.authik.api import org.springframework.http.ResponseEntity import org.springframework.stereotype.Controller import ru.ifmo.se.dating.authik.api.generated.AuthApiDelegate +import ru.ifmo.se.dating.authik.external.telegram.TelegramInitDataParser import ru.ifmo.se.dating.authik.logic.AuthService import ru.ifmo.se.dating.authik.model.generated.AuthGrantMessage import ru.ifmo.se.dating.authik.model.generated.TelegramInitDataMessage -import ru.ifmo.se.dating.authik.external.telegram.TelegramInitDataParser import ru.ifmo.se.dating.exception.AuthenticationException import ru.ifmo.se.dating.exception.GenericException import ru.ifmo.se.dating.logging.Log.Companion.autoLog @@ -28,7 +28,7 @@ class HttpAuthApi( return ResponseEntity.ok(response) } - private fun parseInitData(telegramInitDataMessage: TelegramInitDataMessage) = + private suspend fun parseInitData(telegramInitDataMessage: TelegramInitDataMessage) = try { telegramParser.parse(telegramInitDataMessage) } catch (error: GenericException) { diff --git a/backend/authik/src/main/kotlin/ru/ifmo/se/dating/authik/logic/basic/BasicAuthService.kt b/backend/authik/src/main/kotlin/ru/ifmo/se/dating/authik/logic/basic/BasicAuthService.kt index 1a6d2eba..88839307 100644 --- a/backend/authik/src/main/kotlin/ru/ifmo/se/dating/authik/logic/basic/BasicAuthService.kt +++ b/backend/authik/src/main/kotlin/ru/ifmo/se/dating/authik/logic/basic/BasicAuthService.kt @@ -1,5 +1,6 @@ package ru.ifmo.se.dating.authik.logic.basic +import kotlinx.coroutines.runBlocking import ru.ifmo.se.dating.authik.logic.AuthService import ru.ifmo.se.dating.authik.model.generated.TelegramWebAppInitDataMessage import ru.ifmo.se.dating.authik.security.auth.TokenIssuer @@ -17,8 +18,10 @@ class BasicAuthService( private val log = autoLog() init { - val adamToken = issuer.issue(AccessToken.Payload(User.Id(ADAM_ID))) - log.info("Issued adam token: '${adamToken.text}'") + runBlocking { + val adamToken = issuer.issue(AccessToken.Payload(User.Id(ADAM_ID))) + log.info("Issued adam token: '${adamToken.text}'") + } } override suspend fun authenticate(telegram: TelegramWebAppInitDataMessage): AccessToken = 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 f5db5f3f..131da456 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 @@ -14,6 +14,6 @@ class AuthikSecuredPaths : SpringSecuredPaths { Path("/api/**"), Not(Path("/api/auth/telegram/web-app", HttpMethod.GET)), Not(Path("/api/monitoring/healthcheck", HttpMethod.PUT)), - Not(Path("/actuator/**", HttpMethod.GET)), + Not(Path("/actuator/prometheus", HttpMethod.GET)), ) } diff --git a/backend/authik/src/main/kotlin/ru/ifmo/se/dating/authik/security/auth/JwtTokenIssuer.kt b/backend/authik/src/main/kotlin/ru/ifmo/se/dating/authik/security/auth/JwtTokenIssuer.kt index e140fefd..342a4070 100644 --- a/backend/authik/src/main/kotlin/ru/ifmo/se/dating/authik/security/auth/JwtTokenIssuer.kt +++ b/backend/authik/src/main/kotlin/ru/ifmo/se/dating/authik/security/auth/JwtTokenIssuer.kt @@ -17,7 +17,7 @@ class JwtTokenIssuer( ) : TokenIssuer { private val duration: JavaDuration = duration.toJavaDuration() - override fun issue(payload: AccessToken.Payload): AccessToken { + override suspend fun issue(payload: AccessToken.Payload): AccessToken { val now = clock.instant() return Jwts.builder() .claims(Jwt.serialize(payload)) diff --git a/backend/authik/src/main/kotlin/ru/ifmo/se/dating/authik/security/auth/LoggingTokenIssuer.kt b/backend/authik/src/main/kotlin/ru/ifmo/se/dating/authik/security/auth/LoggingTokenIssuer.kt index 04bab674..b294be95 100644 --- a/backend/authik/src/main/kotlin/ru/ifmo/se/dating/authik/security/auth/LoggingTokenIssuer.kt +++ b/backend/authik/src/main/kotlin/ru/ifmo/se/dating/authik/security/auth/LoggingTokenIssuer.kt @@ -6,7 +6,7 @@ import ru.ifmo.se.dating.security.auth.AccessToken class LoggingTokenIssuer(private val origin: TokenIssuer) : TokenIssuer { private val log = autoLog() - override fun issue(payload: AccessToken.Payload): AccessToken = + override suspend fun issue(payload: AccessToken.Payload): AccessToken = runCatching { origin.issue(payload) } .onSuccess { log.info("Issued access token for user with id ${payload.userId}") } .onFailure { e -> diff --git a/backend/authik/src/main/kotlin/ru/ifmo/se/dating/authik/security/auth/TokenIssuer.kt b/backend/authik/src/main/kotlin/ru/ifmo/se/dating/authik/security/auth/TokenIssuer.kt index f1443d34..8007b98e 100644 --- a/backend/authik/src/main/kotlin/ru/ifmo/se/dating/authik/security/auth/TokenIssuer.kt +++ b/backend/authik/src/main/kotlin/ru/ifmo/se/dating/authik/security/auth/TokenIssuer.kt @@ -3,5 +3,5 @@ package ru.ifmo.se.dating.authik.security.auth import ru.ifmo.se.dating.security.auth.AccessToken interface TokenIssuer { - fun issue(payload: AccessToken.Payload): AccessToken + suspend fun issue(payload: AccessToken.Payload): AccessToken } diff --git a/backend/foundation/src/main/kotlin/ru/ifmo/se/dating/logic/LoggingTransactionalOutbox.kt b/backend/foundation/src/main/kotlin/ru/ifmo/se/dating/logic/LoggingTransactionalOutbox.kt index 6ce0c6ee..45327f7c 100644 --- a/backend/foundation/src/main/kotlin/ru/ifmo/se/dating/logic/LoggingTransactionalOutbox.kt +++ b/backend/foundation/src/main/kotlin/ru/ifmo/se/dating/logic/LoggingTransactionalOutbox.kt @@ -8,7 +8,7 @@ class LoggingTransactionalOutbox( ) : TransactionalOutbox by origin { private val log = Log.forClass(origin.javaClass) - override fun publishable(): Flow = + override suspend fun publishable(): Flow = runCatching { origin.publishable() } .onSuccess { log.info("Retrieved publishable events") } .onFailure { log.warn("Failed to retrieve publishable events") } diff --git a/backend/foundation/src/main/kotlin/ru/ifmo/se/dating/logic/TransactionalOutbox.kt b/backend/foundation/src/main/kotlin/ru/ifmo/se/dating/logic/TransactionalOutbox.kt index 54bb2b6f..ded642e4 100644 --- a/backend/foundation/src/main/kotlin/ru/ifmo/se/dating/logic/TransactionalOutbox.kt +++ b/backend/foundation/src/main/kotlin/ru/ifmo/se/dating/logic/TransactionalOutbox.kt @@ -7,7 +7,7 @@ import ru.ifmo.se.dating.storage.TxEnv @Suppress("ComplexInterface") interface TransactionalOutbox { val tx: TxEnv - fun publishable(): Flow + suspend fun publishable(): Flow suspend fun acquireById(id: Id): E suspend fun isPublished(event: E): Boolean suspend fun doProcess(event: E) diff --git a/backend/foundation/src/main/kotlin/ru/ifmo/se/dating/security/auth/JwtTokenDecoder.kt b/backend/foundation/src/main/kotlin/ru/ifmo/se/dating/security/auth/JwtTokenDecoder.kt index 5e6db88b..5b3a353f 100644 --- a/backend/foundation/src/main/kotlin/ru/ifmo/se/dating/security/auth/JwtTokenDecoder.kt +++ b/backend/foundation/src/main/kotlin/ru/ifmo/se/dating/security/auth/JwtTokenDecoder.kt @@ -12,7 +12,7 @@ class JwtTokenDecoder( private val clock: Clock, private val publicSignKey: PublicKey, ) : TokenDecoder { - override fun decode(token: AccessToken): AccessToken.Payload = + override suspend fun decode(token: AccessToken): AccessToken.Payload = try { Jwts.parser() .verifyWith(publicSignKey) diff --git a/backend/foundation/src/main/kotlin/ru/ifmo/se/dating/security/auth/LoggingTokenDecoder.kt b/backend/foundation/src/main/kotlin/ru/ifmo/se/dating/security/auth/LoggingTokenDecoder.kt index aba15046..c0c5a869 100644 --- a/backend/foundation/src/main/kotlin/ru/ifmo/se/dating/security/auth/LoggingTokenDecoder.kt +++ b/backend/foundation/src/main/kotlin/ru/ifmo/se/dating/security/auth/LoggingTokenDecoder.kt @@ -5,7 +5,7 @@ import ru.ifmo.se.dating.logging.Log.Companion.autoLog class LoggingTokenDecoder(private val origin: TokenDecoder) : TokenDecoder { private val log = autoLog() - override fun decode(token: AccessToken): AccessToken.Payload = + override suspend fun decode(token: AccessToken): AccessToken.Payload = runCatching { origin.decode(token) } .onSuccess { log.debug("Decoded a token of user with id ${it.userId}") } .onFailure { log.warn("Failed to decode an auth token") } diff --git a/backend/foundation/src/main/kotlin/ru/ifmo/se/dating/security/auth/TokenDecoder.kt b/backend/foundation/src/main/kotlin/ru/ifmo/se/dating/security/auth/TokenDecoder.kt index e79e0f13..22ca245c 100644 --- a/backend/foundation/src/main/kotlin/ru/ifmo/se/dating/security/auth/TokenDecoder.kt +++ b/backend/foundation/src/main/kotlin/ru/ifmo/se/dating/security/auth/TokenDecoder.kt @@ -1,5 +1,5 @@ package ru.ifmo.se.dating.security.auth interface TokenDecoder { - fun decode(token: AccessToken): AccessToken.Payload + suspend fun decode(token: AccessToken): AccessToken.Payload } diff --git a/backend/foundation/src/main/kotlin/ru/ifmo/se/dating/spring/security/auth/SpringJwtContextRepository.kt b/backend/foundation/src/main/kotlin/ru/ifmo/se/dating/spring/security/auth/SpringJwtContextRepository.kt index 2287f9c5..22c18a04 100644 --- a/backend/foundation/src/main/kotlin/ru/ifmo/se/dating/spring/security/auth/SpringJwtContextRepository.kt +++ b/backend/foundation/src/main/kotlin/ru/ifmo/se/dating/spring/security/auth/SpringJwtContextRepository.kt @@ -14,7 +14,6 @@ import org.springframework.web.server.ServerWebExchange import reactor.core.publisher.Mono import ru.ifmo.se.dating.exception.AuthenticationException import ru.ifmo.se.dating.exception.GenericException -import ru.ifmo.se.dating.logging.Log.Companion.autoLog import ru.ifmo.se.dating.spring.exception.SpringGenericExceptionHandler @Component @@ -42,8 +41,6 @@ class SpringJwtContextRepository( private val headerName = HttpHeaders.AUTHORIZATION private val bearerPrefix = "Bearer " - private val log = autoLog() - override fun save( exchange: ServerWebExchange, context: SecurityContext, @@ -64,7 +61,7 @@ class SpringJwtContextRepository( null } - private fun extractBearer(exchange: ServerWebExchange): String = runCatching { + private suspend fun extractBearer(exchange: ServerWebExchange): String { val count = exchange.request.headers.getOrEmpty(headerName).size if (count != 1) { throw AuthenticationException( @@ -79,9 +76,6 @@ class SpringJwtContextRepository( ) } - bearer.substringAfter(bearerPrefix) + return bearer.substringAfter(bearerPrefix) } - .onSuccess { log.debug("Extracted a bearer token") } - .onFailure { e -> log.warn("Failed to extract a bearer token: ${e.message}") } - .getOrThrow() } diff --git a/backend/foundation/src/main/kotlin/ru/ifmo/se/dating/spring/storage/SpringLiquibaseMigration.kt b/backend/foundation/src/main/kotlin/ru/ifmo/se/dating/spring/storage/SpringLiquibaseMigration.kt index 48d83ca1..a3e2c48e 100644 --- a/backend/foundation/src/main/kotlin/ru/ifmo/se/dating/spring/storage/SpringLiquibaseMigration.kt +++ b/backend/foundation/src/main/kotlin/ru/ifmo/se/dating/spring/storage/SpringLiquibaseMigration.kt @@ -1,5 +1,6 @@ package ru.ifmo.se.dating.spring.storage +import kotlinx.coroutines.runBlocking import org.springframework.beans.factory.annotation.Value import org.springframework.jdbc.datasource.SingleConnectionDataSource import org.springframework.stereotype.Component @@ -27,7 +28,7 @@ class SpringLiquibaseMigration( private val log = autoLog() init { - log.info("Running a liquibase migration...") + runBlocking { log.info("Running a liquibase migration...") } val suppressClose = false SingleConnectionDataSource(url, username, password, suppressClose).use { @@ -38,6 +39,6 @@ class SpringLiquibaseMigration( ).run() } - log.info("Liquibase migration was completed successfully") + runBlocking { log.info("Liquibase migration was completed successfully") } } } diff --git a/backend/gradle/libs.versions.toml b/backend/gradle/libs.versions.toml index fdb99c7c..da310ca1 100644 --- a/backend/gradle/libs.versions.toml +++ b/backend/gradle/libs.versions.toml @@ -25,6 +25,8 @@ org-jetbrains-kotlinx-kotlinx-coroutines = "1.9.0" io-projectreactor-kotlin-reactor-kotlin-extensions = "1.2.3" io-micrometer = "1.14.3" +com-github-loki4j = "1.6.0" +io-github-numichi-reactive-logger = "6.0.3" io-projectreactor-reactor-test = "3.6.11" junit-junit = "4.13.2" @@ -79,6 +81,8 @@ org-postgresql-postgresql = { module = "org.postgresql:postgresql", version.ref 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" } +com-github-loki4j-loki-logback-appender = { module = "com.github.loki4j:loki-logback-appender", version.ref = "com-github-loki4j" } +io-github-numichi-reactive-logger = { module = "io.github.numichi:reactive-logger", version.ref = "io-github-numichi-reactive-logger" } junit-junit = { module = "junit:junit", version.ref = "junit-junit" } org-testcontainers-postgresql = { module = "org.testcontainers:postgresql", version.ref = "org-testcontainers" } diff --git a/backend/grafana/provisioning/datasources/all.yml b/backend/grafana/provisioning/datasources/all.yml index 867a7545..e89fb50a 100644 --- a/backend/grafana/provisioning/datasources/all.yml +++ b/backend/grafana/provisioning/datasources/all.yml @@ -1,8 +1,15 @@ apiVersion: 1 datasources: + - name: Prometheus label: Prometheus type: prometheus access: proxy url: http://${ITMO_DATING_PROMETHEUS_HOST}:9090 isDefault: true + + - name: Loki + label: Loki + type: loki + access: proxy + url: http://${ITMO_DATING_LOKI_HOST}:3100 diff --git a/backend/loki/Dockerfile b/backend/loki/Dockerfile new file mode 100644 index 00000000..d5d09fd6 --- /dev/null +++ b/backend/loki/Dockerfile @@ -0,0 +1,3 @@ +FROM grafana/loki + +COPY ./config.yaml /etc/loki/local-config.yaml diff --git a/backend/loki/config.yaml b/backend/loki/config.yaml new file mode 100644 index 00000000..3b4c1197 --- /dev/null +++ b/backend/loki/config.yaml @@ -0,0 +1,40 @@ +auth_enabled: false + +server: + http_listen_port: 3100 + +common: + instance_addr: 127.0.0.1 + path_prefix: /loki + storage: + filesystem: + chunks_directory: /loki/chunks + rules_directory: /loki/rules + replication_factor: 1 + ring: + kvstore: + store: inmemory + +compactor: + working_directory: /loki/retention + compaction_interval: 10m + retention_enabled: true + retention_delete_delay: 2h + retention_delete_worker_count: 32 + delete_request_store: filesystem + +schema_config: + configs: + - from: 2020-10-24 + store: tsdb + object_store: filesystem + schema: v13 + index: + prefix: index_ + period: 24h + +limits_config: + retention_period: 72h + +ruler: + alertmanager_url: http://localhost:9093 diff --git a/backend/matchmaker/src/main/kotlin/ru/ifmo/se/dating/matchmaker/api/HttpStatisticsApi.kt b/backend/matchmaker/src/main/kotlin/ru/ifmo/se/dating/matchmaker/api/HttpStatisticsApi.kt index a336e756..0ea1c04e 100644 --- a/backend/matchmaker/src/main/kotlin/ru/ifmo/se/dating/matchmaker/api/HttpStatisticsApi.kt +++ b/backend/matchmaker/src/main/kotlin/ru/ifmo/se/dating/matchmaker/api/HttpStatisticsApi.kt @@ -2,6 +2,7 @@ package ru.ifmo.se.dating.matchmaker.api import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map +import kotlinx.coroutines.runBlocking import org.springframework.http.ResponseEntity import org.springframework.stereotype.Controller import ru.ifmo.se.dating.matchmaker.api.generated.StatisticsApiDelegate @@ -14,8 +15,9 @@ typealias StatisticsAttitudesResponse = @Controller class HttpStatisticsApi(private val service: StatisticsService) : StatisticsApiDelegate { - override fun statisticsAttitudesGet(): StatisticsAttitudesResponse = + override fun statisticsAttitudesGet(): StatisticsAttitudesResponse = runBlocking { service.selectAttitudesByPerson() .map { it.toMessage() } .let { ResponseEntity.ok(it) } + } } diff --git a/backend/matchmaker/src/main/kotlin/ru/ifmo/se/dating/matchmaker/logic/AttitudeService.kt b/backend/matchmaker/src/main/kotlin/ru/ifmo/se/dating/matchmaker/logic/AttitudeService.kt index a16ae8bf..d1f1d213 100644 --- a/backend/matchmaker/src/main/kotlin/ru/ifmo/se/dating/matchmaker/logic/AttitudeService.kt +++ b/backend/matchmaker/src/main/kotlin/ru/ifmo/se/dating/matchmaker/logic/AttitudeService.kt @@ -6,6 +6,6 @@ import ru.ifmo.se.dating.security.auth.User interface AttitudeService { suspend fun express(attitude: Attitude) - fun matches(client: User.Id): Flow - fun suggestions(client: User.Id, limit: Int): Flow + suspend fun matches(client: User.Id): Flow + suspend fun suggestions(client: User.Id, limit: Int): Flow } diff --git a/backend/matchmaker/src/main/kotlin/ru/ifmo/se/dating/matchmaker/logic/StatisticsService.kt b/backend/matchmaker/src/main/kotlin/ru/ifmo/se/dating/matchmaker/logic/StatisticsService.kt index 409d779c..bceea139 100644 --- a/backend/matchmaker/src/main/kotlin/ru/ifmo/se/dating/matchmaker/logic/StatisticsService.kt +++ b/backend/matchmaker/src/main/kotlin/ru/ifmo/se/dating/matchmaker/logic/StatisticsService.kt @@ -4,5 +4,5 @@ import kotlinx.coroutines.flow.Flow import ru.ifmo.se.dating.matchmaker.model.AttitudesStatistics interface StatisticsService { - fun selectAttitudesByPerson(): Flow + suspend fun selectAttitudesByPerson(): Flow } diff --git a/backend/matchmaker/src/main/kotlin/ru/ifmo/se/dating/matchmaker/logic/basic/BasicAttitudeService.kt b/backend/matchmaker/src/main/kotlin/ru/ifmo/se/dating/matchmaker/logic/basic/BasicAttitudeService.kt index 7dc08cc8..cce340fd 100644 --- a/backend/matchmaker/src/main/kotlin/ru/ifmo/se/dating/matchmaker/logic/basic/BasicAttitudeService.kt +++ b/backend/matchmaker/src/main/kotlin/ru/ifmo/se/dating/matchmaker/logic/basic/BasicAttitudeService.kt @@ -26,9 +26,9 @@ class BasicAttitudeService( throw NotFoundException("source or target ids does not exist", exception) } - override fun matches(client: User.Id): Flow = + override suspend fun matches(client: User.Id): Flow = storage.selectLikedBack(client) - override fun suggestions(client: User.Id, limit: Int): Flow = + override suspend fun suggestions(client: User.Id, limit: Int): Flow = storage.selectUnknownFor(client, limit) } diff --git a/backend/matchmaker/src/main/kotlin/ru/ifmo/se/dating/matchmaker/logic/basic/BasicStatisticsService.kt b/backend/matchmaker/src/main/kotlin/ru/ifmo/se/dating/matchmaker/logic/basic/BasicStatisticsService.kt index 835c010f..06f159a7 100644 --- a/backend/matchmaker/src/main/kotlin/ru/ifmo/se/dating/matchmaker/logic/basic/BasicStatisticsService.kt +++ b/backend/matchmaker/src/main/kotlin/ru/ifmo/se/dating/matchmaker/logic/basic/BasicStatisticsService.kt @@ -6,6 +6,6 @@ import ru.ifmo.se.dating.matchmaker.model.AttitudesStatistics import ru.ifmo.se.dating.matchmaker.storage.StatisticsStorage class BasicStatisticsService(private val storage: StatisticsStorage) : StatisticsService { - override fun selectAttitudesByPerson(): Flow = + override suspend fun selectAttitudesByPerson(): Flow = storage.selectAttitudesByPerson() } diff --git a/backend/matchmaker/src/main/kotlin/ru/ifmo/se/dating/matchmaker/logic/logging/LoggingAttitudeService.kt b/backend/matchmaker/src/main/kotlin/ru/ifmo/se/dating/matchmaker/logic/logging/LoggingAttitudeService.kt index 49574149..9dc52687 100644 --- a/backend/matchmaker/src/main/kotlin/ru/ifmo/se/dating/matchmaker/logic/logging/LoggingAttitudeService.kt +++ b/backend/matchmaker/src/main/kotlin/ru/ifmo/se/dating/matchmaker/logic/logging/LoggingAttitudeService.kt @@ -28,7 +28,7 @@ class LoggingAttitudeService(private val origin: AttitudeService) : AttitudeServ } .getOrThrow() - override fun matches(client: User.Id): Flow = + override suspend fun matches(client: User.Id): Flow = runCatching { origin.matches(client) } .onSuccess { log.debug("Got matches for client with id ${client.number}") } .onFailure { e -> @@ -40,7 +40,7 @@ class LoggingAttitudeService(private val origin: AttitudeService) : AttitudeServ } .getOrThrow() - override fun suggestions(client: User.Id, limit: Int): Flow = + override suspend fun suggestions(client: User.Id, limit: Int): Flow = runCatching { origin.suggestions(client, limit) } .onSuccess { log.debug("Got no more than $limit suggestions for client with id $client") diff --git a/backend/matchmaker/src/main/kotlin/ru/ifmo/se/dating/matchmaker/logic/logging/LoggingStatisticsService.kt b/backend/matchmaker/src/main/kotlin/ru/ifmo/se/dating/matchmaker/logic/logging/LoggingStatisticsService.kt index 1b0d1ab8..147cc3df 100644 --- a/backend/matchmaker/src/main/kotlin/ru/ifmo/se/dating/matchmaker/logic/logging/LoggingStatisticsService.kt +++ b/backend/matchmaker/src/main/kotlin/ru/ifmo/se/dating/matchmaker/logic/logging/LoggingStatisticsService.kt @@ -8,7 +8,7 @@ import ru.ifmo.se.dating.matchmaker.model.AttitudesStatistics class LoggingStatisticsService(private val origin: StatisticsService) : StatisticsService { private val log = autoLog() - override fun selectAttitudesByPerson(): Flow = + override suspend fun selectAttitudesByPerson(): Flow = runCatching { origin.selectAttitudesByPerson() } .onSuccess { log.warn("Someone got attitudes by person statistics") } .onFailure { e -> log.warn("Failed to got statistics: ${e.message}") } 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 645352b2..68d8f02a 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,7 +15,6 @@ 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)), + Not(Path("/actuator/prometheus", HttpMethod.GET)), ) } diff --git a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/api/HttpFacultiesApi.kt b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/api/HttpFacultiesApi.kt index 429ce471..c52b1142 100644 --- a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/api/HttpFacultiesApi.kt +++ b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/api/HttpFacultiesApi.kt @@ -2,6 +2,7 @@ package ru.ifmo.se.dating.people.api import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map +import kotlinx.coroutines.runBlocking import org.springframework.http.ResponseEntity import org.springframework.stereotype.Controller import ru.ifmo.se.dating.people.api.generated.FacultiesApiDelegate @@ -11,7 +12,8 @@ import ru.ifmo.se.dating.people.model.generated.FacultyMessage @Controller class HttpFacultiesApi(private val service: FacultyService) : FacultiesApiDelegate { - override fun facultiesGet(): ResponseEntity> = + override fun facultiesGet(): ResponseEntity> = runBlocking { service.getAll().map { it.toMessage() } .let { ResponseEntity.ok(it) } + } } diff --git a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/api/HttpLocationsApi.kt b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/api/HttpLocationsApi.kt index ba7c8877..4315af2e 100644 --- a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/api/HttpLocationsApi.kt +++ b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/api/HttpLocationsApi.kt @@ -2,6 +2,7 @@ package ru.ifmo.se.dating.people.api import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map +import kotlinx.coroutines.runBlocking import org.springframework.http.ResponseEntity import org.springframework.stereotype.Controller import ru.ifmo.se.dating.people.api.generated.LocationsApiDelegate @@ -11,7 +12,8 @@ import ru.ifmo.se.dating.people.model.generated.LocationMessage @Controller class HttpLocationsApi(private val service: LocationService) : LocationsApiDelegate { - override fun locationsGet(): ResponseEntity> = + override fun locationsGet(): ResponseEntity> = runBlocking { service.getAll().map { it.toMessage() } .let { ResponseEntity.ok(it) } + } } diff --git a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/api/HttpPeopleApi.kt b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/api/HttpPeopleApi.kt index e98a3627..518df1ac 100644 --- a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/api/HttpPeopleApi.kt +++ b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/api/HttpPeopleApi.kt @@ -2,6 +2,7 @@ package ru.ifmo.se.dating.people.api import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map +import kotlinx.coroutines.runBlocking import org.springframework.core.io.ByteArrayResource import org.springframework.core.io.Resource import org.springframework.http.ResponseEntity @@ -52,7 +53,7 @@ class HttpPeopleApi( updatedMin: OffsetDateTime?, updatedMax: OffsetDateTime?, sortBy: List?, - ): ResponseEntity> { + ): ResponseEntity> = runBlocking { val area = when (listOfNotNull(latitude, longitude, radius).size) { 0 -> { null @@ -76,7 +77,7 @@ class HttpPeopleApi( } } - return personService.getFiltered( + personService.getFiltered( page = Page(offset = offset.toInt(), limit = limit.toInt()), filter = PersonFilter( firstName = firstName?.let { Regex(it) }, diff --git a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/api/HttpTopicsApi.kt b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/api/HttpTopicsApi.kt index a3a47c1c..a24f63cd 100644 --- a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/api/HttpTopicsApi.kt +++ b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/api/HttpTopicsApi.kt @@ -2,6 +2,7 @@ package ru.ifmo.se.dating.people.api import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map +import kotlinx.coroutines.runBlocking import org.springframework.http.ResponseEntity import org.springframework.stereotype.Controller import ru.ifmo.se.dating.people.api.generated.TopicsApiDelegate @@ -13,8 +14,9 @@ import ru.ifmo.se.dating.people.model.generated.TopicMessage class HttpTopicsApi( private val interestService: InterestService, ) : TopicsApiDelegate { - override fun topicsGet(): ResponseEntity> = + override fun topicsGet(): ResponseEntity> = runBlocking { interestService.getAllTopics() .map { it.toMessage() } .let { ResponseEntity.ok(it) } + } } diff --git a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/FacultyService.kt b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/FacultyService.kt index 98168be4..7579d65a 100644 --- a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/FacultyService.kt +++ b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/FacultyService.kt @@ -6,5 +6,5 @@ import ru.ifmo.se.dating.people.model.Faculty interface FacultyService { suspend fun create(draft: Faculty.Draft): Faculty suspend fun getById(id: Faculty.Id): Faculty? - fun getAll(): Flow + suspend fun getAll(): Flow } diff --git a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/InterestService.kt b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/InterestService.kt index 45c7cdb2..a70d5214 100644 --- a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/InterestService.kt +++ b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/InterestService.kt @@ -8,5 +8,5 @@ import ru.ifmo.se.dating.security.auth.User interface InterestService { suspend fun insert(id: User.Id, interest: Person.Interest) suspend fun remove(id: User.Id, topicId: Topic.Id) - fun getAllTopics(): Flow + suspend fun getAllTopics(): Flow } diff --git a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/LocationService.kt b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/LocationService.kt index fea6d800..99b6e8b7 100644 --- a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/LocationService.kt +++ b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/LocationService.kt @@ -6,5 +6,5 @@ import ru.ifmo.se.dating.people.model.Location interface LocationService { suspend fun create(draft: Location.Draft): Location suspend fun getById(id: Location.Id): Location? - fun getAll(): Flow + suspend fun getAll(): Flow } diff --git a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/PersonService.kt b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/PersonService.kt index a4326320..fbca4e6c 100644 --- a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/PersonService.kt +++ b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/PersonService.kt @@ -13,7 +13,7 @@ interface PersonService { suspend fun getById(id: User.Id): PersonVariant? suspend fun delete(id: User.Id) - fun getFiltered( + suspend fun getFiltered( page: Page, filter: PersonFilter, sortedBy: List>, diff --git a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/basic/BasicFacultyService.kt b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/basic/BasicFacultyService.kt index 9cf770f4..c0f649e0 100644 --- a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/basic/BasicFacultyService.kt +++ b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/basic/BasicFacultyService.kt @@ -12,6 +12,6 @@ class BasicFacultyService(private val storage: FacultyStorage) : FacultyService override suspend fun getById(id: Faculty.Id): Faculty? = storage.selectById(id) - override fun getAll(): Flow = + override suspend fun getAll(): Flow = storage.selectAll() } diff --git a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/basic/BasicInterestService.kt b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/basic/BasicInterestService.kt index a3194a5f..5b7a4334 100644 --- a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/basic/BasicInterestService.kt +++ b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/basic/BasicInterestService.kt @@ -16,6 +16,6 @@ class BasicInterestService( override suspend fun remove(id: User.Id, topicId: Topic.Id) = storage.delete(id, topicId) - override fun getAllTopics(): Flow = + override suspend fun getAllTopics(): Flow = storage.selectAllTopics() } diff --git a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/basic/BasicLocationService.kt b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/basic/BasicLocationService.kt index 09bef202..633632a8 100644 --- a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/basic/BasicLocationService.kt +++ b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/basic/BasicLocationService.kt @@ -12,6 +12,6 @@ class BasicLocationService(private val storage: LocationStorage) : LocationServi override suspend fun getById(id: Location.Id): Location? = storage.selectById(id) - override fun getAll(): Flow = + override suspend fun getAll(): Flow = storage.selectAll() } diff --git a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/basic/BasicPersonOutbox.kt b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/basic/BasicPersonOutbox.kt index 4cc84446..789b7996 100644 --- a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/basic/BasicPersonOutbox.kt +++ b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/basic/BasicPersonOutbox.kt @@ -41,6 +41,6 @@ class BasicPersonOutbox( override suspend fun markPublished(event: PersonVariant) = storage.setIsPublished(event.id, true) - override fun publishable(): Flow = + override suspend fun publishable(): Flow = storage.selectNotSentIds(limit = 64) } diff --git a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/basic/BasicPersonService.kt b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/basic/BasicPersonService.kt index cb9e5e3a..8547ad57 100644 --- a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/basic/BasicPersonService.kt +++ b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/basic/BasicPersonService.kt @@ -71,7 +71,7 @@ class BasicPersonService( storage.setIsPublished(id, false) }.let { background.launch { outbox.process(id) } }.let { } - override fun getFiltered( + override suspend fun getFiltered( page: Page, filter: PersonFilter, sortedBy: List>, diff --git a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/logging/LoggingFacultyService.kt b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/logging/LoggingFacultyService.kt index 89e517fc..a2d858a2 100644 --- a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/logging/LoggingFacultyService.kt +++ b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/logging/LoggingFacultyService.kt @@ -20,7 +20,7 @@ class LoggingFacultyService(private val origin: FacultyService) : FacultyService .onFailure { e -> log.warn("Failed to get faculty with id $id", e) } .getOrThrow() - override fun getAll(): Flow = + override suspend fun getAll(): Flow = runCatching { origin.getAll() } .onSuccess { log.debug("Got all faculties") } .onFailure { e -> log.warn("Failed to get all faculties: ${e.message}") } diff --git a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/logging/LoggingInterestService.kt b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/logging/LoggingInterestService.kt index 1ece6ff5..aa74c552 100644 --- a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/logging/LoggingInterestService.kt +++ b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/logging/LoggingInterestService.kt @@ -34,7 +34,7 @@ class LoggingInterestService(private val origin: InterestService) : InterestServ } .getOrThrow() - override fun getAllTopics(): Flow = + override suspend fun getAllTopics(): Flow = runCatching { origin.getAllTopics() } .onSuccess { log.debug("Got all topics") } .onFailure { e -> log.warn("Failed to get all topics: ${e.message}") } diff --git a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/logging/LoggingLocationService.kt b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/logging/LoggingLocationService.kt index 46daccc9..2546f4aa 100644 --- a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/logging/LoggingLocationService.kt +++ b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/logging/LoggingLocationService.kt @@ -22,7 +22,7 @@ class LoggingLocationService(private val origin: LocationService) : LocationServ .onFailure { e -> log.warn("Failed to get location with id $id", e) } .getOrThrow() - override fun getAll(): Flow = + override suspend fun getAll(): Flow = runCatching { origin.getAll() } .onSuccess { log.debug("Got all locations") } .onFailure { e -> log.warn("Failed to get all locations: ${e.message}") } diff --git a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/logging/LoggingPersonService.kt b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/logging/LoggingPersonService.kt index 79eabd27..a02967ba 100644 --- a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/logging/LoggingPersonService.kt +++ b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/logging/LoggingPersonService.kt @@ -38,7 +38,7 @@ class LoggingPersonService(private val origin: PersonService) : PersonService { .onFailure { e -> log.warn("Failed to delete a person with id $id", e) } .getOrThrow() - override fun getFiltered( + override suspend fun getFiltered( page: Page, filter: PersonFilter, sortedBy: List>, diff --git a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/spring/SpringPersonOutbox.kt b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/spring/SpringPersonOutbox.kt index dfda62fe..7ca961de 100644 --- a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/spring/SpringPersonOutbox.kt +++ b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/logic/spring/SpringPersonOutbox.kt @@ -30,7 +30,7 @@ class SpringPersonOutbox( override val tx: TxEnv get() = origin.tx - override fun publishable(): Flow = + override suspend fun publishable(): Flow = origin.publishable() override suspend fun acquireById(id: User.Id): PersonVariant = 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 03737013..50835474 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,7 +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.PUT)), - Not(Path("/actuator/**", HttpMethod.GET)), + Not(Path("/api/monitoring/healthcheck", HttpMethod.GET)), + Not(Path("/actuator/prometheus", HttpMethod.GET)), ) } diff --git a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/storage/PictureRecordStorage.kt b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/storage/PictureRecordStorage.kt index 1c268ac2..cc53e0bb 100644 --- a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/storage/PictureRecordStorage.kt +++ b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/storage/PictureRecordStorage.kt @@ -8,6 +8,6 @@ interface PictureRecordStorage { suspend fun insert(ownerId: User.Id): Picture suspend fun setIsReferenced(id: Picture.Id, isReferenced: Boolean) suspend fun delete(id: Picture.Id) - fun selectAbandoned(): Flow + suspend fun selectAbandoned(): Flow fun selectByOwner(ownerId: User.Id): Flow } diff --git a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/storage/jooq/JooqPersonStorage.kt b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/storage/jooq/JooqPersonStorage.kt index f3c97c71..59842f1a 100644 --- a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/storage/jooq/JooqPersonStorage.kt +++ b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/storage/jooq/JooqPersonStorage.kt @@ -196,8 +196,6 @@ class JooqPersonStorage( .orderBy(orderByClause) .offset(page.offset) .limit(page.limit) - .also { log.warn("Executed SQL: ${it.sql}") } - .also { log.warn("BindValues: ${it.bindValues}") } } .map { it.enrichToModel() as Person } .filter { filter.area == null || filter.area.contains(it.location.coordinates) } diff --git a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/storage/jooq/JooqPictureRecordStorage.kt b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/storage/jooq/JooqPictureRecordStorage.kt index 14870969..2f730f22 100644 --- a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/storage/jooq/JooqPictureRecordStorage.kt +++ b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/storage/jooq/JooqPictureRecordStorage.kt @@ -33,7 +33,7 @@ class JooqPictureRecordStorage( .where(PICTURE.ID.eq(id.number)) }.let { } - override fun selectAbandoned(): Flow = database.flow { + override suspend fun selectAbandoned(): Flow = database.flow { val threshold = 5.minutes.toJavaDuration() selectFrom(PICTURE) .where( diff --git a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/storage/logging/LoggingPictureRecordStorage.kt b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/storage/logging/LoggingPictureRecordStorage.kt index f0f0ab18..30d45219 100644 --- a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/storage/logging/LoggingPictureRecordStorage.kt +++ b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/storage/logging/LoggingPictureRecordStorage.kt @@ -37,7 +37,7 @@ class LoggingPictureRecordStorage( .onFailure { e -> log.warn("Failed to delete a picture record with id $id", e) } .getOrThrow() - override fun selectAbandoned(): Flow = + override suspend fun selectAbandoned(): Flow = runCatching { origin.selectAbandoned() } .onSuccess { log.info("Retrieved abandoned pictures") } .onFailure { log.warn("Failed to select abandoned pictures") } diff --git a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/storage/minio/MinioClientConfiguration.kt b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/storage/minio/MinioClientConfiguration.kt index 79fbaf50..ffab3766 100644 --- a/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/storage/minio/MinioClientConfiguration.kt +++ b/backend/people/src/main/kotlin/ru/ifmo/se/dating/people/storage/minio/MinioClientConfiguration.kt @@ -1,6 +1,7 @@ package ru.ifmo.se.dating.people.storage.minio import io.minio.MinioClient +import kotlinx.coroutines.runBlocking import org.springframework.beans.factory.annotation.Value import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration @@ -33,6 +34,6 @@ class MinioClientConfiguration { .build() .also { client -> val names = client.listBuckets().joinToString(", ") { "'${it.name()}'" } - log.info("Initialized MinIO client. Found buckets: $names") + runBlocking { log.info("Initialized MinIO client. Found buckets: $names") } } } diff --git a/backend/prometheus/prometheus.yml b/backend/prometheus/prometheus.yml index bf0c9994..364a4dfe 100644 --- a/backend/prometheus/prometheus.yml +++ b/backend/prometheus/prometheus.yml @@ -102,6 +102,13 @@ scrape_configs: type: 'A' port: 9090 + - job_name: loki + dns_sd_configs: + - names: + - loki.dating.se.ifmo.ru + type: 'A' + port: 3100 + - job_name: grafana dns_sd_configs: - names: diff --git a/backend/starter-monitoring/build.gradle.kts b/backend/starter-monitoring/build.gradle.kts index 3c8a9e51..87a3a7b7 100644 --- a/backend/starter-monitoring/build.gradle.kts +++ b/backend/starter-monitoring/build.gradle.kts @@ -8,4 +8,7 @@ dependencies { api(libs.org.springframework.boot.spring.boot.starter.actuator) api(libs.io.micrometer.micrometer.registry.prometheus) + + api(libs.com.github.loki4j.loki.logback.appender) + api(libs.io.github.numichi.reactive.logger) } diff --git a/backend/starter-monitoring/src/main/kotlin/ru/ifmo/se/dating/logging/Log.kt b/backend/starter-monitoring/src/main/kotlin/ru/ifmo/se/dating/logging/Log.kt index 73d96fad..f9147333 100644 --- a/backend/starter-monitoring/src/main/kotlin/ru/ifmo/se/dating/logging/Log.kt +++ b/backend/starter-monitoring/src/main/kotlin/ru/ifmo/se/dating/logging/Log.kt @@ -1,11 +1,11 @@ package ru.ifmo.se.dating.logging interface Log { - fun info(message: String) - fun warn(message: String) - fun warn(message: String, e: Throwable) - fun error(message: String, e: Throwable) - fun debug(message: String) + suspend fun info(message: String) + suspend fun warn(message: String) + suspend fun warn(message: String, e: Throwable) + suspend fun error(message: String, e: Throwable) + suspend fun debug(message: String) companion object { inline fun T.autoLog() = forClass(T::class.java) diff --git a/backend/starter-monitoring/src/main/kotlin/ru/ifmo/se/dating/logging/Slf4jLog.kt b/backend/starter-monitoring/src/main/kotlin/ru/ifmo/se/dating/logging/Slf4jLog.kt index 69c43961..54747de5 100644 --- a/backend/starter-monitoring/src/main/kotlin/ru/ifmo/se/dating/logging/Slf4jLog.kt +++ b/backend/starter-monitoring/src/main/kotlin/ru/ifmo/se/dating/logging/Slf4jLog.kt @@ -1,22 +1,22 @@ package ru.ifmo.se.dating.logging -import org.slf4j.LoggerFactory +import io.github.numichi.reactive.logger.coroutine.CoroutineLogger class Slf4jLog(name: String) : Log { - private val origin = LoggerFactory.getLogger(name) + private val origin = CoroutineLogger.getLogger(name) - override fun info(message: String) = + override suspend fun info(message: String) = origin.info(message) - override fun warn(message: String) = + override suspend fun warn(message: String) = origin.warn(message) - override fun warn(message: String, e: Throwable) = + override suspend fun warn(message: String, e: Throwable) = origin.warn("$message: ${e.message}", e) - override fun error(message: String, e: Throwable) = + override suspend fun error(message: String, e: Throwable) = origin.error("$message: ${e.message}", e) - override fun debug(message: String) = + override suspend fun debug(message: String) = origin.debug(message) } diff --git a/backend/starter-monitoring/src/main/kotlin/ru/ifmo/se/dating/spring/logging/RequestLoggingFilter.kt b/backend/starter-monitoring/src/main/kotlin/ru/ifmo/se/dating/spring/logging/RequestLoggingFilter.kt new file mode 100644 index 00000000..08cb2474 --- /dev/null +++ b/backend/starter-monitoring/src/main/kotlin/ru/ifmo/se/dating/spring/logging/RequestLoggingFilter.kt @@ -0,0 +1,23 @@ +package ru.ifmo.se.dating.spring.logging + +import io.github.numichi.reactive.logger.coroutine.modifyMdc +import org.springframework.http.server.reactive.ServerHttpRequest +import org.springframework.stereotype.Component +import org.springframework.web.server.ServerWebExchange +import org.springframework.web.server.WebFilter +import org.springframework.web.server.WebFilterChain +import reactor.core.publisher.Mono + +@Component +class RequestLoggingFilter : WebFilter { + override fun filter(exchange: ServerWebExchange, chain: WebFilterChain): Mono = + chain.filter(exchange) + .contextWrite { ctx -> ctx.modifyMdc { mdc -> mdc + keys(exchange.request) } } + + private fun keys(request: ServerHttpRequest) = mapOf( + "request_id" to request.id.toString(), + "remote_address" to (request.remoteAddress?.toString() ?: "null"), + "method" to request.method.toString(), + "path" to request.path.toString(), + ) +} diff --git a/backend/starter-monitoring/src/main/resources/logback-spring.xml b/backend/starter-monitoring/src/main/resources/logback-spring.xml new file mode 100644 index 00000000..3aef5b93 --- /dev/null +++ b/backend/starter-monitoring/src/main/resources/logback-spring.xml @@ -0,0 +1,33 @@ + + + + + + http://loki.dating.se.ifmo.ru:3100/loki/api/v1/push + + + + + + [%level] %logger{36}: %msg%n + + + + + + + + + diff --git a/compose.yml b/compose.yml index 55b59967..57dc01bf 100644 --- a/compose.yml +++ b/compose.yml @@ -177,6 +177,15 @@ services: - prometheus-data:/prometheus tty: true hostname: prometheus.dating.se.ifmo.ru + loki: + image: ghcr.io/secs-dev/itmo-dating-loki:latest + build: + context: ./backend/loki + command: -config.file=/etc/loki/local-config.yaml + volumes: + - loki-data:/loki + tty: true + hostname: loki.dating.se.ifmo.ru grafana: image: ghcr.io/secs-dev/itmo-dating-grafana:latest build: @@ -185,6 +194,7 @@ services: 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 + ITMO_DATING_LOKI_HOST: loki.dating.se.ifmo.ru volumes: - grafana-data:/var/lib/grafana tty: true @@ -201,4 +211,5 @@ volumes: minio-data: consul-data: prometheus-data: + loki-data: grafana-data: