GRPC has its own instrumentation for OpenTelemetry, which is used to capture the traffic going through the GRPC server. With it, per-endpoint monitoring can be achieved. List of metrics that are captured can be found here.
Here is how you can integrate OpenTelemetry with the Connect-RPC server
(example uses otel4s
, grpc-opentelemetry
and cats-effect-simple-di
libraries):
// Dependencies.scala
object Dependencies {
def create(runtime: IORuntime): Resource[IO, Dependencies] =
Allocator.create(runtime).map(new Dependencies(_))
}
class Dependencies(allocator: Allocator) {
// Create OpenTelemetry instance
lazy val otel: OtelJava[IO] = allocator.allocate {
OtelJava.autoConfigured[IO]()
}
// Create GRPC OpenTelemetry instance
lazy val grpcOtel: GrpcOpenTelemetry = {
GrpcOpenTelemetry.newBuilder()
.sdk(otel.underlying)
.build()
}
lazy val httpServer: Resource[IO, org.http4s.server.Server] = {
import com.comcast.ip4s.*
for {
// Create httpApp with Connect-RPC routes, specifying your GRPC services
app <- ConnectRouteBuilder
.forServices[IO](
// Inject your GRPC services
)
.withServerConfigurator { sb =>
grpcOtel.configureServerBuilder(sb)
sb
}
.build
// Create http server
server <- EmberServerBuilder.default[IO]
.withHost(host"0.0.0.0")
.withPort(port"8080")
.withHttpApp(app)
.build
} yield server
}
}
// Main.scala
object Main extends IOApp.Simple {
override def run: IO[Unit] = {
Dependencies.create(runtime)
.flatMap { deps =>
(
// deps.grpcServer, <- not listed in the example above, but this is how you can start multiple servers
deps.httpServer,
).parTupled
}
.useForever
}
}