From aab0dc8ee644c9b712f943b0dae25e2d9ba64269 Mon Sep 17 00:00:00 2001 From: AyushChaubey Date: Mon, 6 May 2024 20:34:32 +0200 Subject: [PATCH 1/4] replace byte buddy with java proxy --- .../build.gradle.kts | 1 - .../dataloader/BatchLoaderInterceptor.kt | 50 ++++--- .../BatchLoaderWithContextInterceptor.kt | 50 ++++--- .../DgsDataLoaderInstrumentationProvider.kt | 127 +++++++----------- .../MappedBatchLoaderInterceptor.kt | 51 ++++--- ...MappedBatchLoaderWithContextInterceptor.kt | 53 ++++---- 6 files changed, 171 insertions(+), 161 deletions(-) diff --git a/graphql-dgs-spring-boot-micrometer/build.gradle.kts b/graphql-dgs-spring-boot-micrometer/build.gradle.kts index d9e9f5840..7e81968f8 100644 --- a/graphql-dgs-spring-boot-micrometer/build.gradle.kts +++ b/graphql-dgs-spring-boot-micrometer/build.gradle.kts @@ -1,7 +1,6 @@ dependencies { api(project(":graphql-dgs")) - implementation("net.bytebuddy:byte-buddy") implementation("io.micrometer:micrometer-core") implementation("commons-codec:commons-codec") implementation("com.netflix.spectator:spectator-api:1.7.+") diff --git a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/BatchLoaderInterceptor.kt b/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/BatchLoaderInterceptor.kt index bd437b8aa..9cbe36b5d 100644 --- a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/BatchLoaderInterceptor.kt +++ b/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/BatchLoaderInterceptor.kt @@ -3,34 +3,46 @@ package com.netflix.graphql.dgs.metrics.micrometer.dataloader import com.netflix.graphql.dgs.metrics.DgsMetrics.GqlMetric import com.netflix.graphql.dgs.metrics.DgsMetrics.GqlTag import io.micrometer.core.instrument.MeterRegistry +import io.micrometer.core.instrument.Tag import io.micrometer.core.instrument.Timer -import net.bytebuddy.implementation.bind.annotation.Pipe import org.dataloader.BatchLoader import org.slf4j.LoggerFactory +import java.lang.reflect.InvocationHandler +import java.lang.reflect.Method import java.util.concurrent.CompletionStage internal class BatchLoaderInterceptor( - private val batchLoader: BatchLoader<*, *>, - private val name: String, - private val registry: MeterRegistry -) { + private val batchLoader: BatchLoader<*, *>, + private val name: String, + private val registry: MeterRegistry +) : InvocationHandler { - fun load(@Pipe pipe: Forwarder>, BatchLoader<*, *>>): CompletionStage> { - logger.debug("Starting metered timer[{}] for BatchLoader.", ID) - val timerSampler = Timer.start(registry) - return try { - pipe.to(batchLoader).whenComplete { result, _ -> - logger.debug("Finished timer[{}] for BatchLoader.", ID) - timerSampler.stop( - Timer.builder(ID) - .tags(GqlTag.LOADER_BATCH_SIZE.key, result.size.toString(), GqlTag.LOADER_NAME.key, name) - .register(registry) - ) + override fun invoke(proxy: Any, method: Method, args: Array): CompletionStage> { + if (method.name == "load") { + logger.debug("Starting metered timer[{}] for {}.", ID, javaClass.simpleName) + val timerSampler = Timer.start(registry) + return try { + @Suppress("UNCHECKED_CAST") + val future = method.invoke(batchLoader, *(args)) as CompletionStage> + future.whenComplete { result, _ -> + logger.debug("Stopping timer[{}] for {}", ID, javaClass.simpleName) + timerSampler.stop( + Timer.builder(ID) + .tags( + listOf( + Tag.of(GqlTag.LOADER_NAME.key, name), + Tag.of(GqlTag.LOADER_BATCH_SIZE.key, result.size.toString()) + ) + ).register(registry) + ) + } + } catch (exception: Exception) { + logger.warn("Error creating timer interceptor '{}' for {} with exception {}", ID, javaClass.simpleName, exception.message) + @Suppress("UNCHECKED_CAST") + method.invoke(batchLoader, *(args)) as CompletionStage> } - } catch (exception: Exception) { - logger.warn("Error creating timer interceptor '{}' for {} with exception {}", ID, javaClass.simpleName, exception.message) - pipe.to(batchLoader) } + throw UnsupportedOperationException("Unsupported method: ${method.name}") } companion object { diff --git a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/BatchLoaderWithContextInterceptor.kt b/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/BatchLoaderWithContextInterceptor.kt index 0c047f45c..9f97ee7cd 100644 --- a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/BatchLoaderWithContextInterceptor.kt +++ b/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/BatchLoaderWithContextInterceptor.kt @@ -3,34 +3,46 @@ package com.netflix.graphql.dgs.metrics.micrometer.dataloader import com.netflix.graphql.dgs.metrics.DgsMetrics.GqlMetric import com.netflix.graphql.dgs.metrics.DgsMetrics.GqlTag import io.micrometer.core.instrument.MeterRegistry +import io.micrometer.core.instrument.Tag import io.micrometer.core.instrument.Timer -import net.bytebuddy.implementation.bind.annotation.Pipe import org.dataloader.BatchLoaderWithContext import org.slf4j.LoggerFactory +import java.lang.reflect.InvocationHandler +import java.lang.reflect.Method import java.util.concurrent.CompletionStage internal class BatchLoaderWithContextInterceptor( - private val batchLoader: BatchLoaderWithContext<*, *>, - private val name: String, - private val registry: MeterRegistry -) { + private val batchLoaderWithContext: BatchLoaderWithContext<*, *>, + private val name: String, + private val registry: MeterRegistry +) : InvocationHandler { - fun load(@Pipe pipe: Forwarder>, BatchLoaderWithContext<*, *>>): CompletionStage> { - logger.debug("Starting metered timer[{}] for {}.", ID, javaClass.simpleName) - val timerSampler = Timer.start(registry) - return try { - pipe.to(batchLoader).whenComplete { result, _ -> - logger.debug("Stopping timer[{}] for {}", ID, javaClass.simpleName) - timerSampler.stop( - Timer.builder(ID) - .tags(GqlTag.LOADER_BATCH_SIZE.key, result.size.toString(), GqlTag.LOADER_NAME.key, name) - .register(registry) - ) + override fun invoke(proxy: Any, method: Method, args: Array): CompletionStage> { + if (method.name == "load") { + logger.debug("Starting metered timer[{}] for {}.", ID, javaClass.simpleName) + val timerSampler = Timer.start(registry) + return try { + @Suppress("UNCHECKED_CAST") + val future = method.invoke(batchLoaderWithContext, *(args)) as CompletionStage> + future.whenComplete { result, _ -> + logger.debug("Stopping timer[{}] for {}", ID, javaClass.simpleName) + timerSampler.stop( + Timer.builder(ID) + .tags( + listOf( + Tag.of(GqlTag.LOADER_NAME.key, name), + Tag.of(GqlTag.LOADER_BATCH_SIZE.key, result.size.toString()) + ) + ).register(registry) + ) + } + } catch (exception: Exception) { + logger.warn("Error creating timer interceptor '{}' for {} with exception {}", ID, javaClass.simpleName, exception.message) + @Suppress("UNCHECKED_CAST") + method.invoke(batchLoaderWithContext, *(args)) as CompletionStage> } - } catch (exception: Exception) { - logger.warn("Error creating timer interceptor '{}' for {} with exception {}", ID, javaClass.simpleName, exception.message) - pipe.to(batchLoader) } + throw UnsupportedOperationException("Unsupported method: ${method.name}") } companion object { diff --git a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/DgsDataLoaderInstrumentationProvider.kt b/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/DgsDataLoaderInstrumentationProvider.kt index b6e9e52be..21ef84033 100644 --- a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/DgsDataLoaderInstrumentationProvider.kt +++ b/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/DgsDataLoaderInstrumentationProvider.kt @@ -2,94 +2,61 @@ package com.netflix.graphql.dgs.metrics.micrometer.dataloader import com.netflix.graphql.dgs.DataLoaderInstrumentationExtensionProvider import com.netflix.graphql.dgs.metrics.micrometer.DgsMeterRegistrySupplier -import net.bytebuddy.ByteBuddy -import net.bytebuddy.implementation.MethodDelegation -import net.bytebuddy.implementation.bind.annotation.Pipe -import net.bytebuddy.matcher.ElementMatchers import org.dataloader.BatchLoader import org.dataloader.BatchLoaderWithContext import org.dataloader.MappedBatchLoader import org.dataloader.MappedBatchLoaderWithContext -import java.lang.reflect.Constructor +import java.lang.reflect.Proxy class DgsDataLoaderInstrumentationProvider( - private val meterRegistrySupplier: DgsMeterRegistrySupplier + private val meterRegistrySupplier: DgsMeterRegistrySupplier ) : DataLoaderInstrumentationExtensionProvider { - private val batchLoaderClasses = mutableMapOf>>() - private val batchLoaderWithContextClasses = mutableMapOf>>() - private val mappedBatchLoaderClasses = mutableMapOf>>() - private val mappedBatchLoaderWithContextClasses = mutableMapOf>>() - - override fun provide(original: BatchLoader<*, *>, name: String): BatchLoader<*, *> { - return batchLoaderClasses.getOrPut(name) { - val withBinders = - MethodDelegation - .withDefaultConfiguration() - .withBinders(Pipe.Binder.install(Forwarder::class.java)) - .to(BatchLoaderInterceptor(original, name, meterRegistrySupplier.get())) - ByteBuddy() - .subclass(BatchLoader::class.java) - .method(ElementMatchers.named("load")) - .intercept(withBinders) - .make() - .load(javaClass.classLoader) - .loaded - .getDeclaredConstructor() - }.newInstance() - } - - override fun provide(original: BatchLoaderWithContext<*, *>, name: String): BatchLoaderWithContext<*, *> { - return batchLoaderWithContextClasses.getOrPut(name) { - val withBinders = MethodDelegation.withDefaultConfiguration() - .withBinders(Pipe.Binder.install(Forwarder::class.java)) - .to(BatchLoaderWithContextInterceptor(original, name, meterRegistrySupplier.get())) - - ByteBuddy() - .subclass(BatchLoaderWithContext::class.java) - .method(ElementMatchers.named("load")) - .intercept(withBinders) - .make() - .load(javaClass.classLoader) - .loaded - .getDeclaredConstructor() - }.newInstance() - } - - override fun provide(original: MappedBatchLoader<*, *>, name: String): MappedBatchLoader<*, *> { - return mappedBatchLoaderClasses.getOrPut(name) { - val withBinders = MethodDelegation.withDefaultConfiguration() - .withBinders(Pipe.Binder.install(Forwarder::class.java)).to( - MappedBatchLoaderInterceptor(original, name, meterRegistrySupplier.get()) - ) - - ByteBuddy() - .subclass(MappedBatchLoader::class.java) - .method(ElementMatchers.named("load")) - .intercept(withBinders) - .make() - .load(javaClass.classLoader) - .loaded - .getDeclaredConstructor() - }.newInstance() - } + private val batchLoaderClasses = mutableMapOf>() + private val batchLoaderWithContextClasses = mutableMapOf>() + private val mappedBatchLoaderClasses = mutableMapOf>() + private val mappedBatchLoaderWithContextClasses = mutableMapOf>() + + override fun provide(original: BatchLoader<*, *>, name: String): BatchLoader<*, *> = + batchLoaderClasses.getOrPut(name) { + val handler = BatchLoaderInterceptor(original, name, meterRegistrySupplier.get()) + Proxy.newProxyInstance( + javaClass.classLoader, + arrayOf(BatchLoader::class.java), + handler + ) as BatchLoader<*, *> + } + + override fun provide(original: BatchLoaderWithContext<*, *>, name: String): BatchLoaderWithContext<*, *> = + batchLoaderWithContextClasses.getOrPut(name) { + val handler = BatchLoaderWithContextInterceptor(original, name, meterRegistrySupplier.get()) + Proxy.newProxyInstance( + javaClass.classLoader, + arrayOf(BatchLoaderWithContext::class.java), + handler + ) as BatchLoaderWithContext<*, *> + } + + override fun provide(original: MappedBatchLoader<*, *>, name: String): MappedBatchLoader<*, *> = + mappedBatchLoaderClasses.getOrPut(name) { + val handler = MappedBatchLoaderInterceptor(original, name, meterRegistrySupplier.get()) + Proxy.newProxyInstance( + javaClass.classLoader, + arrayOf(MappedBatchLoader::class.java), + handler + ) as MappedBatchLoader<*, *> + } override fun provide( - original: MappedBatchLoaderWithContext<*, *>, - name: String - ): MappedBatchLoaderWithContext<*, *> { - return mappedBatchLoaderWithContextClasses.getOrPut(name) { - val withBinders = MethodDelegation.withDefaultConfiguration() - .withBinders(Pipe.Binder.install(Forwarder::class.java)) - .to(MappedBatchLoaderWithContextInterceptor(original, name, meterRegistrySupplier.get())) - ByteBuddy() - .subclass(MappedBatchLoaderWithContext::class.java) - .method(ElementMatchers.named("load")) - .intercept(withBinders) - .make() - .load(javaClass.classLoader) - .loaded - .getDeclaredConstructor() - }.newInstance() - } + original: MappedBatchLoaderWithContext<*, *>, + name: String + ): MappedBatchLoaderWithContext<*, *> = + mappedBatchLoaderWithContextClasses.getOrPut(name) { + val handler = MappedBatchLoaderWithContextInterceptor(original, name, meterRegistrySupplier.get()) + Proxy.newProxyInstance( + javaClass.classLoader, + arrayOf(MappedBatchLoaderWithContext::class.java), + handler + ) as MappedBatchLoaderWithContext<*, *> + } } diff --git a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/MappedBatchLoaderInterceptor.kt b/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/MappedBatchLoaderInterceptor.kt index cac3d604b..80d2fbb61 100644 --- a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/MappedBatchLoaderInterceptor.kt +++ b/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/MappedBatchLoaderInterceptor.kt @@ -3,33 +3,46 @@ package com.netflix.graphql.dgs.metrics.micrometer.dataloader import com.netflix.graphql.dgs.metrics.DgsMetrics.GqlMetric import com.netflix.graphql.dgs.metrics.DgsMetrics.GqlTag import io.micrometer.core.instrument.MeterRegistry +import io.micrometer.core.instrument.Tag import io.micrometer.core.instrument.Timer -import net.bytebuddy.implementation.bind.annotation.Pipe import org.dataloader.MappedBatchLoader import org.slf4j.LoggerFactory +import java.lang.reflect.InvocationHandler +import java.lang.reflect.Method import java.util.concurrent.CompletionStage internal class MappedBatchLoaderInterceptor( - private val batchLoader: MappedBatchLoader<*, *>, - private val name: String, - private val registry: MeterRegistry -) { - fun load(@Pipe pipe: Forwarder>, MappedBatchLoader<*, *>>): CompletionStage> { - logger.debug("Starting metered timer[{}] for {}.", ID, javaClass.simpleName) - val timerSampler = Timer.start(registry) - return try { - pipe.to(batchLoader).whenComplete { result, _ -> - logger.debug("Stopping timer[{}] for {}", ID, javaClass.simpleName) - timerSampler.stop( - Timer.builder(ID) - .tags(GqlTag.LOADER_BATCH_SIZE.key, result.size.toString(), GqlTag.LOADER_NAME.key, name) - .register(registry) - ) + private val mappedBatchLoader: MappedBatchLoader<*, *>, + private val name: String, + private val registry: MeterRegistry +) : InvocationHandler { + + override fun invoke(proxy: Any, method: Method, args: Array): CompletionStage> { + if (method.name == "load") { + logger.debug("Starting metered timer[{}] for {}.", ID, javaClass.simpleName) + val timerSampler = Timer.start(registry) + return try { + @Suppress("UNCHECKED_CAST") + val future = method.invoke(mappedBatchLoader, *(args)) as CompletionStage> + future.whenComplete { result, _ -> + logger.debug("Stopping timer[{}] for {}", ID, javaClass.simpleName) + timerSampler.stop( + Timer.builder(ID) + .tags( + listOf( + Tag.of(GqlTag.LOADER_NAME.key, name), + Tag.of(GqlTag.LOADER_BATCH_SIZE.key, result.size.toString()) + ) + ).register(registry) + ) + } + } catch (exception: Exception) { + logger.warn("Error creating timer interceptor '{}' for {} with exception {}", ID, javaClass.simpleName, exception.message) + @Suppress("UNCHECKED_CAST") + method.invoke(mappedBatchLoader, *(args)) as CompletionStage> } - } catch (exception: Exception) { - logger.warn("Error creating timer interceptor '{}' for {} with exception {}", ID, javaClass.simpleName, exception.message) - pipe.to(batchLoader) } + throw UnsupportedOperationException("Unsupported method: ${method.name}") } companion object { diff --git a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/MappedBatchLoaderWithContextInterceptor.kt b/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/MappedBatchLoaderWithContextInterceptor.kt index 54ccbac36..09c968cdd 100644 --- a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/MappedBatchLoaderWithContextInterceptor.kt +++ b/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/MappedBatchLoaderWithContextInterceptor.kt @@ -5,37 +5,44 @@ import com.netflix.graphql.dgs.metrics.DgsMetrics.GqlTag import io.micrometer.core.instrument.MeterRegistry import io.micrometer.core.instrument.Tag import io.micrometer.core.instrument.Timer -import net.bytebuddy.implementation.bind.annotation.Pipe import org.dataloader.MappedBatchLoaderWithContext import org.slf4j.LoggerFactory +import java.lang.reflect.InvocationHandler +import java.lang.reflect.Method import java.util.concurrent.CompletionStage internal class MappedBatchLoaderWithContextInterceptor( - private val batchLoader: MappedBatchLoaderWithContext<*, *>, - private val name: String, - private val registry: MeterRegistry -) { + private val mappedBatchLoaderWithContext: MappedBatchLoaderWithContext<*, *>, + private val name: String, + private val registry: MeterRegistry +) : InvocationHandler { - fun load(@Pipe pipe: Forwarder>, MappedBatchLoaderWithContext<*, *>>): CompletionStage> { - logger.debug("Starting metered timer[{}] for {}.", ID, javaClass.simpleName) - val timerSampler = Timer.start(registry) - return try { - pipe.to(batchLoader).whenComplete { result, _ -> - logger.debug("Stopping timer[{}] for {}", ID, javaClass.simpleName) - timerSampler.stop( - Timer.builder(ID) - .tags( - listOf( - Tag.of(GqlTag.LOADER_NAME.key, name), - Tag.of(GqlTag.LOADER_BATCH_SIZE.key, result.size.toString()) - ) - ).register(registry) - ) + override fun invoke(proxy: Any, method: Method, args: Array): CompletionStage> { + if (method.name == "load") { + logger.debug("Starting metered timer[{}] for {}.", ID, javaClass.simpleName) + val timerSampler = Timer.start(registry) + return try { + @Suppress("UNCHECKED_CAST") + val futureObject = method.invoke(mappedBatchLoaderWithContext, *(args)) as CompletionStage> + futureObject.whenComplete { result, _ -> + logger.debug("Stopping timer[{}] for {}", ID, javaClass.simpleName) + timerSampler.stop( + Timer.builder(ID) + .tags( + listOf( + Tag.of(GqlTag.LOADER_NAME.key, name), + Tag.of(GqlTag.LOADER_BATCH_SIZE.key, result.size.toString()) + ) + ).register(registry) + ) + } + } catch (exception: Exception) { + logger.warn("Error creating timer interceptor '{}' for {} with exception {}", ID, javaClass.simpleName, exception.message) + @Suppress("UNCHECKED_CAST") + method.invoke(mappedBatchLoaderWithContext, *(args)) as CompletionStage> } - } catch (exception: Exception) { - logger.warn("Error creating timer interceptor '{}' for {} with exception {}", ID, javaClass.simpleName, exception.message) - pipe.to(batchLoader) } + throw UnsupportedOperationException("Unsupported method: ${method.name}") } companion object { From 7591f098a128e16322578801fa78d41b337534a1 Mon Sep 17 00:00:00 2001 From: AyushChaubey Date: Mon, 6 May 2024 20:38:25 +0200 Subject: [PATCH 2/4] formatting --- .../dataloader/BatchLoaderInterceptor.kt | 20 +++--- .../BatchLoaderWithContextInterceptor.kt | 20 +++--- .../DgsDataLoaderInstrumentationProvider.kt | 70 +++++++++---------- .../MappedBatchLoaderInterceptor.kt | 20 +++--- ...MappedBatchLoaderWithContextInterceptor.kt | 20 +++--- 5 files changed, 75 insertions(+), 75 deletions(-) diff --git a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/BatchLoaderInterceptor.kt b/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/BatchLoaderInterceptor.kt index 9cbe36b5d..ab361dcd7 100644 --- a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/BatchLoaderInterceptor.kt +++ b/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/BatchLoaderInterceptor.kt @@ -12,9 +12,9 @@ import java.lang.reflect.Method import java.util.concurrent.CompletionStage internal class BatchLoaderInterceptor( - private val batchLoader: BatchLoader<*, *>, - private val name: String, - private val registry: MeterRegistry + private val batchLoader: BatchLoader<*, *>, + private val name: String, + private val registry: MeterRegistry ) : InvocationHandler { override fun invoke(proxy: Any, method: Method, args: Array): CompletionStage> { @@ -27,13 +27,13 @@ internal class BatchLoaderInterceptor( future.whenComplete { result, _ -> logger.debug("Stopping timer[{}] for {}", ID, javaClass.simpleName) timerSampler.stop( - Timer.builder(ID) - .tags( - listOf( - Tag.of(GqlTag.LOADER_NAME.key, name), - Tag.of(GqlTag.LOADER_BATCH_SIZE.key, result.size.toString()) - ) - ).register(registry) + Timer.builder(ID) + .tags( + listOf( + Tag.of(GqlTag.LOADER_NAME.key, name), + Tag.of(GqlTag.LOADER_BATCH_SIZE.key, result.size.toString()) + ) + ).register(registry) ) } } catch (exception: Exception) { diff --git a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/BatchLoaderWithContextInterceptor.kt b/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/BatchLoaderWithContextInterceptor.kt index 9f97ee7cd..f266e9746 100644 --- a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/BatchLoaderWithContextInterceptor.kt +++ b/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/BatchLoaderWithContextInterceptor.kt @@ -12,9 +12,9 @@ import java.lang.reflect.Method import java.util.concurrent.CompletionStage internal class BatchLoaderWithContextInterceptor( - private val batchLoaderWithContext: BatchLoaderWithContext<*, *>, - private val name: String, - private val registry: MeterRegistry + private val batchLoaderWithContext: BatchLoaderWithContext<*, *>, + private val name: String, + private val registry: MeterRegistry ) : InvocationHandler { override fun invoke(proxy: Any, method: Method, args: Array): CompletionStage> { @@ -27,13 +27,13 @@ internal class BatchLoaderWithContextInterceptor( future.whenComplete { result, _ -> logger.debug("Stopping timer[{}] for {}", ID, javaClass.simpleName) timerSampler.stop( - Timer.builder(ID) - .tags( - listOf( - Tag.of(GqlTag.LOADER_NAME.key, name), - Tag.of(GqlTag.LOADER_BATCH_SIZE.key, result.size.toString()) - ) - ).register(registry) + Timer.builder(ID) + .tags( + listOf( + Tag.of(GqlTag.LOADER_NAME.key, name), + Tag.of(GqlTag.LOADER_BATCH_SIZE.key, result.size.toString()) + ) + ).register(registry) ) } } catch (exception: Exception) { diff --git a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/DgsDataLoaderInstrumentationProvider.kt b/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/DgsDataLoaderInstrumentationProvider.kt index 21ef84033..228102653 100644 --- a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/DgsDataLoaderInstrumentationProvider.kt +++ b/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/DgsDataLoaderInstrumentationProvider.kt @@ -9,7 +9,7 @@ import org.dataloader.MappedBatchLoaderWithContext import java.lang.reflect.Proxy class DgsDataLoaderInstrumentationProvider( - private val meterRegistrySupplier: DgsMeterRegistrySupplier + private val meterRegistrySupplier: DgsMeterRegistrySupplier ) : DataLoaderInstrumentationExtensionProvider { private val batchLoaderClasses = mutableMapOf>() @@ -18,45 +18,45 @@ class DgsDataLoaderInstrumentationProvider( private val mappedBatchLoaderWithContextClasses = mutableMapOf>() override fun provide(original: BatchLoader<*, *>, name: String): BatchLoader<*, *> = - batchLoaderClasses.getOrPut(name) { - val handler = BatchLoaderInterceptor(original, name, meterRegistrySupplier.get()) - Proxy.newProxyInstance( - javaClass.classLoader, - arrayOf(BatchLoader::class.java), - handler - ) as BatchLoader<*, *> - } + batchLoaderClasses.getOrPut(name) { + val handler = BatchLoaderInterceptor(original, name, meterRegistrySupplier.get()) + Proxy.newProxyInstance( + javaClass.classLoader, + arrayOf(BatchLoader::class.java), + handler + ) as BatchLoader<*, *> + } override fun provide(original: BatchLoaderWithContext<*, *>, name: String): BatchLoaderWithContext<*, *> = - batchLoaderWithContextClasses.getOrPut(name) { - val handler = BatchLoaderWithContextInterceptor(original, name, meterRegistrySupplier.get()) - Proxy.newProxyInstance( - javaClass.classLoader, - arrayOf(BatchLoaderWithContext::class.java), - handler - ) as BatchLoaderWithContext<*, *> - } + batchLoaderWithContextClasses.getOrPut(name) { + val handler = BatchLoaderWithContextInterceptor(original, name, meterRegistrySupplier.get()) + Proxy.newProxyInstance( + javaClass.classLoader, + arrayOf(BatchLoaderWithContext::class.java), + handler + ) as BatchLoaderWithContext<*, *> + } override fun provide(original: MappedBatchLoader<*, *>, name: String): MappedBatchLoader<*, *> = - mappedBatchLoaderClasses.getOrPut(name) { - val handler = MappedBatchLoaderInterceptor(original, name, meterRegistrySupplier.get()) - Proxy.newProxyInstance( - javaClass.classLoader, - arrayOf(MappedBatchLoader::class.java), - handler - ) as MappedBatchLoader<*, *> - } + mappedBatchLoaderClasses.getOrPut(name) { + val handler = MappedBatchLoaderInterceptor(original, name, meterRegistrySupplier.get()) + Proxy.newProxyInstance( + javaClass.classLoader, + arrayOf(MappedBatchLoader::class.java), + handler + ) as MappedBatchLoader<*, *> + } override fun provide( - original: MappedBatchLoaderWithContext<*, *>, - name: String + original: MappedBatchLoaderWithContext<*, *>, + name: String ): MappedBatchLoaderWithContext<*, *> = - mappedBatchLoaderWithContextClasses.getOrPut(name) { - val handler = MappedBatchLoaderWithContextInterceptor(original, name, meterRegistrySupplier.get()) - Proxy.newProxyInstance( - javaClass.classLoader, - arrayOf(MappedBatchLoaderWithContext::class.java), - handler - ) as MappedBatchLoaderWithContext<*, *> - } + mappedBatchLoaderWithContextClasses.getOrPut(name) { + val handler = MappedBatchLoaderWithContextInterceptor(original, name, meterRegistrySupplier.get()) + Proxy.newProxyInstance( + javaClass.classLoader, + arrayOf(MappedBatchLoaderWithContext::class.java), + handler + ) as MappedBatchLoaderWithContext<*, *> + } } diff --git a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/MappedBatchLoaderInterceptor.kt b/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/MappedBatchLoaderInterceptor.kt index 80d2fbb61..a29f6f237 100644 --- a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/MappedBatchLoaderInterceptor.kt +++ b/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/MappedBatchLoaderInterceptor.kt @@ -12,9 +12,9 @@ import java.lang.reflect.Method import java.util.concurrent.CompletionStage internal class MappedBatchLoaderInterceptor( - private val mappedBatchLoader: MappedBatchLoader<*, *>, - private val name: String, - private val registry: MeterRegistry + private val mappedBatchLoader: MappedBatchLoader<*, *>, + private val name: String, + private val registry: MeterRegistry ) : InvocationHandler { override fun invoke(proxy: Any, method: Method, args: Array): CompletionStage> { @@ -27,13 +27,13 @@ internal class MappedBatchLoaderInterceptor( future.whenComplete { result, _ -> logger.debug("Stopping timer[{}] for {}", ID, javaClass.simpleName) timerSampler.stop( - Timer.builder(ID) - .tags( - listOf( - Tag.of(GqlTag.LOADER_NAME.key, name), - Tag.of(GqlTag.LOADER_BATCH_SIZE.key, result.size.toString()) - ) - ).register(registry) + Timer.builder(ID) + .tags( + listOf( + Tag.of(GqlTag.LOADER_NAME.key, name), + Tag.of(GqlTag.LOADER_BATCH_SIZE.key, result.size.toString()) + ) + ).register(registry) ) } } catch (exception: Exception) { diff --git a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/MappedBatchLoaderWithContextInterceptor.kt b/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/MappedBatchLoaderWithContextInterceptor.kt index 09c968cdd..7856e0fb2 100644 --- a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/MappedBatchLoaderWithContextInterceptor.kt +++ b/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/MappedBatchLoaderWithContextInterceptor.kt @@ -12,9 +12,9 @@ import java.lang.reflect.Method import java.util.concurrent.CompletionStage internal class MappedBatchLoaderWithContextInterceptor( - private val mappedBatchLoaderWithContext: MappedBatchLoaderWithContext<*, *>, - private val name: String, - private val registry: MeterRegistry + private val mappedBatchLoaderWithContext: MappedBatchLoaderWithContext<*, *>, + private val name: String, + private val registry: MeterRegistry ) : InvocationHandler { override fun invoke(proxy: Any, method: Method, args: Array): CompletionStage> { @@ -27,13 +27,13 @@ internal class MappedBatchLoaderWithContextInterceptor( futureObject.whenComplete { result, _ -> logger.debug("Stopping timer[{}] for {}", ID, javaClass.simpleName) timerSampler.stop( - Timer.builder(ID) - .tags( - listOf( - Tag.of(GqlTag.LOADER_NAME.key, name), - Tag.of(GqlTag.LOADER_BATCH_SIZE.key, result.size.toString()) - ) - ).register(registry) + Timer.builder(ID) + .tags( + listOf( + Tag.of(GqlTag.LOADER_NAME.key, name), + Tag.of(GqlTag.LOADER_BATCH_SIZE.key, result.size.toString()) + ) + ).register(registry) ) } } catch (exception: Exception) { From e27dc55b54e90564aac9cb7470a8cfe8d7f3100a Mon Sep 17 00:00:00 2001 From: pbakker Date: Fri, 17 May 2024 13:40:04 -0700 Subject: [PATCH 3/4] Removed some now unneeded duplication of dataloader proxy handlers --- .../dataloader/BatchLoaderInterceptor.kt | 52 ------------------- .../BatchLoaderWithContextInterceptor.kt | 19 ++++--- .../DgsDataLoaderInstrumentationProvider.kt | 6 +-- .../micrometer/dataloader/Forwarder.kt | 5 -- .../MappedBatchLoaderInterceptor.kt | 52 ------------------- ...MappedBatchLoaderWithContextInterceptor.kt | 52 ------------------- 6 files changed, 16 insertions(+), 170 deletions(-) delete mode 100644 graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/BatchLoaderInterceptor.kt delete mode 100644 graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/Forwarder.kt delete mode 100644 graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/MappedBatchLoaderInterceptor.kt delete mode 100644 graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/MappedBatchLoaderWithContextInterceptor.kt diff --git a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/BatchLoaderInterceptor.kt b/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/BatchLoaderInterceptor.kt deleted file mode 100644 index ab361dcd7..000000000 --- a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/BatchLoaderInterceptor.kt +++ /dev/null @@ -1,52 +0,0 @@ -package com.netflix.graphql.dgs.metrics.micrometer.dataloader - -import com.netflix.graphql.dgs.metrics.DgsMetrics.GqlMetric -import com.netflix.graphql.dgs.metrics.DgsMetrics.GqlTag -import io.micrometer.core.instrument.MeterRegistry -import io.micrometer.core.instrument.Tag -import io.micrometer.core.instrument.Timer -import org.dataloader.BatchLoader -import org.slf4j.LoggerFactory -import java.lang.reflect.InvocationHandler -import java.lang.reflect.Method -import java.util.concurrent.CompletionStage - -internal class BatchLoaderInterceptor( - private val batchLoader: BatchLoader<*, *>, - private val name: String, - private val registry: MeterRegistry -) : InvocationHandler { - - override fun invoke(proxy: Any, method: Method, args: Array): CompletionStage> { - if (method.name == "load") { - logger.debug("Starting metered timer[{}] for {}.", ID, javaClass.simpleName) - val timerSampler = Timer.start(registry) - return try { - @Suppress("UNCHECKED_CAST") - val future = method.invoke(batchLoader, *(args)) as CompletionStage> - future.whenComplete { result, _ -> - logger.debug("Stopping timer[{}] for {}", ID, javaClass.simpleName) - timerSampler.stop( - Timer.builder(ID) - .tags( - listOf( - Tag.of(GqlTag.LOADER_NAME.key, name), - Tag.of(GqlTag.LOADER_BATCH_SIZE.key, result.size.toString()) - ) - ).register(registry) - ) - } - } catch (exception: Exception) { - logger.warn("Error creating timer interceptor '{}' for {} with exception {}", ID, javaClass.simpleName, exception.message) - @Suppress("UNCHECKED_CAST") - method.invoke(batchLoader, *(args)) as CompletionStage> - } - } - throw UnsupportedOperationException("Unsupported method: ${method.name}") - } - - companion object { - private val ID = GqlMetric.DATA_LOADER.key - private val logger = LoggerFactory.getLogger(BatchLoaderInterceptor::class.java) - } -} diff --git a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/BatchLoaderWithContextInterceptor.kt b/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/BatchLoaderWithContextInterceptor.kt index f266e9746..3a583b5a8 100644 --- a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/BatchLoaderWithContextInterceptor.kt +++ b/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/BatchLoaderWithContextInterceptor.kt @@ -5,33 +5,40 @@ import com.netflix.graphql.dgs.metrics.DgsMetrics.GqlTag import io.micrometer.core.instrument.MeterRegistry import io.micrometer.core.instrument.Tag import io.micrometer.core.instrument.Timer -import org.dataloader.BatchLoaderWithContext import org.slf4j.LoggerFactory import java.lang.reflect.InvocationHandler import java.lang.reflect.Method import java.util.concurrent.CompletionStage internal class BatchLoaderWithContextInterceptor( - private val batchLoaderWithContext: BatchLoaderWithContext<*, *>, + private val batchLoaderWithContext: Any, private val name: String, private val registry: MeterRegistry ) : InvocationHandler { - override fun invoke(proxy: Any, method: Method, args: Array): CompletionStage> { + override fun invoke(proxy: Any, method: Method, args: Array): CompletionStage<*> { if (method.name == "load") { logger.debug("Starting metered timer[{}] for {}.", ID, javaClass.simpleName) val timerSampler = Timer.start(registry) return try { - @Suppress("UNCHECKED_CAST") - val future = method.invoke(batchLoaderWithContext, *(args)) as CompletionStage> + val future = method.invoke(batchLoaderWithContext, *(args)) as CompletionStage<*> future.whenComplete { result, _ -> logger.debug("Stopping timer[{}] for {}", ID, javaClass.simpleName) + + val resultSize = if (result is List<*>) { + result.size + } else if (result is Map<*, *>) { + result.size + } else { + throw IllegalStateException("BatchLoader or MappedBatchLoader should always return a List/Map. A ${result.javaClass.name} was found.") + } + timerSampler.stop( Timer.builder(ID) .tags( listOf( Tag.of(GqlTag.LOADER_NAME.key, name), - Tag.of(GqlTag.LOADER_BATCH_SIZE.key, result.size.toString()) + Tag.of(GqlTag.LOADER_BATCH_SIZE.key, resultSize.toString()) ) ).register(registry) ) diff --git a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/DgsDataLoaderInstrumentationProvider.kt b/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/DgsDataLoaderInstrumentationProvider.kt index 228102653..c48fd90de 100644 --- a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/DgsDataLoaderInstrumentationProvider.kt +++ b/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/DgsDataLoaderInstrumentationProvider.kt @@ -19,7 +19,7 @@ class DgsDataLoaderInstrumentationProvider( override fun provide(original: BatchLoader<*, *>, name: String): BatchLoader<*, *> = batchLoaderClasses.getOrPut(name) { - val handler = BatchLoaderInterceptor(original, name, meterRegistrySupplier.get()) + val handler = BatchLoaderWithContextInterceptor(original, name, meterRegistrySupplier.get()) Proxy.newProxyInstance( javaClass.classLoader, arrayOf(BatchLoader::class.java), @@ -39,7 +39,7 @@ class DgsDataLoaderInstrumentationProvider( override fun provide(original: MappedBatchLoader<*, *>, name: String): MappedBatchLoader<*, *> = mappedBatchLoaderClasses.getOrPut(name) { - val handler = MappedBatchLoaderInterceptor(original, name, meterRegistrySupplier.get()) + val handler = BatchLoaderWithContextInterceptor(original, name, meterRegistrySupplier.get()) Proxy.newProxyInstance( javaClass.classLoader, arrayOf(MappedBatchLoader::class.java), @@ -52,7 +52,7 @@ class DgsDataLoaderInstrumentationProvider( name: String ): MappedBatchLoaderWithContext<*, *> = mappedBatchLoaderWithContextClasses.getOrPut(name) { - val handler = MappedBatchLoaderWithContextInterceptor(original, name, meterRegistrySupplier.get()) + val handler = BatchLoaderWithContextInterceptor(original, name, meterRegistrySupplier.get()) Proxy.newProxyInstance( javaClass.classLoader, arrayOf(MappedBatchLoaderWithContext::class.java), diff --git a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/Forwarder.kt b/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/Forwarder.kt deleted file mode 100644 index 80193ecd9..000000000 --- a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/Forwarder.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.netflix.graphql.dgs.metrics.micrometer.dataloader - -internal interface Forwarder { - fun to(target: S): T -} diff --git a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/MappedBatchLoaderInterceptor.kt b/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/MappedBatchLoaderInterceptor.kt deleted file mode 100644 index a29f6f237..000000000 --- a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/MappedBatchLoaderInterceptor.kt +++ /dev/null @@ -1,52 +0,0 @@ -package com.netflix.graphql.dgs.metrics.micrometer.dataloader - -import com.netflix.graphql.dgs.metrics.DgsMetrics.GqlMetric -import com.netflix.graphql.dgs.metrics.DgsMetrics.GqlTag -import io.micrometer.core.instrument.MeterRegistry -import io.micrometer.core.instrument.Tag -import io.micrometer.core.instrument.Timer -import org.dataloader.MappedBatchLoader -import org.slf4j.LoggerFactory -import java.lang.reflect.InvocationHandler -import java.lang.reflect.Method -import java.util.concurrent.CompletionStage - -internal class MappedBatchLoaderInterceptor( - private val mappedBatchLoader: MappedBatchLoader<*, *>, - private val name: String, - private val registry: MeterRegistry -) : InvocationHandler { - - override fun invoke(proxy: Any, method: Method, args: Array): CompletionStage> { - if (method.name == "load") { - logger.debug("Starting metered timer[{}] for {}.", ID, javaClass.simpleName) - val timerSampler = Timer.start(registry) - return try { - @Suppress("UNCHECKED_CAST") - val future = method.invoke(mappedBatchLoader, *(args)) as CompletionStage> - future.whenComplete { result, _ -> - logger.debug("Stopping timer[{}] for {}", ID, javaClass.simpleName) - timerSampler.stop( - Timer.builder(ID) - .tags( - listOf( - Tag.of(GqlTag.LOADER_NAME.key, name), - Tag.of(GqlTag.LOADER_BATCH_SIZE.key, result.size.toString()) - ) - ).register(registry) - ) - } - } catch (exception: Exception) { - logger.warn("Error creating timer interceptor '{}' for {} with exception {}", ID, javaClass.simpleName, exception.message) - @Suppress("UNCHECKED_CAST") - method.invoke(mappedBatchLoader, *(args)) as CompletionStage> - } - } - throw UnsupportedOperationException("Unsupported method: ${method.name}") - } - - companion object { - private val ID = GqlMetric.DATA_LOADER.key - private val logger = LoggerFactory.getLogger(MappedBatchLoaderInterceptor::class.java) - } -} diff --git a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/MappedBatchLoaderWithContextInterceptor.kt b/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/MappedBatchLoaderWithContextInterceptor.kt deleted file mode 100644 index 7856e0fb2..000000000 --- a/graphql-dgs-spring-boot-micrometer/src/main/kotlin/com/netflix/graphql/dgs/metrics/micrometer/dataloader/MappedBatchLoaderWithContextInterceptor.kt +++ /dev/null @@ -1,52 +0,0 @@ -package com.netflix.graphql.dgs.metrics.micrometer.dataloader - -import com.netflix.graphql.dgs.metrics.DgsMetrics.GqlMetric -import com.netflix.graphql.dgs.metrics.DgsMetrics.GqlTag -import io.micrometer.core.instrument.MeterRegistry -import io.micrometer.core.instrument.Tag -import io.micrometer.core.instrument.Timer -import org.dataloader.MappedBatchLoaderWithContext -import org.slf4j.LoggerFactory -import java.lang.reflect.InvocationHandler -import java.lang.reflect.Method -import java.util.concurrent.CompletionStage - -internal class MappedBatchLoaderWithContextInterceptor( - private val mappedBatchLoaderWithContext: MappedBatchLoaderWithContext<*, *>, - private val name: String, - private val registry: MeterRegistry -) : InvocationHandler { - - override fun invoke(proxy: Any, method: Method, args: Array): CompletionStage> { - if (method.name == "load") { - logger.debug("Starting metered timer[{}] for {}.", ID, javaClass.simpleName) - val timerSampler = Timer.start(registry) - return try { - @Suppress("UNCHECKED_CAST") - val futureObject = method.invoke(mappedBatchLoaderWithContext, *(args)) as CompletionStage> - futureObject.whenComplete { result, _ -> - logger.debug("Stopping timer[{}] for {}", ID, javaClass.simpleName) - timerSampler.stop( - Timer.builder(ID) - .tags( - listOf( - Tag.of(GqlTag.LOADER_NAME.key, name), - Tag.of(GqlTag.LOADER_BATCH_SIZE.key, result.size.toString()) - ) - ).register(registry) - ) - } - } catch (exception: Exception) { - logger.warn("Error creating timer interceptor '{}' for {} with exception {}", ID, javaClass.simpleName, exception.message) - @Suppress("UNCHECKED_CAST") - method.invoke(mappedBatchLoaderWithContext, *(args)) as CompletionStage> - } - } - throw UnsupportedOperationException("Unsupported method: ${method.name}") - } - - companion object { - private val ID = GqlMetric.DATA_LOADER.key - private val logger = LoggerFactory.getLogger(MappedBatchLoaderWithContextInterceptor::class.java) - } -} From 2baa6de5589bd67dce4be90818f0132ab03c9830 Mon Sep 17 00:00:00 2001 From: pbakker Date: Thu, 23 May 2024 20:48:36 -0700 Subject: [PATCH 4/4] Dependency lock --- graphql-dgs-example-java/dependencies.lock | 8 -------- graphql-dgs-spring-boot-micrometer/dependencies.lock | 12 ------------ .../dependencies.lock | 8 -------- .../dependencies.lock | 8 -------- 4 files changed, 36 deletions(-) diff --git a/graphql-dgs-example-java/dependencies.lock b/graphql-dgs-example-java/dependencies.lock index 17fc5399f..bbec550d2 100644 --- a/graphql-dgs-example-java/dependencies.lock +++ b/graphql-dgs-example-java/dependencies.lock @@ -2287,7 +2287,6 @@ "net.bytebuddy:byte-buddy": { "locked": "1.14.13", "transitive": [ - "com.netflix.graphql.dgs:graphql-dgs-spring-boot-micrometer", "io.mockk:mockk-agent-jvm", "org.assertj:assertj-core", "org.mockito:mockito-core" @@ -3603,12 +3602,6 @@ "com.netflix.graphql.dgs:graphql-dgs-spring-webmvc-autoconfigure" ] }, - "net.bytebuddy:byte-buddy": { - "locked": "1.14.13", - "transitive": [ - "com.netflix.graphql.dgs:graphql-dgs-spring-boot-micrometer" - ] - }, "net.datafaker:datafaker": { "locked": "2.2.2", "transitive": [ @@ -6516,7 +6509,6 @@ "net.bytebuddy:byte-buddy": { "locked": "1.14.13", "transitive": [ - "com.netflix.graphql.dgs:graphql-dgs-spring-boot-micrometer", "io.mockk:mockk-agent-jvm", "org.assertj:assertj-core", "org.mockito:mockito-core" diff --git a/graphql-dgs-spring-boot-micrometer/dependencies.lock b/graphql-dgs-spring-boot-micrometer/dependencies.lock index 9c32a7f87..b7f96fda1 100644 --- a/graphql-dgs-spring-boot-micrometer/dependencies.lock +++ b/graphql-dgs-spring-boot-micrometer/dependencies.lock @@ -247,9 +247,6 @@ "org.springframework.boot:spring-boot-starter-tomcat" ] }, - "net.bytebuddy:byte-buddy": { - "locked": "1.14.13" - }, "org.apache.logging.log4j:log4j-api": { "locked": "2.21.1", "transitive": [ @@ -946,9 +943,6 @@ "org.springframework:spring-context" ] }, - "net.bytebuddy:byte-buddy": { - "locked": "1.14.13" - }, "org.checkerframework:checker-qual": { "locked": "3.37.0", "transitive": [ @@ -1303,9 +1297,6 @@ "org.springframework.boot:spring-boot-starter-tomcat" ] }, - "net.bytebuddy:byte-buddy": { - "locked": "1.14.13" - }, "net.sf.jopt-simple:jopt-simple": { "locked": "5.0.4", "transitive": [ @@ -3051,9 +3042,6 @@ "org.jetbrains.kotlinx:kotlinx-coroutines-reactor" ] }, - "net.bytebuddy:byte-buddy": { - "locked": "1.14.13" - }, "net.datafaker:datafaker": { "locked": "2.2.2", "transitive": [ diff --git a/graphql-dgs-spring-graphql-example-java-webflux/dependencies.lock b/graphql-dgs-spring-graphql-example-java-webflux/dependencies.lock index 53c026b6f..cadb1e6ac 100644 --- a/graphql-dgs-spring-graphql-example-java-webflux/dependencies.lock +++ b/graphql-dgs-spring-graphql-example-java-webflux/dependencies.lock @@ -2741,7 +2741,6 @@ "net.bytebuddy:byte-buddy": { "locked": "1.14.13", "transitive": [ - "com.netflix.graphql.dgs:graphql-dgs-spring-boot-micrometer", "io.mockk:mockk-agent-jvm", "org.assertj:assertj-core", "org.mockito:mockito-core" @@ -4174,12 +4173,6 @@ "name.nkonev.multipart-spring-graphql:multipart-spring-graphql": { "locked": "1.2.2" }, - "net.bytebuddy:byte-buddy": { - "locked": "1.14.13", - "transitive": [ - "com.netflix.graphql.dgs:graphql-dgs-spring-boot-micrometer" - ] - }, "net.datafaker:datafaker": { "locked": "2.2.2", "transitive": [ @@ -6973,7 +6966,6 @@ "net.bytebuddy:byte-buddy": { "locked": "1.14.13", "transitive": [ - "com.netflix.graphql.dgs:graphql-dgs-spring-boot-micrometer", "io.mockk:mockk-agent-jvm", "org.assertj:assertj-core", "org.mockito:mockito-core" diff --git a/graphql-dgs-spring-graphql-example-java/dependencies.lock b/graphql-dgs-spring-graphql-example-java/dependencies.lock index 57aceb1fc..1e6f1da24 100644 --- a/graphql-dgs-spring-graphql-example-java/dependencies.lock +++ b/graphql-dgs-spring-graphql-example-java/dependencies.lock @@ -2882,7 +2882,6 @@ "net.bytebuddy:byte-buddy": { "locked": "1.14.13", "transitive": [ - "com.netflix.graphql.dgs:graphql-dgs-spring-boot-micrometer", "io.mockk:mockk-agent-jvm", "org.assertj:assertj-core", "org.mockito:mockito-core" @@ -4396,12 +4395,6 @@ "name.nkonev.multipart-spring-graphql:multipart-spring-graphql": { "locked": "1.2.2" }, - "net.bytebuddy:byte-buddy": { - "locked": "1.14.13", - "transitive": [ - "com.netflix.graphql.dgs:graphql-dgs-spring-boot-micrometer" - ] - }, "net.datafaker:datafaker": { "locked": "2.2.2", "transitive": [ @@ -7454,7 +7447,6 @@ "net.bytebuddy:byte-buddy": { "locked": "1.14.13", "transitive": [ - "com.netflix.graphql.dgs:graphql-dgs-spring-boot-micrometer", "io.mockk:mockk-agent-jvm", "org.assertj:assertj-core", "org.mockito:mockito-core"