Logging parametrizado
Formatação eficiente de mensagens.
Logging parametrizado é uma aula grátis de Java Academy no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Java Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Java Academy inclui 4 aulas no total.
O problema da concatenação de strings
Concatenar uma mensagem de registro constrói a string completa antes da chamada, mesmo que o nível esteja desativado.
log.debug("id=" + id + " name=" + name) desperdiça CPU quando DEBUG está desativado, porque a string é construída de qualquer maneira.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
String name = "Ada"; int id = 7;
// Bad: string is built even if DEBUG is disabled
log.debug("id=" + id + " name=" + name);
}
}Marcadores de posição com {}
O SLF4J usa {} como marcador de posição. Passe os valores como argumentos adicionais.
A mensagem só é montada se o nível estiver ativado, portanto os registros desativados praticamente não têm custo.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
String name = "Ada"; int id = 7;
// Good: no string built unless DEBUG is on
log.debug("id={} name={}", id, name);
}
}Vários marcadores de posição
Os marcadores de posição são preenchidos na ordem. O primeiro {} recebe o primeiro argumento, o segundo recebe o segundo, e assim por diante.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
log.info("order {} for user {} totaling {} cents", "A-1", 42, 1599);
}
}Por que isso é eficiente
A estrutura verifica primeiro o nível. Se ele estiver desativado, retorna imediatamente sem chamar toString() em nenhum argumento.
A parte dispendiosa, a formatação, acontece de forma tardia, somente quando a mensagem realmente será emitida.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
static String describe(Object o) { System.out.println("toString called"); return o.toString(); }
public static void main(String[] args) {
// Note: passing describe(...) still evaluates eagerly; pass the raw object instead
log.trace("value={}", new int[]{1, 2, 3});
}
}Passe objetos brutos, não strings pré-formatadas
Para obter o benefício da execução tardia, passe o objeto bruto, não uma chamada de método que o formate.
Se você escrever log.debug("{}", buildReport()), buildReport() ainda será executado imediatamente. Passe argumentos que o registrador possa formatar por conta própria.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
Object user = new Object();
// Logger calls user.toString() only if DEBUG is enabled
log.debug("current user: {}", user);
}
}Fornecedores tardios para trabalho pesado
Quando a formatação for realmente dispendiosa, use a API fluente do SLF4J 2.x com um Supplier, para que o trabalho seja adiado.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
static String heavyReport() { return "...expensive..."; }
public static void main(String[] args) {
log.atDebug()
.setMessage("report: {}")
.addArgument(() -> heavyReport())
.log();
}
}Escapando uma chave literal
Se precisar de um {} literal na mensagem, escape-o com uma barra invertida: \\{}.
Isso é raro, mas útil ao registrar texto semelhante a JSON.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
// Logs a literal {} then the value
log.info("empty object is \\{} and id is {}", 7);
}
}Exceção com marcadores de posição
Você pode combinar marcadores de posição com uma exceção ao final. O SLF4J detecta que o último argumento é um Throwable e imprime o rastreamento da pilha.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
int id = 99;
try {
throw new RuntimeException("db down");
} catch (Exception e) {
log.error("failed processing record {}", id, e);
}
}
}Evite argumentos demais
Se a quantidade de marcadores de posição não corresponder à quantidade de argumentos, o SLF4J fará o possível, mas a saída poderá parecer incorreta.
Mantenha as quantidades correspondentes. Para mais de alguns valores, considere usar contexto estruturado (MDC).
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
// Two placeholders, two arguments: correct
log.info("user {} did {}", "ada", "login");
}
}Adicionando contexto com MDC
Para valores compartilhados por muitas linhas, como um identificador de solicitação, coloque-os no MDC em vez de repeti-los em cada mensagem.
Assim, o formato do padrão poderá imprimir automaticamente o valor do MDC em todas as linhas.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
MDC.put("requestId", "req-1234");
try {
log.info("handling request");
log.info("request done");
} finally {
MDC.clear();
}
}
}Resumo das práticas recomendadas
Regras para um registro eficiente:
- Use sempre marcadores de posição
{}, nunca concatenação com+. - Passe objetos brutos, não strings pré-construídas.
- Use fornecedores ou
isXEnabled()para trabalhos realmente pesados. - Use o MDC para contexto transversal.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
log.info("processed {} items in {} ms", 1000, 42);
}
}Verificação rápida
Verifique seus conhecimentos sobre registro parametrizado.
Recapitulação
Você aprendeu sobre o registro parametrizado:
- Use marcadores de posição
{}com argumentos adicionais. - As mensagens são construídas de forma tardia, somente quando o nível está ativado.
- Passe objetos brutos; use fornecedores para trabalhos pesados.
- Use o MDC para valores de contexto compartilhados.
A seguir, a configuração da implementação de suporte Logback.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
log.info("Parameterized logging recap: {}", "done");
}
}Perguntas Frequentes
A aula “Logging parametrizado” é grátis?
Sim — o texto completo de “Logging parametrizado” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Java Academy, atualize para CoddyKit PRO. O curso de Java Academy inclui 4 aulas no total.
O que vou aprender em “Logging parametrizado”?
Formatação eficiente de mensagens. Você pratica Java Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Java Academy?
Nenhuma experiência prévia é necessária. Java Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.
Quanto tempo leva a aula “Logging parametrizado”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Java Academy?
Sim. Cada aula de Java Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Por que usar logging estruturado
- Fachada SLF4J e loggers
- Logging parametrizado
- Configurando o Logback