From 0dc9f24cef4ea4e58afa59fab565e36796c0cb1d Mon Sep 17 00:00:00 2001 From: vlad Date: Fri, 31 Mar 2017 21:39:42 -0700 Subject: Logging clean up, Monadic execution utils --- src/main/scala/xyz/driver/core/app.scala | 8 ++--- src/main/scala/xyz/driver/core/execution.scala | 45 ++++++++++++++++++++++++++ src/main/scala/xyz/driver/core/rest.scala | 7 ++-- 3 files changed, 52 insertions(+), 8 deletions(-) create mode 100644 src/main/scala/xyz/driver/core/execution.scala (limited to 'src/main/scala') diff --git a/src/main/scala/xyz/driver/core/app.scala b/src/main/scala/xyz/driver/core/app.scala index 4966b9d..4b81897 100644 --- a/src/main/scala/xyz/driver/core/app.scala +++ b/src/main/scala/xyz/driver/core/app.scala @@ -99,26 +99,26 @@ object app { case is: IllegalStateException => ctx => MDC.put("trackingId", rest.extractTrackingId(ctx.request)) - log.error(s"Request is not allowed to ${ctx.request.uri}", is) + log.error(s"Request is not allowed to ${ctx.request.method} ${ctx.request.uri}", is) complete(HttpResponse(BadRequest, entity = is.getMessage))(ctx) case cm: ConcurrentModificationException => ctx => MDC.put("trackingId", rest.extractTrackingId(ctx.request)) - log.error(s"Concurrent modification of the resource ${ctx.request.uri}", cm) + log.error(s"Concurrent modification of the resource ${ctx.request.method} ${ctx.request.uri}", cm) complete( HttpResponse(Conflict, entity = "Resource was changed concurrently, try requesting a newer version"))(ctx) case sex: SQLException => ctx => MDC.put("trackingId", rest.extractTrackingId(ctx.request)) - log.error(s"Database exception for the resource ${ctx.request.uri}", sex) + log.error(s"Database exception for the resource ${ctx.request.method} ${ctx.request.uri}", sex) complete(HttpResponse(InternalServerError, entity = "Data access error"))(ctx) case t: Throwable => ctx => MDC.put("trackingId", rest.extractTrackingId(ctx.request)) - log.error(s"Request to ${ctx.request.uri} could not be handled normally", t) + log.error(s"Request to ${ctx.request.method} ${ctx.request.uri} could not be handled normally", t) complete(HttpResponse(InternalServerError, entity = t.getMessage))(ctx) } diff --git a/src/main/scala/xyz/driver/core/execution.scala b/src/main/scala/xyz/driver/core/execution.scala new file mode 100644 index 0000000..f27b905 --- /dev/null +++ b/src/main/scala/xyz/driver/core/execution.scala @@ -0,0 +1,45 @@ +package xyz.driver.core + +import scala.concurrent.{ExecutionContext, Future} +import scalaz.OptionT + +object execution { + + implicit class FutureOptionTExtensions[T](future: Future[T])(implicit executionContext: ExecutionContext) { + + def toOptionT: OptionT[Future, T] = + OptionT.optionT[Future](future.map(value => Option(value))) + + def returnUnit: Future[Unit] = + future.map(_ => Option(())) + + def returnUnitOpt: OptionT[Future, Unit] = + OptionT.optionT[Future](future.map(_ => Option(()))) + + def andEffect[E](effect: Future[E]): Future[T] = + for { + result <- future + _ <- effect + } yield result + + def andEffect[E](effect: OptionT[Future, E]): Future[T] = + andEffect(effect.run) + } + + def illegalState[T](message: String) = + failure(new IllegalStateException(message)) + + def illegalArgument[T](message: String) = + failure(new IllegalArgumentException(message)) + + def failure[T](throwable: Throwable) = + OptionT.optionT(Future.failed[Option[T]](throwable)) + + def collectOrNone[T, R](value: T)(f: PartialFunction[T, OptionT[Future, R]]): OptionT[Future, R] = + f.lift(value).getOrElse(OptionT.optionT(Future.successful(Option.empty[R]))) + + def collectOrDoNothing[T](value: T)(f: PartialFunction[T, OptionT[Future, Unit]]): OptionT[Future, Unit] = + f.lift(value).getOrElse(doNothing) + + val doNothing = OptionT.optionT(Future.successful(Option(()))) +} diff --git a/src/main/scala/xyz/driver/core/rest.scala b/src/main/scala/xyz/driver/core/rest.scala index aa2a75e..39f2cab 100644 --- a/src/main/scala/xyz/driver/core/rest.scala +++ b/src/main/scala/xyz/driver/core/rest.scala @@ -269,7 +269,7 @@ package rest { RawHeader(h._1, h._2): HttpHeader }: _*) - log.audit(s"Sending to ${request.uri} request $request with tracking id ${context.trackingId}") + log.audit(s"Sending request to ${request.method} ${request.uri}") val response = Http()(actorSystem).singleRequest(request)(materializer) @@ -281,8 +281,7 @@ package rest { case Failure(t: Throwable) => val responseTime = time.currentTime() - log.audit(s"Failed to receive response from ${request.uri} to request $requestStub", t) - log.error(s"Failed to receive response from ${request.uri} to request $requestStub", t) + log.error(s"Failed to receive response to ${request.method} ${request.uri}", t) stats.recordStats(Seq("request", request.uri.toString, "fail"), TimeRange(requestTime, responseTime), 1) }(executionContext) @@ -295,7 +294,7 @@ package rest { if (response.status == StatusCodes.NotFound) { Unmarshal(HttpEntity.Empty: ResponseEntity) } else if (response.status.isFailure()) { - throw new Exception(s"Http status is failure ${response.status}") + throw new Exception(s"Http status is failure ${response.status} for ${requestStub.method} ${requestStub.uri}") } else { Unmarshal(response.entity) } -- cgit v1.2.3 From 0ed008ab290074eae0f11fa0149a736e8abd7064 Mon Sep 17 00:00:00 2001 From: vlad Date: Sat, 1 Apr 2017 03:51:29 -0700 Subject: More logging --- src/main/scala/xyz/driver/core/app.scala | 42 +++++++++++++++----------- src/main/scala/xyz/driver/core/execution.scala | 10 +++--- src/main/scala/xyz/driver/core/rest.scala | 3 +- 3 files changed, 32 insertions(+), 23 deletions(-) (limited to 'src/main/scala') diff --git a/src/main/scala/xyz/driver/core/app.scala b/src/main/scala/xyz/driver/core/app.scala index 4b81897..361fb74 100644 --- a/src/main/scala/xyz/driver/core/app.scala +++ b/src/main/scala/xyz/driver/core/app.scala @@ -67,24 +67,32 @@ object app { val versionRt = versionRoute(version, gitHash, time.currentTime()) val _ = Future { - http.bindAndHandle(route2HandlerFlow({ ctx => - val trackingId = rest.extractTrackingId(ctx.request) - MDC.put("trackingId", trackingId) - - def requestLogging: Future[Unit] = Future { - log.audit(s"""Received request {"method":"${ctx.request.method.value}","url": "${ctx.request.uri}"}""") + http.bindAndHandle(route2HandlerFlow(extractHost { origin => + extractClientIP { + ip => + { ctx => + val trackingId = rest.extractTrackingId(ctx.request) + MDC.put("trackingId", trackingId) + MDC.put("origin", origin) + MDC.put("ip", ip.toOption.map(_.getHostAddress).getOrElse("unknown")) + + def requestLogging: Future[Unit] = Future { + log.audit( + s"""Received request {"method":"${ctx.request.method.value}","url": "${ctx.request.uri}"}""") + } + + val contextWithTrackingId = + ctx.withRequest(ctx.request.addHeader(RawHeader(ContextHeaders.TrackingIdHeader, trackingId))) + + handleExceptions(ExceptionHandler(exceptionHandler))({ c => + requestLogging.flatMap { _ => + respondWithHeaders(List(RawHeader(ContextHeaders.TrackingIdHeader, trackingId))) { + modules.map(_.route).foldLeft(versionRt ~ healthRoute ~ swaggerRoutes)(_ ~ _) + }(c) + } + })(contextWithTrackingId) + } } - - val contextWithTrackingId = - ctx.withRequest(ctx.request.addHeader(RawHeader(ContextHeaders.TrackingIdHeader, trackingId))) - - handleExceptions(ExceptionHandler(exceptionHandler))({ c => - requestLogging.flatMap { _ => - respondWithHeaders(List(RawHeader(ContextHeaders.TrackingIdHeader, trackingId))) { - modules.map(_.route).foldLeft(versionRt ~ healthRoute ~ swaggerRoutes)(_ ~ _) - }(c) - } - })(contextWithTrackingId) }), interface, port)(materializer) } } diff --git a/src/main/scala/xyz/driver/core/execution.scala b/src/main/scala/xyz/driver/core/execution.scala index f27b905..0cf92fd 100644 --- a/src/main/scala/xyz/driver/core/execution.scala +++ b/src/main/scala/xyz/driver/core/execution.scala @@ -26,13 +26,13 @@ object execution { andEffect(effect.run) } - def illegalState[T](message: String) = - failure(new IllegalStateException(message)) + def illegalState[T](message: String): OptionT[Future, T] = + failure[T](new IllegalStateException(message)) - def illegalArgument[T](message: String) = - failure(new IllegalArgumentException(message)) + def illegalArgument[T](message: String): OptionT[Future, T] = + failure[T](new IllegalArgumentException(message)) - def failure[T](throwable: Throwable) = + def failure[T](throwable: Throwable): OptionT[Future, T] = OptionT.optionT(Future.failed[Option[T]](throwable)) def collectOrNone[T, R](value: T)(f: PartialFunction[T, OptionT[Future, R]]): OptionT[Future, R] = diff --git a/src/main/scala/xyz/driver/core/rest.scala b/src/main/scala/xyz/driver/core/rest.scala index 39f2cab..dc18375 100644 --- a/src/main/scala/xyz/driver/core/rest.scala +++ b/src/main/scala/xyz/driver/core/rest.scala @@ -281,7 +281,8 @@ package rest { case Failure(t: Throwable) => val responseTime = time.currentTime() - log.error(s"Failed to receive response to ${request.method} ${request.uri}", t) + log.audit(s"Failed to receive response from ${request.method} ${request.uri}", t) + log.error(s"Failed to receive response from ${request.method} ${request.uri}", t) stats.recordStats(Seq("request", request.uri.toString, "fail"), TimeRange(requestTime, responseTime), 1) }(executionContext) -- cgit v1.2.3