All Downloads are FREE. Search and download functionalities are using the official Maven repository.

graphql.nadel.engine.instrumentation.NadelInstrumentationTimer.kt Maven / Gradle / Ivy

package graphql.nadel.engine.instrumentation

import graphql.execution.instrumentation.InstrumentationState
import graphql.nadel.instrumentation.NadelInstrumentation
import graphql.nadel.instrumentation.parameters.NadelInstrumentationTimingParameters
import graphql.nadel.instrumentation.parameters.NadelInstrumentationTimingParameters.Step
import java.time.Duration
import java.time.Instant

internal class NadelInstrumentationTimer(
    private val instrumentation: NadelInstrumentation,
    private val userContext: Any?,
    private val instrumentationState: InstrumentationState?,
) {
    inline fun  time(
        step: Step,
        function: () -> T,
    ): T {
        val start = Instant.now()
        val startNs = System.nanoTime()

        val result = try {
            function()
        } catch (e: Throwable) {
            try {
                emit(step, start = start, startNs = startNs, exception = e)
            } catch (e2: Throwable) {
                e2.addSuppressed(e)
                throw e2
            }

            throw e
        }

        emit(step, start, startNs = startNs)

        return result
    }

    fun batch(): BatchTimer {
        return BatchTimer(timer = this)
    }

    inline fun  batch(function: (BatchTimer) -> T): T {
        return BatchTimer(timer = this).use(function)
    }

    @Suppress("NOTHING_TO_INLINE") // inline anyway
    private inline fun emit(step: Step, start: Instant, startNs: Long, exception: Throwable? = null) {
        val endNs = System.nanoTime()
        val duration = Duration.ofNanos(endNs - startNs)

        instrumentation.onStepTimed(newParameters(step, start, duration, exception))
    }

    @Suppress("NOTHING_TO_INLINE") // inline anyway
    private inline fun emit(step: Step, duration: Duration, exception: Throwable? = null) {
        instrumentation.onStepTimed(newParameters(step, null, duration, exception))
    }

    private fun newParameters(
        step: Step,
        startedAt: Instant?,
        duration: Duration,
        exception: Throwable? = null,
    ): NadelInstrumentationTimingParameters {
        return NadelInstrumentationTimingParameters(
            step = step,
            startedAt = startedAt,
            duration = duration,
            exception = exception,
            context = userContext,
            instrumentationState = instrumentationState,
        )
    }

    class BatchTimer(
        private val timer: NadelInstrumentationTimer,
        private val timings: MutableMap = mutableMapOf(),
    ) {
        private var exception: Throwable? = null

        inline fun  time(step: Step, function: () -> T): T {
            val start = System.nanoTime()
            return try {
                function()
            } catch (e: Throwable) {
                exception = e
                throw e
            } finally {
                val end = System.nanoTime()
                timings[step] = (timings[step] ?: 0) + (end - start)
            }
        }

        fun submit() {
            timings.forEach { (step, durationNs) ->
                timer.emit(step, duration = Duration.ofNanos(durationNs), exception)
            }
        }

        inline fun  use(function: (timer: BatchTimer) -> T): T {
            try {
                return function(this)
            } finally {
                submit()
            }
        }

        override fun toString(): String {
            return "BatchTimer(timings=$timings)"
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy