0Pricing
Java Academy · Lección

Logging parametrizado

Formateo eficiente de mensajes

Logging parametrizado es una lección gratuita de Java Academy en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Java Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Java Academy incluye 4 lecciones en total.

El problema de concatenar cadenas

Concatenar un mensaje de log construye la cadena completa antes de la llamada, incluso si el nivel está desactivado.

log.debug("id=" + id + " name=" + name) desperdicia CPU cuando DEBUG está desactivado, porque la cadena se construye de todos modos.

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 posición con {}

SLF4J utiliza {} como marcador de posición. Pase los valores como argumentos adicionales.

El mensaje solo se ensambla si el nivel está habilitado, por lo que los logs desactivados apenas tienen coste.

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);
    }
}

Varios marcadores de posición

Los marcadores de posición se rellenan en orden. El primer {} toma el primer argumento, el segundo toma el segundo, y así sucesivamente.

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 qué es eficiente

El framework comprueba primero el nivel. Si está desactivado, retorna inmediatamente sin llamar a toString() en ningún argumento.

La parte costosa, el formateo, se realiza de forma diferida solo cuando el mensaje realmente se va a emitir.

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});
    }
}

Pase objetos sin procesar, no cadenas con formato previo

Para aprovechar la evaluación diferida, pase el objeto sin procesar, no una llamada a un método que lo formatee.

Si escribe log.debug("{}", buildReport()), buildReport() aún se ejecuta de forma inmediata. Pase argumentos que el logger pueda formatear por sí mismo.

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);
    }
}

Suppliers diferidos para trabajo costoso

Cuando el formateo es realmente costoso, utilice la fluent API de SLF4J 2.x con un Supplier para diferir el trabajo.

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();
    }
}

Escapar una llave literal

Si necesita incluir un {} literal en el mensaje, escápelo con una barra inversa: \\{}.

Es poco frecuente, pero resulta útil al registrar texto similar 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);
    }
}

Excepción y marcadores de posición

Puede combinar marcadores de posición con una excepción al final. SLF4J detecta que el último argumento es un Throwable e imprime su stack trace.

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);
        }
    }
}

Evitar demasiados argumentos

Si el número de marcadores de posición y el número de argumentos no coinciden, SLF4J hace lo posible, pero la salida puede verse incorrecta.

Manténgalos sincronizados. Para más de un par de valores, considere utilizar contexto estructurado (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");
    }
}

Añadir contexto con MDC

Para los valores compartidos entre muchas líneas, como un identificador de solicitud, colóquelos en el MDC en lugar de repetirlos en cada mensaje.

De este modo, el patrón de salida puede imprimir automáticamente el valor del MDC en cada línea.

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();
        }
    }
}

Resumen de buenas prácticas

Reglas para un registro eficiente:

  • Utilice siempre marcadores de posición {}, nunca concatenación con +.
  • Pase objetos sin procesar, no cadenas creadas previamente.
  • Utilice suppliers o isXEnabled() para trabajos realmente costosos.
  • Utilice MDC para el 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);
    }
}

Comprobación rápida

Compruebe sus conocimientos sobre el registro parametrizado.

Repaso

Ha aprendido a utilizar el registro parametrizado:

  • Utilice marcadores de posición {} con argumentos adicionales.
  • Los mensajes se construyen de forma diferida, solo cuando el nivel está activado.
  • Pase objetos sin procesar; utilice suppliers para trabajos costosos.
  • Utilice MDC para valores contextuales compartidos.

A continuación, la configuración del backend 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");
    }
}

Preguntas frecuentes

¿La lección «Logging parametrizado» es gratis?

Sí — el texto completo de «Logging parametrizado» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Java Academy, actualiza a CoddyKit PRO. El curso de Java Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Logging parametrizado»?

Formateo eficiente de mensajes Practicas Java Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Java Academy?

No se requiere experiencia previa. Java Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.

¿Cuánto tiempo toma la lección «Logging parametrizado»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Java Academy?

Sí. Cada lección de Java Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Por qué usar logging estructurado
  2. Fachada y loggers de SLF4J
  3. Logging parametrizado
  4. Configuración de Logback
← Volver a Java Academy