blob: c36b108b2a755eb21465ceb24a74bf5fb9378e71 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2020, 2021 Stephan Wahlbrink and others.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
# which is available at https://www.apache.org/licenses/LICENSE-2.0.
#
# SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
#
# Contributors:
# Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.jcommons.status.util;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import org.eclipse.statet.jcommons.collections.ImList;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.ObjectUtils.ToStringBuilder;
import org.eclipse.statet.jcommons.status.Status;
import org.eclipse.statet.jcommons.status.StatusLogger;
import org.eclipse.statet.jcommons.status.Statuses;
@NonNullByDefault
public class JUtilLoggingStatusLogger implements StatusLogger {
private static final Function<String, Logger> CREATE_LOG_FUNCTION= Logger::getLogger;
private final ConcurrentHashMap<String, Logger> logs= new ConcurrentHashMap<>();
private final StatusPrinter logStatusPrinter= new StatusPrinter();
public JUtilLoggingStatusLogger() {
}
@Override
public void log(final Status status) {
final Logger log= this.logs.computeIfAbsent(status.getBundleId(), CREATE_LOG_FUNCTION);
final Level level;
switch (status.getSeverity()) {
case Status.ERROR:
level= Level.SEVERE;
break;
case Status.WARNING:
level= Level.WARNING;
break;
default:
level= Level.INFO;
break;
}
if (log.isLoggable(level)) {
final LogRecord record= new LogRecord(level, createMessage(status));
if (status.getException() != null) {
record.setThrown(status.getException());
}
enrichRecord(record, status);
log.log(record);
}
}
protected String createMessage(final Status status) {
final ToStringBuilder sb= new ToStringBuilder();
switch (status.getSeverity()) {
case Status.OK:
case Status.CANCEL:
sb.append(Statuses.getSeverityString(status.getSeverity()));
sb.append(' ');
break;
default:
break;
}
sb.append('[');
sb.append(status.getCode());
sb.append(']');
if (status.getMessage().length() <= 80 && status.getMessage().indexOf('\n') == -1) {
sb.append(' ', status.getMessage());
}
else {
sb.addProp("message", status.getMessage()); //$NON-NLS-1$
}
if (status.isMultiStatus()) {
final ImList<Status> children= status.getChildren();
if (children != null && !children.isEmpty()) {
final StringBuilder sb0= new StringBuilder();
sb0.append("Status:\n");
this.logStatusPrinter.print(children, sb0);
sb.addProp("children", sb0.toString()); //$NON-NLS-1$
}
else {
sb.addProp("children", "<none>"); //$NON-NLS-1$
}
}
return sb.toString();
}
protected void enrichRecord(final LogRecord record, final Status status) {
// set correct caller
try {
final StackTraceElement[] stackTrace= Thread.currentThread().getStackTrace();
for (int i= 1; i < stackTrace.length; i++) {
if (!stackTrace[i].getMethodName().startsWith("log")) { //$NON-NLS-1$
record.setSourceClassName(stackTrace[i].getClassName());
record.setSourceMethodName(stackTrace[i].getMethodName());
break;
}
}
}
catch (final Exception ignore) {}
}
}