Skip to content

Commit

Permalink
Fix logging of internal server errors for the json api
Browse files Browse the repository at this point in the history
changelog_begin

- [HTTP-JSON] Internal server errors are now properly logged again

changelog_end
  • Loading branch information
realvictorprm committed Feb 8, 2022
1 parent 0f4e952 commit 9fffc33
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,15 @@ class Endpoints(
private def responseToRoute(res: Future[HttpResponse]): Route = _ => res map Complete
private def toRoute[A](
res: ET[domain.SyncResponse[A]]
)(implicit metrics: Metrics, jsonWriter: JsonWriter[A]): Route =
)(implicit
lc: LoggingContextOf[InstanceUUID with RequestID],
metrics: Metrics,
jsonWriter: JsonWriter[A],
): Route =
responseToRoute(httpResponse(res))
private def toRoute(res: => Future[Error \/ SearchResult[Error \/ JsValue]]): Route =
private def toRoute(res: => Future[Error \/ SearchResult[Error \/ JsValue]])(implicit
lc: LoggingContextOf[InstanceUUID with RequestID]
): Route =
responseToRoute(httpResponse(res))

private def mkRequestLogMsg(request: HttpRequest, remoteAddress: RemoteAddress) =
Expand Down Expand Up @@ -708,7 +714,7 @@ class Endpoints(

private def httpResponse(
output: Future[Error \/ SearchResult[Error \/ JsValue]]
): Future[HttpResponse] =
)(implicit lc: LoggingContextOf[InstanceUUID with RequestID]): Future[HttpResponse] =
output
.map {
case -\/(e) => httpResponseError(e)
Expand Down Expand Up @@ -750,7 +756,10 @@ class Endpoints(

private def httpResponse[A: JsonWriter](
result: ET[domain.SyncResponse[A]]
)(implicit metrics: Metrics): Future[HttpResponse] = {
)(implicit
lc: LoggingContextOf[InstanceUUID with RequestID],
metrics: Metrics,
): Future[HttpResponse] = {
Timed.future(
metrics.daml.HttpJsonApi.responseCreationTimer,
result
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import akka.http.scaladsl.server.{RequestContext, Route}
import akka.util.ByteString
import com.daml.http.domain.{JwtPayload, JwtPayloadLedgerIdOnly, JwtWritePayload}
import com.daml.http.json.SprayJson
import com.daml.http.util.Logging.{InstanceUUID, RequestID}
import com.daml.http.util.Logging.{InstanceUUID, RequestID, extendWithRequestIdLogCtx}
import util.GrpcHttpErrorCodes._
import com.daml.jwt.domain.{DecodedJwt, Jwt}
import com.daml.ledger.api.auth.{AuthServiceJWTCodec, CustomDamlJWTPayload, StandardJWTPayload}
Expand Down Expand Up @@ -290,27 +290,35 @@ object EndpointsCompanion {
}
}

lazy val notFound: Route = (ctx: RequestContext) =>
def notFound(implicit lc: LoggingContextOf[InstanceUUID]): Route = (ctx: RequestContext) =>
ctx.request match {
case HttpRequest(method, uri, _, _, _) =>
Future.successful(
Complete(httpResponseError(NotFound(s"${method: HttpMethod}, uri: ${uri: Uri}")))
extendWithRequestIdLogCtx(implicit lc =>
Future.successful(
Complete(httpResponseError(NotFound(s"${method: HttpMethod}, uri: ${uri: Uri}")))
)
)
}

private[http] def httpResponseError(error: Error): HttpResponse = {
private[http] def httpResponseError(
error: Error
)(implicit lc: LoggingContextOf[InstanceUUID with RequestID]): HttpResponse = {
import com.daml.http.json.JsonProtocol._
val resp = errorResponse(error)
httpResponse(resp.status, SprayJson.encodeUnsafe(resp))
}
private[this] val logger = ContextualizedLogger.get(getClass)

private[http] def errorResponse(error: Error): domain.ErrorResponse = {
private[http] def errorResponse(
error: Error
)(implicit lc: LoggingContextOf[InstanceUUID with RequestID]): domain.ErrorResponse = {
val (status, errorMsg): (StatusCode, String) = error match {
case InvalidUserInput(e) => StatusCodes.BadRequest -> e
case ParticipantServerError(grpcStatus, d) =>
grpcStatus.asAkkaHttpForJsonApi -> s"$grpcStatus${d.cata((": " + _), "")}"
case ServerError(_) => StatusCodes.InternalServerError -> "HTTP JSON API Server Error"
case ServerError(reason) =>
logger.error(s"Internal server error occured: $reason")
StatusCodes.InternalServerError -> "HTTP JSON API Server Error"
case Unauthorized(e) => StatusCodes.Unauthorized -> e
case NotFound(e) => StatusCodes.NotFound -> e
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import Liskov.<~<
import com.daml.http.domain.TemplateId.toLedgerApiValue
import com.daml.http.domain.TemplateId.{OptionalPkg, RequiredPkg}
import com.daml.http.util.FlowUtil.allowOnlyFirstInput
import com.daml.http.util.Logging.InstanceUUID
import com.daml.http.util.Logging.{InstanceUUID, RequestID, extendWithRequestIdLogCtx}
import com.daml.lf.crypto.Hash
import com.daml.logging.{ContextualizedLogger, LoggingContextOf}
import com.daml.metrics.Metrics
Expand Down Expand Up @@ -697,7 +697,9 @@ class WebSocketService(
}.valueOr(e => Source.single(-\/(e))): Source[Error \/ Message, NotUsed],
)
.takeWhile(_.isRight, inclusive = true) // stop after emitting 1st error
.map(_.fold(e => wsErrorMessage(e), identity): Message)
.map(
_.fold(e => extendWithRequestIdLogCtx(implicit lc1 => wsErrorMessage(e)), identity): Message
)
}

private def parseJson(x: Message): Future[InvalidUserInput \/ JsValue] = x match {
Expand Down Expand Up @@ -931,7 +933,9 @@ class WebSocketService(
.collect { case (_, Some(x)) => x }
}

private[http] def wsErrorMessage(error: Error): TextMessage.Strict =
private[http] def wsErrorMessage(error: Error)(implicit
lc: LoggingContextOf[InstanceUUID with RequestID]
): TextMessage.Strict =
wsMessage(SprayJson.encodeUnsafe(errorResponse(error)))

private[http] def wsMessage(jsVal: JsValue): TextMessage.Strict =
Expand Down

0 comments on commit 9fffc33

Please sign in to comment.