Skip to content

Commit

Permalink
[Self-service error codes] Adapt error factories [DPP-656] (#11270)
Browse files Browse the repository at this point in the history
* Moved ErrorCodesVersionSwitcher to //ledger/error

CHANGELOG_BEGIN
CHANGELOG_END

* Rename ErrorCodeLoggingContext to ContextualizedErrorLogger

* Refactored ErrorFactories
* All error factories use ContextualizedErrorLogger for being able to dispatch self-service error codes.
* The ContextualizedErrorLogger is passed down from the dispatching Ledger API services.
* ErrorFactoriesSpec asserts both legacy (V1) and self-service error codes (V2).

* Adapted ApiSubmissionService

* Addressed Marcin's review comments
  • Loading branch information
tudor-da authored Oct 18, 2021
1 parent b1a6b11 commit 2fc7490
Show file tree
Hide file tree
Showing 63 changed files with 844 additions and 406 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ package script
import com.daml.ledger.api.domain.PartyDetails
import com.daml.ledger.api.v1.transaction.{TransactionTree, TreeEvent}
import com.daml.ledger.api.v1.value
import com.daml.ledger.api.validation.ValueValidator
import com.daml.ledger.api.validation.NoLoggingValueValidator
import com.daml.lf.data.Ref._
import com.daml.lf.data._
import com.daml.lf.engine.script.ledgerinteraction.ScriptLedgerClient
Expand Down Expand Up @@ -699,7 +699,7 @@ object Converter {
tplId <- Converter.fromApiIdentifier(created.getTemplateId)
cid <- ContractId.fromString(created.contractId)
arg <-
ValueValidator
NoLoggingValueValidator
.validateRecord(created.getCreateArguments)
.left
.map(err => s"Failed to validate create argument: $err")
Expand All @@ -713,7 +713,7 @@ object Converter {
tplId <- Converter.fromApiIdentifier(exercised.getTemplateId)
cid <- ContractId.fromString(exercised.contractId)
choice <- ChoiceName.fromString(exercised.choice)
choiceArg <- ValueValidator
choiceArg <- NoLoggingValueValidator
.validateValue(exercised.getChoiceArgument)
.left
.map(err => s"Failed to validate exercise argument: $err")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import com.daml.ledger.api.v1.testing.time_service.TimeServiceGrpc.TimeServiceSt
import com.daml.ledger.api.v1.testing.time_service.{GetTimeRequest, SetTimeRequest, TimeServiceGrpc}
import com.daml.ledger.api.v1.transaction.TreeEvent
import com.daml.ledger.api.v1.transaction_filter.{Filters, InclusiveFilters, TransactionFilter}
import com.daml.ledger.api.validation.ValueValidator
import com.daml.ledger.api.validation.NoLoggingValueValidator
import com.daml.ledger.client.LedgerClient
import com.daml.lf.command
import com.daml.lf.data.Ref._
Expand Down Expand Up @@ -73,12 +73,13 @@ class GrpcLedgerClient(val grpcClient: LedgerClient, val applicationId: Applicat
acsResponses.map(acsPages =>
acsPages.toVector.flatMap(page =>
page.activeContracts.toVector.map(createdEvent => {
val argument = ValueValidator.validateRecord(createdEvent.getCreateArguments) match {
case Left(err) => throw new ConverterException(err.toString)
case Right(argument) => argument
}
val argument =
NoLoggingValueValidator.validateRecord(createdEvent.getCreateArguments) match {
case Left(err) => throw new ConverterException(err.toString)
case Right(argument) => argument
}
val key: Option[Value] = createdEvent.contractKey.map { key =>
ValueValidator.validateValue(key) match {
NoLoggingValueValidator.validateValue(key) match {
case Left(err) => throw new ConverterException(err.toString)
case Right(argument) => argument
}
Expand Down Expand Up @@ -315,7 +316,10 @@ class GrpcLedgerClient(val grpcClient: LedgerClient, val applicationId: Applicat
} yield ScriptLedgerClient.CreateResult(cid)
case TreeEvent(TreeEvent.Kind.Exercised(exercised)) =>
for {
result <- ValueValidator.validateValue(exercised.getExerciseResult).left.map(_.toString)
result <- NoLoggingValueValidator
.validateValue(exercised.getExerciseResult)
.left
.map(_.toString)
templateId <- Converter.fromApiIdentifier(exercised.getTemplateId)
choice <- ChoiceName.fromString(exercised.choice)
} yield ScriptLedgerClient.ExerciseResult(templateId, choice, result)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
package com.daml.http.util

import com.daml.lf
import com.daml.ledger.api.validation.ValueValidator
import com.daml.ledger.api.validation.NoLoggingValueValidator
import com.daml.ledger.api.{v1 => lav1}
import io.grpc.StatusRuntimeException
import scalaz.{Show, \/}
Expand All @@ -23,6 +23,6 @@ object ApiValueToLfValueConverter {
lav1.value.Value => Error \/ lf.value.Value

def apiValueToLfValue: ApiValueToLfValue = { a: lav1.value.Value =>
\/.fromEither(ValueValidator.validateValue(a)).leftMap(e => Error(e))
\/.fromEither(NoLoggingValueValidator.validateValue(a)).leftMap(e => Error(e))
}
}
10 changes: 5 additions & 5 deletions ledger/error/src/main/scala/com/daml/error/BaseError.scala
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,17 @@ trait BaseError extends LocationMixin {
def resources: Seq[(ErrorResource, String)] = Seq()

def logWithContext(extra: Map[String, String] = Map())(implicit
errorCodeLoggingContext: ErrorCodeLoggingContext
contextualizedErrorLogger: ContextualizedErrorLogger
): Unit =
errorCodeLoggingContext.logError(this, extra)
contextualizedErrorLogger.logError(this, extra)

def asGrpcStatusFromContext(implicit
errorCodeLoggingContext: ErrorCodeLoggingContext
contextualizedErrorLogger: ContextualizedErrorLogger
): Status =
code.asGrpcStatus(this)

def asGrpcErrorFromContext(implicit
errorCodeLoggingContext: ErrorCodeLoggingContext
contextualizedErrorLogger: ContextualizedErrorLogger
): StatusRuntimeException =
code.asGrpcError(this)

Expand Down Expand Up @@ -110,7 +110,7 @@ object BaseError {
extends BaseError {

/** The logging context obtained when we created the error, usually passed in as implicit */
def loggingContext: ErrorCodeLoggingContext
def loggingContext: ContextualizedErrorLogger

/** Flag to control if an error should be logged at creation
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,29 @@
package com.daml.error

import com.daml.error.ErrorCode.formatContextAsString
import com.daml.error.ErrorCodeLoggingContext.loggingValueToString
import com.daml.error.ContextualizedErrorLogger.loggingValueToString
import com.daml.logging.entries.LoggingValue
import com.daml.logging.{ContextualizedLogger, LoggingContext}
import org.slf4j.event.Level

/** Abstracts away from the logging tech stack used. */
trait ErrorCodeLoggingContext extends CanLog {
trait ContextualizedErrorLogger {
def properties: Map[String, String]
def correlationId: Option[String]
def logError(err: BaseError, extra: Map[String, String]): Unit
}

trait CanLog {
def info(message: String): Unit
def info(message: String, throwable: Throwable): Unit

def warn(message: String): Unit
def warn(message: String, throwable: Throwable): Unit

def error(message: String): Unit
def error(message: String, throwable: Throwable): Unit
}

class DamlErrorCodeLoggingContext(
class DamlContextualizedErrorLogger(
logger: ContextualizedLogger,
loggingContext: LoggingContext,
val correlationId: Option[String],
) extends ErrorCodeLoggingContext {
) extends ContextualizedErrorLogger {
override def properties: Map[String, String] =
loggingContext.entries.contents.view.map { case (key, value) =>
key -> loggingValueToString(value)
Expand Down Expand Up @@ -70,7 +65,7 @@ class DamlErrorCodeLoggingContext(
}
}

object ErrorCodeLoggingContext {
object ContextualizedErrorLogger {
// TODO error-codes: Extract this function into `LoggingContext` companion (and test)
private[error] val loggingValueToString: LoggingValue => String = {
case LoggingValue.Empty => ""
Expand All @@ -88,3 +83,15 @@ object ErrorCodeLoggingContext {
case LoggingValue.OfJson(json) => json.toString()
}
}

object NoLogging extends ContextualizedErrorLogger {
override def properties: Map[String, String] = Map.empty
override def correlationId: Option[String] = None
override def logError(err: BaseError, extra: Map[String, String]): Unit = ()
override def info(message: String): Unit = ()
override def info(message: String, throwable: Throwable): Unit = ()
override def warn(message: String): Unit = ()
override def warn(message: String, throwable: Throwable): Unit = ()
override def error(message: String): Unit = ()
override def error(message: String, throwable: Throwable): Unit = ()
}
8 changes: 4 additions & 4 deletions ledger/error/src/main/scala/com/daml/error/ErrorCode.scala
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ abstract class ErrorCode(val id: String, val category: ErrorCategory)(implicit
s"${codeStr(correlationId)}: ${ErrorCode.truncateCause(cause)}"

def asGrpcStatus(err: BaseError)(implicit
loggingContext: ErrorCodeLoggingContext
loggingContext: ContextualizedErrorLogger
): Status = {
val ErrorCode.StatusInfo(codeGrpc, message, contextMap, correlationId) =
getStatusInfo(err)
Expand Down Expand Up @@ -131,7 +131,7 @@ abstract class ErrorCode(val id: String, val category: ErrorCategory)(implicit
}

def asGrpcError(err: BaseError)(implicit
loggingContext: ErrorCodeLoggingContext
loggingContext: ContextualizedErrorLogger
): StatusRuntimeException = {
val status = asGrpcStatus(err)
// Builder methods for metadata are not exposed, so going route via creating an exception
Expand All @@ -152,7 +152,7 @@ abstract class ErrorCode(val id: String, val category: ErrorCategory)(implicit

def getStatusInfo(
err: BaseError
)(implicit loggingContext: ErrorCodeLoggingContext): ErrorCode.StatusInfo = {
)(implicit loggingContext: ContextualizedErrorLogger): ErrorCode.StatusInfo = {
val correlationId = loggingContext.correlationId
val message =
if (code.category.securitySensitive)
Expand All @@ -171,7 +171,7 @@ abstract class ErrorCode(val id: String, val category: ErrorCategory)(implicit

private[error] def getTruncatedContext(
err: BaseError
)(implicit loggingContext: ErrorCodeLoggingContext): Map[String, String] = {
)(implicit loggingContext: ContextualizedErrorLogger): Map[String, String] = {
val raw =
(err.context ++ loggingContext.properties).toSeq.filter(_._2.nonEmpty).sortBy(_._2.length)
val maxPerEntry = ErrorCode.MaxContentBytes / Math.max(1, raw.size)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
// Copyright (c) 2021 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

package com.daml.platform.apiserver
package com.daml.error

import com.daml.error.ValueSwitch
import io.grpc.StatusRuntimeException

import scala.concurrent.Future
Expand Down
Loading

0 comments on commit 2fc7490

Please sign in to comment.