Skip to content

Commit

Permalink
stackdriver route tracing [no ticket; risk: low] (#379)
Browse files Browse the repository at this point in the history
stackdriver route tracing
  • Loading branch information
davidangb committed Nov 7, 2019
1 parent 324571c commit cc8ce42
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 25 deletions.
29 changes: 25 additions & 4 deletions project/Dependencies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,19 @@ object Dependencies {
val scalaCheck: ModuleID = "org.scalacheck" %% "scalacheck" % scalaCheckV % "test"
val catsEffect: ModuleID = "org.typelevel" %% "cats-effect" % catsEffectV

val googleOAuth2: ModuleID = "com.google.auth" % "google-auth-library-oauth2-http" % "0.9.0"
val googleStorage: ModuleID = "com.google.apis" % "google-api-services-storage" % "v1-rev20181013-1.27.0" //force this version
val excludIoGrpc = ExclusionRule(organization = "io.grpc", name = "grpc-core")
val ioGrpc: ModuleID = "io.grpc" % "grpc-core" % "1.19.0"

val googleOAuth2: ModuleID = "com.google.auth" % "google-auth-library-oauth2-http" % "0.9.0" excludeAll(excludIoGrpc)
val googleStorage: ModuleID = "com.google.apis" % "google-api-services-storage" % "v1-rev20181013-1.27.0" excludeAll(excludIoGrpc) //force this version

val monocle: ModuleID = "com.github.julien-truffaut" %% "monocle-core" % monocleVersion
val monocleMacro: ModuleID = "com.github.julien-truffaut" %% "monocle-macro" % monocleVersion

val scalaTest: ModuleID = "org.scalatest" %% "scalatest" % scalaTestV % "test"
val mockito: ModuleID = "org.mockito" % "mockito-core" % "2.7.22" % "test"

val unboundid: ModuleID = "com.unboundid" % "unboundid-ldapsdk" % "4.0.6"
val unboundid: ModuleID = "com.unboundid" % "unboundid-ldapsdk" % "4.0.12"
val ehcache: ModuleID = "org.ehcache" % "ehcache" % "3.6.2"

// All of workbench-libs pull in Akka; exclude it since we provide our own Akka dependency.
Expand All @@ -78,9 +81,26 @@ object Dependencies {
val scalikeCoreTest = "org.scalikejdbc" %% "scalikejdbc-test" % scalikejdbcVersion % "test"
val postgres = "org.postgresql" % "postgresql" % postgresDriverVersion

val excludeScalaCllectionCompat = ExclusionRule(organization = "org.scala-lang.modules", name = "scala-collection-compat_2.12")
val opencensusScalaCode: ModuleID = "com.github.sebruck" %% "opencensus-scala-core" % "0.7.0-M2" excludeAll(excludeScalaCllectionCompat) // excludeAll(excludIoGrpc, excludeCatsEffect )
val opencensusAkkaHttp: ModuleID = "com.github.sebruck" %% "opencensus-scala-akka-http" % "0.7.0-M2" excludeAll(excludeScalaCllectionCompat)// excludeAll(excludIoGrpc, excludeCatsEffect)
val opencensusStackDriverExporter: ModuleID = "io.opencensus" % "opencensus-exporter-trace-stackdriver" % "0.23.0" // excludeAll(excludIoGrpc, excludeCatsEffect)
val opencensusLoggingExporter: ModuleID = "io.opencensus" % "opencensus-exporter-trace-logging" % "0.23.0" // excludeAll(excludIoGrpc, excludeCatsEffect)

val openCensusDependencies = Seq(
opencensusScalaCode,
opencensusAkkaHttp,
opencensusStackDriverExporter,
opencensusLoggingExporter
)

// was included transitively before, now explicit
val commonsCodec: ModuleID = "commons-codec" % "commons-codec" % "1.13"

val rootDependencies = Seq(
// proactively pull in latest versions of Jackson libs, instead of relying on the versions
// specified as transitive dependencies, due to OWASP DependencyCheck warnings for earlier versions.
ioGrpc,
logbackClassic,
ravenLogback,
scalaLogging,
Expand Down Expand Up @@ -119,12 +139,13 @@ object Dependencies {
unboundid,
ehcache,
catsEffect,
commonsCodec,

liquibaseCore,

scalikeCore,
scalikeCoreConfig,
scalikeCoreTest,
postgres
)
) ++ openCensusDependencies
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import org.broadinstitute.dsde.workbench.sam.directory.PostgresDirectoryDAO
import org.broadinstitute.dsde.workbench.sam.openam.PostgresAccessPolicyDAO
import org.broadinstitute.dsde.workbench.util.ExecutionContexts
import scalikejdbc.config.DBs
import io.opencensus.scala.akka.http.TracingDirective._

/**
* Created by mbemis on 5/22/17.
Expand Down Expand Up @@ -156,8 +157,10 @@ trait ResourceRoutes extends UserInfoDirectives with SecurityDirectives with Sam
}

def getUserPoliciesForResourceType(resourceType: ResourceType, userInfo: UserInfo): server.Route =
get {
complete(policyEvaluatorService.listUserAccessPolicies(resourceType.name, userInfo.userId))
traceRequest { _ =>
get {
complete(policyEvaluatorService.listUserAccessPolicies(resourceType.name, userInfo.userId))
}
}

def postResource(resourceType: ResourceType, userInfo: UserInfo): server.Route =
Expand Down Expand Up @@ -195,9 +198,11 @@ trait ResourceRoutes extends UserInfoDirectives with SecurityDirectives with Sam

def getActionPermissionForUser(resource: FullyQualifiedResourceId, userInfo: UserInfo, action: String): server.Route =
get {
complete(policyEvaluatorService.hasPermission(resource, ResourceAction(action), userInfo.userId).map { hasPermission =>
StatusCodes.OK -> JsBoolean(hasPermission)
})
traceRequest { span =>
complete(policyEvaluatorService.hasPermission(resource, ResourceAction(action), userInfo.userId).map { hasPermission =>
StatusCodes.OK -> JsBoolean(hasPermission)
})
}
}

def listActionsForUser(resource: FullyQualifiedResourceId, userInfo: UserInfo): server.Route =
Expand All @@ -217,21 +222,25 @@ trait ResourceRoutes extends UserInfoDirectives with SecurityDirectives with Sam
}

def getResourcePolicies(resource: FullyQualifiedResourceId, userInfo: UserInfo): server.Route =
get {
requireAction(resource, SamResourceActions.readPolicies, userInfo.userId) {
complete(resourceService.listResourcePolicies(resource).map { response =>
StatusCodes.OK -> response.toSet
})
traceRequest { _ =>
get {
requireAction(resource, SamResourceActions.readPolicies, userInfo.userId) {
complete(resourceService.listResourcePolicies(resource).map { response =>
StatusCodes.OK -> response.toSet
})
}
}
}

def getPolicy(policyId: FullyQualifiedPolicyId, userInfo: UserInfo): server.Route =
get {
requireOneOfAction(policyId.resource, Set(SamResourceActions.readPolicies, SamResourceActions.readPolicy(policyId.accessPolicyName)), userInfo.userId) {
complete(resourceService.loadResourcePolicy(policyId).map {
case Some(response) => StatusCodes.OK -> response
case None => throw new WorkbenchExceptionWithErrorReport(ErrorReport(StatusCodes.NotFound, "policy not found"))
})
traceRequest { _ =>
get {
requireOneOfAction(policyId.resource, Set(SamResourceActions.readPolicies, SamResourceActions.readPolicy(policyId.accessPolicyName)), userInfo.userId) {
complete(resourceService.loadResourcePolicy(policyId).map {
case Some(response) => StatusCodes.OK -> response
case None => throw new WorkbenchExceptionWithErrorReport(ErrorReport(StatusCodes.NotFound, "policy not found"))
})
}
}
}

Expand Down Expand Up @@ -288,9 +297,11 @@ trait ResourceRoutes extends UserInfoDirectives with SecurityDirectives with Sam

def getUserResourceRoles(resource: FullyQualifiedResourceId, userInfo: UserInfo): server.Route =
get {
complete(resourceService.listUserResourceRoles(resource, userInfo).map { roles =>
StatusCodes.OK -> roles
})
traceRequest { span =>
complete(resourceService.listUserResourceRoles(resource, userInfo).map { roles =>
StatusCodes.OK -> roles
})
}
}

def getAllResourceUsers(resource: FullyQualifiedResourceId, userInfo: UserInfo): server.Route =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server
import akka.http.scaladsl.server.Directives._
import io.opencensus.scala.akka.http.TracingDirective.traceRequest
import org.broadinstitute.dsde.workbench.model.google.GoogleProject
import org.broadinstitute.dsde.workbench.model._
import org.broadinstitute.dsde.workbench.sam.model.SamJsonSupport._
Expand All @@ -26,8 +27,10 @@ trait UserRoutes extends UserInfoDirectives {
pathEndOrSingleSlash {
post {
requireCreateUser { createUser =>
complete {
userService.createUser(createUser).map(userStatus => StatusCodes.Created -> userStatus)
traceRequest { span =>
complete {
userService.createUser(createUser).map(userStatus => StatusCodes.Created -> userStatus)
}
}
}
} ~ requireUserInfo { user =>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package org.broadinstitute.dsde.workbench.sam.util

import io.opencensus.trace.{Span, Status}
import io.opencensus.scala.Tracing._

import cats.effect.IO

object OpenCensusIOUtils {

def traceIOWithParent[T](
name: String,
parentSpan: Span,
failureStatus: Throwable => Status = (_: Throwable) => Status.UNKNOWN
)(f: Span => IO[T]): IO[T] =
traceIOSpan(IO(startSpanWithParent(name, parentSpan)), failureStatus)(f)

def traceIO[T](
name: String,
failureStatus: Throwable => Status = (_: Throwable) => Status.UNKNOWN
)(f: Span => IO[T]) : IO[T] = {

traceIOSpan(IO(startSpan(name)), failureStatus)(f)
}


private def traceIOSpan[T](spanIO: IO[Span], failureStatus: Throwable => Status) (f: Span => IO[T]): IO[T] = {
for {
span <- spanIO
result <- f(span).attempt
_ <- IO(endSpan(span, Status.OK))
} yield result.toTry.get
}

}

0 comments on commit cc8ce42

Please sign in to comment.