Polish "Add more styling support to the Logback and Log4j2 color converters"

See gh-49285
This commit is contained in:
Andy Wilkinson
2026-03-12 09:27:04 +00:00
parent 2e12df8e4f
commit 29e4938971
4 changed files with 47 additions and 39 deletions
@@ -61,14 +61,11 @@ public final class ColorConverter extends LogEventPatternConverter {
static {
Map<String, AnsiElement> ansiElements = new HashMap<>();
// Foreground colors (e.g. "red", "bright_blue")
Arrays.stream(AnsiColor.values())
.filter((color) -> color != AnsiColor.DEFAULT)
.forEach((color) -> ansiElements.put(color.name().toLowerCase(Locale.ROOT), color));
// Text styles (e.g. "bold", "italic", "underline", "reverse", "faint", "normal")
Arrays.stream(AnsiStyle.values())
.forEach((style) -> ansiElements.put(style.name().toLowerCase(Locale.ROOT), style));
// Background colors with "bg_" prefix (e.g. "bg_red", "bg_bright_blue")
Arrays.stream(AnsiBackground.values())
.filter((bg) -> bg != AnsiBackground.DEFAULT)
.forEach((bg) -> ansiElements.put("bg_" + bg.name().toLowerCase(Locale.ROOT), bg));
@@ -153,14 +150,12 @@ public final class ColorConverter extends LogEventPatternConverter {
PatternParser parser = PatternLayout.createPatternParser(config);
List<PatternFormatter> formatters = parser.parse(options[0]);
List<AnsiElement> stylings = new ArrayList<>();
for (int i = 1; i < options.length; i++) {
if (options[i] != null) {
String[] optionParts = options[i].split(",");
for (String optionPart : optionParts) {
AnsiElement element = ELEMENTS.get(optionPart.trim().toLowerCase(Locale.ROOT));
if (element != null) {
stylings.add(element);
}
if (options.length >= 2 && options[1] != null) {
String[] optionParts = options[1].split(",");
for (String optionPart : optionParts) {
AnsiElement element = ELEMENTS.get(optionPart.trim().toLowerCase(Locale.ROOT));
if (element != null) {
stylings.add(element);
}
}
}
@@ -51,14 +51,11 @@ public class ColorConverter extends CompositeConverter<ILoggingEvent> {
static {
Map<String, AnsiElement> ansiElements = new HashMap<>();
// Foreground colors (e.g. "red", "bright_blue")
Arrays.stream(AnsiColor.values())
.filter((color) -> color != AnsiColor.DEFAULT)
.forEach((color) -> ansiElements.put(color.name().toLowerCase(Locale.ROOT), color));
// Text styles (e.g. "bold", "italic", "underline", "reverse", "faint", "normal")
Arrays.stream(AnsiStyle.values())
.forEach((style) -> ansiElements.put(style.name().toLowerCase(Locale.ROOT), style));
// Background colors with "bg_" prefix (e.g. "bg_red", "bg_bright_blue")
Arrays.stream(AnsiBackground.values())
.filter((bg) -> bg != AnsiBackground.DEFAULT)
.forEach((bg) -> ansiElements.put("bg_" + bg.name().toLowerCase(Locale.ROOT), bg));
@@ -237,24 +237,17 @@ class ColorConverterTests {
}
@Test
void multipleStylesCommaSeparated() {
void multipleStyles() {
StringBuilder output = new StringBuilder();
newConverter("bold, red").format(this.event, output);
assertThat(output).hasToString("\033[1;31min\033[0;39m");
}
@Test
void multipleStylesMultipleOptions() {
StringBuilder output = new StringBuilder();
newConverter("bold", "red").format(this.event, output);
assertThat(output).hasToString("\033[1;31min\033[0;39m");
}
@Test
void highlightFatal() {
this.event.setLevel(Level.FATAL);
StringBuilder output = new StringBuilder();
newConverter((String) null).format(this.event, output);
newConverter(null).format(this.event, output);
assertThat(output).hasToString("\033[31min\033[0;39m");
}
@@ -262,7 +255,7 @@ class ColorConverterTests {
void highlightError() {
this.event.setLevel(Level.ERROR);
StringBuilder output = new StringBuilder();
newConverter((String) null).format(this.event, output);
newConverter(null).format(this.event, output);
assertThat(output).hasToString("\033[31min\033[0;39m");
}
@@ -270,7 +263,7 @@ class ColorConverterTests {
void highlightWarn() {
this.event.setLevel(Level.WARN);
StringBuilder output = new StringBuilder();
newConverter((String) null).format(this.event, output);
newConverter(null).format(this.event, output);
assertThat(output).hasToString("\033[33min\033[0;39m");
}
@@ -278,7 +271,7 @@ class ColorConverterTests {
void highlightDebug() {
this.event.setLevel(Level.DEBUG);
StringBuilder output = new StringBuilder();
newConverter((String) null).format(this.event, output);
newConverter(null).format(this.event, output);
assertThat(output).hasToString("\033[32min\033[0;39m");
}
@@ -286,17 +279,13 @@ class ColorConverterTests {
void highlightTrace() {
this.event.setLevel(Level.TRACE);
StringBuilder output = new StringBuilder();
newConverter((String) null).format(this.event, output);
newConverter(null).format(this.event, output);
assertThat(output).hasToString("\033[32min\033[0;39m");
}
private ColorConverter newConverter(@Nullable String... stylings) {
if (stylings == null) {
stylings = new String[] { null };
}
String[] options = new String[1 + stylings.length];
options[0] = this.in;
System.arraycopy(stylings, 0, options, 1, stylings.length);
private ColorConverter newConverter(@Nullable String additionalOptions) {
String[] options = (additionalOptions != null) ? new String[] { this.in, additionalOptions }
: new String[] { this.in };
ColorConverter converter = ColorConverter.newInstance(null, options);
assertThat(converter).isNotNull();
return converter;
@@ -113,15 +113,15 @@ The following table describes the mapping of log levels to colors:
| Green
|===
Alternatively, you can specify the color or style that should be used by providing it as an option to the conversion.
For example, to make the text yellow, use the following setting:
Alternatively, you can specify the color and styles that should be used by providing them as options to the conversion.
For example, to make the text yellow and bold, use the following setting:
[source]
----
%clr(%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}){yellow}
%clr(%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}){yellow,bold}
----
The following colors and styles are supported:
The following text colors are supported:
* `black`
* `blue`
@@ -134,13 +134,40 @@ The following colors and styles are supported:
* `bright_white`
* `bright_yellow`
* `cyan`
* `faint`
* `green`
* `magenta`
* `red`
* `white`
* `yellow`
The following background colors are supported:
* `bg_black`
* `bg_blue`
* `bg_bright_black`
* `bg_bright_blue`
* `bg_bright_cyan`
* `bg_bright_green`
* `bg_bright_magenta`
* `bg_bright_red`
* `bg_bright_white`
* `bg_bright_yellow`
* `bg_cyan`
* `bg_green`
* `bg_magenta`
* `bg_red`
* `bg_white`
* `bg_yellow`
The following styles are supported:
* `bold`
* `faint`
* `italic`
* `normal`
* `reverse`
* `underline`
[[features.logging.file-output]]