Allow converting an error into a gRPC status [KVL-1142] (#11204)

* Allow converting an error into a gRPC status

CHANGELOG_BEGIN
CHANGELOG_END

* Add missing dependencies
This commit is contained in:
fabiotudone-da 2021-10-12 16:04:01 +02:00 committed by GitHub
parent 83d1e3cc0e
commit 04494136bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 23 additions and 7 deletions

View File

@ -49,6 +49,8 @@ da_scala_library(
deps = [
":error",
"//libs-scala/contextualized-logging",
"@maven//:com_google_api_grpc_proto_google_common_protos",
"@maven//:com_google_protobuf_protobuf_java",
"@maven//:io_grpc_grpc_api",
"@maven//:org_slf4j_slf4j_api",
],

View File

@ -3,6 +3,7 @@
package com.daml.error
import com.google.rpc.Status
import io.grpc.StatusRuntimeException
/** The main error interface for everything that should be logged and notified.
@ -50,6 +51,11 @@ trait BaseError extends LocationMixin {
): Unit =
errorCodeLoggingContext.logError(this, extra)
def asGrpcStatusFromContext(implicit
errorCodeLoggingContext: ErrorCodeLoggingContext
): Status =
code.asGrpcStatus(this)
def asGrpcErrorFromContext(implicit
errorCodeLoggingContext: ErrorCodeLoggingContext
): StatusRuntimeException =
@ -88,7 +94,7 @@ object BaseError {
val SecuritySensitiveMessageOnApi =
"An error occurred. Please contact the operator and inquire about the request"
def extractContext[D](obj: D): Map[String, String] = {
def extractContext[D](obj: D): Map[String, String] =
obj.getClass.getDeclaredFields
.filterNot(x => ignoreFields.contains(x.getName) || x.getName.startsWith("_"))
.map { field =>
@ -96,7 +102,6 @@ object BaseError {
(field.getName, field.get(obj).toString)
}
.toMap
}
abstract class Impl(
override val cause: String,
@ -116,9 +121,11 @@ object BaseError {
def log(): Unit = logWithContext()(loggingContext)
def asGrpcError: StatusRuntimeException = {
def asGrpcStatus: Status =
code.asGrpcStatus(this)(loggingContext)
def asGrpcError: StatusRuntimeException =
code.asGrpcError(this)(loggingContext)
}
// Automatically log the error on generation
if (logOnCreation) {

View File

@ -4,6 +4,7 @@
package com.daml.error
import com.daml.error.ErrorCode.{ValidMetadataKeyRegex, truncateResourceForTransport}
import com.google.rpc.Status
import io.grpc.Status.Code
import io.grpc.StatusRuntimeException
import io.grpc.protobuf.StatusProto
@ -58,9 +59,9 @@ abstract class ErrorCode(val id: String, val category: ErrorCategory)(implicit
def toMsg(cause: => String, correlationId: Option[String]): String =
s"${codeStr(correlationId)}: ${ErrorCode.truncateCause(cause)}"
def asGrpcError(err: BaseError)(implicit
def asGrpcStatus(err: BaseError)(implicit
loggingContext: ErrorCodeLoggingContext
): StatusRuntimeException = {
): Status = {
val ErrorCode.StatusInfo(codeGrpc, message, contextMap, correlationId) =
getStatusInfo(err)
@ -126,9 +127,15 @@ abstract class ErrorCode(val id: String, val category: ErrorCategory)(implicit
.foldLeft(statusBuilder) { case (acc, item) =>
acc.addDetails(item)
}
statusBuilder.build()
}
def asGrpcError(err: BaseError)(implicit
loggingContext: ErrorCodeLoggingContext
): StatusRuntimeException = {
val status = asGrpcStatus(err)
// Builder methods for metadata are not exposed, so going route via creating an exception
val ex = StatusProto.toStatusRuntimeException(statusBuilder.build())
val ex = StatusProto.toStatusRuntimeException(status)
// Strip stack trace from exception
new ErrorCode.ApiException(ex.getStatus, ex.getTrailers)
}