在Java中创建用于日志记录或异常的消息的最佳实践



我在Java 6中找到了这段代码。

String mensajeExcluido = ArqSpringContext.getPropiedad("MENSAJE.EXCLUIDO");
LOG.warn("ERROR: Servicio: " + mensajeExcluido + ":" + someDTO.getProperty() +
",tsomeValue:" + someDTO.getValue() + "'.");
throw new Exception(mensajeExcluido);

这个代码

String mensajeExcluido = ArqSpringContext.getPropiedad("REGLA.MENSAJE");
String mensajeWarn = "ALERTA: Otro Servicio: " + mensajeExcluido + ":" +
someDTO.getProperty() + ",tsomeValue:" + someDTO.getValue() + "'.";
LOG.warn(mensajeWarn);
boolean exclusionVisible = Boolean.valueOf(ArqSpringContext.getPropiedad("EXCLUSION.VISIBLE"));
if (exclusionVisible) {
mensajeWarn = "<br></br>" + mensajeWarn;
} else {
mensajeWarn = "";
}
throw new Exception(mensajeExcluido + mensajeWarn);

这个代码的

LOG.warn("No se pudo validar Client Service. Code: " +
someDTO.getStatusCode() + ".");
return "No se pudo validar Client Service. Code: " +
someDTO.getStatusCode() + ".";

为了遵循最佳实践。。。

适用哪些建议

他们将对代码进行哪些更改

应如何处理文本

首先,在检查是否应该打印日志语句之前,尽量避免消息创建处理(即:在检查日志级别之前不要连接消息字符串。

// Better this
if (LOG.isDebugEnabled())
LOG.debug("This is a message with " + variable + " inside");
// Than this
final String message = "This is a message with " + variable + " inside";
if (LOG.isDebugEnabled())
LOG.debug(message);

大多数Java日志记录框架都允许提前检查是否要根据给定的设置打印日志语句。

如果你想省去为每个日志语句编写这些检查的负担,你可以利用Java 8 lambdas并编写这样的实用程序:


import java.util.function.Supplier;
import java.util.logging.Logger;
import static java.util.logging.Level.FINE;
class MyLogger {
public static MyLogger of(final Class<?> loggerClass) {
return new MyLogger(loggerClass);
}
private final Logger logger;
private MyLogger(final Class<?> loggerClass) {
logger = Logger.getLogger(loggerClass.getName());
}
// Supplier will be evaluated AFTER checking if log statement must be executed
public void fine(final Supplier<?> message) {
if (logger.isLoggable(FINE))
logger.log(FINE, message.get().toString());
}
}
static final LOG = MyLogger.of(String.class);
public void example() {
LOG.fine(() -> "This is a message with a system property: " + System.getProperty("property"));
}

最后,您可以利用Java字符串格式来使用String.format格式化日志消息。即:

final String message = String.format("Print %s string and %d digit", "str", 42);

应用于您提供的示例的良好实践是:

/*
* Using java.util.logging in JDK8+
*/
import java.util.logging.Level;
import java.util.logging.Logger;
import static java.lang.String.format;
class Dto {
String getProperty() { return "property"; }
String getValue() { return "property"; }
String getStatusCode() { return "statusCode"; }
}
final Logger LOG = Logger.getGlobal();
final Dto someDTO = new Dto();
void example1() throws Exception {
String mensajeExcluido = System.getProperty("MENSAJE.EXCLUIDO");
// Check if log will be printed before composing the log message
if (LOG.isLoggable(Level.WARNING)) {
// Using String.format usually is clearer and gives you more formatting options
final String messageFormat = "ERROR: Servicio: %s:%s,tsomeValue:%s'.";
LOG.warning(format(messageFormat, mensajeExcluido, someDTO.getProperty(), someDTO.getValue()));
}
// Or using lambdas
LOG.warning(() -> {
final String message = "ERROR: Servicio: %s:%s,tsomeValue:%s'.";
return format(message, mensajeExcluido, someDTO.getProperty(), someDTO.getValue());
});
throw new Exception(mensajeExcluido);
}
void example2() throws Exception {
String mensajeExcluido = System.getProperty("REGLA.MENSAJE");
String mensajeWarn = format(
// The concatenated message is probably missing a single quote at 'someValue'
"ALERTA: Otro Servicio: %s:%s,tsomeValue:%s'.",
mensajeExcluido,
someDTO.getProperty(),
someDTO.getValue()
);
LOG.warning(mensajeWarn);
boolean exclusionVisible = Boolean.parseBoolean(System.getProperty("EXCLUSION.VISIBLE"));
String exceptionMessage = exclusionVisible ?
mensajeExcluido + "<br></br>" + mensajeWarn : mensajeExcluido;
throw new Exception(exceptionMessage);
}
String example3() {
// You can compose the message only once and use it for the log and the result
String message =
format("No se pudo validar Client Service. Code: %s.", someDTO.getStatusCode());
LOG.warning(message);
return message;
}

最新更新