Apache Log4j es una utilidad de registro basada en Java escrita originalmente por Ceki Gülcü. Forma parte de Apache Logging Services, un proyecto de la Apache Software Foundation . Log4j es uno de los diversos marcos de registro de Java .
Desde entonces, Gülcü ha creado SLF4J , Reload4j, [4] y Logback [5] [ se necesita una mejor fuente ], que son alternativas a Log4j. [6]
El equipo Apache Log4j desarrolló Log4j 2 [7] en respuesta a los problemas de Log4j 1.2, 1.3 java.util.logging
y Logback, solucionando problemas que aparecieron en esos marcos. [8] Además, Log4j 2 ofrecía una arquitectura de complementos que lo hacía más extensible que su predecesor. Log4j 2 no es compatible con versiones anteriores 1.x, [9] aunque hay un "adaptador" disponible. El 5 de agosto de 2015, el Comité de Gestión de Proyectos de Apache Logging Services anunció que Log4j 1 había llegado al final de su vida útil y que se recomendaba a los usuarios de Log4j 1 que actualizaran a Apache Log4j 2. [10] El 12 de enero de 2022, Ceki Gülcü lanzó una versión bifurcada y renombrada de log4j 1.2 como Reload4j versión 1.2.18.0 con el objetivo de solucionar los problemas más urgentes en log4j 1.2.17 que se habían acumulado desde su lanzamiento en 2013. [11]
El 9 de diciembre de 2021, el equipo de seguridad de Alibaba Cloud publicó una vulnerabilidad de día cero que implicaba la ejecución de código arbitrario en Log4j 2 y la describió como " Log4Shell ". [12] Tenable la ha caracterizado como "la vulnerabilidad más grande y crítica de la última década". [13]
Apache Log4j 2 es el sucesor de Log4j 1, que se lanzó como versión GA en julio de 2015. El marco se reescribió desde cero y se inspiró en soluciones de registro existentes, incluidas Log4j 1 y java.util.logging. Las principales diferencias [14] [15] con respecto a Log4j 1 son:
Una de las características más reconocidas de Log4j 2 es el rendimiento de los "Registradores asíncronos". [16] Log4j 2 hace uso del disruptor LMAX . [17] La biblioteca reduce la necesidad de bloqueo del núcleo y aumenta el rendimiento del registro en un factor de 12. Por ejemplo, en el mismo entorno Log4j 2 puede escribir más de 18.000.000 de mensajes por segundo, mientras que otros marcos como Logback y Log4j 1 solo escriben < 2.000.000 de mensajes por segundo.
La siguiente tabla define los niveles de registro y los mensajes integrados en Log4j, en orden decreciente de gravedad. La columna de la izquierda enumera la designación del nivel de registro en Log4j y la columna de la derecha proporciona una breve descripción de cada nivel de registro.
Log4j 2 permite a los usuarios definir sus propios niveles de registro. [19] Se proporciona una herramienta generadora de código fuente para crear registradores que admitan niveles de registro personalizados de manera idéntica a los niveles de registro integrados. Los niveles de registro personalizados pueden complementar o reemplazar los niveles de registro integrados.
Log4j se puede configurar [20] a través de un archivo de configuración o mediante código Java. Los archivos de configuración se pueden escribir en formato XML , JSON , YAML o de archivo de propiedades . Se pueden definir tres componentes principales: registradores, anexos y diseños. La configuración del registro a través de un archivo tiene la ventaja de que se puede activar o desactivar sin modificar la aplicación que utiliza Log4j. Se puede permitir que la aplicación se ejecute con el cierre de sesión hasta que haya un problema, por ejemplo, y luego se puede volver a activar el registro simplemente modificando el archivo de configuración.
Los registradores [21] son destinos de mensajes de registro con nombre. Son los nombres que conoce la aplicación Java. Cada registrador se puede configurar de forma independiente en cuanto al nivel de registro (FATAL, ERROR, etc.) que registra actualmente. En las primeras versiones de Log4j, se denominaban categoría y prioridad, pero ahora se denominan registrador y nivel, respectivamente. Un registrador puede enviar mensajes de registro a varios Appenders.
Las salidas reales las realizan los Appenders . [22] Hay numerosos Appenders disponibles, con nombres descriptivos, como FileAppender, RollingFileAppender, ConsoleAppender, SocketAppender, SyslogAppender y SMTPAppender. Log4j 2 agregó Appenders que escriben en Apache Flume , Java Persistence API , Apache Kafka , bases de datos NoSQL , archivos mapeados en memoria , archivos de acceso aleatorio [23] y puntos finales ZeroMQ . Se pueden adjuntar múltiples Appenders a cualquier Logger, por lo que es posible registrar la misma información en múltiples salidas; por ejemplo, en un archivo localmente y en un oyente de socket en otra computadora.
Los anexos utilizan diseños [24] para dar formato a las entradas del registro. Una forma popular de dar formato a los archivos de registro de una línea a la vez es PatternLayout, que utiliza una cadena de patrones, de forma muy similar a la función printf de C / C++ . También existen los formateadores HTMLLayout y XMLLayout para usar cuando los formatos HTML o XML son más convenientes, respectivamente. Log4j 2 agregó diseños para CSV , Graylog Extended Log Format (GELF), [25] JSON , YAML y RFC-5424. [26]
En Log4j 2, se pueden definir filtros [27] en elementos de configuración para brindar un control más preciso sobre qué entradas de registro deben procesar los registradores y los anexos. Además de filtrar por nivel de registro y coincidencia de expresiones regulares en la cadena de mensajes, Log4j 2 agregó filtros de ráfaga, filtros de tiempo, filtrado por otros atributos de eventos de registro como marcadores o mapas de contexto de subprocesos y filtros de script JSR 223 .
Para depurar una configuración que funciona mal:
status
atributo en TRACE para enviar la salida de registro de estado interno a la salida estándar . Para habilitar el registro de estado antes de que se encuentre la configuración, utilice la propiedad Java VM -Dorg.apache.logging.log4j.simplelog.StatusLogger.level=trace
.-Dlog4j.debug
.Para saber dónde se cargó un archivo de configuración log4j2.xml, inspeccione getClass().getResource("/log4j2.xml")
.
También existe una configuración implícita "no configurada" o "predeterminada" de Log4j, la de una aplicación Java instrumentada con Log4j que carece de cualquier configuración de Log4j. Esto imprime en la salida estándar una advertencia de que el programa no está configurado y la URL del sitio web de Log4j donde se pueden encontrar detalles sobre la advertencia y la configuración. Además de imprimir esta advertencia, una aplicación Log4j no configurada solo imprimirá entradas de registro de ERROR o FATAL en la salida estándar.
<?xml version="1.0" encoding="UTF-8"?> < Estado de configuración= "trace" monitorInterval= "60" > <Propiedades> < Nombre de propiedad = "filename" > target/test.log </Propiedad> </Propiedades> <Anexos> < Nombre de consola = "STDOUT" > <PatternLayout patrón= "%d %p %c{1.} [%t] %m%n" /> </Consola> <File name= "file" fileName= "${filename}" > <PatternLayout> <pattern> %d %p %c{1.} [%t] %m%n </pattern> </PatternLayout> </File> </Appenders> <Loggers> <!-- los registradores cuyo nombre comience con 'org.springframework' solo registrarán mensajes de nivel "info" o superior; si recupera los registradores utilizando el nombre de la clase (por ejemplo, Logger.getLogger(AClass.class)) y si AClass es parte del paquete org.springframework, pertenecerá a esta categoría --> <Logger name= "org.springframework" level= "info" additivity= "false" /> <!-- Ejemplo de filtro: para los registradores cuyo nombre comienza con 'com.mycompany.myproduct', las entradas de registro de nivel "debug" o superior cuyos datos ThreadContextMap contienen el par clave-valor "test=123", también envían estas entradas de registro al appender "STDOUT". --> <Logger name= "com.mycompany.myproduct" level= "debug" additivity= "true" > <ThreadContextMapFilter> <KeyValuePair key= "test" value= "123" /> </ThreadContextMapFilter> <AppenderRef ref= "STDOUT" /> </Logger> <!-- De forma predeterminada, se registrarán todos los mensajes de registro de nivel "trace" o superior. Los mensajes de registro se envían al appender "file" y los mensajes de registro de nivel "error" y superior se enviarán al appender "STDOUT". --> < Nivel raíz = "seguimiento" > <AppenderRef ref= "archivo" /> <AppenderRef ref= "STDOUT" nivel= "error" /> < / Raíz> </Registradores> < /Configuración>
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE log4j:configuration PUBLIC "-//LOGGER" "http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd"> <log4j:configuration> <!-- un appender es un destino de salida, como la consola o un archivo; los nombres de los appender se eligen arbitrariamente. --> <appender name= "stdout" class= "org.apache.log4j.ConsoleAppender" > <layout class= "org.apache.log4j.PatternLayout" > <param name= "ConversionPattern" value= "%d{ABSOLUTE} %5p %c{1}:%L - %m%n" /> </layout> </appender> <!-- los registradores de la categoría 'org.springframework' solo registrarán mensajes de nivel "info" o superior; si recupera registradores utilizando el nombre de la clase (por ejemplo, Logger.getLogger(AClass.class)) y si AClass es parte del paquete org.springframework, pertenecerá a esta categoría --> <logger name= "org.springframework" > <level value= "info" /> </logger> <!-- todo en Spring se configuró como "info", pero para la clase PropertyEditorRegistrySupport queremos el registro "debug" --> <logger name= "org.springframework.beans.PropertyEditorRegistrySupport" > <level value= "debug" /> </logger> <logger name= "org.acegisecurity" > <level value= "info" /> </logger> <root> <!-- todos los mensajes de registro de nivel "debug" o superior se registrarán, a menos que se defina lo contrario. Todos los mensajes de registro se registrarán en el appender "stdout", a menos que se defina lo contrario. --> <level value= "debug" /> <appender-ref ref= "stdout" /> </root> </log4j:configuration>
TTCC es un formato de mensaje utilizado por log4j. [28] TTCC es un acrónimo de Time Thread Category Component . Utiliza el siguiente patrón:
%r [%t] %-5p %c %x - %m%n
Dónde
Ejemplo de salida
467 [main] INFO org.apache.log4j.examples.Sort – Saliendo del método principal.
El 24 de noviembre de 2021, Alibaba encontró y notificó a Apache una vulnerabilidad de día cero que implicaba la ejecución remota de código en Log4j 2, denominada "Log4Shell" ( CVE -2021-44228), y la publicó en un tuit el 9 de diciembre de 2021. [12] Los servicios afectados incluyen Cloudflare , iCloud , Minecraft: Java Edition , [42] Steam , Tencent QQ y Twitter . [43] [44] [45] La Apache Software Foundation asignó la máxima calificación de gravedad CVSS de 10 a Log4Shell, ya que millones de servidores podrían ser potencialmente vulnerables al exploit. [45] La empresa de ciberseguridad Tenable caracterizó la vulnerabilidad como "la vulnerabilidad más grande y crítica de la última década" [13] y Free Wortley de Lunasec la caracterizó como "un fallo de diseño de proporciones catastróficas". [46]
En Estados Unidos, la directora de la Agencia de Seguridad de Infraestructura y Ciberseguridad (CISA), Jen Easterly , calificó el exploit de "crítico" y aconsejó a los proveedores que priorizaran las actualizaciones de software, [47] y la agencia alemana Oficina Federal de Seguridad de la Información (BSI) designó el exploit como en su nivel de amenaza más alto, llamándolo una "situación de amenaza extremadamente crítica" (traducido). [48] [49] El Centro Canadiense de Seguridad Cibernética (CCCS) pidió a las organizaciones que tomaran medidas inmediatas. [50]
La característica que causa la vulnerabilidad se puede desactivar con una opción de configuración, que se eliminó [51] en la versión 2.15.0-rc1 de Log4j (publicada oficialmente el 6 de diciembre de 2021, tres días antes de que se publicara la vulnerabilidad), y se reemplazó por varias configuraciones que restringen las búsquedas remotas, mitigando así la vulnerabilidad. [52] [53] Para mayor seguridad, todas las funciones que usan JNDI , en las que se basó esta vulnerabilidad, se desactivarán de forma predeterminada y se eliminará la compatibilidad con las búsquedas de mensajes a partir de la versión 2.16.0. [54] [55]
{{cite journal}}
: Requiere citar revista |journal=
( ayuda )