Skip to content

Commit 52303f0

Browse files
author
akobor
committed
Expose the date of the last uptime check on the API
1 parent 34cad62 commit 52303f0

File tree

6 files changed

+78
-23
lines changed

6 files changed

+78
-23
lines changed

docs/api-doc/kuvasz-latest.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,10 @@ components:
288288
type: string
289289
format: date-time
290290
nullable: true
291+
lastUptimeCheck:
292+
type: string
293+
format: date-time
294+
nullable: true
291295
uptimeError:
292296
type: string
293297
nullable: true

src/main/kotlin/com/kuvaszuptime/kuvasz/models/dto/MonitorDetailsDto.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ data class MonitorDetailsDto(
1616
val updatedAt: OffsetDateTime?,
1717
val uptimeStatus: UptimeStatus?,
1818
val uptimeStatusStartedAt: OffsetDateTime?,
19+
val lastUptimeCheck: OffsetDateTime?,
1920
val uptimeError: String?,
2021
val averageLatencyInMs: Int?,
2122
val p95LatencyInMs: Int?,

src/main/kotlin/com/kuvaszuptime/kuvasz/repositories/MonitorRepository.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class MonitorRepository @Inject constructor(jooqConfig: Configuration) : Monitor
3939
MONITOR.ID,
4040
UPTIME_EVENT.STATUS,
4141
UPTIME_EVENT.STARTED_AT,
42+
UPTIME_EVENT.UPDATED_AT,
4243
UPTIME_EVENT.ERROR
4344
)
4445
.fetchInto(MonitorDetailsDto::class.java)
@@ -50,6 +51,7 @@ class MonitorRepository @Inject constructor(jooqConfig: Configuration) : Monitor
5051
MONITOR.ID,
5152
UPTIME_EVENT.STATUS,
5253
UPTIME_EVENT.STARTED_AT,
54+
UPTIME_EVENT.UPDATED_AT,
5355
UPTIME_EVENT.ERROR
5456
)
5557
.fetchOneInto(MonitorDetailsDto::class.java)
@@ -100,6 +102,7 @@ class MonitorRepository @Inject constructor(jooqConfig: Configuration) : Monitor
100102
MONITOR.UPDATED_AT.`as`("updatedAt"),
101103
UPTIME_EVENT.STATUS.`as`("uptimeStatus"),
102104
UPTIME_EVENT.STARTED_AT.`as`("uptimeStatusStartedAt"),
105+
UPTIME_EVENT.UPDATED_AT.`as`("lastUptimeCheck"),
103106
UPTIME_EVENT.ERROR.`as`("uptimeError"),
104107
round(avg(LATENCY_LOG.LATENCY), -1).`as`("averageLatencyInMs"),
105108
inline(null, SQLDataType.INTEGER).`as`("p95LatencyInMs"),

src/test/kotlin/com/kuvaszuptime/kuvasz/controllers/MonitorControllerTest.kt

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,17 @@ package com.kuvaszuptime.kuvasz.controllers
33
import arrow.core.Option
44
import arrow.core.toOption
55
import com.kuvaszuptime.kuvasz.DatabaseBehaviorSpec
6+
import com.kuvaszuptime.kuvasz.enums.UptimeStatus
67
import com.kuvaszuptime.kuvasz.mocks.createMonitor
8+
import com.kuvaszuptime.kuvasz.mocks.createUptimeEventRecord
79
import com.kuvaszuptime.kuvasz.models.dto.MonitorCreateDto
810
import com.kuvaszuptime.kuvasz.models.dto.MonitorUpdateDto
911
import com.kuvaszuptime.kuvasz.repositories.LatencyLogRepository
1012
import com.kuvaszuptime.kuvasz.repositories.MonitorRepository
13+
import com.kuvaszuptime.kuvasz.repositories.UptimeEventRepository
1114
import com.kuvaszuptime.kuvasz.services.CheckScheduler
1215
import com.kuvaszuptime.kuvasz.testutils.shouldBe
16+
import com.kuvaszuptime.kuvasz.util.getCurrentTimestamp
1317
import io.kotest.assertions.exceptionToMessage
1418
import io.kotest.assertions.throwables.shouldThrow
1519
import io.kotest.core.test.TestCase
@@ -33,6 +37,7 @@ class MonitorControllerTest(
3337
private val monitorClient: MonitorClient,
3438
private val monitorRepository: MonitorRepository,
3539
private val latencyLogRepository: LatencyLogRepository,
40+
private val uptimeEventRepository: UptimeEventRepository,
3641
private val checkScheduler: CheckScheduler
3742
) : DatabaseBehaviorSpec() {
3843

@@ -43,6 +48,14 @@ class MonitorControllerTest(
4348
latencyLogRepository.insertLatencyForMonitor(monitor.id, 1200)
4449
latencyLogRepository.insertLatencyForMonitor(monitor.id, 600)
4550
latencyLogRepository.insertLatencyForMonitor(monitor.id, 600)
51+
val now = getCurrentTimestamp()
52+
createUptimeEventRecord(
53+
repository = uptimeEventRepository,
54+
monitorId = monitor.id,
55+
startedAt = now,
56+
status = UptimeStatus.UP,
57+
endedAt = null
58+
)
4659

4760
val response = monitorClient.getMonitorsWithDetails(enabledOnly = null)
4861
then("it should return them") {
@@ -55,7 +68,8 @@ class MonitorControllerTest(
5568
responseItem.averageLatencyInMs shouldBe 800
5669
responseItem.p95LatencyInMs shouldBe 1200
5770
responseItem.p99LatencyInMs shouldBe 1200
58-
responseItem.uptimeStatus shouldBe null
71+
responseItem.uptimeStatus shouldBe UptimeStatus.UP
72+
responseItem.lastUptimeCheck shouldBe now
5973
responseItem.createdAt shouldBe monitor.createdAt
6074
}
6175
}
@@ -88,15 +102,27 @@ class MonitorControllerTest(
88102
given("MonitorController's getMonitorDetails() endpoint") {
89103
`when`("there is a monitor with the given ID in the database") {
90104
val monitor = createMonitor(monitorRepository)
91-
val response = monitorClient.getMonitorDetails(monitorId = monitor.id)
105+
latencyLogRepository.insertLatencyForMonitor(monitor.id, 1200)
106+
latencyLogRepository.insertLatencyForMonitor(monitor.id, 600)
107+
latencyLogRepository.insertLatencyForMonitor(monitor.id, 600)
108+
val now = getCurrentTimestamp()
109+
createUptimeEventRecord(
110+
repository = uptimeEventRepository,
111+
monitorId = monitor.id,
112+
startedAt = now,
113+
status = UptimeStatus.UP,
114+
endedAt = null
115+
)
92116
then("it should return it") {
117+
val response = monitorClient.getMonitorDetails(monitorId = monitor.id)
93118
response.id shouldBe monitor.id
94119
response.name shouldBe monitor.name
95120
response.url.toString() shouldBe monitor.url
96121
response.enabled shouldBe monitor.enabled
97-
response.averageLatencyInMs shouldBe null
98-
response.uptimeStatus shouldBe null
122+
response.averageLatencyInMs shouldBe 800
123+
response.uptimeStatus shouldBe UptimeStatus.UP
99124
response.createdAt shouldBe monitor.createdAt
125+
response.lastUptimeCheck shouldBe now
100126
}
101127
}
102128

@@ -313,7 +339,8 @@ class MonitorControllerTest(
313339
uptimeCheckInterval = null,
314340
enabled = true
315341
)
316-
val updateRequest = HttpRequest.PATCH<MonitorUpdateDto>("/monitors/${firstCreatedMonitor.id}", updateDto)
342+
val updateRequest =
343+
HttpRequest.PATCH<MonitorUpdateDto>("/monitors/${firstCreatedMonitor.id}", updateDto)
317344
val response = shouldThrow<HttpClientResponseException> {
318345
client.toBlocking().exchange<MonitorUpdateDto, Any>(updateRequest)
319346
}

src/test/kotlin/com/kuvaszuptime/kuvasz/mocks/TestData.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
package com.kuvaszuptime.kuvasz.mocks
22

3+
import com.kuvaszuptime.kuvasz.enums.UptimeStatus
34
import com.kuvaszuptime.kuvasz.repositories.MonitorRepository
5+
import com.kuvaszuptime.kuvasz.repositories.UptimeEventRepository
46
import com.kuvaszuptime.kuvasz.tables.pojos.MonitorPojo
7+
import com.kuvaszuptime.kuvasz.tables.pojos.UptimeEventPojo
58
import com.kuvaszuptime.kuvasz.util.getCurrentTimestamp
9+
import java.time.OffsetDateTime
610

711
fun createMonitor(
812
repository: MonitorRepository,
@@ -22,3 +26,19 @@ fun createMonitor(
2226
repository.insert(monitor)
2327
return monitor
2428
}
29+
30+
fun createUptimeEventRecord(
31+
repository: UptimeEventRepository,
32+
monitorId: Int,
33+
status: UptimeStatus = UptimeStatus.UP,
34+
startedAt: OffsetDateTime,
35+
endedAt: OffsetDateTime?
36+
) =
37+
repository.insert(
38+
UptimeEventPojo()
39+
.setMonitorId(monitorId)
40+
.setStatus(status)
41+
.setStartedAt(startedAt)
42+
.setUpdatedAt(endedAt ?: startedAt)
43+
.setEndedAt(endedAt)
44+
)

src/test/kotlin/com/kuvaszuptime/kuvasz/services/DatabaseCleanerTest.kt

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
package com.kuvaszuptime.kuvasz.services
22

33
import com.kuvaszuptime.kuvasz.DatabaseBehaviorSpec
4-
import com.kuvaszuptime.kuvasz.enums.UptimeStatus
54
import com.kuvaszuptime.kuvasz.mocks.createMonitor
5+
import com.kuvaszuptime.kuvasz.mocks.createUptimeEventRecord
66
import com.kuvaszuptime.kuvasz.repositories.LatencyLogRepository
77
import com.kuvaszuptime.kuvasz.repositories.MonitorRepository
88
import com.kuvaszuptime.kuvasz.repositories.UptimeEventRepository
99
import com.kuvaszuptime.kuvasz.tables.pojos.LatencyLogPojo
10-
import com.kuvaszuptime.kuvasz.tables.pojos.UptimeEventPojo
1110
import com.kuvaszuptime.kuvasz.util.getCurrentTimestamp
1211
import io.kotest.matchers.collections.shouldHaveSize
1312
import io.micronaut.context.annotation.Property
@@ -27,7 +26,12 @@ class DatabaseCleanerTest(
2726
given("a DatabaseCleaner service") {
2827
`when`("there is an UPTIME_EVENT record with an end date greater than retention limit") {
2928
val monitor = createMonitor(monitorRepository)
30-
insertUptimeEventRecord(monitor.id, getCurrentTimestamp().minusDays(1), getCurrentTimestamp())
29+
createUptimeEventRecord(
30+
repository = uptimeEventRepository,
31+
monitorId = monitor.id,
32+
startedAt = getCurrentTimestamp().minusDays(1),
33+
endedAt = getCurrentTimestamp()
34+
)
3135
databaseCleaner.cleanObsoleteData()
3236

3337
then("it should not delete it") {
@@ -38,7 +42,12 @@ class DatabaseCleanerTest(
3842

3943
`when`("there is an UPTIME_EVENT record without an end date") {
4044
val monitor = createMonitor(monitorRepository)
41-
insertUptimeEventRecord(monitor.id, getCurrentTimestamp().minusDays(20), null)
45+
createUptimeEventRecord(
46+
repository = uptimeEventRepository,
47+
monitorId = monitor.id,
48+
startedAt = getCurrentTimestamp().minusDays(20),
49+
endedAt = null
50+
)
4251
databaseCleaner.cleanObsoleteData()
4352

4453
then("it should not delete it") {
@@ -49,10 +58,11 @@ class DatabaseCleanerTest(
4958

5059
`when`("there is an UPTIME_EVENT record with an end date less than retention limit") {
5160
val monitor = createMonitor(monitorRepository)
52-
insertUptimeEventRecord(
53-
monitor.id,
54-
getCurrentTimestamp().minusDays(20),
55-
getCurrentTimestamp().minusDays(8)
61+
createUptimeEventRecord(
62+
repository = uptimeEventRepository,
63+
monitorId = monitor.id,
64+
startedAt = getCurrentTimestamp().minusDays(20),
65+
endedAt = getCurrentTimestamp().minusDays(8)
5666
)
5767
databaseCleaner.cleanObsoleteData()
5868

@@ -86,16 +96,6 @@ class DatabaseCleanerTest(
8696
}
8797
}
8898

89-
private fun insertUptimeEventRecord(monitorId: Int, startedAt: OffsetDateTime, endedAt: OffsetDateTime?) =
90-
uptimeEventRepository.insert(
91-
UptimeEventPojo()
92-
.setMonitorId(monitorId)
93-
.setStatus(UptimeStatus.UP)
94-
.setStartedAt(startedAt)
95-
.setUpdatedAt(endedAt ?: startedAt)
96-
.setEndedAt(endedAt)
97-
)
98-
9999
private fun insertLatencyLogRecord(monitorId: Int, createdAt: OffsetDateTime) =
100100
latencyLogRepository.insert(
101101
LatencyLogPojo()

0 commit comments

Comments
 (0)