Add @MeterTag support with @Timed

  1. Background
  2. What’s MeterTag
  3. Implementation
  4. Reference

Background

Micrometer add @MeterTag support on 2023, we are integrating micrometer with datadog in a spring boot project, this blog document how we set @MeterTag with @Timed

What’s MeterTag

  • With MeterTag annotation, we could add tags to @Timed with some dynamic value, e.g, sth parameters in the input. We could leverage on valueResolver, and use some expression language. For our case, Spel will be totally fine.

Implementation

Import related dependencies, in gradle kotlin, it would contains snippets as below

implementation("io.micrometer:micrometer-registry-statsd:1.11.4")
implementation("io.micrometer:micrometer-core:1.11.4")
implementation("io.micrometer:micrometer-commons:1.11.4")
implementation("org.springframework:spring-aspects")

In application class, enable the AspectJAutoProxy

@SpringBootApplication
@Import(HttpSecurityConfig::class)
@EnableScheduling
@EnableIntegrationManagement
@EnableAspectJAutoProxy(proxyTargetClass = true)
@Modulithic
class Application

fun main(args: Array<String>) {
    runApplication<Application>(args = args)
}

For the annotation you want to use, we need to define the corresponding aspect bean. As we want to enhance the @Timed with @MeterTag we need to set the meterTagAnnotationHandler

@Configuration
class MetricsConfig {
    @Bean
    fun timedAspect(meterRegistry: MeterRegistry): TimedAspect {
        val timedAspect = TimedAspect(meterRegistry)
        timedAspect.setMeterTagAnnotationHandler(
            MeterTagAnnotationHandler(
                { ValueResolver { p -> p.toString() } },
                { CachedSpelValueExpressionResolver() },
            ),
        )
        return timedAspect
    }
}

We mainly leverage on CachedSpelValueExpressionResolver to pass in an expression following spring expression language, the resolver is defined as follow

open class SpelValueExpressionResolver : ValueExpressionResolver {

    private val log = KotlinLogging.logger {}
    override fun resolve(expression: String, parameter: Any): String {
        try {
            val context = SimpleEvaluationContext.forReadOnlyDataBinding().withInstanceMethods().build()
            return parseExpression(expression).getValue(context, parameter, String::class.java) ?: ""
        } catch (ex: Exception) {
            log.error("Exception occurred while trying to evaluate the SpEL expression [$expression]", ex)
        }
        return parameter.toString()
    }

    open fun parseExpression(expression: String): Expression =
        SpelExpressionParser().parseExpression(expression)
}

class CachedSpelValueExpressionResolver : SpelValueExpressionResolver() {
    private val expressionsCache: MutableMap<String, Expression> = ConcurrentHashMap()
    override fun parseExpression(expression: String): Expression =
        expressionsCache.computeIfAbsent(expression) {
            super.parseExpression(expression)
        }
}

After that, we could add metrics as we need:

@DgsData(parentType = DgsConstants.QUERY.TYPE_NAME, field = DgsConstants.QUERY.HelloWorldPing)
@Timed
fun helloWorld(@MeterTag(key="message.size", expression="this.size")message: String): String = message

For local testing, as datadog send out metrics in UDP, we could write some script with a UDP socket server to print out the content

const dgram = require("dgram");

const port = process.argv[2] || 8125;
const socket = dgram.createSocket({ type: "udp4", reuseAddr: true });

socket.on("message", msg => console.log(msg.toString()));
socket.on("error", error => {
  console.log("error", error);
  socket.close();
});
socket.bind(port);

You should be able to see metrics printed out successfully with tags you want then!

Reference

https://github.com/micrometer-metrics/micrometer/pull/3727


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 stone2paul@gmail.com

文章标题:Add @MeterTag support with @Timed

文章字数:476

本文作者:Leilei Chen

发布时间:2023-09-23, 17:01:30

最后更新:2023-09-23, 17:10:57

原始链接:https://www.llchen60.com/Add-MeterTag-support-with-Timed/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录
×

喜欢就点赞,疼爱就打赏