aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/xyz/driver/core/app.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/scala/xyz/driver/core/app.scala')
-rw-r--r--src/main/scala/xyz/driver/core/app.scala105
1 files changed, 83 insertions, 22 deletions
diff --git a/src/main/scala/xyz/driver/core/app.scala b/src/main/scala/xyz/driver/core/app.scala
index 1977d6a..eb9f7ee 100644
--- a/src/main/scala/xyz/driver/core/app.scala
+++ b/src/main/scala/xyz/driver/core/app.scala
@@ -12,13 +12,14 @@ import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.RouteResult._
import akka.http.scaladsl.server.{ExceptionHandler, Route, RouteConcatenation}
import akka.stream.ActorMaterializer
+import com.github.swagger.akka.SwaggerHttpService._
import com.typesafe.config.Config
import com.typesafe.scalalogging.Logger
import io.swagger.models.Scheme
+import io.swagger.util.Json
import org.slf4j.{LoggerFactory, MDC}
-import spray.json.DefaultJsonProtocol
import xyz.driver.core
-import xyz.driver.core.rest.{ContextHeaders, Swagger}
+import xyz.driver.core.rest._
import xyz.driver.core.stats.SystemStats
import xyz.driver.core.time.Time
import xyz.driver.core.time.provider.{SystemTimeProvider, TimeProvider}
@@ -26,12 +27,16 @@ import xyz.driver.core.time.provider.{SystemTimeProvider, TimeProvider}
import scala.compat.Platform.ConcurrentModificationException
import scala.concurrent.duration._
import scala.concurrent.{Await, ExecutionContext, Future}
+import scala.reflect.runtime.universe._
+import scala.util.control.NonFatal
+import scala.util.Try
import scalaz.Scalaz.stringInstance
import scalaz.syntax.equal._
object app {
- class DriverApp(version: String,
+ class DriverApp(appName: String,
+ version: String,
gitHash: String,
modules: Seq[Module],
time: TimeProvider = new SystemTimeProvider(),
@@ -66,7 +71,7 @@ object app {
protected def bindHttp(modules: Seq[Module]): Unit = {
val serviceTypes = modules.flatMap(_.routeTypes)
- val swaggerService = new Swagger(baseUrl, Scheme.forValue(scheme), version, actorSystem, serviceTypes, config)
+ val swaggerService = swaggerOverride(serviceTypes)
val swaggerRoutes = swaggerService.routes ~ swaggerService.swaggerUI
val versionRt = versionRoute(version, gitHash, time.currentTime())
@@ -78,14 +83,11 @@ object app {
{ ctx =>
val trackingId = rest.extractTrackingId(ctx.request)
MDC.put("trackingId", trackingId)
- MDC.put("origin", origin)
- MDC.put("xForwardedFor",
- extractHeader(ctx.request)("x-forwarded-for")
- .orElse(extractHeader(ctx.request)("x_forwarded_for"))
- .getOrElse("unknown"))
- MDC.put("remoteAddress", extractHeader(ctx.request)("remote-address").getOrElse("unknown"))
- MDC.put("userAgent", extractHeader(ctx.request)("user-agent").getOrElse("unknown"))
- MDC.put("ip", ip.toOption.map(_.getHostAddress).getOrElse("unknown"))
+
+ val updatedStacktrace = (rest.extractStacktrace(ctx.request) ++ Array(appName)).mkString("->")
+ MDC.put("stack", updatedStacktrace)
+
+ storeRequestContextToMdc(ctx.request, origin, ip)
def requestLogging: Future[Unit] = Future {
log.info(
@@ -93,7 +95,10 @@ object app {
}
val contextWithTrackingId =
- ctx.withRequest(ctx.request.addHeader(RawHeader(ContextHeaders.TrackingIdHeader, trackingId)))
+ ctx.withRequest(
+ ctx.request
+ .addHeader(RawHeader(ContextHeaders.TrackingIdHeader, trackingId))
+ .addHeader(RawHeader(ContextHeaders.StacktraceHeader, updatedStacktrace)))
handleExceptions(ExceptionHandler(exceptionHandler))({ c =>
requestLogging.flatMap { _ =>
@@ -114,6 +119,51 @@ object app {
}
}
+ private def storeRequestContextToMdc(request: HttpRequest, origin: String, ip: RemoteAddress) = {
+
+ MDC.put("origin", origin)
+ MDC.put("ip", ip.toOption.map(_.getHostAddress).getOrElse("unknown"))
+ MDC.put("remoteHost", ip.toOption.map(_.getHostName).getOrElse("unknown"))
+
+ MDC.put("xForwardedFor",
+ extractHeader(request)("x-forwarded-for")
+ .orElse(extractHeader(request)("x_forwarded_for"))
+ .getOrElse("unknown"))
+ MDC.put("remoteAddress", extractHeader(request)("remote-address").getOrElse("unknown"))
+ MDC.put("userAgent", extractHeader(request)("user-agent").getOrElse("unknown"))
+ }
+
+ protected def swaggerOverride(apiTypes: Seq[Type]) = {
+ new Swagger(baseUrl, Scheme.forValue(scheme), version, actorSystem, apiTypes, config) {
+ override def generateSwaggerJson: String = {
+ import io.swagger.models.Swagger
+
+ import scala.collection.JavaConverters._
+
+ try {
+ val swagger: Swagger = reader.read(toJavaTypeSet(apiTypes).asJava)
+
+ // Removing trailing spaces
+ swagger.setPaths(
+ swagger.getPaths.asScala
+ .map {
+ case (key, path) =>
+ key.trim -> path
+ }
+ .toMap
+ .asJava)
+
+ Json.pretty().writeValueAsString(swagger)
+ } catch {
+ case NonFatal(t) => {
+ logger.error("Issue with creating swagger.json", t)
+ throw t
+ }
+ }
+ }
+ }
+ }
+
/**
* Override me for custom exception handling
*
@@ -148,6 +198,7 @@ object app {
}
protected def versionRoute(version: String, gitHash: String, startupTime: Time): Route = {
+ import spray.json._
import DefaultJsonProtocol._
import SprayJsonSupport._
@@ -155,17 +206,27 @@ object app {
val currentTime = time.currentTime().millis
complete(
Map(
- "version" -> version,
- "gitHash" -> gitHash,
- "modules" -> modules.map(_.name).mkString(", "),
- "startupTime" -> startupTime.millis.toString,
- "serverTime" -> currentTime.toString,
- "uptime" -> (currentTime - startupTime.millis).toString
- ))
+ "version" -> version.toJson,
+ "gitHash" -> gitHash.toJson,
+ "modules" -> modules.map(_.name).toJson,
+ "dependencies" -> collectAppDependencies().toJson,
+ "startupTime" -> startupTime.millis.toString.toJson,
+ "serverTime" -> currentTime.toString.toJson,
+ "uptime" -> (currentTime - startupTime.millis).toString.toJson
+ ).toJson)
}
}
+ protected def collectAppDependencies(): Map[String, String] = {
+
+ def serviceWithLocation(serviceName: String): (String, String) =
+ serviceName -> Try(config.getString(s"services.$serviceName.baseUrl")).getOrElse("not-detected")
+
+ modules.flatMap(module => module.serviceDiscovery.getUsedServices.map(serviceWithLocation).toSeq).toMap
+ }
+
protected def healthRoute: Route = {
+ import spray.json._
import DefaultJsonProtocol._
import SprayJsonSupport._
import spray.json._
@@ -236,13 +297,13 @@ object app {
}
}
- import scala.reflect.runtime.universe._
-
trait Module {
val name: String
def route: Route
def routeTypes: Seq[Type]
+ val serviceDiscovery: ServiceDiscovery with SavingUsedServiceDiscovery = new NoServiceDiscovery()
+
def activate(): Unit = {}
def deactivate(): Unit = {}
}