Change default logging implementation in Helidon - helidon

I would like to use log4j with Helidon. Is there any way to change default logging implementation?

In Helidon, we have decided to use to use Java Util Logging (JUL), to allow our users to choose any logging implementation.
There are bridges for most implementations for JUL. For log4j, you can have a look at this page:
http://people.apache.org/~psmith/logging.apache.org/sandbox/jul-log4j-bridge/examples.html

With Helidon 2.0 you will need:
Add dependency log4j2
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.13.3</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.13.3</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-jul</artifactId>
<version>2.13.3</version>
</dependency>
when start your application, add this variables using external configuration log4j:
-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager
-Dlog4j.configurationFile=file:/conf/log4j2.xml
java -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager
-Dlog4j.configurationFile=file:/conf/log4j2.xml -jar target/your-app.jar
Or when your log4j2.xml is inside src/main/resources/log4j2.xml
-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager
java -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager -jar target/your-app.jar
Example log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="info">
<Appenders>
<Console name="LogToConsole" target="SYSTEM_OUT">
<PatternLayout>
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %p %c{1.} %m%n</Pattern>
</PatternLayout>
</Console>
</Appenders>
<Loggers>
<Logger name="io.helidon" level="info" additivity="false">
<AppenderRef ref="LogToConsole" />
</Logger>
<Root level="info" additivity="false">
<AppenderRef ref="LogToConsole" />
</Root>
</Loggers>
</Configuration>

Related

Splunk log4j2 plugin not working in mule application

I have a requirement to send all mule logs to splunk, so for this i am using splunks Http Event collector mentioned here http://dev.splunk.com/view/event-collector/SP-CAAAE6M
for this i have configured appender in log4j2 xml file as
<Http name="SPLUNK"
url="https://localhost:8088"
token="4B916A8F-C41E-4DD3-80AC-778D3E24F45C" batch_size_bytes="0"
batch_size_count="0" batch_interval="0" disableCertificateValidation="true">
<PatternLayout pattern="%m" />
</Http>
<Logger name="splunk.log4j" level="INFO">
<AppenderRef ref="SPLUNK" />
</Logger>
i have added following libraries in pom file
<dependency>
<groupId>com.splunk.logging</groupId>
<artifactId>splunk-library-javalogging</artifactId>
<version>1.5.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
i know for this to work i need to add splunk jar in /lib/boot so i have copied following jars in /lib/boot
/lib/boot/splunk-1.5.0.0.jar
/lib/boot/splunk-library-javalogging-1.5.2.jar
but even after that when i deploy to standalone server i get following error but surprisingly it works fine in Studio and not in standalone server.
2017-12-11 14:26:12,771 WrapperListener_start_runner ERROR Unable to invoke factory method in class class com.splunk.logging.HttpEventCollectorLog4jAppender for element Http.
2017-12-11 14:26:12,771 WrapperListener_start_runner ERROR Null object returned for Http in Appenders.
2017-12-11 14:26:12,775 WrapperListener_start_runner ERROR Unable to locate appender "SPLUNK" for logger config "splunk.log4j"
does any one know why is this happening?
ERROR Unable to locate appender "SPLUNK" for logger config "splunk.log4j"
This means there is no Appender named "SPLUNK" configured. Make sure your log4j2.xml contains such configuration, for example to output log to console:
<Appenders>
<Console name="SPLUNK" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %c{1} - %msg%n"/>
</Console>
</Appenders>
See the Configuring Appenders and Appenders doc for details.

How to make Log4j2 configurable by environment using Spring Boot 1.3.6.RELEASE

I would like to change some properties from the log4j2.xml file depending on the my application.properties, for example define some properties and then substitute in the log4j2 those properties that are parameters.
I ran different approaches but I still did not get the right thing. I would like to have different configs depending on the environment (DEV, QA or PROD). How to accomplish this?
I'm trying to have this in my properties
#Place holders for log4j2.xml file
log.file.path=/opt/tomcat/logs
log.file.name=dummydummy
log.file.size=100 MB
log.level=DEBUG
My log4j2 below.
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" monitorInterval="30">
<Properties>
<Property name="PID">????</Property>
<property name="name">my-log</property>
</Properties>
<Appenders>
<RollingFile name="file" fileName="${log.file.path}${log.file}.log"
filePattern="${log.file.path}${log.file}-%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout
pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} %5p ${sys:PID} --- [%t] %c{1}(%M:%L) : %m%n%wEx" />
<Policies>
<TimeBasedTriggeringPolicy /><!-- Rotated everyday -->
<SizeBasedTriggeringPolicy size="${log.file.size}" /> <!-- Or every 100 MB -->
</Policies>
</RollingFile>
<Console name="Console" target="SYSTEM_OUT" follow="true">
<PatternLayout
pattern="%clr{%d{yyyy-MM-dd HH:mm:ss.SSS}}{faint} %clr{%5p} %clr{${sys:PID}}{magenta} %clr{---}{faint} %clr{[%t]}{faint} %clr{%c{1}(%M:%L)}{cyan} %clr{:}{faint} %m%n%wEx" />
</Console>
</Appenders>
<Loggers>
<Logger name="org.hibernate.validator.internal.util.Version"
level="warn" />
<Logger name="org.apache.coyote.http11.Http11NioProtocol" level="warn" />
<Logger name="org.apache.tomcat.util.net.NioSelectorPool" level="warn" />
<Logger name="org.apache.catalina.startup.DigesterFactory" level="error" />
<Logger name="org.springframework.web" level="error" />
<Root level="${log.level}">
<AppenderRef ref="Console" />
<AppenderRef ref="file" />
</Root>
</Loggers>
</Configuration>
The properties lookup element allows to refer properties from an external properties file in the log4j configuration.
For your example it should be something like this:
A file env.properties contains the following properties:
log.file.path=/opt/tomcat/logs
log.file.name=dummydummy
log.file.size=100 MB
log.level=DEBUG
The properties lookup should be defined as properties of the log4j2.xml:
<Configuration>
<Properties>
<property name="log.file.path">${bundle:env:log.file.path}</property>
<property name="log.file.name">${bundle:env:log.file.name}</property>
<property name="log.file.size">${bundle:env:log.file.size}</property>
<property name="log.level">${bundle:env:log.level}</property>
</Properties>
Now the properties may be referred in appenders with ${property_name} notation. Each property reference will be interpolated with the real value from the env.properties.
You can find another example of properties lookup here.
As of Log4j 2.13.0 Log4j 2 now provides a Spring Lookup as part of its Spring Cloud Config support. It will allow you to reference properties defined in your application.properties or application.yml file of your Spring Boot application in the log4j2.xml.
Since log4j 2.14.0, you can now use Spring Boot environment variables without Spring Cloud and without doing direct reference to the properties file. You'll need at least Spring Boot 2.0.3
<property name="applicationName">${spring:spring.application.name}</property>
Documentation: https://logging.apache.org/log4j/2.x/log4j-spring-boot/index.html
Maven repository: https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-spring-boot
Ensure that log4j2 starter is added in the classpath and then remove logging related properties in application.properties then spring will load your log4j2.xml from resources folder.
This way you can have full control over logging. If you want to substitute values then refer this link
Note:: If you have actuator in your project then remove spring boot logger starter
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
Workaround in case you need just different property values in log4j2.xml config for different spring profiles (dev, test, prod, etc.).
You could access spring profile files like: ${bundle:application-${sys:spring.profiles.active}:log.file.name}
application-dev.properties file:
log.file.name=dev_log
application-prod.properties file:
log.file.name=app_name
log4j2.xml config:
<Configuration>
<Properties>
<Property name="file_name">${bundle:application-${sys:spring.profiles.active}:log.file.name}</Property>
</Properties>
<Appenders>
<RollingFile name="RollingFile"
fileName="/logs/${file_name}.log"
...
NOTE: You have to add log.file.name property to each spring profile, log4j2 sees it just as separate text files and will not resolve default values from application.properties file and etc.

Mule ESB Log4j2 support

Does Mule ESB support log4j2? I am trying to add log4j2.xml in my esb app, but even after adding log4j2.xml, my mule esb app is defaulting to its own log4j 1.2 implementation. I want my esb app to read my log4j2.xml file and take/consume in the parameters what I am specifying in my log4j2.xml and if log4j2.xml file is present then it should not read its own log4j 1.2 implementation log properties file.
I am having problem in implementing log4j2(.xml) with mule esb app. Any help would be very much appreciated.
The latest version of mule esb is supporting the log4j2 . Hope the version may be tightly coupled that could be the reason it might not work.
Log4j2 has an adapter allows application that are coded against the log4j-1.2 API to use the log4j2 implementation. (See also the FAQ.)
Steps to achieve this:
remove the log4j-1.2.x.jar from the classpath
add the log4j-1.2-api-2.0.jar jar to the classpath.
ensure that log4j-api-2.0.jar and log4j-core-2.0.jar are in the classpath
Now both the log4j-1.2 API and the log4j2 API will delegate to the log4j2 implementation. A sample configuration is here.
Log4j2 is implicitly supported from Mule-3.6.0 onwards. For more info please go through this link Asynchronous Logging in Mule
Mule esb supports log4j.
check if you have imported slf4j libraries.
You need to create/rename log4j2-test.xml
These are my log4j2.xml and my pom.xml files, I´m using mule v7.1.
I hope it helps.
log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="debug">
<Properties>
<Property name="log-path">/my_path/my_logs/my_app</Property>
<Property name="app-id">my_app</Property>
</Properties>
<Appenders>
<RollingFile name="file-log" fileName="${log-path}/${app-id}.log"
filePattern="${log-path}/${app-id}-%d{yyyy-MM-dd}.log">
<PatternLayout>
<pattern>[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n
</pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy interval="1"
modulate="true" />
</Policies>
</RollingFile>
<Console name="console" target="SYSTEM_OUT">
<PatternLayout
pattern="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n" />
</Console>
</Appenders>
<Loggers>
<Logger name="org.apache.logging.log4j" level="warn" additivity="false">
<appender-ref ref="file-log" />
<appender-ref ref="console" />
</Logger>
<Root level="info" additivity="false">
<appender-ref ref="file-log" />
<appender-ref ref="console" />
</Root>`enter code here`
</Loggers>
</Configuration>
pom.xml
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.0</version>
</dependency>

Logback and Jboss 7 - don't work together?

I am having a curious problem. I had this Java application which was previously deployed in tomcat and happily used logback classic as an slf4j implementation. Now when we tried to deploy the same app in a jboss 7.1.final server it doesn't even deploy the application maoning about
java.lang.ClassCastException: org.slf4j.impl.Slf4jLoggerFactory cannot be cast to ch.qos.logback.classic.LoggerContext
This is the offending line of code
final LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
The class that has his is spring injected and that is failing - hence the whole application cannot be deployed. Anyone got a solution to this? Thanks in advance
After looking in this site plus other forums I realised that Jboss 7 comes bundled with it's own slf4j implementation and implement the same ILoggerFactory interface that LoggerContext in logback does. Our application tried to get an instance of the same but the app server imposes it's own slf4j implementation.
I tried to modify the module.xml in jboss\modules\org\slf4j\impl\main and pointed it to logback jars.
<resources>
<resource-root path="logback-classic-0.9.28.jar"/>
<resource-root path="logback-core-0.9.28.jar"/>
</resources>
Now when I start the application I am getting a serious error
Exception starting filter WicketFilter: java.lang.ClassCastException: ch.qos.logback.classic.LoggerContext cannot be cast to ch.qos.logback.classic.LoggerContext
I am at my wits end. Any jboss and logback experts can help?
Thanks in advance
You need to exclude the servers version of slf4j from your deployment. Create a jboss-deployment-structure.xml file and place it in either your WARS META-INF or WEB-INF directory.
The contents of the file should look like this:
<jboss-deployment-structure>
<deployment>
<!-- Exclusions allow you to prevent the server from automatically adding some dependencies -->
<exclusions>
<module name="org.slf4j" />
<module name="org.slf4j.impl" />
</exclusions>
</deployment>
</jboss-deployment-structure>
If you are using the bridges for jul or jcl in your app, you should exclude them too:
<module name="org.slf4j" />
<module name="org.slf4j.jcl-over-slf4j" />
<module name="org.slf4j.impl" />
<module name="org.jboss.logging.jul-to-slf4j-stub" />
There is alternative approach:
you got logging configured in your war
you got all dependencies in your war
you don't configure anything in JBoss server directory, not even additional JBoss modules
Just disable JBoss logging completely and rely on the dependencies in your war. Edit your jboss-deployment-structure.xml as follows:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
<deployment>
<exclusions>
<module name="org.apache.commons.logging" />
<module name="org.apache.log4j" />
<module name="org.jboss.logging" />
<module name="org.jboss.logging.jul-to-slf4j-stub" />
<module name="org.jboss.logmanager" />
<module name="org.jboss.logmanager.log4j" />
<module name="org.slf4j" />
<module name="org.slf4j.impl" />
<module name="org.slf4j.jcl-over-slf4j" />
</exclusions>
</deployment>
</jboss-deployment-structure>
Once you deploy your app, bootstrap logging (boot.log) keeps working also server.log will show deployment logging. But all your application is logged through your (in this example) slf4j+logback in your war.
Note that you should not need to run JBoss with -Dorg.jboss.logging.provider=slf4j, if you specify this, you will need to provide JBoss modules (typically slf4j-api, logback-classic and logback-core), but it is not worth the effort, as JBoss logging is now used only for bootstrap (boot.log) and for deployment info (server.log).
References:
http://tinyapps.blogspot.com/2013/01/getting-logback-and-slf4j-to-work-in.html
https://stackoverflow.com/a/19695680/2587343
To make independent logging with Logback + Json in JBoss EAP 7.0 I need to exclude outdated Jackson implementation too:
jboss-deployment-structure.xml
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
<deployment>
<!-- https://docs.jboss.org/author/display/AS7/Class%20Loading%20in%20AS7.html -->
<!-- https://docs.wildfly.org/16/Developer_Guide.html -->
<exclusions>
<!-- Rely on WAR's SLF4j + Logback instead of JBoss logmananger. -->
<module name="org.apache.commons.logging" />
<module name="org.apache.log4j" />
<module name="org.jboss.as.logging" />
<module name="org.jboss.logging" />
<module name="org.jboss.logging.jul-to-slf4j-stub" />
<module name="org.jboss.logmanager" />
<module name="org.jboss.log4j.logmanager" />
<module name="org.slf4j" />
<module name="org.slf4j.ext" />
<module name="org.slf4j.impl" />
<module name="org.slf4j.jcl-over-slf4j" />
<!-- Built-in Jackson is without the field: Feature.USE_THREAD_LOCAL_FOR_BUFFER_RECYCLING, need to bundle own version. -->
<!-- https://docs.jboss.org/resteasy/docs/3.0.2.Final/userguide/html/json.html -->
<module name="org.jboss.resteasy.resteasy-jackson-provider"/>
<module name="org.jboss.resteasy.resteasy-jackson2-provider"/>
</exclusions>
</deployment>
</jboss-deployment-structure>
pom.xml
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.9</version>
</dependency>
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>7.0.1</version>
</dependency>
logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<charset>UTF-8</charset>
<pattern>%d{HH:mm:ss.SSS} %5p [%15.15t] %logger %m%ex</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<charset>UTF-8</charset>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %5p [%t] %-40.40logger{39} %m%n%ex</pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${my.log.dir}/test-servlet-logging-%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
<totalSizeCap>500MB</totalSizeCap>
</rollingPolicy>
</appender>
<appender name="JSON-FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${my.log.dir}/test-servlet-logging-%d{yyyy-MM-dd}.ndjson</fileNamePattern>
<maxHistory>30</maxHistory>
<totalSizeCap>500MB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<includeContext>false</includeContext>
<includeMdc>true</includeMdc>
<timestampPattern>uuuu-MM-dd'T'HH:mm:ss.SSSxxx</timestampPattern>
<fieldNames>
<timestamp>#timestamp</timestamp>
<message>message</message>
<thread>thread</thread>
<logger>logger</logger>
<level>level</level>
<levelValue>[ignore]</levelValue>
<version>[ignore]</version>
<stackTrace>ex</stackTrace>
</fieldNames>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
<appender-ref ref="JSON-FILE" />
</root>
</configuration>

Use of arquillian glassfish container

I used to have the following maven dependencies to use arquillian glassfish container:
<dependency>
<groupId>org.jboss.arquillian</groupId>
<artifactId>arquillian-junit</artifactId>
<scope>test</scope>
<version>1.0.0.Alpha5</version>
</dependency>
<dependency>
<groupId>org.jboss.arquillian.container</groupId>
<artifactId>arquillian-glassfish-embedded-3.1</artifactId>
<version>1.0.0.Alpha5</version>
</dependency>
I was able to run my tests successfully until I wanted to inject specific resources, that could not be looked up through JNDI.
I improved my domain.xml to have the relevant resources I wanted. But for now, I am not sure arquillian load successfully all the domain.xml (look up failed on "jca/Neo4j/resource").
My arquillian.xml (in src/test/resources):
<?xml version="1.0" encoding="UTF-8"?>
<arquillian xmlns="http://jboss.com/arquillian"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:glassfish="urn:arq:org.jboss.arquillian.container.glassfish.embedded_3">
<glassfish:container>
<glassfish:instanceRoot>src/test/resources/glassfish</glassfish:instanceRoot>
<glassfish:bindPort>9090</glassfish:bindPort>
<glassfish:autoDelete>false</glassfish:autoDelete>
</glassfish:container>
My domain.xml (in src/test/resources/glassfish/config/):
<domain log-root="${com.sun.aas.instanceRoot}/logs" applicationroot="${com.sun.aas.instanceRoot}/applications" version="10.0">
<resources>
<connector-connection-pool name="jca/Neo4j/pool" resource-adapter-name="neo4j-connector-0.1-SNAPSHOT" connection-definition-name="com.netoprise.neo4j.connection.Neo4JConnectionFactory">
<property name="dir" value="${com.sun.aas.instanceRoot}/lib/databases/neo4j"></property>
<property name="xa" value="true"></property>
</connector-connection-pool>
<connector-resource pool-name="jca/Neo4j/pool" jndi-name="jca/Neo4j/resource"></connector-resource>
</resources>
<servers>
<server name="server" config-ref="server-config">
<application-ref ref="neo4j-connector-0.1-SNAPSHOT" virtual-servers="server"></application-ref>
<resource-ref ref="jca/Neo4j/resource"></resource-ref>
</server>
</servers>
...
</domain>
Thanks,
Alex
The Alpha5 was a bit hard to handle :)
Stuff changed a bit and if you like to give the latest 1.0.0.Final-SNAPSHOT a try, you could have a more detailed look at a configuration here:
http://blog.eisele.net/2012/01/arquillian-with-netbeans-glassfish.html
Thanks,
M