В настоящее время я перемещаю один из наших сервисов clojure в vert.x, используя kotlin в качестве основного языка.Большинство вещей работает как шарм, но есть одна проблема, с которой я борюсь уже довольно давно.
Все наши службы используют micrometer.io и prometheus для сбора метрик.Согласно документации , интегрирующий микрометр прост:
val vertx = Vertx.vertx(
VertxOptions().setMetricsOptions(
MicrometerMetricsOptions()
.setPrometheusOptions(VertxPrometheusOptions().setEnabled(true))
.setEnabled(true)
)
)
В общем, этот подход работает хорошо - метрики собираются и предоставляются путем добавления отдельного маршрута:
router.get("/metrics").handler(PrometheusScrapingHandler.create())
Проблема, с которой я сталкиваюсь, заключается в том, что я не знаю, как определить эти параметры, связанные с vert.x (VertxOptions
), только один раз и опубликовать их глобально - в основном всякий раз, когда новый Vertx
Экземпляр создан.
Это проблема, потому что в настоящее время я должен определить эти параметры в трех разных местах:
1.) Server.kt
Позволяетзапустите службу с моей IDE
2.) ServerLauncher
Цель этого класса - запустить сервер из командной строки с помощью gradle.
3.) Интеграционные тесты
Vert.x предоставляет отличное расширение junit5 (VertxExtension
), которое автоматически внедряет экземпляры Vertx
и VertxTestContext
в ваш методы испытаний .Недостатком является то, что невозможно настроить внедренный экземпляр Vertx
, поскольку он всегда внедряет его с настройками по умолчанию .
Таким образом, вы должны соединить все самостоятельно в своем методе тестирования:
@Test
@DisplayName("Call prometheus endpoint and verify core metrics are present")
fun callPrometheusEndpoint(testCtx: VertxTestContext) {
val vertx = Vertx.vertx(
VertxOptions().setMetricsOptions(
MicrometerMetricsOptions()
.setPrometheusOptions(VertxPrometheusOptions().setEnabled(true))
.setEnabled(true)
)
)
vertx.deployVerticle(
MyVerticle(),
testCtx.completing()
)
WebClient.create(vertx)
.get(8080, "localhost", "/internal/prometheus")
.`as`(BodyCodec.string())
.send(testCtx.succeeding { resp ->
testCtx.verify {
// assertions to follow...
testCtx.completeNow()
}
})
}
Мне интересно, есть ли способ определить VertxOptions
только один раз и таким образом переопределить /дополнять используемые настройки по умолчанию всякий раз, когда создается экземпляр Vertx
?
Обновление 1
Я решил извлечь отдельный класс Application
, чтобы настроить экземпляр Vertx
и избавиться от Server.kt
и ServerLauncher.kt
,
class Application(
private val profileSetting: String? = System.getenv("ACTIVE_PROFILES"),
private val logger: Logger = LoggerFactory.getLogger(Application::class.java)!!
) {
fun bootstrap() {
val profiles = activeProfiles()
val vertx = bootstrapVertx(profiles)
val configRetriever = bootstrapConfigRetriever(vertx, profiles)
val myVerticle = MyVerticle(configRetriever)
vertx.deployVerticle(myVerticle) { startup ->
if (startup.succeeded()) {
logger.info("Application startup finished")
} else {
logger.error("Application startup failed", startup.cause())
vertx.close()
}
}
}
internal fun activeProfiles(): List<String> {
logger.info("Configured profiles: {}", profileSetting)
return profileSetting
?.let { it.split(',').map { p -> p.trim() }.filter { p -> p.isNotBlank() } }
?: emptyList()
}
internal fun bootstrapVertx(profiles: List<String>): Vertx {
registerModules()
val vertxOptions = VertxOptionsFactory(profiles).create()
return Vertx.vertx(vertxOptions)
}
internal fun bootstrapConfigRetriever(vertx: Vertx, profiles: List<String>): ConfigRetriever {
return ConfigRetrieverFactory(profiles).create(vertx)
}
private fun registerModules() {
Json.mapper.apply { registerKotlinModule() }
Json.prettyMapper.apply { registerKotlinModule() }
}
companion object {
@JvmStatic
fun main(args: Array<String>) = Application().bootstrap()
}
}
Я не нашел способа передать настроенный экземпляр Vertx
в VertxExtention
.
Обновление 2
Я создал запрос на извлечение , который решает проблему предварительной настройки экземпляров vertx в тестах.