getMessages() {
+ return messages;
+ }
+ }
+
+ private void logMessages(LambdaLogger logger) {
+ logger.log("trace", LogLevel.TRACE);
+ logger.log("debug", LogLevel.DEBUG);
+ logger.log("info", LogLevel.INFO);
+ logger.log("warn", LogLevel.WARN);
+ logger.log("error", LogLevel.ERROR);
+ logger.log("fatal", LogLevel.FATAL);
+ }
+
+ @Test
+ public void testWithoutFiltering() {
+ TestLogger logger = new TestLogger(LogLevel.UNDEFINED, LogFormat.TEXT);
+ logMessages(logger);
+
+ assertEquals(6, logger.getMessages().size());
+ }
+
+ @Test
+ public void testWithFiltering() {
+ TestLogger logger = new TestLogger(LogLevel.WARN, LogFormat.TEXT);
+ logMessages(logger);
+
+ assertEquals(3, logger.getMessages().size());
+ }
+
+ @Test
+ public void testUndefinedLogLevelWithFiltering() {
+ TestLogger logger = new TestLogger(LogLevel.WARN, LogFormat.TEXT);
+ logger.log("undefined");
+
+ assertEquals(1, logger.getMessages().size());
+ }
+
+ @Test
+ public void testFormattingLogMessages() {
+ TestLogger logger = new TestLogger(LogLevel.INFO, LogFormat.TEXT);
+ logger.log("test message", LogLevel.INFO);
+
+ assertEquals(1, logger.getMessages().size());
+ assertEquals("[INFO] test message", new String(logger.getMessages().get(0)));
+ }
+}
diff --git a/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/logging/FrameTypeTest.java b/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/logging/FrameTypeTest.java
new file mode 100644
index 00000000..65078790
--- /dev/null
+++ b/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/logging/FrameTypeTest.java
@@ -0,0 +1,39 @@
+package com.amazonaws.services.lambda.runtime.api.client.logging;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+import com.amazonaws.services.lambda.runtime.logging.LogLevel;
+import com.amazonaws.services.lambda.runtime.logging.LogFormat;
+
+public class FrameTypeTest {
+
+ @Test
+ public void logFrames() {
+ assertHexEquals(
+ 0xa55a0003,
+ FrameType.getValue(LogLevel.UNDEFINED, LogFormat.TEXT)
+ );
+
+ assertHexEquals(
+ 0xa55a001b,
+ FrameType.getValue(LogLevel.FATAL, LogFormat.TEXT)
+ );
+ }
+
+
+ /**
+ * Helper function to make it easier to debug failing test.
+ *
+ * @param expected Expected value as int
+ * @param actual Actual value as int
+ */
+ private void assertHexEquals(int expected, int actual) {
+ assertEquals(
+ Integer.toHexString(expected),
+ Integer.toHexString(actual)
+ );
+ }
+
+}
diff --git a/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/logging/FramedTelemetryLogSinkTest.java b/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/logging/FramedTelemetryLogSinkTest.java
index e8dbb73b..e3e68a69 100644
--- a/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/logging/FramedTelemetryLogSinkTest.java
+++ b/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/logging/FramedTelemetryLogSinkTest.java
@@ -20,6 +20,9 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import com.amazonaws.services.lambda.runtime.logging.LogLevel;
+import com.amazonaws.services.lambda.runtime.logging.LogFormat;
+
public class FramedTelemetryLogSinkTest {
private static final int DEFAULT_BUFFER_SIZE = 256;
@@ -35,13 +38,16 @@ private long timestamp() {
@Test
public void logSingleFrame() throws IOException {
- byte[] message = "hello world\nsomething on a new line!\n".getBytes();
+ byte[] message = "{\"message\": \"hello world\nsomething on a new line!\"}".getBytes();
+ LogLevel logLevel = LogLevel.ERROR;
+ LogFormat logFormat = LogFormat.JSON;
+
File tmpFile = tmpFolder.resolve("pipe").toFile();
FileOutputStream fos = new FileOutputStream(tmpFile);
FileDescriptor fd = fos.getFD();
long before = timestamp();
try (FramedTelemetryLogSink logSink = new FramedTelemetryLogSink(fd)) {
- logSink.log(message);
+ logSink.log(logLevel, logFormat, message);
}
long after = timestamp();
@@ -54,7 +60,7 @@ public void logSingleFrame() throws IOException {
// first 4 bytes indicate the type
int type = buf.getInt();
- assertEquals(FrameType.LOG.getValue(), type);
+ assertEquals(FrameType.getValue(logLevel, logFormat), type);
// next 4 bytes indicate the length of the message
int len = buf.getInt();
@@ -71,7 +77,7 @@ public void logSingleFrame() throws IOException {
assertArrayEquals(message, actual);
// rest of buffer should be empty
- while(buf.hasRemaining())
+ while (buf.hasRemaining())
assertEquals(ZERO_BYTE, buf.get());
}
@@ -79,13 +85,16 @@ public void logSingleFrame() throws IOException {
public void logMultipleFrames() throws IOException {
byte[] firstMessage = "hello world\nsomething on a new line!".getBytes();
byte[] secondMessage = "hello again\nhere's another message\n".getBytes();
+ LogLevel logLevel = LogLevel.ERROR;
+ LogFormat logFormat = LogFormat.TEXT;
+
File tmpFile = tmpFolder.resolve("pipe").toFile();
FileOutputStream fos = new FileOutputStream(tmpFile);
FileDescriptor fd = fos.getFD();
long before = timestamp();
try (FramedTelemetryLogSink logSink = new FramedTelemetryLogSink(fd)) {
- logSink.log(firstMessage);
- logSink.log(secondMessage);
+ logSink.log(logLevel, logFormat, firstMessage);
+ logSink.log(logLevel, logFormat, secondMessage);
}
long after = timestamp();
@@ -96,10 +105,10 @@ public void logMultipleFrames() throws IOException {
// reset the position to the start
buf.position(0);
- for(byte[] message : Arrays.asList(firstMessage, secondMessage)) {
+ for (byte[] message : Arrays.asList(firstMessage, secondMessage)) {
// first 4 bytes indicate the type
int type = buf.getInt();
- assertEquals(FrameType.LOG.getValue(), type);
+ assertEquals(FrameType.getValue(logLevel, logFormat), type);
// next 4 bytes indicate the length of the message
int len = buf.getInt();
@@ -117,7 +126,7 @@ public void logMultipleFrames() throws IOException {
}
// rest of buffer should be empty
- while(buf.hasRemaining())
+ while (buf.hasRemaining())
assertEquals(ZERO_BYTE, buf.get());
}
@@ -125,7 +134,7 @@ public void logMultipleFrames() throws IOException {
* The implementation of FramedTelemetryLogSink was based on java.nio.channels.WritableByteChannel which would
* throw ClosedByInterruptException if Thread.currentThread.interrupt() was called. The implementation was changed
* and this test ensures that logging works even if the current thread was interrupted.
- *
+ *
* https://t.corp.amazon.com/0304370986/
*/
@Test
@@ -138,7 +147,7 @@ public void interruptedThread() throws IOException {
try (FramedTelemetryLogSink logSink = new FramedTelemetryLogSink(fd)) {
Thread.currentThread().interrupt();
- logSink.log(message);
+ logSink.log(LogLevel.ERROR, LogFormat.TEXT, message);
}
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
@@ -150,8 +159,8 @@ public void interruptedThread() throws IOException {
assertEquals(expectedBytes, readBytes);
- for(int i = 0; i < message.length; i++) {
- assertEquals(buffer[i + headerSizeBytes], message[i]);
+ for (int i = 0; i < message.length; i++) {
+ assertEquals(message[i], buffer[i + headerSizeBytes]);
}
} finally {
// clear interrupted status of the current thread
diff --git a/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/logging/JsonLogFormatterTest.java b/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/logging/JsonLogFormatterTest.java
new file mode 100644
index 00000000..8630d5fe
--- /dev/null
+++ b/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/logging/JsonLogFormatterTest.java
@@ -0,0 +1,57 @@
+package com.amazonaws.services.lambda.runtime.api.client.logging;
+
+import com.amazonaws.services.lambda.runtime.api.client.api.LambdaContext;
+import com.amazonaws.services.lambda.runtime.serialization.PojoSerializer;
+import com.amazonaws.services.lambda.runtime.serialization.factories.GsonFactory;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import com.amazonaws.services.lambda.runtime.logging.LogLevel;
+
+public class JsonLogFormatterTest {
+
+ @Test
+ void testFormattingWithoutLambdaContext() {
+ assertFormatsString("test log", LogLevel.WARN, null);
+ }
+
+ @Test
+ void testFormattingWithLambdaContext() {
+ LambdaContext context = new LambdaContext(
+ 0,
+ 0,
+ "request-id",
+ null,
+ null,
+ "function-name",
+ null,
+ null,
+ "function-arn",
+ null
+ );
+ assertFormatsString("test log", LogLevel.WARN, context);
+ }
+
+ void assertFormatsString(String message, LogLevel logLevel, LambdaContext context) {
+ JsonLogFormatter logFormatter = new JsonLogFormatter();
+ if (context != null) {
+ logFormatter.setLambdaContext(context);
+ }
+ String output = logFormatter.format(message, logLevel);
+
+ PojoSerializer serializer = GsonFactory.getInstance().getSerializer(StructuredLogMessage.class);
+ assert_expected_log_message(serializer.fromJson(output), message, logLevel, context);
+ }
+
+ void assert_expected_log_message(StructuredLogMessage result, String message, LogLevel logLevel, LambdaContext context) {
+ assertEquals(message, result.message);
+ assertEquals(logLevel, result.level);
+ assertNotNull(result.timestamp);
+
+ if (context != null) {
+ assertEquals(context.getAwsRequestId(), result.AWSRequestId);
+ }
+ }
+}
diff --git a/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/logging/StdOutLogSinkTest.java b/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/logging/StdOutLogSinkTest.java
index 83399646..b1bbefc4 100644
--- a/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/logging/StdOutLogSinkTest.java
+++ b/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/logging/StdOutLogSinkTest.java
@@ -10,6 +10,9 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
+import com.amazonaws.services.lambda.runtime.logging.LogFormat;
+import com.amazonaws.services.lambda.runtime.logging.LogLevel;
+
public class StdOutLogSinkTest {
private final PrintStream originalOutPrintStream = System.out;
@@ -35,6 +38,20 @@ public void testSingleLog() {
assertEquals("hello\nworld", bos.toString());
}
+ @Test
+ public void testSingleLogWithLogLevel() {
+ System.setOut(capturedOutPrintStream);
+ try {
+ try (StdOutLogSink logSink = new StdOutLogSink()) {
+ logSink.log(LogLevel.ERROR, LogFormat.TEXT, "hello\nworld".getBytes());
+ }
+ } finally {
+ System.setOut(originalOutPrintStream);
+ }
+
+ assertEquals("hello\nworld", bos.toString());
+ }
+
@Test
public void testContextLoggerWithStdoutLogSink_logBytes() {
System.setOut(capturedOutPrintStream);
diff --git a/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/logging/TextLogFormatterTest.java b/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/logging/TextLogFormatterTest.java
new file mode 100644
index 00000000..598074a3
--- /dev/null
+++ b/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/logging/TextLogFormatterTest.java
@@ -0,0 +1,25 @@
+package com.amazonaws.services.lambda.runtime.api.client.logging;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import com.amazonaws.services.lambda.runtime.logging.LogLevel;
+
+class TextLogFormatterTest {
+ @Test
+ void testFormattingStringWithLogLevel() {
+ assertFormatsString("test log", LogLevel.WARN, "[WARN] test log");
+ }
+
+ @Test
+ void testFormattingStringWithoutLogLevel() {
+ assertFormatsString("test log", LogLevel.UNDEFINED, "test log");
+ }
+
+ void assertFormatsString(String input, LogLevel logLevel, String expected) {
+ LogFormatter logFormatter = new TextLogFormatter();
+ String output = logFormatter.format(input, logLevel);
+ assertEquals(expected, output);
+ }
+}
\ No newline at end of file