Skip to content

Commit f589b18

Browse files
maxdayAlexander Smirnov
and
Alexander Smirnov
authored
Use Lambda-Runtime-Function-Error-Type for reporting errors in format "Runtime.<Error>" (#501)
* Introduce Runtime. error codes * fix: apply linting * Remove unused imports --------- Co-authored-by: Alexander Smirnov <[email protected]>
1 parent ff5d9e0 commit f589b18

File tree

8 files changed

+86
-53
lines changed

8 files changed

+86
-53
lines changed

aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/AWSLambda.java

+19-12
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@
1111
import com.amazonaws.services.lambda.runtime.api.client.logging.LambdaContextLogger;
1212
import com.amazonaws.services.lambda.runtime.api.client.logging.LogSink;
1313
import com.amazonaws.services.lambda.runtime.api.client.logging.StdOutLogSink;
14+
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.LambdaError;
1415
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.LambdaRuntimeApiClient;
1516
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.LambdaRuntimeApiClientImpl;
17+
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.RapidErrorType;
1618
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.converters.LambdaErrorConverter;
1719
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.converters.XRayErrorCauseConverter;
1820
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest;
19-
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.LambdaError;
20-
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.XRayErrorCause;
2121
import com.amazonaws.services.lambda.runtime.api.client.util.LambdaOutputStream;
2222
import com.amazonaws.services.lambda.runtime.api.client.util.UnsafeUtil;
2323
import com.amazonaws.services.lambda.runtime.logging.LogFormat;
@@ -215,7 +215,9 @@ private static void startRuntime(String handler, LambdaContextLogger lambdaLogge
215215
requestHandler = findRequestHandler(handler, customerClassLoader);
216216
} catch (UserFault userFault) {
217217
lambdaLogger.log(userFault.reportableError(), lambdaLogger.getLogFormat() == LogFormat.JSON ? LogLevel.ERROR : LogLevel.UNDEFINED);
218-
LambdaError error = LambdaErrorConverter.fromUserFault(userFault);
218+
LambdaError error = new LambdaError(
219+
LambdaErrorConverter.fromUserFault(userFault),
220+
RapidErrorType.BadFunctionCode);
219221
runtimeClient.reportInitError(error);
220222
System.exit(1);
221223
return;
@@ -243,17 +245,20 @@ private static void startRuntime(String handler, LambdaContextLogger lambdaLogge
243245
shouldExit = f.fatal;
244246
userFault = f;
245247
UserFault.filterStackTrace(f);
246-
247-
LambdaError error = LambdaErrorConverter.fromUserFault(f);
248+
LambdaError error = new LambdaError(
249+
LambdaErrorConverter.fromUserFault(f),
250+
RapidErrorType.BadFunctionCode);
248251
runtimeClient.reportInvocationError(request.getId(), error);
249252
} catch (Throwable t) {
250253
shouldExit = t instanceof VirtualMachineError || t instanceof IOError;
251254
UserFault.filterStackTrace(t);
252255
userFault = UserFault.makeUserFault(t);
253256

254-
LambdaError error = LambdaErrorConverter.fromThrowable(t);
255-
XRayErrorCause xRayErrorCause = XRayErrorCauseConverter.fromThrowable(t);
256-
runtimeClient.reportInvocationError(request.getId(), error, xRayErrorCause);
257+
LambdaError error = new LambdaError(
258+
LambdaErrorConverter.fromThrowable(t),
259+
XRayErrorCauseConverter.fromThrowable(t),
260+
RapidErrorType.UserException);
261+
runtimeClient.reportInvocationError(request.getId(), error);
257262
} finally {
258263
if (userFault != null) {
259264
lambdaLogger.log(userFault.reportableError(), lambdaLogger.getLogFormat() == LogFormat.JSON ? LogLevel.ERROR : LogLevel.UNDEFINED);
@@ -268,16 +273,18 @@ static void onInitComplete(final LambdaContextLogger lambdaLogger) throws IOExce
268273
runtimeClient.restoreNext();
269274
} catch (Exception e1) {
270275
logExceptionCloudWatch(lambdaLogger, e1);
271-
LambdaError error = LambdaErrorConverter.fromThrowable(e1);
272-
runtimeClient.reportInitError(error);
276+
runtimeClient.reportInitError(new LambdaError(
277+
LambdaErrorConverter.fromThrowable(e1),
278+
RapidErrorType.BeforeCheckpointError));
273279
System.exit(64);
274280
}
275281
try {
276282
Core.getGlobalContext().afterRestore(null);
277283
} catch (Exception restoreExc) {
278284
logExceptionCloudWatch(lambdaLogger, restoreExc);
279-
LambdaError error = LambdaErrorConverter.fromThrowable(restoreExc);
280-
runtimeClient.reportRestoreError(error);
285+
runtimeClient.reportRestoreError(new LambdaError(
286+
LambdaErrorConverter.fromThrowable(restoreExc),
287+
RapidErrorType.AfterRestoreError));
281288
System.exit(64);
282289
}
283290
}

aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/DtoSerializers.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*/
55
package com.amazonaws.services.lambda.runtime.api.client.runtimeapi;
66

7-
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.LambdaError;
7+
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.ErrorRequest;
88
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.XRayErrorCause;
99
import com.amazonaws.services.lambda.runtime.serialization.PojoSerializer;
1010
import com.amazonaws.services.lambda.runtime.serialization.factories.GsonFactory;
@@ -13,7 +13,7 @@
1313

1414
public class DtoSerializers {
1515

16-
public static byte[] serialize(LambdaError error) {
16+
public static byte[] serialize(ErrorRequest error) {
1717
return serialize(error, SingletonHelper.LAMBDA_ERROR_SERIALIZER);
1818
}
1919

@@ -36,7 +36,7 @@ private static <T> byte[] serialize(T pojo, PojoSerializer<T> serializer) {
3636
* This way the serializers will be loaded lazily
3737
*/
3838
private static class SingletonHelper {
39-
private static final PojoSerializer<LambdaError> LAMBDA_ERROR_SERIALIZER = GsonFactory.getInstance().getSerializer(LambdaError.class);
39+
private static final PojoSerializer<ErrorRequest> LAMBDA_ERROR_SERIALIZER = GsonFactory.getInstance().getSerializer(ErrorRequest.class);
4040
private static final PojoSerializer<XRayErrorCause> X_RAY_ERROR_CAUSE_SERIALIZER = GsonFactory.getInstance().getSerializer(XRayErrorCause.class);
4141
}
4242
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
SPDX-License-Identifier: Apache-2.0
4+
*/
5+
package com.amazonaws.services.lambda.runtime.api.client.runtimeapi;
6+
7+
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.ErrorRequest;
8+
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.XRayErrorCause;
9+
10+
public class LambdaError {
11+
12+
public final ErrorRequest errorRequest;
13+
14+
public final XRayErrorCause xRayErrorCause;
15+
16+
public final RapidErrorType errorType;
17+
18+
public LambdaError(ErrorRequest errorRequest, XRayErrorCause xRayErrorCause, RapidErrorType errorType) {
19+
this.errorRequest = errorRequest;
20+
this.xRayErrorCause = xRayErrorCause;
21+
this.errorType = errorType;
22+
}
23+
24+
public LambdaError(ErrorRequest errorRequest, RapidErrorType errorType) {
25+
this(errorRequest, null, errorType);
26+
}
27+
}

aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/LambdaRuntimeApiClient.java

-10
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
package com.amazonaws.services.lambda.runtime.api.client.runtimeapi;
66

77
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest;
8-
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.LambdaError;
9-
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.XRayErrorCause;
108
import java.io.IOException;
119

1210
/**
@@ -40,14 +38,6 @@ public interface LambdaRuntimeApiClient {
4038
*/
4139
void reportInvocationError(String requestId, LambdaError error) throws IOException;
4240

43-
/**
44-
* Report invocation error
45-
* @param requestId request id
46-
* @param error error to report
47-
* @param xRayErrorCause X-Ray error cause
48-
*/
49-
void reportInvocationError(String requestId, LambdaError error, XRayErrorCause xRayErrorCause) throws IOException;
50-
5141
/**
5242
* SnapStart endpoint to report that beforeCheckoint hooks were executed
5343
*/

aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/LambdaRuntimeApiClientImpl.java

+10-18
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
package com.amazonaws.services.lambda.runtime.api.client.runtimeapi;
66

77
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest;
8-
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.LambdaError;
9-
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.XRayErrorCause;
108
import java.io.IOException;
119
import java.io.InputStream;
1210
import java.io.OutputStream;
@@ -46,7 +44,7 @@ public LambdaRuntimeApiClientImpl(String hostnameAndPort) {
4644
@Override
4745
public void reportInitError(LambdaError error) throws IOException {
4846
String endpoint = this.baseUrl + "/2018-06-01/runtime/init/error";
49-
reportLambdaError(endpoint, error, null);
47+
reportLambdaError(endpoint, error, XRAY_ERROR_CAUSE_MAX_HEADER_SIZE);
5048
}
5149

5250
@Override
@@ -61,13 +59,8 @@ public void reportInvocationSuccess(String requestId, byte[] response) {
6159

6260
@Override
6361
public void reportInvocationError(String requestId, LambdaError error) throws IOException {
64-
reportInvocationError(requestId, error, null);
65-
}
66-
67-
@Override
68-
public void reportInvocationError(String requestId, LambdaError error, XRayErrorCause xRayErrorCause) throws IOException {
6962
String endpoint = invocationEndpoint + requestId + "/error";
70-
reportLambdaError(endpoint, error, xRayErrorCause);
63+
reportLambdaError(endpoint, error, XRAY_ERROR_CAUSE_MAX_HEADER_SIZE);
7164
}
7265

7366
@Override
@@ -82,22 +75,21 @@ public void restoreNext() throws IOException {
8275
@Override
8376
public void reportRestoreError(LambdaError error) throws IOException {
8477
String endpoint = this.baseUrl + "/2018-06-01/runtime/restore/error";
85-
reportLambdaError(endpoint, error, null);
78+
reportLambdaError(endpoint, error, XRAY_ERROR_CAUSE_MAX_HEADER_SIZE);
8679
}
8780

88-
void reportLambdaError(String endpoint, LambdaError error, XRayErrorCause xRayErrorCause) throws IOException {
81+
void reportLambdaError(String endpoint, LambdaError error, int maxXrayHeaderSize) throws IOException {
8982
Map<String, String> headers = new HashMap<>();
90-
if (error.errorType != null && !error.errorType.isEmpty()) {
91-
headers.put(ERROR_TYPE_HEADER, error.errorType);
92-
}
93-
if (xRayErrorCause != null) {
94-
byte[] xRayErrorCauseJson = DtoSerializers.serialize(xRayErrorCause);
95-
if (xRayErrorCauseJson != null && xRayErrorCauseJson.length < XRAY_ERROR_CAUSE_MAX_HEADER_SIZE) {
83+
headers.put(ERROR_TYPE_HEADER, error.errorType.getRapidError());
84+
85+
if (error.xRayErrorCause != null) {
86+
byte[] xRayErrorCauseJson = DtoSerializers.serialize(error.xRayErrorCause);
87+
if (xRayErrorCauseJson != null && xRayErrorCauseJson.length < maxXrayHeaderSize) {
9688
headers.put(XRAY_ERROR_CAUSE_HEADER, new String(xRayErrorCauseJson));
9789
}
9890
}
9991

100-
byte[] payload = DtoSerializers.serialize(error);
92+
byte[] payload = DtoSerializers.serialize(error.errorRequest);
10193
int responseCode = doPost(endpoint, headers, payload);
10294
if (responseCode != HTTP_ACCEPTED) {
10395
throw new LambdaRuntimeClientException(endpoint, responseCode);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*
2+
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
SPDX-License-Identifier: Apache-2.0
4+
*/
5+
package com.amazonaws.services.lambda.runtime.api.client.runtimeapi;
6+
7+
public enum RapidErrorType {
8+
BadFunctionCode,
9+
UserException,
10+
BeforeCheckpointError,
11+
AfterRestoreError;
12+
13+
public String getRapidError() {
14+
return "Runtime." + this;
15+
}
16+
}

aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/converters/LambdaErrorConverter.java

+8-7
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,28 @@
55
package com.amazonaws.services.lambda.runtime.api.client.runtimeapi.converters;
66

77
import com.amazonaws.services.lambda.runtime.api.client.UserFault;
8-
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.LambdaError;
8+
import com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.ErrorRequest;
99

1010
public class LambdaErrorConverter {
1111
private LambdaErrorConverter() {
1212
}
1313

14-
public static LambdaError fromUserFault(UserFault userFault) {
14+
public static ErrorRequest fromUserFault(UserFault userFault) {
1515
// Not setting stacktrace for compatibility with legacy/native runtime
16-
return new LambdaError(userFault.msg, userFault.exception, null);
16+
return new ErrorRequest(userFault.msg, userFault.exception, null);
1717
}
1818

19-
public static LambdaError fromThrowable(Throwable throwable) {
20-
String errorMessage = throwable.getLocalizedMessage() == null
21-
? throwable.getClass().getName() : throwable.getLocalizedMessage();
19+
public static ErrorRequest fromThrowable(Throwable throwable) {
20+
String errorMessage = throwable.getLocalizedMessage() == null
21+
? throwable.getClass().getName()
22+
: throwable.getLocalizedMessage();
2223
String errorType = throwable.getClass().getName();
2324

2425
StackTraceElement[] trace = throwable.getStackTrace();
2526
String[] stackTrace = new String[trace.length];
2627
for (int i = 0; i < trace.length; i++) {
2728
stackTrace[i] = trace[i].toString();
2829
}
29-
return new LambdaError(errorMessage, errorType, stackTrace);
30+
return new ErrorRequest(errorMessage, errorType, stackTrace);
3031
}
3132
}
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@
44
*/
55
package com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto;
66

7-
public class LambdaError {
7+
public class ErrorRequest {
88
public String errorMessage;
99
public String errorType;
1010
public String[] stackTrace;
1111

1212
@SuppressWarnings("unused")
13-
public LambdaError() {
13+
public ErrorRequest() {
1414
}
1515

16-
public LambdaError(String errorMessage, String errorType, String[] stackTrace) {
16+
public ErrorRequest(String errorMessage, String errorType, String[] stackTrace) {
1717
this.errorMessage = errorMessage;
1818
this.errorType = errorType;
1919
this.stackTrace = stackTrace;

0 commit comments

Comments
 (0)