Skip to content

Commit

Permalink
Merge pull request #1 from dm-drogeriemarkt/reset-debug-log
Browse files Browse the repository at this point in the history
sanitize API and reset debug log and make this 2.0.0 because of API change
  • Loading branch information
waschmittel authored Nov 15, 2019
2 parents e3216e2 + 4a2acde commit 3e1ef37
Show file tree
Hide file tree
Showing 9 changed files with 182 additions and 151 deletions.
35 changes: 24 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ Because this is a library, Checkstyle is used to make sure all public classes/me

## Usage

### Updating from Version 1.x.x to 2.x.x

* `LogCapture.forUnitTest()` has been replaced with `LogCapture.forCurrentPackage()`
* `LogCapture.forIntegrationTest(...)` has been replaced with `LogCapture.forPackages(...)`
* `logCapture.addAppender()` has been replaced with `logCapture.addAppenderAndSetLogLevelToDebug()`
* `logCapture.removeAppender()` has been replaced with `logCapture.removeAppenderAndResetLogLevel()`

### Maven

Add log-capture as a test dependency to your project. If you use Maven, add this to your pom.xml:
Expand All @@ -43,16 +50,15 @@ Add log-capture as a test dependency to your project. If you use Maven, add this
```java
package my.company.application;

import de.dm.infrastructure.logcapture.LogCapture;
...

public class MyUnitTest {

Logger logger = LoggerFactory.getLogger(MyUnitTest.class);

// captures logs from any packages, but only if the log event's call stack
// indicates that it has been caused by the test
@Rule
public LogCapture logCapture = LogCapture.forUnitTest();
public LogCapture logCapture = LogCapture.forCurrentPackage();

@Test
public void twoLogMessagesInOrder() {
Expand All @@ -73,6 +79,7 @@ package my.company.application;

import utility.that.logs.Tool;
import irrelevant.utility.Irrelevant;
import de.dm.infrastructure.logcapture.LogCapture;
...

public class MyIntegrationTest {
Expand All @@ -81,7 +88,7 @@ public class MyIntegrationTest {

// captures only logs from my.company and utility.that.logs and sub-packages
@Rule
public LogCapture logCapture = LogCapture.forIntegrationTest("my.company", "utility.that.logs");
public LogCapture logCapture = LogCapture.forPackages("my.company", "utility.that.logs");

@Test
public void twoLogMessagesInOrder() {
Expand Down Expand Up @@ -114,7 +121,7 @@ public class MyUnitTest {
Logger logger = LoggerFactory.getLogger(MyUnitTest.class);

@Rule
public LogCapture logCapture = LogCapture.forUnitTest();
public LogCapture logCapture = LogCapture.forCurrentPackage();

@Test
public void logMessageWithMdcInformation() {
Expand Down Expand Up @@ -160,7 +167,7 @@ java.lang.AssertionError: Expected log message has occurred, but never with the

## Usage with non-JUnit Runner

If you intend to use LogCapture outside of a JUnit test, you cannot rely on JUnit's `@Rule` annotation and must call LocCapture's `addAppender()` and `removeAppender()` methods manually.
If you intend to use LogCapture outside of a JUnit test, you cannot rely on JUnit's `@Rule` annotation and must call LocCapture's `addAppenderAndSetLogLevelToDebug()` and `removeAppenderAndResetLogLevel()` methods manually.

Be aware that this will still cause JUnit to be a dependency.

Expand All @@ -173,10 +180,11 @@ Here's an Example that shows how to use LogCapture with Cucumber 4:
```cucumber
And with MDC logging context
| contextId | contentRegex |
| verkaufsbon_vo | ^MDC_JSON_VALUE:.*2401219817317 |
* the following messages where logged
| mdc_key | ^some mdc value |
* the following messages were logged
| level | messageRegex |
| INFO | ^Received bon$ |
| INFO | ^Something happened$ |
| INFO | ^Something else happened with the same mdc context$ |
```

#### Cucumber stepdefs
Expand All @@ -187,11 +195,16 @@ You can create these stepdefs in your project to use log-capture in feature file
public class LoggingStepdefs {
private ExpectedMdcEntry[] expectedMdcEntries;

public LogCapture logCapture = LogCapture.forIntegrationTest("my.company.app");
public LogCapture logCapture = LogCapture.forPackages("my.company.app");

@Before
public void setupLogCapture() {
logCapture.addAppender();
logCapture.addAppenderAndSetLogLevelToDebug();
}

@After
public void stopLogCapture() {
logCapture.removeAppenderAndResetLogLevel();
}

@And("with MDC logging context")
Expand Down
16 changes: 8 additions & 8 deletions checkstyle.xml
Original file line number Diff line number Diff line change
Expand Up @@ -154,12 +154,12 @@
<module name="JavadocType">
<property name="scope" value="public"/>
</module>
<module name="MissingJavadocMethod"><!-- enable this for a library, disable for an application -->
<property name="scope" value="protected"/>
</module>
<module name="JavadocMethod">
<property name="allowedAnnotations" value="Override, Test"/>
<property name="validateThrows" value="true"/>
<property name="scope" value="protected"/>
<property name="allowMissingJavadoc"
value="false"/><!-- set this to false for a library, true for an application -->
<property name="allowUndeclaredRTE" value="true"/>
</module>
<module name="MethodName">
Expand All @@ -184,11 +184,6 @@
<property name="allowedAbbreviationLength" value="32"/>
</module>
<module name="CatchParameterName"/>
<module name="LineLength">
<property name="severity" value="info"/>
<property name="max" value="200"/>
<property name="tabWidth" value="4"/>
</module>
<module name="TodoComment">
<property name="severity" value="warning"/>
<property name="format" value="TODO|FIXME.*"/>
Expand Down Expand Up @@ -234,4 +229,9 @@
<module name="FileLength"/>
<module name="Translation"/>
<module name="UniqueProperties"/>
<module name="LineLength">
<property name="severity" value="info"/>
<property name="max" value="200"/>
<property name="tabWidth" value="4"/>
</module>
</module>
15 changes: 11 additions & 4 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>de.dm.infrastructure</groupId>
<artifactId>log-capture</artifactId>
<version>1.0.2-SNAPSHOT</version>
<version>2.0.0-SNAPSHOT</version>

<name>Log Capture</name>
<description>Makes it possible to capture logs and assert if things have been logged</description>
Expand All @@ -30,13 +30,14 @@

<properties>
<java.version>1.8</java.version>
<lombok.version>1.18.4</lombok.version>
<lombok.version>1.18.10</lombok.version>
<logback.version>1.2.3</logback.version>
<junit.version>4.12</junit.version>
<encoding>UTF-8</encoding>

<checkstyle.version>8.22</checkstyle.version>
<jacoco.version>0.8.4</jacoco.version>
<assertj-core.version>3.14.0</assertj-core.version>
<checkstyle.version>8.26</checkstyle.version>
<jacoco.version>0.8.5</jacoco.version>
<maven-surefire-plugin.version>2.22.2</maven-surefire-plugin.version>
<maven-checkstyle-plugin.version>3.1.0</maven-checkstyle-plugin.version>
<maven-source-plugin.version>3.1.0</maven-source-plugin.version>
Expand Down Expand Up @@ -64,6 +65,12 @@
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>${assertj-core.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,30 +11,26 @@
import lombok.Setter;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Getter
@Setter
class CapturingAppender extends ContextAwareBase implements Appender<ILoggingEvent> {

List<LoggedEvent> loggedEvents = new ArrayList<>();
final List<String> capturedPackages;
final Set<String> capturedPackages;

private String name;
private boolean started;
private final boolean captureStackTrace;

CapturingAppender(LoggerContext loggerContext, boolean captureStackTrace, List<String> capturedPackages) {
CapturingAppender(LoggerContext loggerContext, Set<String> capturedPackages) {
this.capturedPackages = capturedPackages;
setName("CAPTURE-" + Thread.currentThread().getId());
setContext(loggerContext);
this.captureStackTrace = captureStackTrace;
}

@Override
Expand All @@ -44,16 +40,12 @@ public synchronized void doAppend(ILoggingEvent loggingEvent) {
new LoggedEvent(
loggingEvent.getLevel(),
loggingEvent.getFormattedMessage(),
captureStackTrace ? getMethodsInCallStack(loggingEvent) : null,
loggingEvent.getMDCPropertyMap()
));
}
}

private boolean eventIsRelevant(ILoggingEvent loggingEvent) {
if (capturedPackages.size() == 0) {
return true;
}
for (String packageName : capturedPackages) {
if (loggingEvent.getLoggerName().startsWith(packageName)) {
return true;
Expand All @@ -62,22 +54,12 @@ private boolean eventIsRelevant(ILoggingEvent loggingEvent) {
return false;
}

private static Set<String> getMethodsInCallStack(ILoggingEvent loggingEvent) {
return Arrays.stream(loggingEvent.getCallerData())
.map(CapturingAppender::toMethodName)
.collect(Collectors.toSet());
}

private static String toMethodName(StackTraceElement callerData) {
return String.format("%s.%s", callerData.getClassName(), callerData.getMethodName());
}

Integer whenCapturedNext(Level level, String regex, int startIndex, StackTraceElement caller, ExpectedMdcEntry... expectedMdcEntries) {
Integer whenCapturedNext(Level level, String regex, int startIndex, ExpectedMdcEntry... expectedMdcEntries) {
Pattern pattern = Pattern.compile(".*" + regex + ".*");
LoggedEvent eventWithWrongMdcContents = null;
for (int i = startIndex; i < loggedEvents.size(); i++) {
LoggedEvent event = loggedEvents.get(i);
if (eventMatchesWithoutMdc(event, level, pattern, caller)) {
if (eventMatchesWithoutMdc(event, level, pattern)) {
if (containsMdcEntries(event.getMdcData(), expectedMdcEntries)) {
return i;
}
Expand All @@ -90,10 +72,8 @@ Integer whenCapturedNext(Level level, String regex, int startIndex, StackTraceEl
throw new AssertionError(String.format("Expected log message has not occurred: Level: %s, Regex: \"%s\"", level, regex));
}

private boolean eventMatchesWithoutMdc(LoggedEvent event, Level level, Pattern pattern, StackTraceElement caller) {
return eventHasLevel(event, level)
&& eventMatchesPattern(event, pattern)
&& eventIsRelevantToTest(event, caller);
private boolean eventMatchesWithoutMdc(LoggedEvent event, Level level, Pattern pattern) {
return eventHasLevel(event, level) && eventMatchesPattern(event, pattern);
}

private void throwAssertionForFoundMessageWithWrongMdcContents(Level level, String regex, LoggedEvent eventWithWrongMdcContents) {
Expand All @@ -109,11 +89,6 @@ private void throwAssertionForFoundMessageWithWrongMdcContents(Level level, Stri
throw new AssertionError(assertionMessage.toString());
}

// if the call stack is null, it's an integration test where filtering is done via logger name instead of the call stack
private boolean eventIsRelevantToTest(LoggedEvent event, StackTraceElement caller) {
return event.getMethodsInCallStack() == null || event.getMethodsInCallStack().contains(toMethodName(caller));
}

private boolean eventMatchesPattern(LoggedEvent event, Pattern pattern) {
return pattern.matcher(event.getFormattedMessage()).matches();
}
Expand Down
Loading

0 comments on commit 3e1ef37

Please sign in to comment.