From ab2a06e810c7bc7b0ee2d933f64346f4f0f1e1bc Mon Sep 17 00:00:00 2001 From: Walter Oggioni Date: Wed, 29 Apr 2026 22:31:53 +0800 Subject: [PATCH] refactor --- gradle.properties | 2 +- rbcs-api/build.gradle | 1 + rbcs-api/src/main/java/module-info.java | 2 +- .../rbcs/api/TelemetryController.java | 9 +++++ rbcs-cli/src/main/java/module-info.java | 4 ++- .../rbcs/cli/RemoteBuildCacheServerCli.kt | 8 +++++ .../net/woggioni/rbcs/common/Logging.kt | 7 ++-- .../kotlin/net/woggioni/rbcs/common/RBCS.kt | 20 +++++------ rbcs-server-otel/build.gradle | 35 +++++++++++++++---- .../src/main/java/module-info.java | 20 +++++++++++ .../rbcs/server/otel/OtelController.kt | 20 ++++++----- rbcs-server/src/main/java/module-info.java | 6 +--- .../rbcs/server/RemoteBuildCacheServer.kt | 11 +++--- 13 files changed, 104 insertions(+), 41 deletions(-) create mode 100644 rbcs-api/src/main/java/net/woggioni/rbcs/api/TelemetryController.java create mode 100644 rbcs-server-otel/src/main/java/module-info.java rename rbcs-server/src/main/kotlin/net/woggioni/rbcs/server/otel/OtelSdkIntegration.kt => rbcs-server-otel/src/main/kotlin/net/woggioni/rbcs/server/otel/OtelController.kt (68%) diff --git a/gradle.properties b/gradle.properties index f4ced78..325441b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ org.gradle.caching=true rbcs.version = 0.5.0 -lys.version = 2026.04.28 +lys.version = 2026.04.29 gitea.maven.url = https://gitea.woggioni.net/api/packages/woggioni/maven docker.registry.url=gitea.woggioni.net diff --git a/rbcs-api/build.gradle b/rbcs-api/build.gradle index c1d6c07..7cceab7 100644 --- a/rbcs-api/build.gradle +++ b/rbcs-api/build.gradle @@ -11,6 +11,7 @@ dependencies { api catalog.netty.buffer api catalog.netty.handler api catalog.netty.codec.http + api catalog.jetbrains.annotations } publishing { diff --git a/rbcs-api/src/main/java/module-info.java b/rbcs-api/src/main/java/module-info.java index e282812..74093d7 100644 --- a/rbcs-api/src/main/java/module-info.java +++ b/rbcs-api/src/main/java/module-info.java @@ -8,7 +8,7 @@ module net.woggioni.rbcs.api { requires io.netty.buffer; requires org.slf4j; requires java.xml; - + requires org.jetbrains.annotations; exports net.woggioni.rbcs.api; exports net.woggioni.rbcs.api.exception; diff --git a/rbcs-api/src/main/java/net/woggioni/rbcs/api/TelemetryController.java b/rbcs-api/src/main/java/net/woggioni/rbcs/api/TelemetryController.java new file mode 100644 index 0000000..686ebab --- /dev/null +++ b/rbcs-api/src/main/java/net/woggioni/rbcs/api/TelemetryController.java @@ -0,0 +1,9 @@ +package net.woggioni.rbcs.api; + +import io.netty.channel.ChannelHandler; +import org.jetbrains.annotations.NotNull; + +public interface TelemetryController { + void initialize(); + @NotNull ChannelHandler createHandler(); +} diff --git a/rbcs-cli/src/main/java/module-info.java b/rbcs-cli/src/main/java/module-info.java index 4026852..ea68e79 100644 --- a/rbcs-cli/src/main/java/module-info.java +++ b/rbcs-cli/src/main/java/module-info.java @@ -1,11 +1,11 @@ module net.woggioni.rbcs.cli { requires org.slf4j; + requires net.woggioni.jwo; requires net.woggioni.rbcs.server; requires info.picocli; requires net.woggioni.rbcs.common; requires net.woggioni.rbcs.client; requires kotlin.stdlib; - requires net.woggioni.jwo; requires net.woggioni.rbcs.api; exports net.woggioni.rbcs.cli.impl.converters to info.picocli; @@ -14,4 +14,6 @@ module net.woggioni.rbcs.cli { opens net.woggioni.rbcs.cli to info.picocli, net.woggioni.rbcs.common; exports net.woggioni.rbcs.cli; + + uses net.woggioni.rbcs.api.TelemetryController; } \ No newline at end of file diff --git a/rbcs-cli/src/main/kotlin/net/woggioni/rbcs/cli/RemoteBuildCacheServerCli.kt b/rbcs-cli/src/main/kotlin/net/woggioni/rbcs/cli/RemoteBuildCacheServerCli.kt index 0b0c273..ce9dd61 100644 --- a/rbcs-cli/src/main/kotlin/net/woggioni/rbcs/cli/RemoteBuildCacheServerCli.kt +++ b/rbcs-cli/src/main/kotlin/net/woggioni/rbcs/cli/RemoteBuildCacheServerCli.kt @@ -1,6 +1,8 @@ package net.woggioni.rbcs.cli import net.woggioni.jwo.Application +import net.woggioni.jwo.LoggerController +import net.woggioni.rbcs.api.TelemetryController import net.woggioni.rbcs.cli.impl.AbstractVersionProvider import net.woggioni.rbcs.cli.impl.RbcsCommand import net.woggioni.rbcs.cli.impl.commands.BenchmarkCommand @@ -14,6 +16,8 @@ import net.woggioni.rbcs.common.RbcsUrlStreamHandlerFactory import net.woggioni.rbcs.common.createLogger import picocli.CommandLine import picocli.CommandLine.Model.CommandSpec +import java.util.ServiceLoader +import net.woggioni.rbcs.common.RBCS.loadService @CommandLine.Command( @@ -61,6 +65,10 @@ class RemoteBuildCacheServerCli : RbcsCommand() { @JvmStatic fun main(vararg args: String) { + loadService(TelemetryController::class.java) + .firstOrNull() + ?.initialize() + LoggerController.initializeLoggers() System.exit(createCommandLine().execute(*args)) } } diff --git a/rbcs-common/src/main/kotlin/net/woggioni/rbcs/common/Logging.kt b/rbcs-common/src/main/kotlin/net/woggioni/rbcs/common/Logging.kt index 9247481..9c24152 100644 --- a/rbcs-common/src/main/kotlin/net/woggioni/rbcs/common/Logging.kt +++ b/rbcs-common/src/main/kotlin/net/woggioni/rbcs/common/Logging.kt @@ -2,6 +2,7 @@ package net.woggioni.rbcs.common import io.netty.channel.Channel import io.netty.channel.ChannelHandlerContext +import net.woggioni.jwo.LoggerController import java.nio.file.Files import java.nio.file.Path import java.util.logging.LogManager @@ -11,8 +12,10 @@ import org.slf4j.MDC import org.slf4j.event.Level import org.slf4j.spi.LoggingEventBuilder -inline fun T.contextLogger() = LoggerFactory.getLogger(T::class.java) -inline fun createLogger() = LoggerFactory.getLogger(T::class.java) +fun lazyLogger(cls: Class) = LoggerController.lazyLogger(cls) + +inline fun T.contextLogger() = lazyLogger(T::class.java) +inline fun createLogger() = lazyLogger(T::class.java) inline fun Logger.traceParam(messageBuilder: () -> Pair>) { if (isTraceEnabled) { diff --git a/rbcs-common/src/main/kotlin/net/woggioni/rbcs/common/RBCS.kt b/rbcs-common/src/main/kotlin/net/woggioni/rbcs/common/RBCS.kt index f228f6c..12e630b 100644 --- a/rbcs-common/src/main/kotlin/net/woggioni/rbcs/common/RBCS.kt +++ b/rbcs-common/src/main/kotlin/net/woggioni/rbcs/common/RBCS.kt @@ -1,5 +1,7 @@ package net.woggioni.rbcs.common +import net.woggioni.jwo.JWO +import net.woggioni.jwo.Tuple2 import java.io.IOException import java.net.InetAddress import java.net.ServerSocket @@ -9,18 +11,10 @@ import java.nio.file.Files import java.nio.file.Path import java.security.KeyStore import java.security.MessageDigest -import java.security.cert.CertPathValidator -import java.security.cert.CertPathValidatorException -import java.security.cert.CertificateException -import java.security.cert.CertificateFactory -import java.security.cert.PKIXParameters -import java.security.cert.PKIXRevocationChecker -import java.security.cert.X509Certificate -import java.util.EnumSet +import java.security.cert.* +import java.util.* import javax.net.ssl.TrustManagerFactory import javax.net.ssl.X509TrustManager -import net.woggioni.jwo.JWO -import net.woggioni.jwo.Tuple2 object RBCS { fun String.toUrl(): URL = URL.of(URI(this), null) @@ -164,4 +158,10 @@ object RBCS { .single() as X509TrustManager } } + + inline fun U.loadService(serviceClass : Class): Sequence { + return (U::class.java.module.layer?.let { layer -> + ServiceLoader.load(layer, serviceClass) + } ?: ServiceLoader.load(serviceClass)).asSequence() + } } \ No newline at end of file diff --git a/rbcs-server-otel/build.gradle b/rbcs-server-otel/build.gradle index 2934d10..4da6f77 100644 --- a/rbcs-server-otel/build.gradle +++ b/rbcs-server-otel/build.gradle @@ -5,11 +5,20 @@ plugins { } configurations { + bundle { + canBeResolved = false + canBeConsumed = false + transitive = true + } + + filteredBundle { canBeResolved = true canBeConsumed = false transitive = true + extendsFrom bundle + resolutionStrategy { dependencies { exclude group: 'org.slf4j', module: 'slf4j-api' @@ -19,27 +28,39 @@ configurations { } } - implementation { - extendsFrom bundle - } - release { transitive = false canBeConsumed = true canBeResolved = true } + + compileOnly { + extendsFrom bundle + } } dependencies { - bundle catalog.opentelemetry.netty['4']['1'] + compileOnly project(':rbcs-common') + compileOnly project(':rbcs-api') + + compileOnly catalog.netty.transport + compileOnly catalog.slf4j.api + compileOnly catalog.kotlin.stdlib.jdk8 + compileOnly catalog.logback.core + compileOnly catalog.logback.classic + + bundle catalog.opentelemetry.netty.'4'.'1' bundle catalog.opentelemetry.sdk.extension.autoconfigure - bundle catalog.opentelemetry.logback.appender['1']['0'] + bundle catalog.opentelemetry.logback.appender.'1'.'0' + bundle catalog.opentelemetry.logback.mdc.'1'.'0' bundle catalog.opentelemetry.extension.trace.propagators bundle catalog.opentelemetry.exporter.otlp + bundle catalog.opentelemetry.runtime.telemetry } Provider bundleTask = tasks.register("bundle", Tar) { - from(configurations.bundle) + from(tasks.named(JavaPlugin.JAR_TASK_NAME)) + from(configurations.filteredBundle) group = BasePlugin.BUILD_GROUP } diff --git a/rbcs-server-otel/src/main/java/module-info.java b/rbcs-server-otel/src/main/java/module-info.java new file mode 100644 index 0000000..4c3d6ce --- /dev/null +++ b/rbcs-server-otel/src/main/java/module-info.java @@ -0,0 +1,20 @@ +module net.woggioni.rbcs.server.otel { + requires net.woggioni.rbcs.common; + requires kotlin.stdlib; + requires io.netty.transport; + requires io.netty.common; + requires io.netty.buffer; + requires org.slf4j; + + requires ch.qos.logback.core; + requires ch.qos.logback.classic; + requires io.opentelemetry.api; + requires io.opentelemetry.sdk.autoconfigure; + requires io.opentelemetry.instrumentation.runtime_telemetry; + requires io.opentelemetry.instrumentation.netty_4_1; + requires io.opentelemetry.instrumentation.logback_appender_1_0; + requires io.opentelemetry.extension.trace.propagation; + requires net.woggioni.rbcs.api; + + provides net.woggioni.rbcs.api.TelemetryController with net.woggioni.rbcs.server.otel.OtelController; +} diff --git a/rbcs-server/src/main/kotlin/net/woggioni/rbcs/server/otel/OtelSdkIntegration.kt b/rbcs-server-otel/src/main/kotlin/net/woggioni/rbcs/server/otel/OtelController.kt similarity index 68% rename from rbcs-server/src/main/kotlin/net/woggioni/rbcs/server/otel/OtelSdkIntegration.kt rename to rbcs-server-otel/src/main/kotlin/net/woggioni/rbcs/server/otel/OtelController.kt index b2f792b..a1eccfc 100644 --- a/rbcs-server/src/main/kotlin/net/woggioni/rbcs/server/otel/OtelSdkIntegration.kt +++ b/rbcs-server-otel/src/main/kotlin/net/woggioni/rbcs/server/otel/OtelController.kt @@ -2,13 +2,17 @@ package net.woggioni.rbcs.server.otel import io.netty.channel.ChannelHandler import io.opentelemetry.api.GlobalOpenTelemetry +import io.opentelemetry.instrumentation.logback.appender.v1_0.OpenTelemetryAppender import io.opentelemetry.instrumentation.netty.v4_1.NettyServerTelemetry +import io.opentelemetry.instrumentation.runtimetelemetry.RuntimeTelemetry +import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk +import net.woggioni.rbcs.api.TelemetryController import net.woggioni.rbcs.common.createLogger import net.woggioni.rbcs.common.info -object OtelSdkIntegration { +class OtelController : TelemetryController { - private val log = createLogger() + private val log = createLogger() private val appenderAvailable: Boolean by lazy { runCatching { @@ -22,30 +26,28 @@ object OtelSdkIntegration { ) } - fun initialize() { + override fun initialize() { log.info { "Initializing OpenTelemetry SDK with auto-configuration" } - val sdk = io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk.builder() + val sdk = AutoConfiguredOpenTelemetrySdk.builder() .setResultAsGlobal() .build() .openTelemetrySdk + RuntimeTelemetry.create(sdk) if (appenderAvailable) { runCatching { - val clazz = Class.forName("io.opentelemetry.instrumentation.logback.appender.v1_0.OpenTelemetryAppender") - clazz.getMethod("install", Class.forName("io.opentelemetry.api.OpenTelemetry")) - .invoke(null, sdk) + OpenTelemetryAppender.install(sdk) log.info { "OpenTelemetry logback appender installed" } }.onFailure { ex -> val msg = ex.localizedMessage ?: ex.javaClass.name log.info { "Failed to install OpenTelemetry logback appender: $msg" } } } - log.info { "OpenTelemetry SDK initialized successfully" } } - fun createHandler(): ChannelHandler { + override fun createHandler(): ChannelHandler { return NettyServerTelemetry.create(GlobalOpenTelemetry.get()).createCombinedHandler() } } diff --git a/rbcs-server/src/main/java/module-info.java b/rbcs-server/src/main/java/module-info.java index 9aaf4c1..fb7a95f 100644 --- a/rbcs-server/src/main/java/module-info.java +++ b/rbcs-server/src/main/java/module-info.java @@ -17,11 +17,6 @@ module net.woggioni.rbcs.server { requires io.netty.common; requires io.netty.codec; requires io.netty.codec.haproxy; - requires static io.opentelemetry.api; - requires static io.opentelemetry.instrumentation.netty_4_1; - requires static io.opentelemetry.sdk.autoconfigure; - requires static io.opentelemetry.instrumentation.logback_appender_1_0; - requires static io.opentelemetry.extension.trace.propagation; requires org.slf4j; exports net.woggioni.rbcs.server; @@ -31,5 +26,6 @@ module net.woggioni.rbcs.server { uses CacheProvider; + uses net.woggioni.rbcs.api.TelemetryController; provides CacheProvider with FileSystemCacheProvider, InMemoryCacheProvider; } \ No newline at end of file diff --git a/rbcs-server/src/main/kotlin/net/woggioni/rbcs/server/RemoteBuildCacheServer.kt b/rbcs-server/src/main/kotlin/net/woggioni/rbcs/server/RemoteBuildCacheServer.kt index 3cd454e..b31eb2a 100644 --- a/rbcs-server/src/main/kotlin/net/woggioni/rbcs/server/RemoteBuildCacheServer.kt +++ b/rbcs-server/src/main/kotlin/net/woggioni/rbcs/server/RemoteBuildCacheServer.kt @@ -26,12 +26,14 @@ import io.netty.util.AttributeKey import io.netty.util.concurrent.EventExecutorGroup import net.woggioni.rbcs.api.AsyncCloseable import net.woggioni.rbcs.api.Configuration +import net.woggioni.rbcs.api.TelemetryController import net.woggioni.rbcs.api.exception.ConfigurationException import net.woggioni.rbcs.common.* import net.woggioni.rbcs.common.PasswordSecurity.decodePasswordHash import net.woggioni.rbcs.common.PasswordSecurity.hashPassword import net.woggioni.rbcs.common.RBCS.getTrustManager import net.woggioni.rbcs.common.RBCS.loadKeystore +import net.woggioni.rbcs.common.RBCS.loadService import net.woggioni.rbcs.common.RBCS.toUrl import net.woggioni.rbcs.server.auth.AbstractNettyHttpAuthenticator import net.woggioni.rbcs.server.auth.Authorizer @@ -43,7 +45,6 @@ import net.woggioni.rbcs.server.handler.MaxRequestSizeHandler import net.woggioni.rbcs.server.handler.ProxyProtocolHandler import net.woggioni.rbcs.server.handler.ReadTriggerDuplexHandler import net.woggioni.rbcs.server.handler.ServerHandler -import net.woggioni.rbcs.server.otel.OtelSdkIntegration import net.woggioni.rbcs.server.throttling.BucketManager import net.woggioni.rbcs.server.throttling.ThrottlingHandler import java.io.OutputStream @@ -415,7 +416,10 @@ class RemoteBuildCacheServer(private val cfg: Configuration) { } pipeline.addLast(HttpServerCodec(httpDecoderConfig)) if(cfg.isEnableTelemetry) { - OtelSdkIntegration.createHandler().let { pipeline.addLast(it) } + loadService(TelemetryController::class.java) + .firstOrNull() + ?.createHandler() + ?.let { pipeline.addLast(it) } } pipeline.addLast(ReadTriggerDuplexHandler.NAME, ReadTriggerDuplexHandler()) pipeline.addLast(MaxRequestSizeHandler.NAME, MaxRequestSizeHandler(cfg.connection.maxRequestSize)) @@ -511,9 +515,6 @@ class RemoteBuildCacheServer(private val cfg: Configuration) { } fun run(): ServerHandle { - if(cfg.isEnableTelemetry) { - OtelSdkIntegration.initialize() - } // Create the multithreaded event loops for the server val bossGroup = MultiThreadIoEventLoopGroup(1, NioIoHandler.newFactory()) val channelFactory = ChannelFactory { NioSocketChannel() }