in endorsed/src/org.apache.sis.util/main/org/apache/sis/util/logging/MonolineFormatter.java [691:845]
public String format(final LogRecord record) {
boolean faint = false; // Whether to use faint text for level < INFO.
String emphasisStart = ""; // ANSI escape sequence for bold text if we use it.
String emphasisEnd = ""; // ANSI escape sequence for stopping bold text if we use it.
final Level level = record.getLevel();
synchronized (buffer) {
final boolean colored = (colors != null);
if (colored && level.intValue() >= LEVEL_THRESHOLD.intValue()) {
emphasisStart = X364.BOLD.sequence();
emphasisEnd = X364.NORMAL.sequence();
faint = faintSupported;
}
buffer.setLength(header.length());
/*
* Append the time (e.g. "00:00:12.365"). The time pattern can be set either
* programmatically by a call to `setTimeFormat(…)`, or in logging.properties
* file with the "org.apache.sis.util.logging.MonolineFormatter.time" property.
*/
if (timeFormat != null) {
Date time = new Date(Math.max(0, record.getMillis() - startMillis));
timeFormat.format(time, buffer, new FieldPosition(0));
buffer.append(' ');
}
/*
* Append the level (e.g. "FINE"). We do not provide the option to turn level off for now.
* This level will be formatted with a colorized background if ANSI escape sequences are enabled.
*/
int margin = buffer.length();
String levelColor = "", levelReset = "";
if (SHOW_LEVEL) {
if (colored) {
levelColor = colorAt(level);
levelReset = X364.BACKGROUND_DEFAULT.sequence();
}
final int offset = buffer.append(levelColor).append(emphasisStart).length();
final int length = buffer.append(level.getLocalizedName()).length() - offset;
buffer.append(emphasisEnd).append(CharSequences.spaces(levelWidth - length));
margin += buffer.length() - emphasisEnd.length() - offset;
buffer.append(levelReset).append(' ');
}
/*
* Append the logger name or source class name, in long of short form.
* The name may be formatted in bold characters if ANSI escape sequences are enabled.
*/
String source;
switch (sourceFormat) {
case LOGGER_SHORT: // Fall through
case LOGGER_LONG: source = record.getLoggerName(); break;
case METHOD: // Fall through
case CLASS_SHORT: // Fall through
case CLASS_LONG: source = record.getSourceClassName(); break;
default: source = null; break;
}
if (source != null) {
switch (sourceFormat) {
case METHOD: // Fall through
case LOGGER_SHORT: // Fall through
case CLASS_SHORT: {
// Works even if there is no '.' since we get -1 as index.
source = source.substring(source.lastIndexOf('.') + 1);
break;
}
}
if (sourceFormat == METHOD) {
source = source + '.' + record.getSourceMethodName();
}
buffer.append(emphasisStart).append('[').append(source).append(']').append(emphasisEnd).append(' ');
}
/*
* Now prepare the LineAppender for the message. We set a line separator prefixed by some
* number of spaces in order to align message body on the column after the level name.
*/
String bodyLineSeparator = writer.getLineSeparator();
final String lineSeparator = System.lineSeparator();
if (bodyLineSeparator.length() != lineSeparator.length() + margin + 1) {
if (CONTINUATION_MARGIN != 0) {
final int highlight = Math.min(CONTINUATION_MARGIN, margin);
bodyLineSeparator = lineSeparator
+ levelColor + Strings.CONTINUATION_MARK + CharSequences.spaces(highlight - 1)
+ levelReset + CharSequences.spaces(margin - highlight + 1);
} else {
bodyLineSeparator = lineSeparator;
}
writer.setLineSeparator(bodyLineSeparator);
}
if (faint) {
buffer.append(X364.FAINT.sequence());
}
final Throwable exception = record.getThrown();
String message = formatMessage(record);
int maximalLength = Integer.MAX_VALUE;
int length = 0;
if (message != null) {
length = CharSequences.skipTrailingWhitespaces(message, 0, message.length());
if (maximalLineLength != null) {
maximalLength = maximalLineLength.getAsInt();
}
}
/*
* Up to this point, we wrote directly in the StringBuilder for performance reasons.
* Now for the message part, we need to use the LineAppender in order to replace EOL
* and tabulations.
*/
writer.setMaximalLineLength(Math.max(maximalLength - margin - 3, 10));
writer.setCurrentLineLength(X364.lengthOfPlain(buffer, 0, buffer.length()));
try {
if (message != null) {
writer.append(message, 0, length);
}
if (exception != null) {
if (message != null) {
writer.append("\nCaused by: "); // LineAppender will replace '\n' by the system EOL.
}
if (level.intValue() >= LEVEL_THRESHOLD.intValue()) {
exception.printStackTrace(printer);
} else {
printAbridged(exception, writer, record.getLoggerName(),
record.getSourceClassName(), record.getSourceMethodName());
}
}
writer.clear();
writer.flush();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
/*
* We wrote the main content, but maybe with some extra lines. Trim the last lines by skipping white spaces
* and line separator (EOL). If the `bodyLineSeparator` margin is found immediately before the white spaces
* and EOL that we skipped, we repeat this process until we find at least one non-white character after the
* `bodyLineSeparator`.
*/
int lastMargin = buffer.length();
do {
length = CharSequences.skipTrailingWhitespaces(buffer, 0, lastMargin);
lastMargin = buffer.lastIndexOf(bodyLineSeparator);
buffer.setLength(length);
length -= lastMargin;
} while (length > 0 && length <= bodyLineSeparator.length());
if (faint) {
buffer.append(X364.NORMAL.sequence());
}
/*
* At this point we finished to write the message, except for the final line separator.
* If the message spans more than one line, there is CONTINUATION_MARK characters in the
* margin. Replace the last occurrence of those characters by CONTINUATION_END.
*/
lastMargin = CharSequences.indexOf(buffer, Strings.CONTINUATION_MARK,
lastMargin + lineSeparator.length(),
lastMargin + bodyLineSeparator.length());
if (lastMargin >= 0) {
buffer.setCharAt(lastMargin, Strings.CONTINUATION_END);
}
return buffer.append(lineSeparator).toString();
}
}