Skip to content

Commit

Permalink
Add clr and property patterns for boot support
Browse files Browse the repository at this point in the history
  • Loading branch information
agentgt committed Aug 22, 2024
1 parent ea15972 commit bc277d2
Show file tree
Hide file tree
Showing 6 changed files with 239 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,14 @@ public static LogProvider<PatternCompiler> of(Consumer<Builder> consumer) {
.build(LogProperties.GLOBAL_ANSI_DISABLE_PROPERTY) //
.get(config.properties()) //
.value(false);
var b = PatternConfig.builder().fromProperties(config.properties());
var b = PatternConfig.builder()
.propertyFunction(PatternConfig.propertyFunction(config.properties(),
PatternConfig.PATTERN_PROPERY_PREFIX))
.fromProperties(config.properties());
if (ansiDisable) {
b.ansiDisabled(true);
}

return b.build();
});
Builder b = builder();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.function.Function;

import org.eclipse.jdt.annotation.Nullable;

import io.jstach.rainbowgum.LogConfig;
import io.jstach.rainbowgum.LogProperties;
Expand All @@ -26,6 +29,11 @@ public sealed interface PatternConfig extends Configurator {
*/
public static final String PATTERN_CONFIG_PREFIX = LogProperties.ROOT_PREFIX + "pattern.config.{name}.";

/**
* Key Values that can be retrieved by various patterns.
*/
public static final String PATTERN_PROPERY_PREFIX = LogProperties.ROOT_PREFIX + "pattern.property.";

/**
* Default zoneId if not specified.
* @return zone id.
Expand All @@ -45,6 +53,14 @@ public sealed interface PatternConfig extends Configurator {
*/
public boolean ansiDisabled();

/**
* Key Value function for ad-hoc property replacements and lookup in various patterns.
* @return function.
* @see #PATTERN_PROPERY_PREFIX
*/
@SuppressWarnings("exports")
public Function<String, @Nullable String> propertyFunction();

/**
* Creates a builder to create formatter config.
* @return builder.
Expand Down Expand Up @@ -76,6 +92,7 @@ public static PatternConfigBuilder copy(PatternConfigBuilder builder, PatternCon
builder.ansiDisabled(config.ansiDisabled());
builder.lineSeparator(config.lineSeparator());
builder.zoneId(config.zoneId());
builder.propertyFunction(config.propertyFunction());
return builder;
}

Expand All @@ -97,6 +114,27 @@ public static PatternConfig ofUniversal() {
return StandardFormatterConfig.UNIVERSAL_FORMATTER_CONFIG;
}

/**
* Creates a property function.
* @param properties log properties.
* @param prefix prefix keys before asking LogProperties.
* @return function.
*/
@SuppressWarnings("exports")
public static Function<String, @Nullable String> propertyFunction(LogProperties properties, String prefix) {
record LogPropertiesPatternKeyValues(String prefix,
LogProperties properties) implements Function<String, @Nullable String> {

@Override
public @Nullable String apply(String t) {
String key = LogProperties.concatKey(prefix, t);
return properties.valueOrNull(key);
}

}
return new LogPropertiesPatternKeyValues(prefix, properties);
}

@Override
default boolean configure(LogConfig config, Pass pass) {
config.serviceRegistry().put(PatternConfig.class, ServiceRegistry.DEFAULT_SERVICE_NAME, this);
Expand Down Expand Up @@ -132,11 +170,28 @@ default boolean ansiDisabled() {
return false;
}

@Override
default Function<String, @Nullable String> propertyFunction() {
return StandardPropertyFunction.INSTANCE;
}

enum StandardPropertyFunction implements Function<String, @Nullable String> {

INSTANCE;

@Override
public @Nullable String apply(String t) {
return null;
}

}

}

enum StandardFormatterConfig implements DefaultFormatterConfig {

DEFAULT_FORMATTER_CONFIG(), UNIVERSAL_FORMATTER_CONFIG {
DEFAULT_FORMATTER_CONFIG(), //
UNIVERSAL_FORMATTER_CONFIG {
@Override
public String lineSeparator() {
return "\n";
Expand All @@ -155,6 +210,7 @@ public boolean ansiDisabled() {

}

record SimpleFormatterConfig(ZoneId zoneId, String lineSeparator, boolean ansiDisabled) implements PatternConfig {
record SimpleFormatterConfig(ZoneId zoneId, String lineSeparator, boolean ansiDisabled,
Function<String, @Nullable String> propertyFunction) implements PatternConfig {

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.jstach.rainbowgum.pattern.format;

import java.time.ZoneId;
import java.util.function.Function;

import org.eclipse.jdt.annotation.Nullable;

Expand All @@ -14,6 +15,7 @@
import io.jstach.rainbowgum.annotation.LogConfigurable.ConvertParameter;
import io.jstach.rainbowgum.annotation.LogConfigurable.KeyParameter;
import io.jstach.rainbowgum.annotation.LogConfigurable.PassThroughParameter;
import io.jstach.rainbowgum.pattern.format.DefaultFormatterConfig.StandardPropertyFunction;
import io.jstach.rainbowgum.spi.RainbowGumServiceProvider;
import io.jstach.rainbowgum.spi.RainbowGumServiceProvider.Configurator;
import io.jstach.svc.ServiceProvider;
Expand Down Expand Up @@ -57,14 +59,17 @@ static LogProvider<LogEncoder> provideEncoder(@KeyParameter String name, String
}

@LogConfigurable(name = "PatternConfigBuilder", prefix = PatternConfig.PATTERN_CONFIG_PREFIX)
static PatternConfig provideFormatterConfig(@KeyParameter String name,
@ConvertParameter("convertZoneId") @Nullable ZoneId zoneId, @Nullable String lineSeparator,
@Nullable Boolean ansiDisabled) {
static PatternConfig provideFormatterConfig(@KeyParameter String name, //
@ConvertParameter("convertZoneId") @Nullable ZoneId zoneId, //
@Nullable String lineSeparator, //
@Nullable Boolean ansiDisabled, //
@PassThroughParameter @Nullable Function<String, @Nullable String> propertyFunction) {
PatternConfig dc = PatternConfig.of();
ansiDisabled = ansiDisabled == null ? dc.ansiDisabled() : ansiDisabled;
lineSeparator = lineSeparator == null ? dc.lineSeparator() : lineSeparator;
zoneId = zoneId == null ? dc.zoneId() : zoneId;
return new SimpleFormatterConfig(zoneId, lineSeparator, ansiDisabled);
propertyFunction = propertyFunction == null ? StandardPropertyFunction.INSTANCE : propertyFunction;
return new SimpleFormatterConfig(zoneId, lineSeparator, ansiDisabled, propertyFunction);

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import static io.jstach.rainbowgum.pattern.format.ANSIConstants.RED_FG;
import static io.jstach.rainbowgum.pattern.format.ANSIConstants.WHITE_FG;
import static io.jstach.rainbowgum.pattern.format.ANSIConstants.YELLOW_FG;
import static io.jstach.rainbowgum.pattern.format.ANSIConstants.FAINT;

import java.lang.System.Logger.Level;
import java.time.ZoneId;
Expand Down Expand Up @@ -176,6 +177,23 @@ protected LogFormatter _create(PatternConfig config, PatternKeyword node) {

}

},
PROPERTY() {

@Override
protected LogFormatter _create(PatternConfig config, PatternKeyword node) {
String key = node.optOrNull(0);
if (key == null) {
return LogFormatter.builder().text("Property_HAS_NO_KEY").build();
}
var f = config.propertyFunction();
var v = f.apply(key);
if (v == null) {
return LogFormatter.noop();
}
return LogFormatter.builder().text(v).build();
}

};

static final String ISO8601_STR = "ISO8601";
Expand Down Expand Up @@ -235,6 +253,8 @@ final class ANSIConstants {

final static String BOLD = "1;";

final static String FAINT = "2;";

final static String RESET = "0;";

final static String BLACK_FG = "30";
Expand Down Expand Up @@ -288,7 +308,53 @@ private static String levelToANSI(Level level) {

}

enum HightlightCompositeFactory implements CompositeFactory {
record ClrLevelFormatter(@Nullable LogFormatter child) implements LogFormatter.EventFormatter {

@Override
public void format(StringBuilder output, LogEvent event) {
/*
* TODO should a null child be a noop? Need to see what logback does for compat.
*/
var level = event.level();
String code = levelToANSI(level);
output.append(ANSIConstants.ESC_START);
output.append(code);
output.append(ANSIConstants.ESC_END);
if (child != null) {
child.format(output, event);
}
output.append(ANSIConstants.SET_DEFAULT_COLOR);
}

private static String levelToANSI(Level level) {
return switch (level) {
case ERROR -> RED_FG;
case WARNING -> YELLOW_FG;
case INFO -> GREEN_FG;
case DEBUG -> GREEN_FG;
case TRACE -> GREEN_FG;
default -> DEFAULT_FG;
};
}

}

record ClrStaticFormatter(@Nullable LogFormatter child, String code) implements LogFormatter.EventFormatter {

@Override
public void format(StringBuilder output, LogEvent event) {
output.append(ANSIConstants.ESC_START);
output.append(code);
output.append(ANSIConstants.ESC_END);
if (child != null) {
child.format(output, event);
}
output.append(ANSIConstants.SET_DEFAULT_COLOR);
}

}

enum HighlightCompositeFactory implements CompositeFactory {

HIGHTLIGHT() {

Expand All @@ -303,6 +369,39 @@ public LogFormatter create(PatternConfig config, PatternKeyword node, @Nullable
return new HighlightFormatter(child);
}

},

CLR() {

@Override
public LogFormatter create(PatternConfig config, PatternKeyword node, @Nullable LogFormatter child) {
if (config.ansiDisabled()) {
if (child == null) {
return LogFormatter.noop();
}
return child;
}
String color = node.optOrNull(0, HighlightCompositeFactory::parseColor);
if (color == null) {
return new ClrLevelFormatter(child);
}
return new ClrStaticFormatter(child, color);
}

};

static String parseColor(String color) {
color = color.toLowerCase(Locale.ROOT);
return switch (color) {
case "blue" -> BLACK_FG;
case "cyan" -> CYAN_FG;
case "faint" -> FAINT + DEFAULT_FG;
case "green" -> GREEN_FG;
case "magenta" -> MAGENTA_FG;
case "red" -> RED_FG;
case "yellow" -> YELLOW_FG;
default -> throw new IllegalArgumentException("Bad color:" + color);
};
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,11 @@ enum KeywordKey implements PatternKey {
* <a href="https://logback.qos.ch/manual/layouts.html#mdc">MDC keywords</a>
*/
MDC("X", "mdc"), //
/**
* <a href="https://logback.qos.ch/manual/layouts.html#mdc">Property keywords</a>
* @see PatternConfig#propertyFunction()
*/
PROPERTY("property"), //
/**
* <a href="https://logback.qos.ch/manual/layouts.html#ex">Throwable keywords</a>
*/
Expand Down Expand Up @@ -263,6 +268,47 @@ public List<String> aliases() {

}

// config.conversionRule("clr", ColorConverter.class);
// config.conversionRule("correlationId", CorrelationIdConverter.class);
// config.conversionRule("esb", EnclosedInSquareBracketsConverter.class);
// config.conversionRule("wex", WhitespaceThrowableProxyConverter.class);
// config.conversionRule("wEx", ExtendedWhitespaceThrowableProxyConverter.class)

/**
* Spring Boot patterns.
*/
@CaseChanging
enum SpringBootKey implements PatternKey {

/*
* TODO maybe this should be in the spring boot module only?
*/

/**
* <a href=
* "https://docs.spring.io/spring-boot/reference/features/logging.html#features.logging.console-output.color-coded">
* Spring Boot color pattern key</a>
*
*/
CLR("clr");

private final List<String> aliases;

private SpringBootKey(List<String> aliases) {
this.aliases = aliases;
}

private SpringBootKey(String... others) {
this(List.of(others));
}

@Override
public List<String> aliases() {
return this.aliases;
}

}

}

final class DefaultPatternRegistry implements PatternRegistry {
Expand Down Expand Up @@ -325,7 +371,7 @@ static PatternRegistry registerDefaults(PatternRegistry registry) {
case FILE -> KeywordFactory.of(CallerInfoFormatter.FILE);
case LINE -> KeywordFactory.of(CallerInfoFormatter.LINE);
case METHOD -> KeywordFactory.of(CallerInfoFormatter.METHOD);
default -> throw new IllegalArgumentException("Unexpected value: " + c);
case PROPERTY -> StandardKeywordFactory.PROPERTY;
};

registry.register(c, keyword);
Expand All @@ -349,11 +395,18 @@ static PatternRegistry registerDefaults(PatternRegistry registry) {
case BOLD_RED -> ColorCompositeFactory.BOLD_RED;
case BOLD_WHITE -> ColorCompositeFactory.BOLD_WHITE;
case BOLD_YELLOW -> ColorCompositeFactory.BOLD_YELLOW;
case HIGHLIGHT -> HightlightCompositeFactory.HIGHTLIGHT;
case HIGHLIGHT -> HighlightCompositeFactory.HIGHTLIGHT;
};
registry.register(c, factory);
}

for (SpringBootKey sk : SpringBootKey.values()) {
var factory = switch (sk) {
case CLR -> HighlightCompositeFactory.CLR;
};
registry.register(sk, factory);
}

registry.register(BareKey.BARE, BareCompositeFactory.BARE);
return registry;
}
Expand Down
Loading

0 comments on commit bc277d2

Please sign in to comment.