Skip to content

Commit

Permalink
feat(prism-agent): add http metrics (#585)
Browse files Browse the repository at this point in the history
* First working version of unified metrics from different sources

* Fix test compilations

* Reractor ZHttp4sBlazeServer to catch all errors

* format
  • Loading branch information
shotexa committed Jul 7, 2023
1 parent c0db5c8 commit f62d7f5
Show file tree
Hide file tree
Showing 8 changed files with 131 additions and 97 deletions.
27 changes: 18 additions & 9 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ inThisBuild(
"-unchecked",
"-Dquill.macro.log=false", // disable quill macro logs
"-Wunused:all",
"-Wconf:any:warning", // TODO: change unused imports to errors, Wconf configuration string is different from scala 2, figure out how!
"-Wconf:any:warning" // TODO: change unused imports to errors, Wconf configuration string is different from scala 2, figure out how!
// TODO "-feature",
// TODO "-Xfatal-warnings",
// TODO "-Yexplicit-nulls",
Expand All @@ -48,22 +48,22 @@ lazy val V = new {
val zioJson = "0.3.0"
val zioHttp = "0.0.3"
val zioCatsInterop = "3.3.0"
val zioMetrics = "2.0.6"
val zioMetricsConnector = "2.1.0"
val zioMock = "1.0.0-RC10"

// https://mvnrepository.com/artifact/io.circe/circe-core
val circe = "0.14.2"

// val tapir = "1.0.3"
val tapir = "1.2.3"
val tapir = "1.6.0"
val tapirLegacy = "1.2.3" // TODO: remove

val typesafeConfig = "1.4.2"
val protobuf = "3.1.9"
val testContainersScala = "0.40.16"

val doobie = "1.0.0-RC2"
val quill = "4.6.0"
val iris = "0.1.0" // TODO REMOVE
val iris = "0.1.0" // TODO: remove
val flyway = "9.8.3"
val logback = "1.4.5"

Expand All @@ -80,6 +80,7 @@ lazy val V = new {
// https://github.com/jopenlibs/vault-java-driver/issues/36
// v5.4.0 is not available on Maven yet.
val vaultDriver = "5.3.0"
val micrometer = "1.11.1"
}

/** Dependencies */
Expand All @@ -91,7 +92,11 @@ lazy val D = new {
val zioJson: ModuleID = "dev.zio" %% "zio-json" % V.zioJson
val zioHttp: ModuleID = "dev.zio" %% "zio-http" % V.zioHttp
val zioCatsInterop: ModuleID = "dev.zio" %% "zio-interop-cats" % V.zioCatsInterop
val zioMetrics: ModuleID = "dev.zio" %% "zio-metrics-connectors" % V.zioMetrics
val zioMetricsConnectorMicrometer: ModuleID = "dev.zio" %% "zio-metrics-connectors-micrometer" % V.zioMetricsConnector
val tapirPrometheusMetrics: ModuleID = "com.softwaremill.sttp.tapir" %% "tapir-prometheus-metrics" % V.tapir
val micrometer: ModuleID = "io.micrometer" % "micrometer-registry-prometheus" % V.micrometer
val micrometerPrometheusRegistry = "io.micrometer" % "micrometer-core" % V.micrometer


val zioConfig: ModuleID = "dev.zio" %% "zio-config" % V.zioConfig
val zioConfigMagnolia: ModuleID = "dev.zio" %% "zio-config-magnolia" % V.zioConfig
Expand All @@ -105,7 +110,6 @@ lazy val D = new {
val didcommx: ModuleID = "org.didcommx" % "didcomm" % "0.3.1"
val peerDidcommx: ModuleID = "org.didcommx" % "peerdid" % "0.3.0"
val didScala: ModuleID = "app.fmgp" %% "did" % "0.0.0+113-61efa271-SNAPSHOT"

// https://mvnrepository.com/artifact/com.nimbusds/nimbus-jose-jwt/9.16-preview.1
val jwk: ModuleID = "com.nimbusds" % "nimbus-jose-jwt" % "9.25.4"

Expand Down Expand Up @@ -288,7 +292,9 @@ lazy val D_PrismAgent = new {
val tapirSwaggerUiBundle = "com.softwaremill.sttp.tapir" %% "tapir-swagger-ui-bundle" % V.tapir
val tapirJsonZio = "com.softwaremill.sttp.tapir" %% "tapir-json-zio" % V.tapir

val tapirZioHttpServer = "com.softwaremill.sttp.tapir" %% "tapir-zio-http-server" % V.tapir
// FIXME: using newest tapir (1.6.0) for this dependency needs refactoring, because it has transitive dependency on zio-http 3.0.0,
// if used all imports for zio.http will use ne newest version, which will break the compilation
val tapirZioHttpServer = "com.softwaremill.sttp.tapir" %% "tapir-zio-http-server" % V.tapirLegacy
val tapirHttp4sServerZio = "com.softwaremill.sttp.tapir" %% "tapir-http4s-server-zio" % V.tapir
val http4sBlazeServer = "org.http4s" %% "http4s-blaze-server" % "0.23.12"

Expand Down Expand Up @@ -320,7 +326,10 @@ lazy val D_PrismAgent = new {
D.zioJson,
logback,
D.zioHttp,
D.zioMetrics,
D.zioMetricsConnectorMicrometer,
D.tapirPrometheusMetrics,
D.micrometer,
D.micrometerPrometheusRegistry
)
val bouncyDependencies: Seq[ModuleID] = Seq(bouncyBcpkix, bouncyBcprov)
val tapirDependencies: Seq[ModuleID] =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package io.iohk.atala.pollux.core.service

import io.iohk.atala.pollux.core.service.URIDereferencerError.{ConnectionError, ResourceNotFound, UnexpectedError}
import zio.http.*
import zio.http.model.*
import zio.{IO, Scope, ULayer, ZIO, ZLayer}
import zio.*

import java.net.URI

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,43 @@ package io.iohk.atala.agent.server
import com.nimbusds.jose.crypto.bc.BouncyCastleProviderSingleton
import io.iohk.atala.agent.server.http.ZioHttpClient
import io.iohk.atala.agent.server.sql.Migrations as AgentMigrations
import io.iohk.atala.agent.walletapi.service.ManagedDIDService
import io.iohk.atala.agent.walletapi.service.ManagedDIDServiceImpl
import io.iohk.atala.agent.walletapi.service.{ManagedDIDService, ManagedDIDServiceImpl}
import io.iohk.atala.agent.walletapi.sql.JdbcDIDNonSecretStorage
import io.iohk.atala.castor.controller.{DIDControllerImpl, DIDRegistrarControllerImpl}
import io.iohk.atala.castor.core.service.DIDServiceImpl
import io.iohk.atala.castor.core.util.DIDOperationValidator
import io.iohk.atala.connect.controller.ConnectionControllerImpl
import io.iohk.atala.connect.core.service.ConnectionServiceImpl
import io.iohk.atala.connect.sql.repository.JdbcConnectionRepository
import io.iohk.atala.connect.sql.repository.Migrations as ConnectMigrations
import io.iohk.atala.connect.sql.repository.{JdbcConnectionRepository, Migrations as ConnectMigrations}
import io.iohk.atala.issue.controller.IssueControllerImpl
import io.iohk.atala.mercury.*
import io.iohk.atala.pollux.core.service.CredentialServiceImpl
import io.iohk.atala.pollux.core.service.PresentationServiceImpl
import io.iohk.atala.pollux.core.service.VerificationPolicyServiceImpl
import io.iohk.atala.pollux.core.service.{CredentialSchemaServiceImpl, URIDereferencer, HttpURIDereferencerImpl}
import io.iohk.atala.pollux.credentialschema.controller.CredentialSchemaController
import io.iohk.atala.pollux.credentialschema.controller.CredentialSchemaControllerImpl
import io.iohk.atala.pollux.credentialschema.controller.VerificationPolicyControllerImpl
import io.iohk.atala.pollux.sql.repository.JdbcCredentialRepository
import io.iohk.atala.pollux.sql.repository.JdbcPresentationRepository
import io.iohk.atala.pollux.sql.repository.JdbcVerificationPolicyRepository
import io.iohk.atala.pollux.sql.repository.{JdbcCredentialSchemaRepository, Migrations as PolluxMigrations}
import io.iohk.atala.pollux.core.service.*
import io.iohk.atala.pollux.credentialschema.controller.{
CredentialSchemaController,
CredentialSchemaControllerImpl,
VerificationPolicyControllerImpl
}
import io.iohk.atala.pollux.sql.repository.{
JdbcCredentialRepository,
JdbcCredentialSchemaRepository,
JdbcPresentationRepository,
JdbcVerificationPolicyRepository,
Migrations as PolluxMigrations
}
import io.iohk.atala.presentproof.controller.PresentProofControllerImpl
import io.iohk.atala.resolvers.DIDResolver
import io.iohk.atala.system.controller.SystemControllerImpl
import java.security.Security
import io.micrometer.prometheus.{PrometheusConfig, PrometheusMeterRegistry}
import zio.*
import zio.metrics.connectors.prometheus.PrometheusPublisher
import zio.metrics.connectors.{MetricsConfig, prometheus}
import zio.metrics.connectors.micrometer
import zio.metrics.connectors.micrometer.MicrometerConfig
import zio.metrics.jvm.DefaultJvmMetrics

import java.security.Security

object MainApp extends ZIOAppDefault {

Security.insertProviderAt(BouncyCastleProviderSingleton.getInstance(), 2)

def didCommAgentLayer(didCommServiceUrl: String): ZLayer[ManagedDIDService, Nothing, DidAgent] = {
val aux = for {
managedDIDService <- ZIO.service[ManagedDIDService]
Expand Down Expand Up @@ -92,11 +93,6 @@ object MainApp extends ZIOAppDefault {

_ <- migrations

/** AppConfig & SystemController & PresentProofController & DIDRegistrarController & DIDController &
* IssueController & ConnectionController & VerificationPolicyController & CredentialSchemaController &
* ManagedDIDService
*/

app <- PrismAgentApp
.run(didCommServicePort)
.provide(
Expand All @@ -108,9 +104,9 @@ object MainApp extends ZIOAppDefault {
// observability
DefaultJvmMetrics.live.unit,
SystemControllerImpl.layer,
ZLayer.succeed(MetricsConfig(5.seconds)),
prometheus.prometheusLayer,
prometheus.publisherLayer,
ZLayer.succeed(PrometheusMeterRegistry(PrometheusConfig.DEFAULT)),
ZLayer.succeed(MicrometerConfig.default),
micrometer.micrometerLayer,
// controller
ConnectionControllerImpl.layer,
CredentialSchemaControllerImpl.layer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import io.iohk.atala.pollux.core.service.CredentialService
import io.iohk.atala.pollux.core.service.PresentationService
import io.iohk.atala.pollux.credentialschema.SchemaRegistryServerEndpoints
import io.iohk.atala.pollux.credentialschema.VerificationPolicyServerEndpoints
import io.iohk.atala.pollux.vc.jwt.{DidResolver as JwtDidResolver}
import io.iohk.atala.pollux.vc.jwt.DidResolver as JwtDidResolver
import io.iohk.atala.presentproof.controller.PresentProofServerEndpoints
import io.iohk.atala.resolvers.DIDResolver
import io.iohk.atala.system.controller.SystemServerEndpoints
Expand Down Expand Up @@ -78,10 +78,6 @@ object PrismAgentApp {

}

/** AppConfig & SystemController & PresentProofController & DIDRegistrarController & DIDController & IssueController &
* ConnectionController & VerificationPolicyController & CredentialSchemaController
*/

object AgentHttpServer {
def run =
for {
Expand All @@ -103,7 +99,8 @@ object AgentHttpServer {
allPresentProofEndpoints ++
allSystemEndpoints
)
server <- ZHttp4sBlazeServer.make
appConfig <- ZIO.service[AppConfig]
_ <- ZHttp4sBlazeServer.start(allEndpoints, port = appConfig.agent.httpEndpoint.http.port)
_ <- server.start(allEndpoints, port = appConfig.agent.httpEndpoint.http.port).debug
} yield ()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package io.iohk.atala.agent.server.http

import io.iohk.atala.api.http.ErrorResponse
import io.iohk.atala.system.controller.SystemEndpoints
import io.micrometer.prometheus.PrometheusMeterRegistry
import org.http4s.*
import org.http4s.blaze.server.BlazeServerBuilder
import org.http4s.server.Router
import sttp.tapir.*
import sttp.tapir.server.http4s.Http4sServerOptions
import sttp.tapir.server.http4s.ztapir.ZHttp4sServerInterpreter
import sttp.tapir.server.metrics.prometheus.PrometheusMetrics
import sttp.tapir.ztapir.ZServerEndpoint
import zio.*
import zio.interop.catz.*

class ZHttp4sBlazeServer(micrometerRegistry: PrometheusMeterRegistry) {

private val tapirPrometheusMetricsZIO: Task[PrometheusMetrics[Task]] = ZIO.attempt {
PrometheusMetrics.default[Task](registry = micrometerRegistry.getPrometheusRegistry)
}

private val serverOptionsZIO: ZIO[PrometheusMetrics[Task], Throwable, Http4sServerOptions[Task]] = for {
srv <- ZIO.service[PrometheusMetrics[Task]]
options <- ZIO.attempt {
Http4sServerOptions
.customiseInterceptors[Task]
.defaultHandlers(ErrorResponse.failureResponseHandler)
.metricsInterceptor(
srv.metricsInterceptor(
ignoreEndpoints = Seq(SystemEndpoints.metrics)
)
)
.options
}
} yield options

def start(
endpoints: List[ZServerEndpoint[Any, Any]],
port: Int
): Task[ExitCode] = {

val serve = for {
metrics <- tapirPrometheusMetricsZIO
options <- serverOptionsZIO.provide(ZLayer.succeed(metrics))
serve <- ZIO.attempt {
val http4sEndpoints: HttpRoutes[Task] =
ZHttp4sServerInterpreter(options)
.from(endpoints)
.toRoutes

ZIO.executor.flatMap(executor =>
BlazeServerBuilder[Task]
.withExecutionContext(executor.asExecutionContext)
.bindHttp(port, "0.0.0.0")
.withHttpApp(Router("/" -> http4sEndpoints).orNotFound)
.serve
.compile
.drain
)
}
} yield serve

serve.flatten.exitCode
}
}

object ZHttp4sBlazeServer {
def make: URIO[PrometheusMeterRegistry, ZHttp4sBlazeServer] = {
for {
micrometerRegistry <- ZIO.service[PrometheusMeterRegistry]
zHttp4sBlazeServer = ZHttp4sBlazeServer(micrometerRegistry)
} yield zHttp4sBlazeServer
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,24 @@ package io.iohk.atala.system.controller
import io.iohk.atala.agent.server.buildinfo.BuildInfo
import io.iohk.atala.api.http.{ErrorResponse, RequestContext}
import io.iohk.atala.system.controller.http.HealthInfo
import zio.metrics.connectors.prometheus
import zio.metrics.connectors.prometheus.PrometheusPublisher
import io.micrometer.prometheus.PrometheusMeterRegistry
import zio.*

class SystemControllerImpl(
prometheus: PrometheusPublisher
prometheusRegistry: PrometheusMeterRegistry
) extends SystemController {

override def health()(implicit rc: RequestContext): IO[ErrorResponse, HealthInfo] = {
ZIO.succeed(HealthInfo(version = BuildInfo.version))
}

override def metrics()(implicit rc: RequestContext): IO[ErrorResponse, String] = {
prometheus.get
ZIO.succeed(prometheusRegistry.scrape)
}

}

object SystemControllerImpl {
val layer: URLayer[PrometheusPublisher, SystemController] =
val layer: URLayer[PrometheusMeterRegistry, SystemController] =
ZLayer.fromFunction(SystemControllerImpl(_))
}

0 comments on commit f62d7f5

Please sign in to comment.