Skip to content

Commit

Permalink
Modul med metrikker gir mulighet til å telle antall ganger ett endepu…
Browse files Browse the repository at this point in the history
…nkt har blitt kallt (#794)
  • Loading branch information
stigebil authored Apr 18, 2024
1 parent a01cd9d commit 2c13ecd
Show file tree
Hide file tree
Showing 14 changed files with 319 additions and 10 deletions.
2 changes: 1 addition & 1 deletion http-client/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
<artifactId>kotlin-stdlib</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
Expand Down
2 changes: 1 addition & 1 deletion leader/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
<artifactId>kotlin-stdlib</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
Expand Down
114 changes: 114 additions & 0 deletions metrikker/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>no.nav.familie.felles</groupId>
<artifactId>felles</artifactId>
<version>${revision}${sha1}${changelist}</version>
</parent>

<artifactId>metrikker</artifactId>
<version>${revision}${sha1}${changelist}</version>
<name>Felles - Metrikker</name>
<description>Felles kode for metrikker</description>
<packaging>jar</packaging>

<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
</dependency>


<!-- Test -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.mockk</groupId>
<artifactId>mockk-jvm</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>testCompile</id>
<phase>test-compile</phase>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package no.nav.familie.metrikker

import io.micrometer.core.instrument.Counter
import io.micrometer.core.instrument.Metrics
import jakarta.annotation.PostConstruct
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
import org.springframework.context.ApplicationContext
import org.springframework.stereotype.Component
import org.springframework.web.method.HandlerMethod
import org.springframework.web.servlet.mvc.method.RequestMappingInfo
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping

@Component
@ConditionalOnProperty("familie.tellAPIEndepunkterIBruk")
class TellAPIEndepunkterIBrukInitialiserer(
@Value("\${NAIS_APP_NAME}") private val applicationName: String,
private val applicationContext: ApplicationContext,
@Value("\${familie.tellAPIEndepunkterIBruk.paths:/api}") private val pathStartWidth: List<String>,
) {
init {
metrikker.clear()
}

@PostConstruct
fun populerMapMedCountersForRestEndepunkt() {
val requestMappingHandlerMapping: RequestMappingHandlerMapping =
applicationContext
.getBean("requestMappingHandlerMapping", RequestMappingHandlerMapping::class.java)
val requestMappings: Map<RequestMappingInfo, HandlerMethod> = requestMappingHandlerMapping.handlerMethods

requestMappings.forEach { (info, handler) ->
info.patternValues.forEach { path ->
if (pathStartWidth.any { path.startsWith(it) }) {
val metrikknavn = "$applicationName.${info.methodsCondition}$path".tilMetrikknavn()
val key = "${info.methodsCondition}$path"
metrikker.put(
key,
Metrics.counter(
metrikknavn,
METRIKK_TAG_TYPE,
"endepunkt",
METRIKK_PATH_TYPE,
path,
METRIKK_REQUEST_METODE_TYPE,
"${info.methodsCondition}",
),
)
}
}
}
}

private fun String.tilMetrikknavn() =
this
.replace("[", "")
.replace("]", "")
.replace("{", "")
.replace("}", "")
.replace("/", ".")
.replace("_", ".")

companion object {
private val metrikker = mutableMapOf<String, Counter>()
val metrikkerForEndepunkter
get() = metrikker.toMap()

private const val METRIKK_TAG_TYPE = "type"
private const val METRIKK_PATH_TYPE = "path"
private const val METRIKK_REQUEST_METODE_TYPE = "requestMetode"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package no.nav.familie.metrikker

import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
import org.springframework.stereotype.Component
import org.springframework.web.servlet.AsyncHandlerInterceptor
import org.springframework.web.servlet.HandlerMapping

/**
* Sett property familie.tellAPIEndepunkterIBruk: true i application.yaml for å skru
* på metrikker for hvor mange ganger et endepunkt har blitt kalt
*
* For å konfigurere andre endepunkter enn de som starter på /api så kan man bruke
* familie.tellAPIEndepunkterIBruk.paths: /foo,/bar
*
*/
@Component
@ConditionalOnProperty("familie.tellAPIEndepunkterIBruk")
class TellAPIEndepunkterIBrukInterceptor : AsyncHandlerInterceptor {
override fun preHandle(
request: HttpServletRequest,
response: HttpServletResponse,
handler: Any,
): Boolean {
val path = request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE) as String
TellAPIEndepunkterIBrukInitialiserer.metrikkerForEndepunkter.get("[${request.method}]$path")?.increment()
return super.preHandle(request, response, handler)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package no.nav.familie.metrikker

import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
import org.springframework.context.annotation.Configuration
import org.springframework.web.servlet.config.annotation.InterceptorRegistry
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer

@Configuration
@ConditionalOnProperty("familie.tellAPIEndepunkterIBruk")
open class TellAPIEndpunkterIBrukWebConfig : WebMvcConfigurer {
override fun addInterceptors(registry: InterceptorRegistry) {
registry.addInterceptor(TellAPIEndepunkterIBrukInterceptor()).addPathPatterns("/api/**")
super.addInterceptors(registry)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package no.nav.familie.metrikker

import io.mockk.clearAllMocks
import io.mockk.every
import io.mockk.mockk
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.springframework.context.ApplicationContext
import org.springframework.web.bind.annotation.RequestMethod
import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition
import org.springframework.web.servlet.mvc.method.RequestMappingInfo
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping

class TellAPIEndepunkterIBrukTest {
val applicationContext: ApplicationContext = mockk()
val requestMappingHandlerMapping: RequestMappingHandlerMapping = mockk()
val info: RequestMappingInfo = mockk()

@BeforeEach
fun setUp() {
clearAllMocks()
}

@Test
fun `skal opprette map med key og counter når det finnes en requestmapping`() {
settOppTestData("/api/foo", RequestMethod.GET)

TellAPIEndepunkterIBrukInitialiserer("test", applicationContext, listOf("/api")).populerMapMedCountersForRestEndepunkt()

assertThat(TellAPIEndepunkterIBrukInitialiserer.metrikkerForEndepunkter).hasSize(1)
assertThat(TellAPIEndepunkterIBrukInitialiserer.metrikkerForEndepunkter.containsKey("[GET]/api/foo")).isTrue()
assertThat(
TellAPIEndepunkterIBrukInitialiserer.metrikkerForEndepunkter.get("[GET]/api/foo")?.id?.name,
).isEqualTo("test.GET.api.foo")
}

@Test
fun `skal opprette map med key og counter når det finnes en requestmapping med pathParam og navnet på counteren saneres`() {
settOppTestData("/api/foo/{fooId}", RequestMethod.POST)

TellAPIEndepunkterIBrukInitialiserer("test", applicationContext, listOf("/api")).populerMapMedCountersForRestEndepunkt()

assertThat(TellAPIEndepunkterIBrukInitialiserer.metrikkerForEndepunkter).hasSize(1)
assertThat(TellAPIEndepunkterIBrukInitialiserer.metrikkerForEndepunkter.containsKey("[POST]/api/foo/{fooId}")).isTrue()
assertThat(
TellAPIEndepunkterIBrukInitialiserer.metrikkerForEndepunkter.get("[POST]/api/foo/{fooId}")?.id?.name,
).isEqualTo("test.POST.api.foo.fooId")
}

@Test
fun `skal ikke opprette map med counter for annet enn pathparam som starter med api`() {
settOppTestData("/internal/foobar", RequestMethod.POST)

TellAPIEndepunkterIBrukInitialiserer("test", applicationContext, listOf("/api")).populerMapMedCountersForRestEndepunkt()

assertThat(TellAPIEndepunkterIBrukInitialiserer.metrikkerForEndepunkter).hasSize(0)
}

private fun settOppTestData(
path: String,
method: RequestMethod,
) {
every { info.patternValues } returns setOf(path)
every { info.methodsCondition } returns RequestMethodsRequestCondition(method)

every { requestMappingHandlerMapping.handlerMethods } returns
mapOf(Pair(info, mockk()))
every {
applicationContext.getBean(
"requestMappingHandlerMapping",
RequestMappingHandlerMapping::class.java,
)
} returns
requestMappingHandlerMapping
}
}
2 changes: 1 addition & 1 deletion modell/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
<artifactId>kotlin-stdlib</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
Expand Down
3 changes: 2 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
<module>kafka</module>
<module>valutakurs-klient</module>
<module>unleash</module>
<module>metrikker</module>
</modules>

<dependencyManagement>
Expand All @@ -60,7 +61,7 @@
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
Expand Down
2 changes: 1 addition & 1 deletion sikkerhet/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
<artifactId>kotlin-stdlib</artifactId>
</dependency>
<dependency>
<groupId>no.nav.security</groupId>
Expand Down
2 changes: 1 addition & 1 deletion util/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
<artifactId>kotlin-stdlib</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
Expand Down
2 changes: 1 addition & 1 deletion valutakurs-klient/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
<artifactId>kotlin-stdlib</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
Expand Down
Loading

0 comments on commit 2c13ecd

Please sign in to comment.