Using JsonLayout with SOLR logs - json

I'm trying to log all events from SOLR in JSON format by using JSONLayout. I'm using the official docker image from SOLR but I can't get it to work. Here's my setup:
Dockerfile
FROM solr:7
COPY log4j2-json.xml /opt/solr/server/resources/log4j2.xml
USER root
RUN chmod 644 /opt/solr/server/resources/log4j2.xml
RUN chown solr:solr /opt/solr/server/resources/log4j2.xml
USER solr
EXPOSE 8983
CMD ["solr-precreate", "gettingstarted"]
log4j2.xml original file (without JsonLayout) which does create the solr.log file (using PatternLayout):
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<Configuration>
<Appenders>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout>
<Pattern>
%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p (%t) [%X{collection} %X{shard} %X{replica} %X{core}] %c{1.} %m%n
</Pattern>
</PatternLayout>
</Console>
<RollingFile
name="RollingFile"
fileName="${sys:solr.log.dir}/solr.log"
filePattern="${sys:solr.log.dir}/solr.log.%i" >
<PatternLayout>
<Pattern>
%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p (%t) [%X{collection} %X{shard} %X{replica} %X{core}] %c{1.} %m%n
</Pattern>
</PatternLayout>
<Policies>
<OnStartupTriggeringPolicy />
<SizeBasedTriggeringPolicy size="32 MB"/>
</Policies>
<DefaultRolloverStrategy max="10"/>
</RollingFile>
<RollingFile
name="SlowFile"
fileName="${sys:solr.log.dir}/solr_slow_requests.log"
filePattern="${sys:solr.log.dir}/solr_slow_requests.log.%i" >
<PatternLayout>
<Pattern>
%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p (%t) [%X{collection} %X{shard} %X{replica} %X{core}] %c{1.} %m%n
</Pattern>
</PatternLayout>
<Policies>
<OnStartupTriggeringPolicy />
<SizeBasedTriggeringPolicy size="32 MB"/>
</Policies>
<DefaultRolloverStrategy max="10"/>
</RollingFile>
</Appenders>
<Loggers>
<Logger name="org.apache.hadoop" level="warn"/>
<Logger name="org.apache.solr.update.LoggingInfoStream" level="off"/>
<Logger name="org.apache.zookeeper" level="warn"/>
<Logger name="org.apache.solr.core.SolrCore.SlowRequest" level="info" additivity="false">
<AppenderRef ref="SlowFile"/>
</Logger>
<Root level="info">
<AppenderRef ref="RollingFile"/>
<AppenderRef ref="STDOUT"/>
</Root>
</Loggers>
</Configuration>
log4j2.xml with JsonLayout in RollingFile appender which breaks it. No solr.log file is created:
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<Configuration>
<Appenders>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout>
<Pattern>
%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p (%t) [%X{collection} %X{shard} %X{replica} %X{core}] %c{1.} %m%n
</Pattern>
</PatternLayout>
</Console>
<RollingFile
name="RollingFile"
fileName="${sys:solr.log.dir}/solr.log"
filePattern="${sys:solr.log.dir}/solr.log.%i" >
<JsonLayout complete="false" compact="true" eventEol="true" />
<Policies>
<OnStartupTriggeringPolicy />
<SizeBasedTriggeringPolicy size="32 MB"/>
</Policies>
<DefaultRolloverStrategy max="10"/>
</RollingFile>
<RollingFile
name="SlowFile"
fileName="${sys:solr.log.dir}/solr_slow_requests.log"
filePattern="${sys:solr.log.dir}/solr_slow_requests.log.%i" >
<PatternLayout>
<Pattern>
%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p (%t) [%X{collection} %X{shard} %X{replica} %X{core}] %c{1.} %m%n
</Pattern>
</PatternLayout>
<Policies>
<OnStartupTriggeringPolicy />
<SizeBasedTriggeringPolicy size="32 MB"/>
</Policies>
<DefaultRolloverStrategy max="10"/>
</RollingFile>
</Appenders>
<Loggers>
<Logger name="org.apache.hadoop" level="warn"/>
<Logger name="org.apache.solr.update.LoggingInfoStream" level="off"/>
<Logger name="org.apache.zookeeper" level="warn"/>
<Logger name="org.apache.solr.core.SolrCore.SlowRequest" level="info" additivity="false">
<AppenderRef ref="SlowFile"/>
</Logger>
<Root level="debug">
<AppenderRef ref="RollingFile"/>
<AppenderRef ref="STDOUT"/>
</Root>
</Loggers>
</Configuration>
I would expect to see the solr.log file to be created in the logdir and see the events in json format. But the solr.log file isn't even created. SOLR does however start.
What am I missing?
Thanks for your help.
PS. I found this thread which describes the same problem but no solution: see here

On solr official docker image 8.11.2 the same problem is caused by a missing jackson library in the classpath:
ERROR Could not create plugin of type class org.apache.logging.log4j.core.layout.JsonLayout for element JsonLayout: java.lang.NoClassDefFoundError: com/fasterxml/jackson/databind/ser/FilterProvider java.lang.NoClassDefFoundError: com/fasterxml/jackson/databind/ser/FilterProvider
at org.apache.logging.log4j.core.layout.JsonLayout.<init>(JsonLayout.java:159)
This is definitely a bug (https://issues.apache.org/jira/browse/SOLR-16342), but since the jackson library exists elsewhere in the original image, there is a possible workaround to apply while building the docker. Basically you can link the needed jackson jars that exists in /opt/solr/server/solr-webapp/webapp/WEB-INF/lib/ to /opt/solr/server/lib/ext/:
RUN ln -s /opt/solr/server/solr-webapp/webapp/WEB-INF/lib/jackson-core-2.13.3.jar /opt/solr/server/lib/ext/jackson-core-2.13.3.jar && \
ln -s /opt/solr/server/solr-webapp/webapp/WEB-INF/lib/jackson-databind-2.13.3.jar /opt/solr/server/lib/ext/jackson-databind-2.13.3.jar && \
ln -s /opt/solr/server/solr-webapp/webapp/WEB-INF/lib/jackson-annotations-2.13.3.jar /opt/solr/server/lib/ext/jackson-annotations-2.13.3.jar
Moreover:
JsonTemplate is considered deprecated. JsonTemplateLayout provides
more capabilitites and should be used instead.
(see https://logging.apache.org/log4j/2.x/manual/layouts.html#JSONLayout)
If you move to <JsonTemplateLayout /> it works out of the box in solr.

Related

logs disappear in cloud run once I start using google's LoggingAppender in logback?

I have no idea how to debug since there is no errors. I have this logback file but this made all the logs disappear for my cloudrun instance EXCEPT the system.out stuff that logback logs on startup..
<?xml version="1.0" encoding="UTF-8" ?>
<configuration scan="true" scanPeriod="30 seconds" debug="true">
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
<resetJUL>true</resetJUL>
</contextListener>
<appender name="CLOUD" class="com.google.cloud.logging.logback.LoggingAppender">
<!-- Optional : filter logs at or above a level -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<flushLevel>WARN</flushLevel> <!-- Optional : default ERROR -->
</appender>
<appender name="ASYNC-SERVERLOG" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="CLOUD" />
</appender>
<!-- TBD for later use for apps that use log4jdbc it doesn't hurt apps that
don't use it -->
<logger name="jdbc.sqlonly" level="INFO" />
<logger name="jdbc.sqltiming" level="WARN" />
<logger name="jdbc.audit" level="WARN" />
<logger name="jdbc.resultset" level="WARN" />
<logger name="jdbc.connection" level="WARN" />
<root>
<level value="INFO" />
<appender-ref ref="ASYNC-SERVERLOG" />
</root>
</configuration>
Any ideas why logging stops working or where the logging is going to? Now that I changed logging to this, logging seems to go to the void :(.
I also tried out this post which logs to ConsoleAppender but NOTHING shows up in the json format although it is doing a line for EACH log statement I do which is really nice
GKE & Stackdriver: Java logback logging format?
I then tried this approach which is using FileAppender
How do I map my java app logging events to corresponding cloud logging event levels in GCP Felexible non-compat App Engine?
My logback for this one was
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>/var/log/app.log</file>
<append>true</append>
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="com.orderlyhealth.GCPCloudLoggingJSONLayout">
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg</pattern>
</layout>
</encoder>
</appender>
<appender name="ASYNC-SERVERLOG" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="FILE" />
</appender>
Any ideas?
The Java logging instructions in the documentation should help: https://cloud.google.com/run/docs/logging#run_manual_logging-java
In Cloud Run, output to Stdout and Stderr are forwarded on to Stackdriver. Logs which are recorded in files are lost.
I'm not sure the implications of the ASYNC-SERVERLOG appender, but on Cloud Run there is only CPU available to process and send logs while a request is being processed, so if something is asynchronously sending logs it will only work during that request or a future request that reaches the same container instance.

Logback log level change not working

I'm using an application called Apache Drill that uses logback for logging. I'm trying to edit it's shipped logback.xml configuration file to output debugging messages.
Here is the file, untouched
<?xml version="1.0" encoding="UTF-8" ?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<configuration>
<!-- <appender name="SOCKET"
class="de.huxhorn.lilith.logback.appender.ClassicMultiplexSocketAppender">
<Compressing>true</Compressing>
<ReconnectionDelay>10000</ReconnectionDelay>
<IncludeCallerData>true</IncludeCallerData>
<RemoteHosts>${LILITH_HOSTNAME:-localhost}</RemoteHosts>
</appender>
-->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<appender name="QUERY" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.query.path}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>${log.query.path}.%i</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>10</maxIndex>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>100MB</maxFileSize>
</triggeringPolicy>
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>${log.path}.%i</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>10</maxIndex>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>100MB</maxFileSize>
</triggeringPolicy>
<encoder>
<pattern>%date{ISO8601} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<logger name="org.apache.drill" additivity="false">
<level value="info" />
<appender-ref ref="FILE" />
</logger>
<logger name="query.logger" additivity="false">
<level value="info" />
<appender-ref ref="QUERY" />
<!-- <appender-ref ref="SOCKET" /> -->
</logger>
<!--
<logger name="org.apache.drill" additivity="false">
<level value="debug" />
<appender-ref ref="SOCKET" />
</logger>
-->
<root>
<level value="error" />
<appender-ref ref="STDOUT" />
</root>
</configuration>
All I did afterwards was editing
<logger name="org.apache.drill" additivity="false">
<level value="info" />
<appender-ref ref="FILE" />
</logger>
to be
<logger name="org.apache.drill" additivity="false">
<level value="debug" />
<appender-ref ref="FILE" />
</logger>
And absolutely nothing changed !
This is the java command used to start the application (Search for -cp /home/gelbana/drillv11/conf, the logback.xml file is located in the conf directory)
/usr/java/jdk1.8.0_112/bin/java -Xms10G -Xmx10G -XX:MaxDirectMemorySize=230G -XX:ReservedCodeCacheSize=1G -Ddrill.exec.enable-epoll=false -XX:MaxPermSize=512M -Djava.io.tmpdir=/home/gelbana/drillv11/tmp -Ddrill.memory.debug.allocator=true -XX:+CMSClassUnloadingEnabled -XX:+UseG1GC -Dlog.path=/home/gelbana/drillv11/log/drillbit.log -Dlog.query.path=/home/gelbana/drillv11/log/drillbit_queries.json -cp /home/gelbana/drillv11/conf:/home/gelbana/drillv11/jars/*:/home/gelbana/drillv11/jars/ext/*:/home/gelbana/drillv11/jars/3rdparty/*:/home/gelbana/drillv11/jars/classb/* org.apache.drill.exec.server.Drillbit
The drillbit.out file has the following lines at the beginning
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/home/gelbana/drillv11/jars/3rdparty/slf4j-simple-1.7.25.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/gelbana/drillv11/jars/classb/logback-classic-1.0.13.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.SimpleLoggerFactory]
I tried changing all levels to DEBUG, ALL but still, nothing changed. I can't find a single DBEUG in the logs.
The changes you made should work. I made the same change and ran a drillbit and I can see debug logs in drillbit.log. For example:
DEBUG o.a.drill.exec.server.StartupOptions - Parsing arguments.
The drillbit.out file should tell you something about how Logback configured itself. Have a look at that file, specifically the entries which relate to LoggerContext for example:
Found resource [logback.xml] at ...
Resource [logback.xml] occurs multiple times on the classpath
And you'll likely find that Logback relveals the answer via it's own logging.

Root Level Logging is effective in service mix

I am using slf4j & logback for logging and my application is deployed in Apache Service Mix where other modules are using my logging service. Everything works fine when i test it in a standalone environment but i face problem when i deploy it in a service mix container. At that time, only root level logging is effective and other logging levels are ignored.
Below is my logback-test.xml configuration, Kindly help i am stuck in this issue for the last 4 days.
<!-- This property describes the location of the property file. -->
<property
file="C:/Users/evikdew/ccl_code/log.properties" />
<!-- This appender prints on the console. -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<!-- This appender contains the properties for the logs that would be written
to a file. -->
<appender name="FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_DIRECTORY}\${LOG_FILE_NAME}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_FILE_PATTERN}</fileNamePattern>
<maxHistory>${MAX_LOG_HISTORY}</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${LOGGING_PATTERN}
</pattern>
</encoder>
</appender>
<logger name="com.ericsson" level="Error" additivity="false">
<appender-ref ref="FILE" />
</logger>
<logger name="com.ericsson" level="INFO" additivity="false">
<appender-ref ref="FILE" />
</logger>
<logger name="com.ericsson" level="DEBUG" additivity="false">
<appender-ref ref="FILE" />
</logger>
<root level="DEBUG">
<appender-ref ref="STDOUT" />
</root>
As Servicemix 4.x is based on top of Karaf, the standard logging mechanism is Pax Logging. Pax Logging is configured by the org.ops4j.pax.logging.cfg file, as Karaf uses Configuration Admin Service to configure OSGi services. That's why the config file still uses the log4j properties notation.
If you need special appenders, some are already included like a MDC appender for logging bundle wise, or a ZipRollingFileappender.
Support for the external logback configuration was introduced with Pax Loggin 1.7 I think, and I doubt it is already included in ServiceMix 4.5.x
So you have to stick to the log4j notation or exchange the Pax Logging versions yourself.

Excessive "-INFO...RenameUtil - Renaming file..." in Jetty8 stderrrout with Logback RequestLogImpl

My app runs in Jetty8 and is leveraging Logback's RequestLogImpl (which is just great, by the way). Recently we discovered that if logback has a problem rolling over files, the logging message that would have alerted us to that appears nowhere because we had not configured Jetty to redirect its stderrout to any log file. My current release corrected that problem, but now I notice an excessive volume of INFO messages from logback in the jetty stderrout file like
06:32:14,893 |-INFO in c.q.l.co.rolling.helper.RenameUtil - Renaming file [/data/logs/md-stage-app4.dev.mgg.request.3.log] to [/data/logs/md-stage-app4.dev.mgg.request.4.log]
I only really care about these messages if the rename failed or something, which these messages come out as WARN. How can I get the logback stuff to just log at WARN and above into the jetty stderrout logfile?
My app itself does, indeed, <root level="info"> the root logger.
etc/jetty.xml has the following excerpt:
<!-- Logback Access Log implementation -->
<Ref id="RequestLog">
<Set name="requestLog">
<New id="requestLogImpl" class="ch.qos.logback.access.jetty.RequestLogImpl">
<Set name="fileName">etc/logbackAccess.xml</Set>
</New>
</Set>
</Ref>
etc/logbackAccess.xml is:
<configuration>
<!-- always a good activate OnConsoleStatusListener -->
<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
<appender name="SIZE_ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>/data/logs/md-app3.request.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>/data/logs/md-app3.request.%i.log</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>5</maxIndex>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>1MB</maxFileSize>
</triggeringPolicy>
<encoder>
<pattern>%h %l %u [%t] "%r" %s %b%n%fullRequest%n</pattern>
</encoder>
</appender>
<appender-ref ref="SIZE_ROLLING" />
</configuration>
The status messages are printed because of the line
<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
in logback-access.xml (etc/logbackAccess.xml in your case). By adapting OnConsoleStatusListener and OnPrintStreamStatusListenerBase, you should be able able to create a custom StatusListener which prints status messages except INFO messages originating at RenameUtil.

Config SLF4J using library to use LOG4J configuration

I have a project using log4j. Now I have to introduce a library using slf4j. Can I ask slf4j to initialize itself based on log4j config? So I basicly want log4j as underlying library under slf4j.
UPDATE:
log4j config is like this:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration debug="true" xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="fileAppender" class="org.apache.log4j.rolling.RollingFileAppender">
<param name="file" value="${log.dir}/${log.file}.log" />
<param name="append" value="true" />
<rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
<param name="FileNamePattern" value="${archive.log.dir}/${log.file}.%d{yyyy-MM-dd}.gz" />
<param name="ActiveFileName" value="${log.dir}/${log.file}.log"/>
</rollingPolicy>
<layout class="org.apache.log4j.EnhancedPatternLayout">
<param name="ConversionPattern" value="%d{yyMMdd HH:mm:ss,SSS} [%t] %-5p %c %X %m%n" />
</layout>
</appender>
<logger name="org.hibernate">
<level value="ALL" />
<appender-ref ref="fileAppender"/>
</logger>
<root>
<priority value="info" />
<appender-ref ref="fileAppender" />
</root>
</log4j:configuration>
I also use apache-log4j-extras version 1.0.
log4j version is 1.2.16
Yes, you need three jar files in your project's classpath:
slf4j-api-1.6.1.jar // the slf4j API
slf4j-log4j12-1.6.1.jar // log4j bindings for slf4j
log4j-1.2.15.jar // log4j itself
Make sure you have the same version of slf4j-api and slf4j-log4j12, otherwise it won't work. You can also use the newest log4j version, 1.2.16 if I'm not mistaken.