英文:
Best Practices to create Message for Logging or Exception in 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() + ".";
为了遵循最佳实践...
适用的建议是什么?
这些建议会对代码产生什么改变?
如何处理文本?
英文:
I found this code in Java 6.
String mensajeExcluido = ArqSpringContext.getPropiedad("MENSAJE.EXCLUIDO");
LOG.warn("ERROR: Servicio: " + mensajeExcluido + ":" + someDTO.getProperty() +
",\tsomeValue:" + someDTO.getValue() + "'.");
throw new Exception(mensajeExcluido);
this code
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);
an this code
LOG.warn("No se pudo validar Client Service. Code: " +
someDTO.getStatusCode() + ".");
return "No se pudo validar Client Service. Code: " +
someDTO.getStatusCode() + ".";
In order to follow best practices...
What recommendations are applicable?
What changes would they make to the code?
How should texts be handled?
答案1
得分: 1
First, try to avoid message creation processing before checking if the log statement should be printed (I.e.: don't concatenate the messages strings before checking the log level.
// 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);
Most Java logging frameworks allow a check to know in advance if a log statement is going to be printed based on the given settings.
If you want to save you the burden of writting those checks for each log statement, you can take advantage of Java 8 lambdas and code an utility like this:
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"));
}
And finally, you can take advantage of Java string formatting to format log messages using String.format
. I.e.:
final String message = String.format("Print %s string and %d digit", "str", 42);
Those good practices applied to the examples you provided would be:
/*
* 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;
}
英文:
First, try to avoid message creation processing before checking if the log statement should be printed (I.e.: don't concatenate the messages strings before checking the log level.
// 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);
Most Java logging frameworks allow a check to know in advance if a log statement is going to be printed based on the given settings.
If you want to save you the burden of writting those checks for each log statement, you can take advantage of Java 8 lambdas and code an utility like this:
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"));
}
And finally, you can take advantage of Java string formatting to format log messages using String.format
. I.e.:
final String message = String.format("Print %s string and %d digit", "str", 42);
Those good practices applied to the examples you provided would be:
/*
* 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;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论