Skip to content

Commit

Permalink
Add Micrometer Prometheus timer interceptor (#29)
Browse files Browse the repository at this point in the history
* Add Micrometer & Prometheus counter interceptor

* Formatting code

* Remove spring boot actuator dependency

* Formatting code
  • Loading branch information
yuxin-zhao authored Jun 12, 2020
1 parent cb9937b commit ac9ad45
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 0 deletions.
6 changes: 6 additions & 0 deletions buildSrc/src/main/kotlin/dependencies.kt
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ object Dependencies {
const val cp = "$group:spring-boot-configuration-processor"

const val jackson = "$group:spring-boot-starter-json"

const val actuator = "$group:spring-boot-starter-actuator"
}
}

Expand Down Expand Up @@ -111,6 +113,10 @@ object Dependencies {
const val wagonHttp = "$group.wagon:wagon-http"
}

object Micrometer {
const val prometheus = "io.micrometer:micrometer-registry-prometheus"
}

const val elastic5 = "org.elasticsearch.client:transport"

const val mysql = "mysql:mysql-connector-java"
Expand Down
1 change: 1 addition & 0 deletions dependencies/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,6 @@ dependencies {
api("org.eclipse.jgit:org.eclipse.jgit:5.7.0.202003110725-r")
api("com.palantir.gradle.docker:gradle-docker:0.25.0")
api("io.grpc:grpc-kotlin-stub:0.1.2")
api("io.micrometer:micrometer-registry-prometheus:1.5.1")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.bybutter.sisyphus.middleware.configuration

object SpringApplicationConfigArtifactPropertyExporter : ConfigFormatFilePropertyExporter() {
override val names: Collection<String> = listOf("spring/application")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
com.bybutter.sisyphus.middleware.configuration.SpringApplicationConfigArtifactPropertyExporter
3 changes: 3 additions & 0 deletions starter/sisyphus-grpc-server-starter/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ description = "Starter for building gRPC server in Sisyphus Framework"
dependencies {
api(project(":lib:sisyphus-protobuf"))
api(project(":middleware:sisyphus-grpc-client"))
api(project(":middleware:sisyphus-configuration-artifact"))
implementation(Dependencies.Grpc.stub)
implementation(Dependencies.Spring.Boot.actuator)
implementation(Dependencies.Micrometer.prometheus)
runtimeOnly(Dependencies.Grpc.netty)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.bybutter.sisyphus.starter.grpc

import io.micrometer.core.instrument.MeterRegistry
import io.micrometer.core.instrument.Timer
import java.time.Duration
import org.springframework.stereotype.Component

/**
* When Sisyphus calls other service interfaces, It will give priority to see if the service is referenced locally,
* if requested, request the local service interfaces.
* The remote request will be initiated if the local request is not available.
* Requesting local services has little overhead for network requests,
* So it may be inaccurate to calculate the average time of the request。
* Use two [Timer] to count remote request and all requests separately.
* */
@Component
class MicrometerRegistrar constructor(private var registry: MeterRegistry) {
/**
* Only record remote requests
* */
private val remoteRequestTimer: Timer by lazy {
registry.timer("sisyphus_remote_request")
}
/**
* Log all requests
* */
private val allRequestTimer: Timer by lazy {
registry.timer("sisyphus_all_request")
}

fun incrRemoteRequest(duration: Duration) {
remoteRequestTimer.record(duration)
}

fun incrAllRequest(duration: Duration) {
allRequestTimer.record(duration)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.bybutter.sisyphus.starter.grpc.support

import com.bybutter.sisyphus.starter.grpc.MicrometerRegistrar
import io.grpc.Context
import io.grpc.Contexts
import io.grpc.ForwardingServerCall
import io.grpc.Metadata
import io.grpc.ServerCall
import io.grpc.ServerCallHandler
import io.grpc.ServerInterceptor
import io.grpc.Status
import java.time.Duration
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component

@Component
class ServerMicrometerInterceptor : ServerInterceptor {
@Autowired
private lateinit var micrometerRegistrar: MicrometerRegistrar

override fun <ReqT : Any, RespT : Any> interceptCall(call: ServerCall<ReqT, RespT>, headers: Metadata, next: ServerCallHandler<ReqT, RespT>): ServerCall.Listener<ReqT> {
val host = headers.get(Metadata.Key.of("host", Metadata.ASCII_STRING_MARSHALLER))?.toString()
return Contexts.interceptCall(Context.current(), ServerMicrometerCall(call, micrometerRegistrar, host), headers, next)
}
}

class ServerMicrometerCall<ReqT : Any, RespT : Any>(call: ServerCall<ReqT, RespT>, private val micrometerRegistrar: MicrometerRegistrar, private val host: String?) : ForwardingServerCall.SimpleForwardingServerCall<ReqT, RespT>(call) {
override fun close(status: Status, trailers: Metadata) {
val costDuration = Duration.ofNanos(System.nanoTime() - REQUEST_TIMESTAMP_CONTEXT_KEY.get())
micrometerRegistrar.incrAllRequest(costDuration)
if (host != null && !host.startsWith("localhost")) {
micrometerRegistrar.incrRemoteRequest(costDuration)
}
super.close(status, trailers)
}
}

0 comments on commit ac9ad45

Please sign in to comment.