Skip to content

Commit e061d08

Browse files
bdoyle0182Brendan Doyle
andauthored
Add Activation Error Logging Config to Container Proxy (#4981)
* change activation error log level to warn * add container proxy activation error logging config Co-authored-by: Brendan Doyle <brendand@qualtrics.com>
1 parent ed3f76e commit e061d08

3 files changed

Lines changed: 31 additions & 15 deletions

File tree

common/scala/src/main/scala/org/apache/openwhisk/core/WhiskConfig.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ object ConfigKeys {
248248
val containerProxy = "whisk.container-proxy"
249249
val containerProxyTimeouts = s"$containerProxy.timeouts"
250250
val containerProxyHealth = s"$containerProxy.action-health-check"
251+
val containerProxyActivationErrorLogs = s"$containerProxy.log-activation-errors"
251252

252253
val s3 = "whisk.s3"
253254
val query = "whisk.query-limit"

core/invoker/src/main/resources/application.conf

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,12 @@ whisk {
157157
check-period = 3 seconds # how often should prewarm containers be pinged (tcp connection attempt)
158158
max-fails = 3 # prewarm containers that fail this number of times will be destroyed and replaced
159159
}
160+
161+
log-activation-errors {
162+
application-errors = false
163+
developer-errors = false
164+
whisk-errors = true
165+
}
160166
}
161167

162168
# tracing configuration

core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/ContainerProxy.scala

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ class ContainerProxy(factory: (TransactionId,
258258
instance: InvokerInstanceId,
259259
poolConfig: ContainerPoolConfig,
260260
healtCheckConfig: ContainerProxyHealthCheckConfig,
261+
activationErrorLoggingConfig: ContainerProxyActivationErrorLogConfig,
261262
unusedTimeout: FiniteDuration,
262263
pauseGrace: FiniteDuration,
263264
testTcp: Option[ActorRef])
@@ -935,37 +936,41 @@ class ContainerProxy(factory: (TransactionId,
935936

936937
// Disambiguate activation errors and transform the Either into a failed/successful Future respectively.
937938
activationWithLogs.flatMap {
938-
case Right(act) if !act.response.isSuccess && !act.response.isApplicationError =>
939-
val truncatedResult = truncatedError(act)
940-
logging.info(
941-
this,
942-
s"Activation ${act.activationId} was unsuccessful at container ${stateData.getContainer} (with ${activeCount} still active) due to ${truncatedResult}")
943-
Future.failed(ActivationUnsuccessfulError(act))
944-
case Left(error) => Future.failed(error)
945-
case Right(act) =>
946-
if (act.response.isApplicationError) {
947-
val truncatedResult = truncatedError(act)
948-
logging.error(
949-
this,
950-
s"Activation ${act.activationId} at container ${stateData.getContainer} (with ${activeCount} still active) returned an error ${truncatedResult}")
939+
case Right(act) if act.response.isSuccess || act.response.isApplicationError =>
940+
if (act.response.isApplicationError && activationErrorLoggingConfig.applicationErrors) {
941+
logTruncatedError(act)
951942
}
952943
Future.successful(act)
944+
case Right(act) =>
945+
if ((act.response.isContainerError && activationErrorLoggingConfig.developerErrors) ||
946+
(act.response.isWhiskError && activationErrorLoggingConfig.whiskErrors)) {
947+
logTruncatedError(act)
948+
}
949+
Future.failed(ActivationUnsuccessfulError(act))
950+
case Left(error) => Future.failed(error)
953951
}
954952
}
955953
//to ensure we don't blow up logs with potentially large activation response error
956-
private def truncatedError(act: WhiskActivation) = {
954+
private def logTruncatedError(act: WhiskActivation) = {
957955
val truncate = 1024
958956
val resultString = act.response.result.map(_.compactPrint).getOrElse("[no result]")
959-
if (resultString.length > truncate) {
957+
val truncatedResult = if (resultString.length > truncate) {
960958
s"${resultString.take(truncate)}..."
961959
} else {
962960
resultString
963961
}
962+
val errorTypeMessage = ActivationResponse.messageForCode(act.response.statusCode)
963+
logging.warn(
964+
this,
965+
s"Activation ${act.activationId} at container ${stateData.getContainer} (with $activeCount still active) returned a $errorTypeMessage: $truncatedResult")
964966
}
965967
}
966968

967969
final case class ContainerProxyTimeoutConfig(idleContainer: FiniteDuration, pauseGrace: FiniteDuration)
968970
final case class ContainerProxyHealthCheckConfig(enabled: Boolean, checkPeriod: FiniteDuration, maxFails: Int)
971+
final case class ContainerProxyActivationErrorLogConfig(applicationErrors: Boolean,
972+
developerErrors: Boolean,
973+
whiskErrors: Boolean)
969974

970975
object ContainerProxy {
971976
def props(factory: (TransactionId,
@@ -982,6 +987,7 @@ object ContainerProxy {
982987
poolConfig: ContainerPoolConfig,
983988
healthCheckConfig: ContainerProxyHealthCheckConfig =
984989
loadConfigOrThrow[ContainerProxyHealthCheckConfig](ConfigKeys.containerProxyHealth),
990+
activationErrorLogConfig: ContainerProxyActivationErrorLogConfig = activationErrorLogging,
985991
unusedTimeout: FiniteDuration = timeouts.idleContainer,
986992
pauseGrace: FiniteDuration = timeouts.pauseGrace,
987993
tcp: Option[ActorRef] = None) =
@@ -994,6 +1000,7 @@ object ContainerProxy {
9941000
instance,
9951001
poolConfig,
9961002
healthCheckConfig,
1003+
activationErrorLogConfig,
9971004
unusedTimeout,
9981005
pauseGrace,
9991006
tcp))
@@ -1002,6 +1009,8 @@ object ContainerProxy {
10021009
private val containerCount = new Counter
10031010

10041011
val timeouts = loadConfigOrThrow[ContainerProxyTimeoutConfig](ConfigKeys.containerProxyTimeouts)
1012+
val activationErrorLogging =
1013+
loadConfigOrThrow[ContainerProxyActivationErrorLogConfig](ConfigKeys.containerProxyActivationErrorLogs)
10051014

10061015
/**
10071016
* Generates a unique container name.

0 commit comments

Comments
 (0)