Search code examples
ignite

Apache Ignite Structured Logging


I am looking to enable structured logging for Ignite. Ignite runs inside a docker container. I enabled the log4j2 module and added a log4j2 configuration file that tries to use <JsonTemplateLayout.../> as described here but in the logs i get the message:

Console contains an invalid element or attribute "JsonTemplateLayout"

Which is probably caused by not having the log4j-layout-template-json dependency available inside ignite. Is there a way how to add the dependency to Ignite or is there another option on how to get structured logging working?

Ignite configuration:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util.xsd">
  <bean class="org.apache.ignite.configuration.IgniteConfiguration">
    ...
    <property name="gridLogger">
      <bean class="org.apache.ignite.logger.log4j2.Log4J2Logger">
        <constructor-arg type="java.lang.String" value="config/ignite-log4j2-custom.xml"/>
      </bean>
    </property>
  </bean>
</beans>

log4j2 configuration:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration monitorInterval="60" status="debug">
    <Appenders>
        <Console name="CONSOLE" target="SYSTEM_OUT">
            <!-- <PatternLayout pattern="[%d{ISO8601}][%-5p][%t][%c{1}]%notEmpty{[%markerSimpleName]} %m%n"/> -->
            <ThresholdFilter level="ERROR" onMatch="DENY" onMismatch="ACCEPT"/>
            <JsonTemplateLayout eventTemplateUri="classpath:EcsLayout.json"/>
        </Console>
        <Console name="CONSOLE_ERR" target="SYSTEM_ERR">
            <!-- <PatternLayout pattern="[%d{ISO8601}][%-5p][%t][%c{1}]%notEmpty{[%markerSimpleName]} %m%n"/> -->
            <JsonTemplateLayout eventTemplateUri="classpath:EcsLayout.json"/>
        </Console>
        <File name="CONSISTENCY" fileName="${sys:IGNITE_HOME}/work/log/consistency.log">
            <PatternLayout>
                <Pattern>"[%d{ISO8601}][%-5p][%t][%c{1}] %m%n"</Pattern>
            </PatternLayout>
        </File>
        <Routing name="FILE">
            <Routes pattern="$${sys:nodeId}">
                <Route>
                    <RollingFile name="Rolling-${sys:nodeId}" fileName="${sys:IGNITE_HOME}/work/log/${sys:appId}-${sys:nodeId}.log"
                                 filePattern="${sys:IGNITE_HOME}/work/log/${sys:appId}-${sys:nodeId}-%i-%d{yyyy-MM-dd}.log.gz">
                        <PatternLayout pattern="[%d{ISO8601}][%-5p][%t][%c{1}]%notEmpty{[%markerSimpleName]} %m%n"/>
                        <Policies>
                            <TimeBasedTriggeringPolicy interval="6" modulate="true" />
                            <SizeBasedTriggeringPolicy size="10 MB" />
                        </Policies>
                    </RollingFile>
                </Route>
            </Routes>
        </Routing>
    </Appenders>
    <Loggers>
        <!-- <Logger name="org.apache.ignite" level="INFO"/> -->
        <!--
            Uncomment to disable courtesy notices, such as SPI configuration
            consistency warnings.
        -->
        <!--
        <Logger name="org.apache.ignite.CourtesyConfigNotice" level=OFF/>
        -->
        <Logger name="org.springframework" level="WARN"/>
        <Logger name="org.eclipse.jetty" level="WARN"/>
        <Logger name="org.apache.ignite.internal.visor.consistency" additivity="false" level="INFO">
            <AppenderRef ref="CONSISTENCY"/>
        </Logger>
        <!--
        Avoid warnings about failed bind attempt when multiple nodes running on the same host.
        -->
        <Logger name="org.eclipse.jetty.util.log" level="ERROR"/>
        <Logger name="org.eclipse.jetty.util.component" level="ERROR"/>
        <Logger name="com.amazonaws" level="WARN"/>
        <Root level="INFO">
            <!-- Uncomment to enable logging to console. -->
            <AppenderRef ref="CONSOLE" level="INFO"/>
            <AppenderRef ref="CONSOLE_ERR" level="ERROR"/>
            <AppenderRef ref="FILE" level="DEBUG"/>
        </Root>
    </Loggers>
</Configuration>

When adding the JAR to libs (as suggested by Stanislav below) i get a step further but also get an error (not a java person so any hint is highly appreciated):

main ERROR An exception occurred processing Appender CONSOLE org.apache.logging.log4j.core.appender.AppenderLoggingException: java.lang.IllegalAccessError: class org.apache.logging.log4j.layout.template.json.JsonTemplateLayout$StringBuilderEncoder tried to access method 'void org.apache.logging.log4j.core.layout.TextEncoderHelper.encodeText(java.nio.charset.CharsetEncoder, java.nio.CharBuffer, java.nio.ByteBuffer, java.lang.StringBuilder, org.apache.logging.log4j.core.layout.ByteBufferDestination)' (org.apache.logging.log4j.layout.template.json.JsonTemplateLayout$StringBuilderEncoder and org.apache.logging.log4j.core.layout.TextEncoderHelper are in unnamed module of loader 'app')
        at org.apache.logging.log4j.core.config.AppenderControl.tryCallAppender(AppenderControl.java:165)
        at org.apache.logging.log4j.core.config.AppenderControl.callAppender0(AppenderControl.java:134)
        at org.apache.logging.log4j.core.config.AppenderControl.callAppenderPreventRecursion(AppenderControl.java:125)
        at org.apache.logging.log4j.core.config.AppenderControl.callAppender(AppenderControl.java:89)
        at org.apache.logging.log4j.core.config.LoggerConfig.callAppenders(LoggerConfig.java:542)
        at org.apache.logging.log4j.core.config.LoggerConfig.processLogEvent(LoggerConfig.java:500)
        at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:483)
        at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:417)
        at org.apache.logging.log4j.core.config.AwaitCompletionReliabilityStrategy.log(AwaitCompletionReliabilityStrategy.java:82)
        at org.apache.logging.log4j.core.Logger.log(Logger.java:161)
        at org.apache.logging.log4j.spi.AbstractLogger.tryLogMessage(AbstractLogger.java:2205)
        at org.apache.logging.log4j.spi.AbstractLogger.logMessageTrackRecursion(AbstractLogger.java:2159)
        at org.apache.logging.log4j.spi.AbstractLogger.logMessageSafely(AbstractLogger.java:2142)
        at org.apache.logging.log4j.spi.AbstractLogger.logMessage(AbstractLogger.java:2017)
        at org.apache.logging.log4j.spi.AbstractLogger.logIfEnabled(AbstractLogger.java:1983)
        at org.apache.logging.log4j.spi.AbstractLogger.info(AbstractLogger.java:1275)
        at org.apache.ignite.logger.log4j2.Log4J2Logger.info(Log4J2Logger.java:472)
        at org.apache.ignite.logger.log4j2.Log4J2Logger.info(Log4J2Logger.java:464)
        at org.apache.ignite.internal.GridLoggerProxy.info(GridLoggerProxy.java:137)
        at org.apache.ignite.internal.plugin.IgniteLogInfoProviderImpl.ackConfiguration(IgniteLogInfoProviderImpl.java:222)
        at org.apache.ignite.internal.plugin.IgniteLogInfoProviderImpl.ackKernalInited(IgniteLogInfoProviderImpl.java:98)
        at org.apache.ignite.internal.IgniteKernal.start(IgniteKernal.java:902)
        at org.apache.ignite.internal.IgnitionEx$IgniteNamedInstance.start0(IgnitionEx.java:1799)
        at org.apache.ignite.internal.IgnitionEx$IgniteNamedInstance.start(IgnitionEx.java:1721)
        at org.apache.ignite.internal.IgnitionEx.start0(IgnitionEx.java:1160)
        at org.apache.ignite.internal.IgnitionEx.startConfigurations(IgnitionEx.java:1054)
        at org.apache.ignite.internal.IgnitionEx.start(IgnitionEx.java:940)
        at org.apache.ignite.internal.IgnitionEx.start(IgnitionEx.java:839)
        at org.apache.ignite.internal.IgnitionEx.start(IgnitionEx.java:709)
        at org.apache.ignite.internal.IgnitionEx.start(IgnitionEx.java:678)
        at org.apache.ignite.Ignition.start(Ignition.java:353)
        at org.apache.ignite.startup.cmdline.CommandLineStartup.main(CommandLineStartup.java:365)
Caused by: java.lang.IllegalAccessError: class org.apache.logging.log4j.layout.template.json.JsonTemplateLayout$StringBuilderEncoder tried to access method 'void org.apache.logging.log4j.core.layout.TextEncoderHelper.encodeText(java.nio.charset.CharsetEncoder, java.nio.CharBuffer, java.nio.ByteBuffer, java.lang.StringBuilder, org.apache.logging.log4j.core.layout.ByteBufferDestination)' (org.apache.logging.log4j.layout.template.json.JsonTemplateLayout$StringBuilderEncoder and org.apache.logging.log4j.core.layout.TextEncoderHelper are in unnamed module of loader 'app')
        at org.apache.logging.log4j.layout.template.json.JsonTemplateLayout$StringBuilderEncoder.encode(JsonTemplateLayout.java:241)
        at org.apache.logging.log4j.layout.template.json.JsonTemplateLayout$StringBuilderEncoder.encode(JsonTemplateLayout.java:216)
        at org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.encode(JsonTemplateLayout.java:304)
        at org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.encode(JsonTemplateLayout.java:58)
        at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.directEncodeEvent(AbstractOutputStreamAppender.java:197)
        at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.tryAppend(AbstractOutputStreamAppender.java:190)
        at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.append(AbstractOutputStreamAppender.java:181)
        at org.apache.logging.log4j.core.config.AppenderControl.tryCallAppender(AppenderControl.java:161)
        ... 31 more

Solution

As Stanislav Lukyanov (see accepted answer) suggested the solution was to just download the JAR and place it below $IGNITE_HOME/libs. The error mentioned above was caused by a version mismatch. Having the following JARs with correct version made it work:

  • log4j-api-2.17.1.jar (default provided by ignite distribution)
  • log4j-core-2.17.1.jar (default provided by ignite distribution)
  • ignite-log4j2-2.13.0.jar (default provided by ignite distribution)
  • log4j-layout-template-json-2.17.1.jar (added, did not work with version 2.18.x)

Solution

  • If you run Ignite using Maven, you'll need to add the required dependency to your application POM, as described in the documentation:

    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-layout-template-json</artifactId>
        <version>2.18.0</version>
    </dependency>
    

    If you run Ignite using a ZIP distribution, you'll need to download the dependency as a JAR, e.g. from here and add it to the $IGNITE_HOME/libs.