Skip to content

Commit

Permalink
feature: Use log prefix as format
Browse files Browse the repository at this point in the history
This replaces fabric8io#876 as its a bit more flexible and does not require a new configuration option.
You can use now a prefix `%z` for an empty string
  • Loading branch information
rhuss committed Nov 4, 2017
1 parent b00e9a7 commit 3603627
Show file tree
Hide file tree
Showing 9 changed files with 192 additions and 48 deletions.
2 changes: 1 addition & 1 deletion samples/data-jolokia/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
</parent>

<artifactId>dmp-sample-data-jolokia</artifactId>
<version>0.22.1</version>
<version>0.22-SNAPSHOT</version>
<!-- add custom lifecycle -->
<packaging>docker</packaging>

Expand Down
10 changes: 9 additions & 1 deletion src/main/asciidoc/inc/start/_logging.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,15 @@ When running containers the standard output and standard error of the container
| If set to `false` log output is disabled. This is useful if you want to disable log output by default but want to use the other configuration options when log output is switched on on the command line with `-Ddocker.showLogs`. Logging is enabled by default if a `<log>` section is given.

| *prefix*
| Prefix to use for the log output in order to identify the container. By default the image `alias` is used or alternatively the container `id`.
a| Prefix to use for the log output in order to identify the container. You can use placeholders in the prefix which are replaced on the fly:

* `%a`: Alias of the image, or, if not set, the short container id.
* `%c`: Short container id (i.e. the first 6 chars of the container id
* `%C`: The full container id
* `%n`: The image name
* `%z`: An empty string
By default the format is "`%a> `".

| *date*
a| Dateformat to use for log timestamps. If `<date>` is not given no timestamp will be shown. The date specification can be either a constant or a date format. The recognized constants are:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ public void log(int type, Timestamp timestamp, String txt) {
public void error(String error) {
ps().println(error);
}

private void addLogEntry(PrintStream ps, LogEntry logEntry) {
// TODO: Add the entry to a queue, and let the queue be picked up with a small delay from an extra
// thread which then can sort the entries by time before printing it out in order to avoid race conditions.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public boolean isLogStdout() {
}

public String getPrompt(boolean withColor,Timestamp timestamp) {
return formatTimestamp(timestamp,withColor) + formatPrefix(prefix, withColor) + "> ";
return formatTimestamp(timestamp,withColor) + formatPrefix(prefix, withColor);
}

public String getFile(){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,20 @@
* limitations under the License.
*/

import java.util.HashMap;
import java.util.Map;

import io.fabric8.maven.docker.config.ImageConfiguration;
import io.fabric8.maven.docker.config.LogConfiguration;
import io.fabric8.maven.docker.config.RunImageConfiguration;
import io.fabric8.maven.docker.util.FormatParameterReplacer;

/**
* @author roland
* @since 26/09/15
*/
public class LogOutputSpecFactory {
private static final String DEFAULT_PREFIX_FORMAT = "%a> ";
private boolean useColor;
private boolean logStdout;
private String logDate;
Expand All @@ -41,7 +46,7 @@ public LogOutputSpec createSpec(String containerId, ImageConfiguration imageConf
LogConfiguration logConfig = extractLogConfiguration(imageConfiguration);

addLogFormat(builder, logConfig);
addPrefix(builder, logConfig.getPrefix(), imageConfiguration.getAlias(), containerId);
addPrefix(builder, logConfig.getPrefix(), imageConfiguration, containerId);
builder.file(logConfig.getFileLocation())
.useColor(useColor)
.logStdout(logStdout)
Expand All @@ -50,15 +55,58 @@ public LogOutputSpec createSpec(String containerId, ImageConfiguration imageConf
return builder.build();
}

private void addPrefix(LogOutputSpec.Builder builder, String logPrefix, String alias, String containerId) {
String prefix = logPrefix;
if (prefix == null) {
prefix = alias;
}
if (prefix == null) {
prefix = containerId.substring(0, 6);
private void addPrefix(LogOutputSpec.Builder builder, String logPrefix, ImageConfiguration imageConfig, String containerId) {
String prefixFormat = logPrefix;
if (prefixFormat == null) {
prefixFormat = DEFAULT_PREFIX_FORMAT;
}
builder.prefix(prefix);
FormatParameterReplacer formatParameterReplacer = new FormatParameterReplacer(getPrefixFormatParameterLookups(imageConfig, containerId));
builder.prefix(formatParameterReplacer.replace(prefixFormat));
}

private Map<String, FormatParameterReplacer.Lookup> getPrefixFormatParameterLookups(final ImageConfiguration imageConfig, final String containerId) {
Map<String, FormatParameterReplacer.Lookup> ret = new HashMap<>();

ret.put("z", new FormatParameterReplacer.Lookup() {
@Override
public String lookup() {
return "";
}
});

ret.put("c", new FormatParameterReplacer.Lookup() {
@Override
public String lookup() {
return containerId.substring(0, 6);
}
});

ret.put("C", new FormatParameterReplacer.Lookup() {
@Override
public String lookup() {
return containerId;
}
});

ret.put("a", new FormatParameterReplacer.Lookup() {
@Override
public String lookup() {
String alias = imageConfig.getAlias();
if (alias != null) {
return alias;
}
return containerId.substring(0, 6);
}
});

ret.put("n", new FormatParameterReplacer.Lookup() {
@Override
public String lookup() {
return imageConfig.getName();
}
});

return ret;
}

private void addLogFormat(LogOutputSpec.Builder builder, LogConfiguration logConfig) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package io.fabric8.maven.docker.util;

import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.maven.project.MavenProject;

/**
* @author roland
* @since 04.11.17
*/
public class FormatParameterReplacer {

// Detect format elements within the name
private Pattern FORMAT_IDENTIFIER_PATTERN = Pattern.compile("^(.*?)%([^a-zA-Z]*)([a-zA-Z])(.*)$");

private final Map<String, Lookup> lookupMap;

public FormatParameterReplacer(Map<String, Lookup> lookupMap) {
this.lookupMap = lookupMap;
}

public String replace(String input) {
StringBuilder ret = new StringBuilder();
while (true) {
Matcher matcher = FORMAT_IDENTIFIER_PATTERN.matcher(input);
if (!matcher.matches()) {
ret.append(input);
return ret.toString();
}
ret.append(matcher.group(1));
ret.append(formatElement(matcher.group(2),matcher.group(3)));
input = matcher.group(4);
}
}

private String formatElement(String options, String what) {
FormatParameterReplacer.Lookup lookup = lookupMap.get(what);
if (lookup == null) {
throw new IllegalArgumentException(String.format("No image name format element '%%%s' known", what) );
}
String val = lookup.lookup();
return String.format("%" + (options != null ? options : "") + "s",val);
}


// Lookup abstraction
public interface Lookup {
String lookup();
}

}
45 changes: 11 additions & 34 deletions src/main/java/io/fabric8/maven/docker/util/ImageNameFormatter.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,58 +34,33 @@
*/
public class ImageNameFormatter implements ConfigHelper.NameFormatter {

private final Map<String, Lookup> lookups;

private final FormatParameterReplacer formatParamReplacer;

private final Date now;

public ImageNameFormatter(MavenProject project, Date now) {
this.lookups = new HashMap<>();
this.now = now;
initLookups(project);
formatParamReplacer = new FormatParameterReplacer(initLookups(project));
}

// Detect format elements within the name
private Pattern FORMAT_IDENTIFIER_PATTERN = Pattern.compile("^(.*?)%([^a-zA-Z]*)([a-zA-Z])(.*)$");

@Override
public String format(String name) {
if (name == null) {
return null;
}
StringBuilder ret = new StringBuilder();
String rest = name;

while (true) {
Matcher matcher = FORMAT_IDENTIFIER_PATTERN.matcher(rest);
if (!matcher.matches()) {
ret.append(rest);
return ret.toString();
}
ret.append(matcher.group(1));
ret.append(formatElement(matcher.group(2),matcher.group(3)));
rest = matcher.group(4);
}
return formatParamReplacer.replace(name);
}

// =====================================================================================

private String formatElement(String options, String what) {
Lookup lookup = lookups.get(what);
if (lookup == null) {
throw new IllegalArgumentException(String.format("No image name format element '%%%s' known", what) );
}
String val = lookup.lookup();
return String.format("%" + (options != null ? options : "") + "s",val);
}

// Lookup abstraction
private interface Lookup {
String lookup();
}

// Lookup classes
private void initLookups(final MavenProject project) {
private Map<String, FormatParameterReplacer.Lookup> initLookups(final MavenProject project) {
// Sanitized group id
final Map<String, FormatParameterReplacer.Lookup> lookups = new HashMap<>();

lookups.put("g", new DefaultUserLookup(project));

// Sanitized artifact id
Expand All @@ -95,11 +70,12 @@ private void initLookups(final MavenProject project) {
lookups.put("v", new DefaultTagLookup(project, DefaultTagLookup.Mode.PLAIN, now));
lookups.put("t", new DefaultTagLookup(project, DefaultTagLookup.Mode.SNAPSHOT_WITH_TIMESTAMP, now));
lookups.put("l", new DefaultTagLookup(project, DefaultTagLookup.Mode.SNAPSHOT_LATEST, now));
return lookups;
}

// ==============================================================================================

private static abstract class AbstractLookup implements Lookup {
public static abstract class AbstractLookup implements FormatParameterReplacer.Lookup {
protected final MavenProject project;

private AbstractLookup(MavenProject project) {
Expand All @@ -109,8 +85,9 @@ private AbstractLookup(MavenProject project) {
protected String getProperty(String key) {
return project.getProperties().getProperty(key);
}

}


private static class DefaultUserLookup extends AbstractLookup {

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public class DefaultLogCallbackTest {
public void before() throws IOException {
file = File.createTempFile("logcallback", ".log");
file.deleteOnExit();
spec = new LogOutputSpec.Builder().prefix("callback-test")
spec = new LogOutputSpec.Builder().prefix("callback-test> ")
.file(file.toString()).build();
callback = new DefaultLogCallback(spec);
callback.open();
Expand Down Expand Up @@ -76,7 +76,7 @@ public void shouldLogToStdout() throws IOException, DoneException {
PrintStream stdout = System.out;
try {
System.setOut(ps);
spec = new LogOutputSpec.Builder().prefix("stdout")
spec = new LogOutputSpec.Builder().prefix("stdout> ")
.build();
callback = new DefaultLogCallback(spec);
callback.open();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package io.fabric8.maven.docker.log;

import java.util.Arrays;
import java.util.Collection;

import io.fabric8.maven.docker.config.ImageConfiguration;
import io.fabric8.maven.docker.config.LogConfiguration;
import io.fabric8.maven.docker.config.RunImageConfiguration;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import static org.junit.Assert.assertEquals;

/**
* @author roland
* @since 04.11.17
*/
@RunWith(Parameterized.class)
public class LogOutputSpecFactoryTest {

private static String ALIAS = "fcn";
private static String NAME = "rhuss/fcn:1.0";
private static String CONTAINER_ID = "1234567890";

@Parameterized.Parameters(name = "{index}: format \"{0}\" --> \"{1}\"")
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][] {
{ "%z", "" },
{ null, ALIAS + "> "},
{ "%c", CONTAINER_ID.substring(0,6) },
{ "%C: ", CONTAINER_ID + ": " },
{ "%n -- ", NAME + " -- " },
{ "%z%c%n%C %a", CONTAINER_ID.substring(0,6) + NAME + CONTAINER_ID + " " + ALIAS }
});
}

@Parameterized.Parameter(0)
public String prefixFormat;

@Parameterized.Parameter(1)
public String expectedPrefix;

@Test
public void prefix() {
LogOutputSpec spec = createSpec(prefixFormat);
assertEquals(expectedPrefix, spec.getPrompt(false, null));
}

private LogOutputSpec createSpec(String prefix) {
LogOutputSpecFactory factory = new LogOutputSpecFactory(false, false, null);
LogConfiguration logConfig = new LogConfiguration.Builder().prefix(prefix).build();
RunImageConfiguration runConfig = new RunImageConfiguration.Builder().log(logConfig).build();
ImageConfiguration imageConfiguration = new ImageConfiguration.Builder().alias(ALIAS).name(NAME).runConfig(runConfig).build();
return factory.createSpec(CONTAINER_ID,imageConfiguration);
}
}

0 comments on commit 3603627

Please sign in to comment.