diff --git a/NOTICE b/NOTICE index fe34699ffbb07a1b16729ba8716040f30ad86228..5196dd9e9e341fbaee2f8ec7e17806cf0f7f8e0a 100644 --- a/NOTICE +++ b/NOTICE @@ -24,6 +24,7 @@ The following software have components provided under the terms of this license: - Apache Log4j API (from ) - Apache Log4j Core (from ) - Apache Log4j JUL Adapter (from ) +- Apache Log4j SLF4J Binding (from ) - Apache Log4j to SLF4J Adapter (from ) - Asynchronous Http Client (from ) - Asynchronous Http Client Netty Utils (from ) diff --git a/pom.xml b/pom.xml index 46b526d6fd9c27369506e8b17e782cacc058187a..33c4dcd2fb82e00637f17256bc84148a43de6dfa 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ org.opengroup.osdu core-lib-azure jar - 0.0.10 + 0.0.11 core-lib-azure @@ -79,7 +79,7 @@ org.opengroup.osdu os-core-common - 0.0.13 + 0.3.4 @@ -124,12 +124,6 @@ org.springframework.boot spring-boot-starter-log4j2 2.2.4.RELEASE - - - org.apache.logging.log4j - log4j-slf4j-impl - - com.microsoft.azure diff --git a/src/main/java/org/opengroup/osdu/azure/filters/TransactionLogFilter.java b/src/main/java/org/opengroup/osdu/azure/filters/TransactionLogFilter.java new file mode 100644 index 0000000000000000000000000000000000000000..63a432446331da1991cadd887e8f16f369179c72 --- /dev/null +++ b/src/main/java/org/opengroup/osdu/azure/filters/TransactionLogFilter.java @@ -0,0 +1,133 @@ +// Copyright © Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package org.opengroup.osdu.azure.filters; + +import org.opengroup.osdu.core.common.logging.JaxRsDpsLog; +import org.opengroup.osdu.core.common.model.http.DpsHeaders; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Component; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.function.Function; + +/** + * For logging start and end of request. + */ +@Component +@ConditionalOnProperty(value = "logging.transaction.enabled", havingValue = "true", matchIfMissing = false) +public final class TransactionLogFilter implements Filter { + private static final String LOGGER_NAME = "TxnLogger"; + private static final List WHITELIST_HEADERS = Arrays.asList( + DpsHeaders.CORRELATION_ID, + DpsHeaders.DATA_PARTITION_ID, + DpsHeaders.CONTENT_TYPE); + private static final String START_LOG_TEMPLATE = "Start Web-API %s %s %s"; + private static final String END_LOG_TEMPLATE = "End Web-API %s %s %s status=%d time=%d ms"; + + @Autowired + private JaxRsDpsLog jaxRsDpsLog; + + /** + * Filter logic. + * @param servletRequest Request object. + * @param servletResponse Response object. + * @param filterChain Filter Chain object. + * @throws IOException + * @throws ServletException + */ + @Override + public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, + final FilterChain filterChain) throws IOException, ServletException { + final HttpServletRequest httpRequest = (HttpServletRequest) servletRequest; + final HttpServletResponse httpResponse = (HttpServletResponse) servletResponse; + logTransactionStart(httpRequest); + final long start = System.currentTimeMillis(); + filterChain.doFilter(servletRequest, servletResponse); + final long timeTaken = System.currentTimeMillis() - start; + logTransactionEnd(httpRequest, httpResponse, timeTaken); + } + + /** + * Logs start of a request. + * @param request Request Object. + */ + private void logTransactionStart(final HttpServletRequest request) { + jaxRsDpsLog.info(LOGGER_NAME, String.format(START_LOG_TEMPLATE, request.getMethod(), request.getServletPath(), + getRequestHeadersString(request))); + } + + /** + * Logs end of a request. + * @param request Request object. + * @param response Response object. + * @param timeTaken timeTaken in ms taken for request to complete. + */ + private void logTransactionEnd(final HttpServletRequest request, final HttpServletResponse response, + final long timeTaken) { + jaxRsDpsLog.info(LOGGER_NAME, String.format(END_LOG_TEMPLATE, request.getMethod(), request.getServletPath(), + getResponseHeadersString(response), response.getStatus(), timeTaken)); + + } + + /** + * To construct string representation of request headers. + * @param request Request Object. + * @return String representation of request headers. + */ + private String getRequestHeadersString(final HttpServletRequest request) { + return getHeadersString(request::getHeader); + } + + /** + * To construct string representation of response headers. + * @param response Response Object. + * @return String representation of response headers. + */ + private String getResponseHeadersString(final HttpServletResponse response) { + return getHeadersString(response::getHeader); + } + + /** + * Construct string representation of headers. + * @param headerGetter Header value supplier + * @return String representation of headers + */ + private String getHeadersString(final Function headerGetter) { + final StringBuilder headers = new StringBuilder(); + for (String headerName: WHITELIST_HEADERS) { + if (headerGetter.apply(headerName) != null) { + headers.append(headerName); + headers.append(":"); + headers.append(headerGetter.apply(headerName)); + headers.append(","); + } + } + + if (headers.length() != 0) { + headers.deleteCharAt(headers.length() - 1); + } + return String.format("Headers: {%s}", headers.toString()); + } +} diff --git a/src/main/java/org/opengroup/osdu/azure/logging/Slf4JLogger.java b/src/main/java/org/opengroup/osdu/azure/logging/Slf4JLogger.java new file mode 100644 index 0000000000000000000000000000000000000000..26d6296bb91922d6660d79365c4f2daa9df28e21 --- /dev/null +++ b/src/main/java/org/opengroup/osdu/azure/logging/Slf4JLogger.java @@ -0,0 +1,124 @@ +// Copyright © Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package org.opengroup.osdu.azure.logging; + +import org.opengroup.osdu.core.common.logging.ILogger; +import org.opengroup.osdu.core.common.logging.audit.AuditPayload; +import org.opengroup.osdu.core.common.model.http.HeadersToLog; +import org.opengroup.osdu.core.common.model.http.Request; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Component; +import java.util.Map; + +/** + * {@link ILogger} implementation with Slf4J Logger. + */ +@Component +@Primary +@ConditionalOnProperty(value = "logging.slf4jlogger.enabled", havingValue = "true", matchIfMissing = false) +public final class Slf4JLogger implements ILogger { + private static final String DEFAULT_LOGGER_NAME = Slf4JLogger.class.getName(); + + @Autowired + private HeadersToLog headersToLog; + + @Autowired + private Slf4jLoggerFactory slf4jLoggerFactory; + + @Override + public void audit(final String logPrefix, final AuditPayload auditPayload, final Map headers) { + this.audit(DEFAULT_LOGGER_NAME, logPrefix, auditPayload, headers); + } + + @Override + public void audit(final String loggerName, final String logPrefix, final AuditPayload payload, final Map headers) { + slf4jLoggerFactory.getLogger(loggerName).info("{} {} {}", logPrefix, payload, + this.headersToLog.createStandardLabelsFromMap(headers)); + } + + @Override + public void request(final String logPrefix, final Request request, final Map headers) { + this.request(DEFAULT_LOGGER_NAME, logPrefix, request, headers); + } + + @Override + public void request(final String loggerName, final String logPrefix, final Request request, final Map headers) { + slf4jLoggerFactory.getLogger(loggerName).info("{} {} {}", logPrefix, request, + this.headersToLog.createStandardLabelsFromMap(headers)); + } + + @Override + public void info(final String logPrefix, final String message, final Map headers) { + this.info(DEFAULT_LOGGER_NAME, logPrefix, message, headers); + } + + @Override + public void info(final String loggerName, final String logPrefix, final String message, final Map headers) { + slf4jLoggerFactory.getLogger(loggerName).info("{} {} {}", logPrefix, message, + this.headersToLog.createStandardLabelsFromMap(headers)); + } + + @Override + public void warning(final String logPrefix, final String message, final Map headers) { + this.warning(DEFAULT_LOGGER_NAME, logPrefix, message, headers); + } + + @Override + public void warning(final String loggerName, final String logPrefix, final String message, final Map headers) { + slf4jLoggerFactory.getLogger(loggerName).warn("{} {} {}", logPrefix, message, + this.headersToLog.createStandardLabelsFromMap(headers)); + } + + @Override + public void warning(final String logPrefix, final String message, final Exception e, final Map headers) { + this.warning(DEFAULT_LOGGER_NAME, logPrefix, message, e, headers); + } + + @Override + public void warning(final String loggerName, final String logPrefix, final String message, final Exception ex, final Map headers) { + slf4jLoggerFactory.getLogger(loggerName).warn("{} {} {}", logPrefix, message, + this.headersToLog.createStandardLabelsFromMap(headers), ex); + } + + @Override + public void error(final String logPrefix, final String message, final Map headers) { + this.error(DEFAULT_LOGGER_NAME, logPrefix, message, headers); + } + + @Override + public void error(final String loggerName, final String logPrefix, final String message, final Map headers) { + slf4jLoggerFactory.getLogger(loggerName).error("{} {} {}", logPrefix, message, + this.headersToLog.createStandardLabelsFromMap(headers)); + } + + @Override + public void error(final String logPrefix, final String message, final Exception e, + final Map headers) { + this.error(DEFAULT_LOGGER_NAME, logPrefix, message, e, headers); + } + + @Override + public void error(final String loggerName, final String logPrefix, final String message, final Exception ex, final Map headers) { + slf4jLoggerFactory.getLogger(loggerName).error("{} {} {}", logPrefix, message, + this.headersToLog.createStandardLabelsFromMap(headers), ex); + } + + @Override + public void close() throws Exception { + // do nothing + } +} diff --git a/src/main/java/org/opengroup/osdu/azure/logging/Slf4JLoggerConfiguration.java b/src/main/java/org/opengroup/osdu/azure/logging/Slf4JLoggerConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..9d8e0871768a2975f4ec6e0346f28f4a3f542ebe --- /dev/null +++ b/src/main/java/org/opengroup/osdu/azure/logging/Slf4JLoggerConfiguration.java @@ -0,0 +1,36 @@ +// Copyright © Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package org.opengroup.osdu.azure.logging; + +import org.opengroup.osdu.core.common.model.http.HeadersToLog; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.Collections; + +/** + * Creating beans needed for Slf4JLogger. + */ +@Configuration +public class Slf4JLoggerConfiguration { + /** + * Bean for HeadersToLog used in {@link Slf4JLogger}. + * @return {@link HeadersToLog} instance + */ + @Bean + public HeadersToLog headersToLog() { + return new HeadersToLog(Collections.emptyList()); + } +} diff --git a/src/main/java/org/opengroup/osdu/azure/logging/Slf4jLoggerFactory.java b/src/main/java/org/opengroup/osdu/azure/logging/Slf4jLoggerFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..973f173eafbf4b26bd17b0b20f12b916c285af38 --- /dev/null +++ b/src/main/java/org/opengroup/osdu/azure/logging/Slf4jLoggerFactory.java @@ -0,0 +1,34 @@ +// Copyright © Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package org.opengroup.osdu.azure.logging; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +/** + * Factory for slf4j logger instances. + */ +@Component +public final class Slf4jLoggerFactory { + /** + * Returns slf4j logger instance based on name. + * @param loggerName name of the logger + * @return {@link Logger} instance + */ + public Logger getLogger(final String loggerName) { + return LoggerFactory.getLogger(loggerName); + } +} diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml index 73989b11298eead4f27289c737db6d9866b2e8ed..4076cec31ddbcefb2c3888d6a38eda58ceb2911a 100644 --- a/src/main/resources/log4j2.xml +++ b/src/main/resources/log4j2.xml @@ -23,15 +23,20 @@ - + - + + + + + + \ No newline at end of file diff --git a/src/test/java/org/opengroup/osdu/azure/filters/TransactionLogFilterTest.java b/src/test/java/org/opengroup/osdu/azure/filters/TransactionLogFilterTest.java new file mode 100644 index 0000000000000000000000000000000000000000..acb2c6a8d0b43b10d1ff5dd34898ee46eeb1766c --- /dev/null +++ b/src/test/java/org/opengroup/osdu/azure/filters/TransactionLogFilterTest.java @@ -0,0 +1,98 @@ +// Copyright © Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package org.opengroup.osdu.azure.filters; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.opengroup.osdu.core.common.logging.JaxRsDpsLog; +import org.opengroup.osdu.core.common.model.http.DpsHeaders; + +import javax.servlet.FilterChain; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +/** + * Tests for {@link TransactionLogFilter} + */ +@ExtendWith(MockitoExtension.class) +public class TransactionLogFilterTest { + private static final int STATUS_CODE = 200; + @Mock + private HttpServletRequest servletRequest; + @Mock + private HttpServletResponse servletResponse; + @Mock + private FilterChain filterChain; + @Mock + private JaxRsDpsLog jaxRsDpsLog; + + @InjectMocks + private TransactionLogFilter logFilter; + + @BeforeEach + public void setup() { + when(servletResponse.getStatus()).thenReturn(STATUS_CODE); + } + + @Test + public void testStartAndEndMessagesAreLoggedProperly() throws Exception { + final String startLogMessage = "Start Web-API PUT records Headers: {correlation-id:abc}"; + final String endMessage = "End Web-API PUT records Headers: {correlation-id:abc} status=200 time="; + when(servletRequest.getMethod()).thenReturn("PUT"); + when(servletRequest.getServletPath()).thenReturn("records"); + when(servletRequest.getHeader(eq(DpsHeaders.CORRELATION_ID))).thenReturn("abc"); + when(servletResponse.getHeader(eq(DpsHeaders.CORRELATION_ID))).thenReturn("abc"); + final ArgumentCaptor logMessageCaptor = ArgumentCaptor.forClass(String.class); + doNothing().when(jaxRsDpsLog).info(eq("TxnLogger"), logMessageCaptor.capture()); + this.logFilter.doFilter(servletRequest, servletResponse, filterChain); + verify(servletRequest, times(2)).getMethod(); + verify(servletRequest, times(2)).getServletPath(); + verify(servletRequest, times(2)).getHeader(eq(DpsHeaders.CORRELATION_ID)); + verify(servletResponse, times(2)).getHeader(eq(DpsHeaders.CORRELATION_ID)); + verify(servletResponse, times(1)).getStatus(); + assertEquals(2, logMessageCaptor.getAllValues().size()); + assertEquals(startLogMessage, logMessageCaptor.getAllValues().get(0)); + assertEquals(true, logMessageCaptor.getAllValues().get(1).startsWith(endMessage)); + } + + @Test + public void testStartAndEndMessagesAreLoggedProperlyWithNoHeaders() throws Exception { + final String startLogMessage = "Start Web-API PUT records Headers: {}"; + final String endMessage = "End Web-API PUT records Headers: {} status=200 time="; + when(servletRequest.getMethod()).thenReturn("PUT"); + when(servletRequest.getServletPath()).thenReturn("records"); + final ArgumentCaptor logMessageCaptor = ArgumentCaptor.forClass(String.class); + doNothing().when(jaxRsDpsLog).info(eq("TxnLogger"), logMessageCaptor.capture()); + this.logFilter.doFilter(servletRequest, servletResponse, filterChain); + verify(servletRequest, times(2)).getMethod(); + verify(servletRequest, times(2)).getServletPath(); + verify(servletResponse, times(1)).getStatus(); + assertEquals(2, logMessageCaptor.getAllValues().size()); + assertEquals(startLogMessage, logMessageCaptor.getAllValues().get(0)); + assertEquals(true, logMessageCaptor.getAllValues().get(1).startsWith(endMessage)); + } +} diff --git a/src/test/java/org/opengroup/osdu/azure/logging/Slf4JLoggerFactoryTest.java b/src/test/java/org/opengroup/osdu/azure/logging/Slf4JLoggerFactoryTest.java new file mode 100644 index 0000000000000000000000000000000000000000..1bdd8376f7b057ba2c2cbdd244041d7155425af1 --- /dev/null +++ b/src/test/java/org/opengroup/osdu/azure/logging/Slf4JLoggerFactoryTest.java @@ -0,0 +1,50 @@ +// Copyright © Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package org.opengroup.osdu.azure.logging; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.junit.jupiter.MockitoExtension; +import org.slf4j.Logger; + +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertSame; + +/** + * Contains tests for {@link Slf4jLoggerFactory} + */ +@ExtendWith(MockitoExtension.class) +public class Slf4JLoggerFactoryTest { + private static final String LOGGER_NAME1 = Slf4JLoggerFactoryTest.class.getName(); + private static final String LOGGER_NAME2 = Slf4jLoggerFactory.class.getName(); + + @InjectMocks + private Slf4jLoggerFactory slf4jLoggerFactory; + + @Test + public void testSameLoggerInstanceReturnedWhenCalledWithSameName() { + final Logger logger1 = slf4jLoggerFactory.getLogger(LOGGER_NAME1); + final Logger logger2 = slf4jLoggerFactory.getLogger(LOGGER_NAME1); + assertSame(logger1, logger2, "when called with same name, it should return same instance"); + } + + @Test + public void testDifferentLoggerInstanceReturnedWhenCalledWithDifferentName() { + final Logger logger1 = slf4jLoggerFactory.getLogger(LOGGER_NAME1); + final Logger logger2 = slf4jLoggerFactory.getLogger(LOGGER_NAME2); + assertNotEquals(logger1, logger2, "when called with different names, it should return different instances"); + } +} diff --git a/src/test/java/org/opengroup/osdu/azure/logging/Slf4JLoggerTest.java b/src/test/java/org/opengroup/osdu/azure/logging/Slf4JLoggerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..6bf151a0b24d0b17e6be5a42821c153ce5f1ddba --- /dev/null +++ b/src/test/java/org/opengroup/osdu/azure/logging/Slf4JLoggerTest.java @@ -0,0 +1,202 @@ +// Copyright © Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package org.opengroup.osdu.azure.logging; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.opengroup.osdu.core.common.logging.audit.AuditPayload; +import org.opengroup.osdu.core.common.model.http.HeadersToLog; +import org.opengroup.osdu.core.common.model.http.Request; +import org.slf4j.Logger; + +import java.util.HashMap; +import java.util.Map; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +/** + * Contains tests for {@link Slf4JLogger} + */ +@ExtendWith(MockitoExtension.class) +public class Slf4JLoggerTest { + private static final String LOG_PREFIX = "services.app"; + private static final String DEFAULT_LOGGER_NAME = Slf4JLogger.class.getName(); + private static final String LOGGER_NAME = Slf4JLoggerTest.class.getName(); + private static final String LOG_MESSAGE = "Hello world !"; + + @Mock + private HeadersToLog headersToLog; + + @Mock + private AuditPayload auditPayload; + + @Mock + private Slf4jLoggerFactory slf4jLoggerFactory; + + @Mock + private Request request; + + @Mock + private Logger logger; + + @Mock + private Exception e; + + private final Map headers = new HashMap<>(); + + @InjectMocks + Slf4JLogger slf4JLogger; + + @BeforeEach + public void setup() { + when(slf4jLoggerFactory.getLogger(any())).thenReturn(logger); + when(headersToLog.createStandardLabelsFromMap(eq(headers))).thenReturn(headers); + } + + @Test + public void testAudit() { + doNothing().when(logger).info(eq("{} {} {}"), eq(LOG_PREFIX), eq(auditPayload), eq(headers)); + slf4JLogger.audit(LOG_PREFIX, auditPayload, headers); + verify(logger, times(1)).info(eq("{} {} {}"), eq(LOG_PREFIX), eq(auditPayload), eq(headers)); + verify(slf4jLoggerFactory, times(1)).getLogger(eq(DEFAULT_LOGGER_NAME)); + verify(headersToLog, times(1)).createStandardLabelsFromMap(eq(headers)); + } + + @Test + public void testAuditWithLoggerName() { + doNothing().when(logger).info(eq("{} {} {}"), eq(LOG_PREFIX), eq(auditPayload), eq(headers)); + slf4JLogger.audit(LOGGER_NAME, LOG_PREFIX, auditPayload, headers); + verify(logger, times(1)).info(eq("{} {} {}"), eq(LOG_PREFIX), eq(auditPayload), eq(headers)); + verify(slf4jLoggerFactory, times(1)).getLogger(eq(LOGGER_NAME)); + verify(headersToLog, times(1)).createStandardLabelsFromMap(eq(headers)); + } + + @Test + public void testRequest() { + doNothing().when(logger).info(eq("{} {} {}"), eq(LOG_PREFIX), eq(request), eq(headers)); + slf4JLogger.request(LOG_PREFIX, request, headers); + verify(logger, times(1)).info(eq("{} {} {}"), eq(LOG_PREFIX), eq(request), eq(headers)); + verify(slf4jLoggerFactory, times(1)).getLogger(eq(DEFAULT_LOGGER_NAME)); + verify(headersToLog, times(1)).createStandardLabelsFromMap(eq(headers)); + } + + @Test + public void testRequestWithLoggerName() { + doNothing().when(logger).info(eq("{} {} {}"), eq(LOG_PREFIX), eq(request), eq(headers)); + slf4JLogger.request(LOGGER_NAME, LOG_PREFIX, request, headers); + verify(logger, times(1)).info(eq("{} {} {}"), eq(LOG_PREFIX), eq(request), eq(headers)); + verify(slf4jLoggerFactory, times(1)).getLogger(eq(LOGGER_NAME)); + verify(headersToLog, times(1)).createStandardLabelsFromMap(eq(headers)); + } + + @Test + public void testInfo() { + doNothing().when(logger).info(eq("{} {} {}"), eq(LOG_PREFIX), eq(LOG_MESSAGE), eq(headers)); + slf4JLogger.info(LOG_PREFIX, LOG_MESSAGE, headers); + verify(logger, times(1)).info(eq("{} {} {}"), eq(LOG_PREFIX), eq(LOG_MESSAGE), eq(headers)); + verify(slf4jLoggerFactory, times(1)).getLogger(eq(DEFAULT_LOGGER_NAME)); + verify(headersToLog, times(1)).createStandardLabelsFromMap(eq(headers)); + } + + @Test + public void testInfoWithLoggerName() { + doNothing().when(logger).info(eq("{} {} {}"), eq(LOG_PREFIX), eq(LOG_MESSAGE), eq(headers)); + slf4JLogger.info(LOGGER_NAME, LOG_PREFIX, LOG_MESSAGE, headers); + verify(logger, times(1)).info(eq("{} {} {}"), eq(LOG_PREFIX), eq(LOG_MESSAGE), eq(headers)); + verify(slf4jLoggerFactory, times(1)).getLogger(eq(LOGGER_NAME)); + verify(headersToLog, times(1)).createStandardLabelsFromMap(eq(headers)); + } + + @Test + public void testWarning() { + doNothing().when(logger).warn(eq("{} {} {}"), eq(LOG_PREFIX), eq(LOG_MESSAGE), eq(headers)); + slf4JLogger.warning(LOG_PREFIX, LOG_MESSAGE, headers); + verify(logger, times(1)).warn(eq("{} {} {}"), eq(LOG_PREFIX), eq(LOG_MESSAGE), eq(headers)); + verify(slf4jLoggerFactory, times(1)).getLogger(eq(DEFAULT_LOGGER_NAME)); + verify(headersToLog, times(1)).createStandardLabelsFromMap(eq(headers)); + } + + @Test + public void testWarningWithLoggerName() { + doNothing().when(logger).warn(eq("{} {} {}"), eq(LOG_PREFIX), eq(LOG_MESSAGE), eq(headers)); + slf4JLogger.warning(LOGGER_NAME, LOG_PREFIX, LOG_MESSAGE, headers); + verify(logger, times(1)).warn(eq("{} {} {}"), eq(LOG_PREFIX), eq(LOG_MESSAGE), eq(headers)); + verify(slf4jLoggerFactory, times(1)).getLogger(eq(LOGGER_NAME)); + verify(headersToLog, times(1)).createStandardLabelsFromMap(eq(headers)); + } + + @Test + public void testWarningWithException() { + doNothing().when(logger).warn(eq("{} {} {}"), eq(LOG_PREFIX), eq(LOG_MESSAGE), eq(headers), eq(e)); + slf4JLogger.warning(LOG_PREFIX, LOG_MESSAGE, e, headers); + verify(logger, times(1)).warn(eq("{} {} {}"), eq(LOG_PREFIX), eq(LOG_MESSAGE), eq(headers), eq(e)); + verify(slf4jLoggerFactory, times(1)).getLogger(eq(DEFAULT_LOGGER_NAME)); + verify(headersToLog, times(1)).createStandardLabelsFromMap(eq(headers)); + } + + @Test + public void testWarningWithExceptionAndLoggerName() { + doNothing().when(logger).warn(eq("{} {} {}"), eq(LOG_PREFIX), eq(LOG_MESSAGE), eq(headers), eq(e)); + slf4JLogger.warning(LOGGER_NAME, LOG_PREFIX, LOG_MESSAGE, e, headers); + verify(logger, times(1)).warn(eq("{} {} {}"), eq(LOG_PREFIX), eq(LOG_MESSAGE), eq(headers), eq(e)); + verify(slf4jLoggerFactory, times(1)).getLogger(eq(LOGGER_NAME)); + verify(headersToLog, times(1)).createStandardLabelsFromMap(eq(headers)); + } + + @Test + public void testError() { + doNothing().when(logger).error(eq("{} {} {}"), eq(LOG_PREFIX), eq(LOG_MESSAGE), eq(headers)); + slf4JLogger.error(LOG_PREFIX, LOG_MESSAGE, headers); + verify(logger, times(1)).error(eq("{} {} {}"), eq(LOG_PREFIX), eq(LOG_MESSAGE), eq(headers)); + verify(slf4jLoggerFactory, times(1)).getLogger(eq(DEFAULT_LOGGER_NAME)); + verify(headersToLog, times(1)).createStandardLabelsFromMap(eq(headers)); + } + + @Test + public void testErrorWithLoggerName() { + doNothing().when(logger).error(eq("{} {} {}"), eq(LOG_PREFIX), eq(LOG_MESSAGE), eq(headers)); + slf4JLogger.error(LOGGER_NAME, LOG_PREFIX, LOG_MESSAGE, headers); + verify(logger, times(1)).error(eq("{} {} {}"), eq(LOG_PREFIX), eq(LOG_MESSAGE), eq(headers)); + verify(slf4jLoggerFactory, times(1)).getLogger(eq(LOGGER_NAME)); + verify(headersToLog, times(1)).createStandardLabelsFromMap(eq(headers)); + } + + @Test + public void testErrorWithException() { + doNothing().when(logger).error(eq("{} {} {}"), eq(LOG_PREFIX), eq(LOG_MESSAGE), eq(headers), eq(e)); + slf4JLogger.error(LOG_PREFIX, LOG_MESSAGE, e, headers); + verify(logger, times(1)).error(eq("{} {} {}"), eq(LOG_PREFIX), eq(LOG_MESSAGE), eq(headers), eq(e)); + verify(slf4jLoggerFactory, times(1)).getLogger(eq(DEFAULT_LOGGER_NAME)); + verify(headersToLog, times(1)).createStandardLabelsFromMap(eq(headers)); + } + + @Test + public void testErrorWithExceptionAndLoggerName() { + doNothing().when(logger).error(eq("{} {} {}"), eq(LOG_PREFIX), eq(LOG_MESSAGE), eq(headers), eq(e)); + slf4JLogger.error(LOGGER_NAME, LOG_PREFIX, LOG_MESSAGE, e, headers); + verify(logger, times(1)).error(eq("{} {} {}"), eq(LOG_PREFIX), eq(LOG_MESSAGE), eq(headers), eq(e)); + verify(slf4jLoggerFactory, times(1)).getLogger(eq(LOGGER_NAME)); + verify(headersToLog, times(1)).createStandardLabelsFromMap(eq(headers)); + } +}