pixel
pixel

Reputation: 26473

How to aggregate metrics across URIs in webclient?

I have a WebClient that makes calls to the backend:

https://example.com/foo?q=1 https://example.com/foo?q=2 https://example.com/foo?q=3

I want to collect metrics across endpoints. Currently, every uri is collected separately.

Is there is a way to configure MetricsWebClientFilterFunction to achieve that?

Upvotes: 2

Views: 1492

Answers (2)

pixel
pixel

Reputation: 26473

@checketts suggested using uri templates and this is ihmo way simpler solution.

So in WebClient instead of using:

.uri { uri -> uri.path("foo").queryParam("q", "1").build() }

I used:

 .uri("foo?q={id}", "1")

Underneath the latter WebClient sets attribute:

attribute(URI_TEMPLATE_ATTRIBUTE, uriTemplate);

which is later used in WebClientExchangeTags:

String uri = (String) request.attribute(URI_TEMPLATE_ATTRIBUTE).orElseGet(() -> request.url().toString());

Upvotes: 4

pixel
pixel

Reputation: 26473

I added custom WebClientExchangeTagsProvider and registered it as a bean:

class SameUriWebClientExchangeTagsProvider : WebClientExchangeTagsProvider {
    override fun tags(request: ClientRequest, response: ClientResponse?, throwable: Throwable?): Iterable<Tag> {
        val method = WebClientExchangeTags.method(request)
        val uri = tag(request)
        val clientName = WebClientExchangeTags.clientName(request)
        val status = WebClientExchangeTags.status(response, throwable)
        val outcome = WebClientExchangeTags.outcome(response)
        return listOf(method, uri, clientName, status, outcome)
    }

    private fun tag(request: ClientRequest): Tag {
        val uri = request.attribute(WebClient::class.java.name + ".uriTemplate")
            .orElseGet {
                request.url().toString()
            } as String

        return Tag.of("uri", URI(uri).path)
    }
}

Upvotes: 0

Related Questions