diff --git a/flint-core/src/main/java/org/opensearch/flint/core/logging/CustomJsonLayout.java b/flint-core/src/main/java/org/opensearch/flint/core/logging/CustomJsonLayout.java
index 98715c2c2..40e72c99f 100644
--- a/flint-core/src/main/java/org/opensearch/flint/core/logging/CustomJsonLayout.java
+++ b/flint-core/src/main/java/org/opensearch/flint/core/logging/CustomJsonLayout.java
@@ -18,6 +18,13 @@
import java.util.HashMap;
import java.util.Map;
+/**
+ * CustomJsonLayout is a plugin for formatting log events as JSON strings.
+ *
+ *
The layout is designed to be used with OpenSearch Flint logging. It extracts environment-specific information,
+ * such as the cluster name, from the environment variable "FLINT_CLUSTER_NAME" and splits it into domain name and client ID.
+ *
+ */
@Plugin(name = "CustomJsonLayout", category = "Core", elementType = Layout.ELEMENT_TYPE, printObject = true)
public class CustomJsonLayout extends AbstractStringLayout {
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
@@ -41,24 +48,33 @@ protected CustomJsonLayout(Charset charset) {
super(charset);
}
+ /**
+ * Plugin factory method to create an instance of CustomJsonLayout.
+ *
+ * @param charset The charset for encoding the log event. If not specified, defaults to UTF-8.
+ * @return A new instance of CustomJsonLayout with the specified charset.
+ */
@PluginFactory
public static CustomJsonLayout createLayout(@PluginAttribute(value = "charset", defaultString = "UTF-8") Charset charset) {
return new CustomJsonLayout(charset);
}
+ /**
+ * Converts the log event to a JSON string.
+ * If the log event's message does not follow the expected format, it returns the formatted message directly.
+ *
+ * @param event the log event to format.
+ * @return A string representation of the log event in JSON format.
+ */
@Override
public String toSerializable(LogEvent event) {
- if (!(event.getMessage() instanceof OperationMessage)) {
- return event.getMessage().getFormattedMessage() + System.lineSeparator();
- }
-
Map logEventMap = new HashMap<>();
logEventMap.put("timestamp", event.getTimeMillis());
logEventMap.put("message", event.getMessage().getFormattedMessage());
logEventMap.put("domainName", DOMAIN_NAME);
logEventMap.put("clientId", CLIENT_ID);
- if (event.getMessage().getParameters().length == 1) {
+ if (event.getMessage() instanceof OperationMessage && event.getMessage().getParameters().length == 1) {
logEventMap.put("StatusCode", event.getMessage().getParameters()[0]);
}
diff --git a/flint-core/src/main/java/org/opensearch/flint/core/logging/CustomLogging.java b/flint-core/src/main/java/org/opensearch/flint/core/logging/CustomLogging.java
new file mode 100644
index 000000000..de3879b1d
--- /dev/null
+++ b/flint-core/src/main/java/org/opensearch/flint/core/logging/CustomLogging.java
@@ -0,0 +1,36 @@
+package org.opensearch.flint.core.logging;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+/**
+ * CustomLogging class using the {@link CustomJsonLayout} for logging.
+ */
+public class CustomLogging {
+ // Define a static logger variable so that it references the custom logger
+ private static final Logger logger = LogManager.getLogger(CustomLogging.class);
+
+ public static void logDebug(String message) {
+ logger.debug(message);
+ }
+
+ public static void logInfo(String message) {
+ logger.info(message);
+ }
+
+ public static void logWarning(String message) {
+ logger.warn(message);
+ }
+
+ public static void logWarning(String message, Throwable e) {
+ logger.warn(message, e);
+ }
+
+ public static void logError(String message) {
+ logger.error(message);
+ }
+
+ public static void logError(String message, Throwable throwable) {
+ logger.error(message, throwable);
+ }
+}
\ No newline at end of file
diff --git a/flint-core/src/main/scala/org/opensearch/flint/core/http/handler/HttpStatusCodeResultPredicate.java b/flint-core/src/main/scala/org/opensearch/flint/core/http/handler/HttpStatusCodeResultPredicate.java
index ee2a23e3f..fa82e3655 100644
--- a/flint-core/src/main/scala/org/opensearch/flint/core/http/handler/HttpStatusCodeResultPredicate.java
+++ b/flint-core/src/main/scala/org/opensearch/flint/core/http/handler/HttpStatusCodeResultPredicate.java
@@ -18,6 +18,7 @@
* @param result type (supposed to be HttpResponse for OS client)
*/
public class HttpStatusCodeResultPredicate implements CheckedPredicate {
+
private static final Logger LOG = Logger.getLogger(HttpStatusCodeResultPredicate.class.getName());
/**
diff --git a/flint-core/src/test/java/org/opensearch/flint/core/logging/CustomJsonLayoutTest.java b/flint-core/src/test/java/org/opensearch/flint/core/logging/CustomJsonLayoutTest.java
index 271f00a06..c936677c0 100644
--- a/flint-core/src/test/java/org/opensearch/flint/core/logging/CustomJsonLayoutTest.java
+++ b/flint-core/src/test/java/org/opensearch/flint/core/logging/CustomJsonLayoutTest.java
@@ -1,51 +1,76 @@
-/*
- * Copyright OpenSearch Contributors
- * SPDX-License-Identifier: Apache-2.0
- */
-
package org.opensearch.flint.core.logging;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.message.Message;
+import org.junit.Before;
import org.junit.Test;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.util.Map;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-
public class CustomJsonLayoutTest {
- @Test
- public void testSuccessfulLogPlainMessage() {
- LogEvent event = mock(LogEvent.class);
- when(event.getMessage()).thenReturn(mock(Message.class));
- when(event.getMessage().getFormattedMessage()).thenReturn("Test message");
+ private Map writeableEnvironmentVariables;
- CustomJsonLayout layout = CustomJsonLayout.createLayout(StandardCharsets.UTF_8);
- String result = layout.toSerializable(event);
- assertNotNull(result);
- assertEquals(result, "Test message" + System.lineSeparator());
- }
-
- @Test
- public void testSuccessfulLogOperationMessage() throws NoSuchFieldException, IllegalAccessException {
+ @Before
+ public void setUp() throws NoSuchFieldException, IllegalAccessException {
+ // Setup writable environment variables
Class> classOfMap = System.getenv().getClass();
Field field = classOfMap.getDeclaredField("m");
field.setAccessible(true);
- Map writeableEnvironmentVariables = (Map)field.get(System.getenv());
+ writeableEnvironmentVariables = (Map) field.get(System.getenv());
writeableEnvironmentVariables.put("FLINT_CLUSTER_NAME", "1234567890:testDomain");
+ }
+ private void cleanUp() {
+ // Clean up environment variables
+ writeableEnvironmentVariables.remove("FLINT_CLUSTER_NAME");
+ }
+
+ private LogEvent setupLogEvent(Class extends Message> messageClass, String formattedMessage, Object... parameters) {
LogEvent event = mock(LogEvent.class);
when(event.getTimeMillis()).thenReturn(System.currentTimeMillis());
- when(event.getMessage()).thenReturn(mock(OperationMessage.class));
- when(event.getMessage().getFormattedMessage()).thenReturn("Test message");
- when(event.getMessage().getParameters()).thenReturn(new Object[] {new Integer(200)});
+
+ Message message = mock(messageClass);
+ when(message.getFormattedMessage()).thenReturn(formattedMessage);
+ if (parameters.length > 0) {
+ when(message.getParameters()).thenReturn(parameters);
+ }
+ when(event.getMessage()).thenReturn(message);
+
+ Exception mockException = new Exception("Test exception message");
+ when(event.getThrown()).thenReturn(mockException);
+
+ return event;
+ }
+
+ @Test
+ public void testSuccessfulLogPlainMessage() {
+ LogEvent event = setupLogEvent(Message.class, "Test message");
+
+ try {
+ CustomJsonLayout layout = CustomJsonLayout.createLayout(StandardCharsets.UTF_8);
+
+ String result = layout.toSerializable(event);
+ assertNotNull(result);
+ assertTrue(result.contains("\"message\":\"Test message\""));
+ assertTrue(result.contains("\"clientId\":\"1234567890\""));
+ assertTrue(result.contains("\"domainName\":\"testDomain\""));
+ assertFalse(result.contains("\"StatusCode\""));
+ assertTrue(result.contains("\"Exception\":\"java.lang.Exception\""));
+ assertTrue(result.contains("\"ExceptionMessage\":\"Test exception message\""));
+ } finally {
+ cleanUp();
+ }
+ }
+
+ @Test
+ public void testSuccessfulLogOperationMessage() {
+ LogEvent event = setupLogEvent(OperationMessage.class, "Test message", 200);
try {
CustomJsonLayout layout = CustomJsonLayout.createLayout(StandardCharsets.UTF_8);
@@ -56,9 +81,10 @@ public void testSuccessfulLogOperationMessage() throws NoSuchFieldException, Ill
assertTrue(result.contains("\"clientId\":\"1234567890\""));
assertTrue(result.contains("\"domainName\":\"testDomain\""));
assertTrue(result.contains("\"StatusCode\":200"));
+ assertTrue(result.contains("\"Exception\":\"java.lang.Exception\""));
+ assertTrue(result.contains("\"ExceptionMessage\":\"Test exception message\""));
} finally {
- // since system environment is shared by other tests. Make sure to remove them before exiting.
- writeableEnvironmentVariables.remove("FLINT_CLUSTER_NAME");
+ cleanUp();
}
}
}