diff --git a/README.md b/README.md
index 24a476d9d..e514449cb 100644
--- a/README.md
+++ b/README.md
@@ -168,6 +168,14 @@ public class DockerComposeRuleTest {
This will automatically record logs for all containers in real time to the specified directory. Collection will stop when the containers terminate.
+The `LogDirectory` class contains utility methods to generate these paths. For example, you can write logs directly into the `$CIRCLE_ARTIFACTS` directory on CI (but fall back to `build/dockerLogs` locally) using:
+
+```java
+ .saveLogsTo(circleAwareLogDirectory(MyTest.class))
+```
+
+Methods in `LogDirectory` are intended to be statically imported for readability.
+
Skipping shutdown
-----------------
diff --git a/build.gradle b/build.gradle
index 2f77b19a9..5cf472dac 100644
--- a/build.gradle
+++ b/build.gradle
@@ -71,6 +71,7 @@ dependencies {
testCompile "org.mockito:mockito-core:$mockitoVersion"
testCompile "com.github.tomakehurst:wiremock:2.0.6-beta"
testCompile "com.google.code.findbugs:jsr305:3.0.0"
+ testCompile "com.github.stefanbirkner:system-rules:1.16.1"
}
// Instead of copying files out of `$buildDir/test-results/` on CircleCI, we can
diff --git a/src/main/java/com/palantir/docker/compose/DockerComposeRule.java b/src/main/java/com/palantir/docker/compose/DockerComposeRule.java
index fc4865a61..34fa3a1eb 100644
--- a/src/main/java/com/palantir/docker/compose/DockerComposeRule.java
+++ b/src/main/java/com/palantir/docker/compose/DockerComposeRule.java
@@ -32,6 +32,7 @@
import com.palantir.docker.compose.logging.DoNothingLogCollector;
import com.palantir.docker.compose.logging.FileLogCollector;
import com.palantir.docker.compose.logging.LogCollector;
+import com.palantir.docker.compose.logging.LogDirectory;
import java.io.IOException;
import java.util.List;
import org.immutables.value.Value;
@@ -169,6 +170,14 @@ public Builder file(String dockerComposeYmlFile) {
return files(DockerComposeFiles.from(dockerComposeYmlFile));
}
+ /**
+ * Save the output of docker logs to files, stored in the path
directory.
+ *
+ * See {@link LogDirectory} for some useful utilities, for example:
+ * {@link LogDirectory#circleAwareLogDirectory}.
+ *
+ * @param path directory into which log files should be saved
+ */
public Builder saveLogsTo(String path) {
return logCollector(FileLogCollector.fromPath(path));
}
diff --git a/src/main/java/com/palantir/docker/compose/logging/LogDirectory.java b/src/main/java/com/palantir/docker/compose/logging/LogDirectory.java
new file mode 100644
index 000000000..7187fc101
--- /dev/null
+++ b/src/main/java/com/palantir/docker/compose/logging/LogDirectory.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2016 Palantir Technologies, Inc. All rights reserved.
+ */
+
+package com.palantir.docker.compose.logging;
+
+import java.util.Optional;
+
+public class LogDirectory {
+
+ private LogDirectory() {}
+
+ /**
+ * For tests running on CircleCI, save logs into $CIRCLE_ARTIFACTS/dockerLogs/<testClassName>
.
+ * This ensures partial logs can be recovered if the build is cancelled or times out, and
+ * also avoids needless copying.
+ *
+ * Otherwise, save logs from local runs to a folder inside $project/build/dockerLogs
named
+ * after the test class.
+ *
+ * @param testClass the JUnit test class whose name will appear on the log folder
+ */
+ public static String circleAwareLogDirectory(Class> testClass) {
+ String artifactRoot = Optional.ofNullable(System.getenv("CIRCLE_ARTIFACTS")).orElse("build");
+ return artifactRoot + "/dockerLogs/" + testClass.getSimpleName();
+ }
+
+ /**
+ * Save logs into a new folder, $project/build/dockerLogs/<testClassName>.
+ */
+ public static String gradleDockerLogsDirectory(Class> testClass) {
+ return "build/dockerLogs/" + testClass.getSimpleName();
+ }
+}
diff --git a/src/test/java/com/palantir/docker/compose/logging/LogDirectoryTest.java b/src/test/java/com/palantir/docker/compose/logging/LogDirectoryTest.java
new file mode 100644
index 000000000..34969ce98
--- /dev/null
+++ b/src/test/java/com/palantir/docker/compose/logging/LogDirectoryTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2016 Palantir Technologies, Inc. All rights reserved.
+ */
+
+package com.palantir.docker.compose.logging;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.contrib.java.lang.system.EnvironmentVariables;
+
+public class LogDirectoryTest {
+
+ @Rule
+ public final EnvironmentVariables variablesRule = new EnvironmentVariables();
+
+ @Test
+ public void gradleDockerLogsDirectory_should_use_class_simple_name() {
+ String directory = LogDirectory.gradleDockerLogsDirectory(SomeTestClass.class);
+ assertThat(directory, is("build/dockerLogs/SomeTestClass"));
+ }
+
+ @Test
+ public void circleAwareLogDirectory_should_match_gradleDockerLogsDirectory_by_default() {
+ variablesRule.set("CIRCLE_ARTIFACTS", null);
+ String directory = LogDirectory.circleAwareLogDirectory(SomeTestClass.class);
+ assertThat(directory, is("build/dockerLogs/SomeTestClass"));
+ }
+
+ @Test
+ public void circleAwareLogDirectory_should_use_circle_environment_variable_if_available() {
+ variablesRule.set("CIRCLE_ARTIFACTS", "/tmp/circle-artifacts.g4DjuuD");
+
+ String directory = LogDirectory.circleAwareLogDirectory(SomeTestClass.class);
+ assertThat(directory, is("/tmp/circle-artifacts.g4DjuuD/dockerLogs/SomeTestClass"));
+ }
+
+ private static class SomeTestClass {}
+}