diff --git a/.ci/api-current.txt b/.ci/api-current.txt index fafb54a2c0..fd07a7ea41 100644 --- a/.ci/api-current.txt +++ b/.ci/api-current.txt @@ -4398,7 +4398,7 @@ public final class net.corda.core.node.services.StatesNotAvailableException exte @DoNotImplement public interface net.corda.core.node.services.TelemetryService @Nullable - public abstract net.corda.core.internal.telemetry.OpenTelemetryHandle getOpenTelemetry() + public abstract T getTelemetryHandle(Class) ## public final class net.corda.core.node.services.TimeWindowChecker extends java.lang.Object public () @@ -9455,11 +9455,11 @@ public final class net.corda.client.rpc.CordaRPCConnection extends java.lang.Obj public (net.corda.client.rpc.RPCConnection, java.util.concurrent.ExecutorService, net.corda.client.rpc.internal.ReconnectingCordaRPCOps, kotlin.jvm.internal.DefaultConstructorMarker) public void close() public void forceClose() - @Nullable - public net.corda.core.internal.telemetry.OpenTelemetryHandle getOpenTelemetry() @NotNull public net.corda.core.messaging.CordaRPCOps getProxy() public int getServerProtocolVersion() + @Nullable + public T getTelemetryHandle(Class) public void notifyServerAndClose() public static final net.corda.client.rpc.CordaRPCConnection$Companion Companion ## @@ -9491,11 +9491,11 @@ public final class net.corda.client.rpc.PermissionException extends net.corda.co public interface net.corda.client.rpc.RPCConnection extends java.io.Closeable public abstract void close() public abstract void forceClose() - @Nullable - public abstract net.corda.core.internal.telemetry.OpenTelemetryHandle getOpenTelemetry() @NotNull public abstract I getProxy() public abstract int getServerProtocolVersion() + @Nullable + public abstract T getTelemetryHandle(Class) public abstract void notifyServerAndClose() ## public class net.corda.client.rpc.RPCException extends net.corda.core.CordaRuntimeException diff --git a/build.gradle b/build.gradle index 12e27dbc7f..3e7a605a38 100644 --- a/build.gradle +++ b/build.gradle @@ -644,6 +644,7 @@ bintrayConfig { gpgSign = true gpgPassphrase = System.getenv('CORDA_BINTRAY_GPG_PASSPHRASE') publications = [ + 'corda-opentelemetry', 'corda-opentelemetry-driver', 'corda-jfx', 'corda-mock', diff --git a/client/rpc/src/main/kotlin/net/corda/client/rpc/CordaRPCClient.kt b/client/rpc/src/main/kotlin/net/corda/client/rpc/CordaRPCClient.kt index 7613ef9d8f..10f9585c03 100644 --- a/client/rpc/src/main/kotlin/net/corda/client/rpc/CordaRPCClient.kt +++ b/client/rpc/src/main/kotlin/net/corda/client/rpc/CordaRPCClient.kt @@ -11,7 +11,6 @@ import net.corda.core.context.Trace import net.corda.core.identity.CordaX500Name import net.corda.core.internal.PLATFORM_VERSION import net.corda.core.internal.VisibleForTesting -import net.corda.core.internal.telemetry.OpenTelemetryHandle import net.corda.core.messaging.ClientRpcSslOptions import net.corda.core.messaging.CordaRPCOps import net.corda.core.serialization.SerializationCustomSerializer @@ -78,8 +77,8 @@ class CordaRPCConnection private constructor( override fun forceClose() = doCloseLogic { actualConnection.forceClose() } - override fun getOpenTelemetry(): OpenTelemetryHandle? { - return actualConnection.getOpenTelemetry() + override fun getTelemetryHandle(telemetryClass: Class): T? { + return actualConnection.getTelemetryHandle(telemetryClass) } private inline fun doCloseLogic(close: () -> Unit) { diff --git a/client/rpc/src/main/kotlin/net/corda/client/rpc/RPCConnection.kt b/client/rpc/src/main/kotlin/net/corda/client/rpc/RPCConnection.kt index 336d66e435..cab461b149 100644 --- a/client/rpc/src/main/kotlin/net/corda/client/rpc/RPCConnection.kt +++ b/client/rpc/src/main/kotlin/net/corda/client/rpc/RPCConnection.kt @@ -1,7 +1,6 @@ package net.corda.client.rpc import net.corda.core.DoNotImplement -import net.corda.core.internal.telemetry.OpenTelemetryHandle import net.corda.core.messaging.RPCOps import java.io.Closeable @@ -25,7 +24,8 @@ interface RPCConnection : Closeable { /** * Returns the configured openTelemetry global. Returns null if opentelemetry has not been configured. */ - fun getOpenTelemetry(): OpenTelemetryHandle? + fun getTelemetryHandle(telemetryClass: Class): T? + /** * Closes this client gracefully by sending a notification to the server, so it can immediately clean up resources. diff --git a/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/RPCClient.kt b/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/RPCClient.kt index d677cde23e..e529676301 100644 --- a/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/RPCClient.kt +++ b/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/RPCClient.kt @@ -1,7 +1,6 @@ package net.corda.client.rpc.internal import net.corda.client.rpc.CordaRPCClientConfiguration -import net.corda.core.internal.telemetry.OpenTelemetryHandle import net.corda.client.rpc.RPCConnection import net.corda.client.rpc.UnrecoverableRPCException import net.corda.client.rpc.ext.RPCConnectionListener @@ -24,6 +23,7 @@ import net.corda.nodeapi.internal.RoundRobinConnectionPolicy import net.corda.nodeapi.internal.config.SslConfiguration import org.apache.activemq.artemis.api.core.TransportConfiguration import org.apache.activemq.artemis.api.core.client.ActiveMQClient +import org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants import java.lang.reflect.Proxy import java.util.concurrent.CopyOnWriteArraySet @@ -99,7 +99,9 @@ class RPCClient( // Without this any type of "send" time failures will not be delivered back to the client isBlockOnNonDurableSend = true } - val rpcClientTelemetry = RPCClientTelemetry("rpcClient-${targetLegalIdentity.toString()}", rpcConfiguration.openTelemetryEnabled, + + val targetString = "${transport.params[TransportConstants.HOST_PROP_NAME]}:${transport.params[TransportConstants.PORT_PROP_NAME]}" + val rpcClientTelemetry = RPCClientTelemetry("rpcClient-$targetString", rpcConfiguration.openTelemetryEnabled, rpcConfiguration.simpleLogTelemetryEnabled, rpcConfiguration.spanStartEndEventsEnabled) val sessionId = Trace.SessionId.newInstance() val distributionMux = DistributionMux(listeners, username) @@ -122,8 +124,8 @@ class RPCClient( override val proxy = ops override val serverProtocolVersion = serverProtocolVersion - override fun getOpenTelemetry(): OpenTelemetryHandle? { - return rpcClientTelemetry.getOpenTelemetryHandle() + override fun getTelemetryHandle(telemetryClass: Class): T? { + return rpcClientTelemetry.getTelemetryHandle(telemetryClass) } private fun close(notify: Boolean) { @@ -133,6 +135,7 @@ class RPCClient( proxyHandler.forceClose() } serverLocator.close() + rpcClientTelemetry.telemetryService.shutdownTelemetry() } override fun notifyServerAndClose() { diff --git a/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/RPCClientTelemetry.kt b/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/RPCClientTelemetry.kt index b0cbebea21..8073a88a2f 100644 --- a/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/RPCClientTelemetry.kt +++ b/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/RPCClientTelemetry.kt @@ -1,6 +1,5 @@ package net.corda.client.rpc.internal -import net.corda.core.internal.telemetry.OpenTelemetryHandle import net.corda.core.internal.telemetry.OpenTelemetryComponent import net.corda.core.internal.telemetry.SimpleLogTelemetryComponent import net.corda.core.internal.telemetry.TelemetryServiceImpl @@ -35,8 +34,7 @@ class RPCClientTelemetry(val serviceName: String, val openTelemetryEnabled: Bool } } - fun getOpenTelemetryHandle(): OpenTelemetryHandle? { - // Will return a handle clients can use to interact with opentelemetry - return null + fun getTelemetryHandle(telemetryClass: Class): T? { + return telemetryService.getTelemetryHandle(telemetryClass) } } \ No newline at end of file diff --git a/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/ReconnectingCordaRPCOps.kt b/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/ReconnectingCordaRPCOps.kt index bc45db07d2..6f7df5cf84 100644 --- a/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/ReconnectingCordaRPCOps.kt +++ b/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/ReconnectingCordaRPCOps.kt @@ -6,7 +6,6 @@ import net.corda.client.rpc.CordaRPCClientConfiguration import net.corda.client.rpc.CordaRPCConnection import net.corda.client.rpc.GracefulReconnect import net.corda.client.rpc.MaxRpcRetryException -import net.corda.core.internal.telemetry.OpenTelemetryHandle import net.corda.client.rpc.PermissionException import net.corda.client.rpc.RPCConnection import net.corda.client.rpc.RPCException @@ -298,8 +297,8 @@ class ReconnectingCordaRPCOps private constructor( currentRPCConnection?.forceClose() } } - override fun getOpenTelemetry(): OpenTelemetryHandle? { - return currentRPCConnection?.getOpenTelemetry() + override fun getTelemetryHandle(telemetryClass: Class): T? { + return currentRPCConnection?.getTelemetryHandle(telemetryClass) } fun isClosed(): Boolean = currentState == CLOSED } diff --git a/core-deterministic/build.gradle b/core-deterministic/build.gradle index dbf572f06d..6ffa0df5a5 100644 --- a/core-deterministic/build.gradle +++ b/core-deterministic/build.gradle @@ -45,7 +45,7 @@ dependencies { api "org.slf4j:slf4j-api:$slf4j_version" compileOnly "io.opentelemetry:opentelemetry-api:${open_telemetry_version}" - compileOnly project(':opentelemetry-driver') + compileOnly project(':opentelemetry') // These dependencies will become "runtime" scoped in our published POM. // See publish.dependenciesFrom.defaultScope. diff --git a/core/build.gradle b/core/build.gradle index 3939983353..0ae956a805 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -28,7 +28,7 @@ dependencies { obfuscatorImplementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" compileOnly "io.opentelemetry:opentelemetry-api:${open_telemetry_version}" - compileOnly project(':opentelemetry-driver') + compileOnly project(':opentelemetry') testImplementation sourceSets.obfuscator.output testImplementation "org.junit.jupiter:junit-jupiter-api:${junit_jupiter_version}" testImplementation "junit:junit:$junit_version" diff --git a/core/src/main/kotlin/net/corda/core/internal/telemetry/OpenTelemetryComponent.kt b/core/src/main/kotlin/net/corda/core/internal/telemetry/OpenTelemetryComponent.kt index fb31a2d899..f3f92583ee 100644 --- a/core/src/main/kotlin/net/corda/core/internal/telemetry/OpenTelemetryComponent.kt +++ b/core/src/main/kotlin/net/corda/core/internal/telemetry/OpenTelemetryComponent.kt @@ -42,25 +42,30 @@ data class OpenTelemetryContext(val spanContext: SerializableSpanContext, val st data class SpanInfo(val name: String, val span: Span, val spanScope: Scope, val spanEventContext: SerializableSpanContext? = null, val parentSpanEventContext: SerializableSpanContext? = null) -class TracerSetup { - var openTelemetry: OpenTelemetry? = null - fun getTracer(serviceName: String): Tracer { - return try { - with(OpenTelemetryDriver.getOpenTelemetry(serviceName)) { - openTelemetry = this - tracerProvider.get(OpenTelemetryComponent::class.java.name) - } +class TracerSetup(serviceName: String) { + private var openTelemetryDriver: Any? = null + val openTelemetry: OpenTelemetry by lazy { + try { + openTelemetryDriver = OpenTelemetryDriver(serviceName) + (openTelemetryDriver as OpenTelemetryDriver).openTelemetry } catch (ex: NoClassDefFoundError) { - GlobalOpenTelemetry.getTracerProvider().get(OpenTelemetryComponent::class.java.name) + GlobalOpenTelemetry.get() } } + fun getTracer(): Tracer { + return openTelemetry.tracerProvider.get(OpenTelemetryComponent::class.java.name) + } + + fun shutdown() { + (openTelemetryDriver as? OpenTelemetryDriver)?.shutdown() + } } @Suppress("TooManyFunctions") class OpenTelemetryComponent(val serviceName: String, val spanStartEndEventsEnabled: Boolean) : TelemetryComponent { - val tracerSetup = TracerSetup() - val tracer: Tracer = tracerSetup.getTracer(serviceName) + val tracerSetup = TracerSetup(serviceName) + val tracer: Tracer = tracerSetup.getTracer() companion object { private val log: Logger = LoggerFactory.getLogger(OpenTelemetryComponent::class.java) @@ -72,13 +77,8 @@ class OpenTelemetryComponent(val serviceName: String, val spanStartEndEventsEnab val baggages = ConcurrentHashMap() override fun isEnabled(): Boolean { - if (tracerSetup.openTelemetry != null) { - // The SDK is on the classpath. - return true - } - // Now see if the open telemetry java agent is available - val tracer = GlobalOpenTelemetry.getTracerProvider().get(OpenTelemetryComponent::class.java.name) - return tracer.javaClass.name != "io.opentelemetry.api.trace.DefaultTracer" + // DefaultTracer is the NoOp tracer in the OT API + return tracerSetup.getTracer().javaClass.name != "io.opentelemetry.api.trace.DefaultTracer" } override fun name(): String = OPENTELEMETRY_COMPONENT_NAME @@ -90,9 +90,14 @@ class OpenTelemetryComponent(val serviceName: String, val spanStartEndEventsEnab is EndSpanEvent -> endSpan(event.telemetryId) is SetStatusEvent -> setStatus(event.telemetryId, event.telemetryStatusCode, event.message) is RecordExceptionEvent -> recordException(event.telemetryId, event.throwable) + is ShutdownTelemetryEvent -> shutdownTelemetry() } } + private fun shutdownTelemetry() { + tracerSetup.shutdown() + } + @Suppress("LongParameterList") private fun startSpanForFlow(name: String, attributes: Map, telemetryId: UUID, flowLogic: FlowLogic<*>?, telemetryDataItem: TelemetryDataItem?) { @@ -289,6 +294,10 @@ class OpenTelemetryComponent(val serviceName: String, val spanStartEndEventsEnab return Baggage.current().asMap().mapValues { it.value.value } } + override fun getTelemetryHandles(): List { + return tracerSetup.openTelemetry.let { listOf(it) } + } + private fun setStatus(telemetryId: UUID, telemetryStatusCode: TelemetryStatusCode, message: String) { val spanInfo = spans[telemetryId] spanInfo?.span?.setStatus(toOpenTelemetryStatus(telemetryStatusCode), message) diff --git a/core/src/main/kotlin/net/corda/core/internal/telemetry/OpenTelemetryHandle.kt b/core/src/main/kotlin/net/corda/core/internal/telemetry/OpenTelemetryHandle.kt deleted file mode 100644 index 2f55ad0b36..0000000000 --- a/core/src/main/kotlin/net/corda/core/internal/telemetry/OpenTelemetryHandle.kt +++ /dev/null @@ -1,3 +0,0 @@ -package net.corda.core.internal.telemetry - -interface OpenTelemetryHandle \ No newline at end of file diff --git a/core/src/main/kotlin/net/corda/core/internal/telemetry/SimpleLogTelemetryComponent.kt b/core/src/main/kotlin/net/corda/core/internal/telemetry/SimpleLogTelemetryComponent.kt index f7f2114eb0..f7dcc119a9 100644 --- a/core/src/main/kotlin/net/corda/core/internal/telemetry/SimpleLogTelemetryComponent.kt +++ b/core/src/main/kotlin/net/corda/core/internal/telemetry/SimpleLogTelemetryComponent.kt @@ -111,6 +111,10 @@ class SimpleLogTelemetryComponent : TelemetryComponent { return logContexts[uuid]?.baggage ?: emptyMap() } + override fun getTelemetryHandles(): List { + return emptyList() + } + @Suppress("UNUSED_PARAMETER") private fun setStatus(telemetryId: UUID, telemetryStatusCode: TelemetryStatusCode, message: String) { when(telemetryStatusCode) { diff --git a/core/src/main/kotlin/net/corda/core/internal/telemetry/TelemetryServiceImpl.kt b/core/src/main/kotlin/net/corda/core/internal/telemetry/TelemetryServiceImpl.kt index 889b60b5b0..54bc1249f7 100644 --- a/core/src/main/kotlin/net/corda/core/internal/telemetry/TelemetryServiceImpl.kt +++ b/core/src/main/kotlin/net/corda/core/internal/telemetry/TelemetryServiceImpl.kt @@ -2,6 +2,7 @@ package net.corda.core.internal.telemetry import net.corda.core.CordaInternal import net.corda.core.flows.FlowLogic +import net.corda.core.internal.uncheckedCast import net.corda.core.node.ServiceHub import net.corda.core.node.services.TelemetryService import net.corda.core.serialization.CordaSerializable @@ -66,6 +67,8 @@ class StartSpanEvent(val name: String, val attributes: Map, val class EndSpanEvent(val telemetryId: UUID): TelemetryEvent class SetStatusEvent(val telemetryId: UUID, val telemetryStatusCode: TelemetryStatusCode, val message: String): TelemetryEvent class RecordExceptionEvent(val telemetryId: UUID, val throwable: Throwable): TelemetryEvent +class InitialiseTelemetryEvent: TelemetryEvent +class ShutdownTelemetryEvent: TelemetryEvent interface TelemetryComponent { fun name(): String @@ -77,6 +80,7 @@ interface TelemetryComponent { fun getCurrentSpanId(): String fun getCurrentTraceId(): String fun getCurrentBaggage(): Map + fun getTelemetryHandles(): List } interface TelemetryComponentId { @@ -121,6 +125,21 @@ class TelemetryServiceImpl : SingletonSerializeAsToken(), TelemetryService { private val telemetryComponents: MutableMap = mutableMapOf() + @CordaInternal + fun initialiseTelemetry() { + telemetryComponents.values.forEach { + it.onTelemetryEvent(InitialiseTelemetryEvent()) + } + } + + @CordaInternal + fun shutdownTelemetry() { + telemetryComponents.values.forEach { + it.onTelemetryEvent(ShutdownTelemetryEvent()) + } + telemetryComponents.clear() + } + @CordaInternal fun addTelemetryComponent(telemetryComponent: TelemetryComponent) { telemetryComponents[telemetryComponent.name()] = telemetryComponent @@ -223,11 +242,18 @@ class TelemetryServiceImpl : SingletonSerializeAsToken(), TelemetryService { it.setCurrentTelemetryId(telemetryIds.componentTelemetryIds[it.name()]!!) } } + + private fun getTelemetryHandles(): List { + return telemetryComponents.values.map { it.getTelemetryHandles() }.flatten() + } - override fun getOpenTelemetry(): OpenTelemetryHandle? { - return telemetryComponents[OpenTelemetryComponent.OPENTELEMETRY_COMPONENT_NAME]?.let { - null // (it as? OpenTelemetryComponent)?.tracerSetup?.openTelemetry + override fun getTelemetryHandle(telemetryClass: Class): T? { + getTelemetryHandles().forEach { + if (telemetryClass.isInstance(it)) + @Suppress("UNCHECKED_CAST") + return uncheckedCast(it as T) } + return null } } diff --git a/core/src/main/kotlin/net/corda/core/node/services/TelemetryService.kt b/core/src/main/kotlin/net/corda/core/node/services/TelemetryService.kt index 2b0e54df34..c7acdac425 100644 --- a/core/src/main/kotlin/net/corda/core/node/services/TelemetryService.kt +++ b/core/src/main/kotlin/net/corda/core/node/services/TelemetryService.kt @@ -1,9 +1,9 @@ package net.corda.core.node.services import net.corda.core.DoNotImplement -import net.corda.core.internal.telemetry.OpenTelemetryHandle + @DoNotImplement interface TelemetryService { - fun getOpenTelemetry(): OpenTelemetryHandle? + fun getTelemetryHandle(telemetryClass: Class): T? } \ No newline at end of file diff --git a/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt b/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt index ed3b2a8ec9..192a82ecad 100644 --- a/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt +++ b/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt @@ -263,6 +263,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration, if (configuration.telemetry.simpleLogTelemetryEnabled) { it.addTelemetryComponent(SimpleLogTelemetryComponent()) } + runOnStop += { it.shutdownTelemetry() } }.tokenize() val schemaService = NodeSchemaService(cordappLoader.cordappSchemas).tokenize() val identityService = PersistentIdentityService(cacheFactory).tokenize() diff --git a/node/src/test/kotlin/net/corda/node/internal/telemetry/TelemetryTests.kt b/node/src/test/kotlin/net/corda/node/internal/telemetry/TelemetryTests.kt index 862b7d7543..ff774bb628 100644 --- a/node/src/test/kotlin/net/corda/node/internal/telemetry/TelemetryTests.kt +++ b/node/src/test/kotlin/net/corda/node/internal/telemetry/TelemetryTests.kt @@ -289,6 +289,10 @@ class TelemetryTests { @Suppress("UNUSED_PARAMETER") fun recordException(telemetryId: UUID, throwable: Throwable) { } + + override fun getTelemetryHandles(): List { + return emptyList() + } } diff --git a/opentelemetry/build.gradle b/opentelemetry/build.gradle new file mode 100644 index 0000000000..57399a3c5f --- /dev/null +++ b/opentelemetry/build.gradle @@ -0,0 +1,31 @@ +import static org.gradle.api.JavaVersion.VERSION_1_8 + +plugins { + // Apply the org.jetbrains.kotlin.jvm Plugin to add support for Kotlin. + id 'org.jetbrains.kotlin.jvm' // version '1.6.21' + // Apply the java-library plugin for API and implementation separation. + id 'java-library' + //id 'com.github.johnrengelman.shadow' // version '7.1.2' + id 'net.corda.plugins.publish-utils' +} + +description 'OpenTelemetry SDK Bundle' + +// This driver is required by core, so must always be 1.8. See core build.gradle. +targetCompatibility = VERSION_1_8 + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" + implementation platform("io.opentelemetry:opentelemetry-bom:$open_telemetry_version") + implementation "io.opentelemetry:opentelemetry-sdk" + implementation "io.opentelemetry:opentelemetry-exporter-otlp" + implementation "io.opentelemetry:opentelemetry-semconv:$open_telemetry_sem_conv_version" + implementation ("com.squareup.okhttp3:okhttp:$okhttp_version") { + force = true + } +} + +publish { + name 'corda-opentelemetry' +} + diff --git a/opentelemetry-driver/build.gradle b/opentelemetry/opentelemetry-driver/build.gradle similarity index 58% rename from opentelemetry-driver/build.gradle rename to opentelemetry/opentelemetry-driver/build.gradle index 32b848f7ee..57802afed8 100644 --- a/opentelemetry-driver/build.gradle +++ b/opentelemetry/opentelemetry-driver/build.gradle @@ -15,19 +15,12 @@ description 'OpenTelemetry Driver' targetCompatibility = VERSION_1_8 dependencies { - // Use the Kotlin JDK 8 standard library. - implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:4.9.1' - implementation "io.opentelemetry:opentelemetry-api:$open_telemetry_version" - - implementation platform("io.opentelemetry:opentelemetry-bom:$open_telemetry_version") - implementation "io.opentelemetry:opentelemetry-sdk" - implementation 'io.opentelemetry:opentelemetry-exporter-otlp' - implementation "io.opentelemetry:opentelemetry-semconv:$open_telemetry_sem_conv_version" + implementation project(":opentelemetry") } shadowJar { - archiveClassifier = jdkClassifier - relocate 'kotlin', 'privatekotlin' + archiveClassifier = null + classifier = null exclude "**/Log4j2Plugins.dat" zip64 true } diff --git a/opentelemetry-driver/src/main/kotlin/net/corda/opentelemetrydriver/OpenTelemetryDriver.kt b/opentelemetry/src/main/kotlin/net/corda/opentelemetrydriver/OpenTelemetryDriver.kt similarity index 60% rename from opentelemetry-driver/src/main/kotlin/net/corda/opentelemetrydriver/OpenTelemetryDriver.kt rename to opentelemetry/src/main/kotlin/net/corda/opentelemetrydriver/OpenTelemetryDriver.kt index 7c52764a17..d1c568ce03 100644 --- a/opentelemetry-driver/src/main/kotlin/net/corda/opentelemetrydriver/OpenTelemetryDriver.kt +++ b/opentelemetry/src/main/kotlin/net/corda/opentelemetrydriver/OpenTelemetryDriver.kt @@ -14,36 +14,31 @@ import io.opentelemetry.sdk.trace.SdkTracerProvider import io.opentelemetry.sdk.trace.export.BatchSpanProcessor import io.opentelemetry.semconv.resource.attributes.ResourceAttributes -object OpenTelemetryDriver { - private fun buildAndGetOpenTelemetry(serviceName: String): OpenTelemetry { - val resource: Resource = Resource.getDefault() +class OpenTelemetryDriver(serviceName: String) { + + private val resource: Resource = Resource.getDefault() .merge(Resource.create(Attributes.of(ResourceAttributes.SERVICE_NAME, serviceName))) - val sdkTracerProvider: SdkTracerProvider = SdkTracerProvider.builder() - .addSpanProcessor(BatchSpanProcessor.builder(OtlpGrpcSpanExporter.builder().build()).build()) + private val sdkTracerProvider = SdkTracerProvider.builder() + .addSpanProcessor(BatchSpanProcessor.builder(OtlpGrpcSpanExporter.builder().build()).build()) .setResource(resource) .build() - val sdkMeterProvider: SdkMeterProvider = SdkMeterProvider.builder() + private val sdkMeterProvider = SdkMeterProvider.builder() .registerMetricReader(PeriodicMetricReader.builder(OtlpGrpcMetricExporter.builder().build()).build()) .setResource(resource) .build() - return OpenTelemetrySdk.builder() + val openTelemetry: OpenTelemetry = OpenTelemetrySdk.builder() .setTracerProvider(sdkTracerProvider) .setMeterProvider(sdkMeterProvider) .setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance())) - .buildAndRegisterGlobal() - } + .build() - @Volatile - private var OPENTELEMETRY_INSTANCE: OpenTelemetry? = null - - fun getOpenTelemetry(serviceName: String): OpenTelemetry { - return OPENTELEMETRY_INSTANCE ?: synchronized(this) { - OPENTELEMETRY_INSTANCE ?: buildAndGetOpenTelemetry(serviceName).also { - OPENTELEMETRY_INSTANCE = it - } - } + fun shutdown() { + sdkTracerProvider?.forceFlush() + sdkMeterProvider?.forceFlush() + sdkTracerProvider?.shutdown() + sdkMeterProvider?.shutdown() } } diff --git a/settings.gradle b/settings.gradle index e89f1ac33b..395b3a40b6 100644 --- a/settings.gradle +++ b/settings.gradle @@ -28,7 +28,8 @@ pluginManagement { // The project is named 'corda-project' and not 'corda' because if this is named the same as the // output JAR from the capsule then the buildCordaJAR task goes into an infinite loop. rootProject.name = 'corda-project' -include 'opentelemetry-driver' +include 'opentelemetry' +include 'opentelemetry:opentelemetry-driver' include 'confidential-identities' include 'finance:contracts' include 'finance:workflows'