Skip to content

Commit fc667e5

Browse files
committed
Merge branch 'master' into S3backfill-allow-range-zero-val
* master: Make menu links configurable (#434) Log create/clone/update errors to Datadog, not just browser UI (#433)
2 parents 6fcb532 + 5639a74 commit fc667e5

File tree

5 files changed

+67
-5
lines changed

5 files changed

+67
-5
lines changed

service/src/main/kotlin/app/cash/backfila/ui/UiModule.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,10 @@ class UiModule : KAbstractModule() {
3030
install(WebActionModule.create<BackfillShowButtonHandlerAction>())
3131
}
3232
}
33+
34+
/**
35+
* Identifies the Misk dashboard for Backfila so dashboard links and other customization can be added.
36+
*/
37+
@Retention(AnnotationRetention.RUNTIME)
38+
@Target(AnnotationTarget.FUNCTION)
39+
annotation class BackfilaDashboard

service/src/main/kotlin/app/cash/backfila/ui/actions/BackfillCreateHandlerAction.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import app.cash.backfila.ui.pages.BackfillShowAction
99
import javax.inject.Inject
1010
import javax.inject.Singleton
1111
import kotlinx.html.div
12-
import misk.exceptions.BadRequestException
1312
import misk.scope.ActionScoped
1413
import misk.security.authz.Authenticated
1514
import misk.web.Get
@@ -22,6 +21,7 @@ import misk.web.mediatype.MediaTypes
2221
import misk.web.toResponseBody
2322
import okhttp3.Headers
2423
import okio.ByteString.Companion.encodeUtf8
24+
import wisp.logging.getLogger
2525

2626
@Singleton
2727
class BackfillCreateHandlerAction @Inject constructor(
@@ -74,6 +74,7 @@ class BackfillCreateHandlerAction @Inject constructor(
7474
AlertError(message = "Backfill create or clone failed: $e", label = "Try Again", onClick = "history.back(); return false;")
7575
}
7676
}
77+
logger.error(e) { "Backfill create or clone failed $e" }
7778
return Response(
7879
body = errorHtmlResponseBody,
7980
statusCode = 200,
@@ -91,6 +92,8 @@ class BackfillCreateHandlerAction @Inject constructor(
9192
}
9293

9394
companion object {
95+
private val logger = getLogger<BackfillCreateHandlerAction>()
96+
9497
const val PATH = "/api/backfill/create"
9598

9699
private fun <T>String?.ifNotBlank(block: (String) -> T) = if (this.isNullOrBlank()) null else block(this)

service/src/main/kotlin/app/cash/backfila/ui/actions/BackfillShowButtonHandlerAction.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import app.cash.backfila.dashboard.UpdateBackfillRequest
99
import app.cash.backfila.service.persistence.BackfillState
1010
import app.cash.backfila.ui.components.AlertError
1111
import app.cash.backfila.ui.components.DashboardPageLayout
12+
import javax.inject.Inject
13+
import javax.inject.Singleton
1214
import kotlinx.html.div
1315
import misk.security.authz.Authenticated
1416
import misk.web.Get
@@ -21,8 +23,7 @@ import misk.web.actions.WebAction
2123
import misk.web.mediatype.MediaTypes
2224
import misk.web.toResponseBody
2325
import okhttp3.Headers
24-
import javax.inject.Inject
25-
import javax.inject.Singleton
26+
import wisp.logging.getLogger
2627

2728
@Singleton
2829
class BackfillShowButtonHandlerAction @Inject constructor(
@@ -91,6 +92,7 @@ class BackfillShowButtonHandlerAction @Inject constructor(
9192
AlertError(message = "Update backfill field failed: $e", label = "Try Again", onClick = "history.back(); return false;")
9293
}
9394
}
95+
logger.error(e) { "Update backfill field failed $e" }
9496
return Response(
9597
body = errorHtmlResponseBody,
9698
statusCode = 200,
@@ -106,6 +108,8 @@ class BackfillShowButtonHandlerAction @Inject constructor(
106108
}
107109

108110
companion object {
111+
private val logger = getLogger<BackfillShowButtonHandlerAction>()
112+
109113
const val PATH = "/api/backfill/{id}/update"
110114
fun path(id: String) = PATH.replace("{id}", id)
111115
fun path(id: Long) = path(id.toString())

service/src/main/kotlin/app/cash/backfila/ui/components/DashboardPageLayout.kt

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import app.cash.backfila.service.BackfilaConfig
55
import app.cash.backfila.service.persistence.BackfilaDb
66
import app.cash.backfila.service.persistence.BackfillRunQuery
77
import app.cash.backfila.service.persistence.BackfillState
8+
import app.cash.backfila.ui.BackfilaDashboard
89
import app.cash.backfila.ui.pages.IndexAction
910
import jakarta.inject.Inject
1011
import kotlinx.html.TagConsumer
@@ -30,6 +31,7 @@ import misk.tailwind.pages.MenuSection
3031
import misk.tailwind.pages.Navbar
3132
import misk.web.HttpCall
3233
import misk.web.ResponseBody
34+
import misk.web.dashboard.DashboardTab
3335
import misk.web.dashboard.HtmlLayout
3436
import okio.BufferedSink
3537
import wisp.deployment.Deployment
@@ -47,6 +49,7 @@ class DashboardPageLayout @Inject constructor(
4749
private val getBackfillRunsAction: GetBackfillRunsAction,
4850
@BackfilaDb private val transacter: Transacter,
4951
private val queryFactory: Query.Factory,
52+
private val allTabs: List<DashboardTab>,
5053
) {
5154
private var newBuilder = false
5255
private var headBlock: TagConsumer<*>.() -> Unit = {}
@@ -57,6 +60,10 @@ class DashboardPageLayout @Inject constructor(
5760
clientHttpCall.get().url.encodedPath
5861
}
5962

63+
private val backfilaLinks by lazy {
64+
allTabs.filter { it.dashboardAnnotationKClass == BackfilaDashboard::class }
65+
}
66+
6067
private fun setNewBuilder() = apply { newBuilder = true }
6168

6269
fun newBuilder(): DashboardPageLayout = DashboardPageLayout(
@@ -67,6 +74,7 @@ class DashboardPageLayout @Inject constructor(
6774
getBackfillRunsAction = getBackfillRunsAction,
6875
transacter = transacter,
6976
queryFactory = queryFactory,
77+
allTabs = allTabs,
7078
).setNewBuilder()
7179

7280
fun title(title: String) = apply {
@@ -181,9 +189,30 @@ class DashboardPageLayout @Inject constructor(
181189
href = "/backfills/",
182190
isSelected = currentPath == "/backfills/",
183191
),
184-
),
192+
) + backfilaLinks.filter { it.menuCategory == "Backfila" }.map { tab ->
193+
Link(
194+
label = tab.menuLabel,
195+
href = tab.menuUrl,
196+
isSelected = currentPath.startsWith(tab.menuUrl),
197+
)
198+
},
185199
),
186-
) + if (services.isNotEmpty()) {
200+
) + if (backfilaLinks.filterNot { it.menuCategory == "Backfila" }.isNotEmpty()) {
201+
backfilaLinks.filterNot { it.menuCategory == "Backfila" }.groupBy { it.menuCategory }.map { (category, tabs) ->
202+
MenuSection(
203+
title = category,
204+
links = tabs.map { tab ->
205+
Link(
206+
label = tab.menuLabel,
207+
href = tab.menuUrl,
208+
isSelected = currentPath.startsWith(tab.menuUrl),
209+
)
210+
},
211+
)
212+
}
213+
} else {
214+
listOf()
215+
} + if (services.isNotEmpty()) {
187216
listOf(
188217
MenuSection(
189218
title = "Your Services",

service/src/test/kotlin/app/cash/backfila/development/BackfilaDevelopmentService.kt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import app.cash.backfila.protos.clientservice.RunBatchResponse
1616
import app.cash.backfila.service.BackfilaConfig
1717
import app.cash.backfila.service.BackfilaServiceModule
1818
import app.cash.backfila.service.persistence.DbBackfillRun
19+
import app.cash.backfila.ui.BackfilaDashboard
1920
import misk.MiskApplication
2021
import misk.MiskRealServiceModule
2122
import misk.audit.NoOpAuditClientModule
@@ -28,8 +29,10 @@ import misk.jdbc.DataSourceConfig
2829
import misk.jdbc.DataSourceType
2930
import misk.security.authz.FakeCallerAuthenticator
3031
import misk.security.authz.MiskCallerAuthenticator
32+
import misk.security.authz.Unauthenticated
3133
import misk.web.MiskWebModule
3234
import misk.web.WebConfig
35+
import misk.web.dashboard.DashboardModule
3336
import okio.ByteString.Companion.encodeUtf8
3437
import wisp.deployment.Deployment
3538

@@ -54,6 +57,22 @@ fun main(args: Array<String>) {
5457
multibind<MiskCallerAuthenticator>().to<FakeCallerAuthenticator>()
5558
bind<ViewLogsUrlProvider>().to<DevelopmentViewLogsUrlProvider>()
5659

60+
// Example custom link that shows up in navbar
61+
install(
62+
DashboardModule.createMenuLink<BackfilaDashboard, Unauthenticated>(
63+
label = "Go to Repo",
64+
url = "https://github.com/cashapp/backfila",
65+
category = "Backfila",
66+
),
67+
)
68+
install(
69+
DashboardModule.createMenuLink<BackfilaDashboard, Unauthenticated>(
70+
label = "Test other link",
71+
url = "https://github.com/cashapp/backfila",
72+
category = "Alpha",
73+
),
74+
)
75+
5776
newMapBinder<String, BackfilaCallbackConnectorProvider>(ForConnectors::class)
5877
.permitDuplicates().addBinding("DEV")
5978
.toInstance(object : BackfilaCallbackConnectorProvider {

0 commit comments

Comments
 (0)