Directing JUL logging to SLF4J does not work - java

I am using a third party library (Sphinx) which uses java.util.logging. I have been trying several approaches to route its logs to slf4j. The logging library I wish to use is Log4j2, which is configured like this:
Configuration:
properties:
property:
- name: logPath
value: logs
- name: logName
value: flux
- name: rootLevel
value: info
- name: useConsole
value: ALLOW
Appenders:
Console:
name: Console
target: SYSTEM_OUT
ThresholdFilter:
level: ${sys:rootLevel}
onMatch: ${sys:useConsole}
PatternLayout:
pattern: "%d{yyyy.MM.dd G HH:mm:ss,SSS z} %-5p [%t] %C{2} (%F:%L) - %m%n"
RollingRandomAccessFile:
name: File
fileName: "${sys:logPath}/${sys:logName}.log"
filePattern: "${sys:logPath}/${sys:logName}.%d{yyyy-MM-dd}.log"
PatternLayout:
pattern: "%d{yyyy.MM.dd G HH:mm:ss,SSS z} %-5p [%t] %C{2} (%F:%L) - %m%n"
Policies:
TimeBasedTriggeringPolicy:
interval: 1
Loggers:
Root:
level: ${sys:rootLevel}
AppenderRef:
- ref: File
- ref: Console
I applied without success all the solutions I could find on this and other forums. Among others:
I added this maven dependency to my POM:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>1.7.20</version>
</dependency>
I also tried with calling this in a static block:
SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();
And tried setting the system property:
System.setProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager");
In my last attempt I passed the VM argument:
-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager
and got the exception below:
Could not load Logmanager "org.apache.logging.log4j.jul.LogManager"
java.lang.ClassNotFoundException: org.apache.logging.log4j.jul.LogManager
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.util.logging.LogManager$1.run(LogManager.java:195)
at java.util.logging.LogManager$1.run(LogManager.java:181)
at java.security.AccessController.doPrivileged(Native Method)
at java.util.logging.LogManager.<clinit>(LogManager.java:181)
at org.chatbot.stt.SttEngineDemo.<clinit>(SttEngineDemo.java:25)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
Am I doing something wrong? What else can I try?
Update:
I also tried redirecting jul to log4j2, bypassing slf4j, hence changing my original strategy (thanks for the suggestion #rgoers).
In order to do this, I added the dependency below:
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-jul</artifactId>
<version>2.5</version>
</dependency>
and also set the System property
java.util.logging.manager to: org.apache.logging.log4j.jul.LogManager
Then the sphinx logs are gone. I know they are not routed to my log4j2 logger since most of the Sphinx logs have the level INFO and they should be processed by log4j2. So still not correct.

If you want to route the messages to Log4j 2 why not just use Log4j 2's bridge? log4j-jul-2.5.jar

We have a solution here working and the difference I noticed is: logger.setUseParentHandler(false) and logger.addHandler(new org.slf4j.bridge.SLF4JBridgeHandler());
I make sure I don't have any other handler and then attach the SLF4JBridgeHandler to the Logger instance.
import java.io.File;
import java.io.IOException;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.bridge.SLF4JBridgeHandler;
class Helper {
public static Logger get(String name) {
Logger logger = Logger.getLogger(name);
logger.setUseParentHandlers(false);
configureLogger(logger);
return logger;
}
private static void configureLogger(Logger logger) {
try {
// Remove Console Handler
Handler[] handlers = logger.getHandlers();
for (int i = handlers.length - 1; i >= 0; --i) {
logger.removeHandler(handlers[i]);
}
// Add handler for SLF4J
logger.addHandler(new org.slf4j.bridge.SLF4JBridgeHandler());
} catch (Throwable ex) {
logger.log(Level.SEVERE, "configureLogger", ex);
}
}
}

I have a JEE-Webapp, an wanted to log servlet-filter.
The underlying Tomcat 8.5 has already initialized the JUL at startup.
So I needed to override the Tomcat-initialization.
This code worked for me.
SLF4JBridgeHandler.removeHandlersForRootLogger();
LogManager manager = LogManager.getLogManager();
Enumeration<String> loggernames = LogManager.getLogManager().getLoggerNames();
while(loggernames.hasMoreElements()) {
String loggername = loggernames.nextElement();
Logger logger = manager.getLogger(loggername);
Handler[] handlers = logger.getHandlers();
for (int i = handlers.length - 1; i >= 0; --i) {
logger.removeHandler(handlers[i]);
logger.setUseParentHandlers(true);
}
}
SLF4JBridgeHandler.install();
// Decision what to log is on slf4j-Side. So we delegate every log-request.
Logger.getLogger("").setLevel(Level.FINEST);

Related

Wildfly log prints the same line twice

When I log a message in the code the server prints twice the same message with the only difference of the date at the beginning.
I'm using the default log configuration that comes with the server Wildfly 10.
Server.log
09:43:09,122 INFO [es.myapp.business.scheduler.boundary.Job] (default task-91) ----------INIT Job Mon Nov 20 10:05:08 CET 2017
2017-11-20 09:43:09,122 INFO [es.myapp.business.scheduler.boundary.Job] (default task-91) ----------INIT Job Mon Nov 20 10:05:08 CET 2017
Job.java
import org.apache.log4j.Logger;
...
public class Job {
protected Logger logger = Logger.getLogger(getClass().getName());
public void execute() throws IOException {
logger.info("----------INIT Job " + new Date());
}
}
Wildfly logging.properties
# Note this file has been generated and will be overwritten if a
# logging subsystem has been defined in the XML configuration.
# Additional loggers to configure (the root logger is always configured)
loggers=sun.rmi,org.jboss.as.config,com.arjuna
logger.level=INFO
logger.handlers=FILE,CONSOLE
logger.sun.rmi.level=WARN
logger.sun.rmi.useParentHandlers=true
logger.org.jboss.as.config.level=DEBUG
logger.org.jboss.as.config.useParentHandlers=true
logger.com.arjuna.level=WARN
logger.com.arjuna.useParentHandlers=true
handler.CONSOLE=org.jboss.logmanager.handlers.ConsoleHandler
handler.CONSOLE.level=INFO
handler.CONSOLE.formatter=COLOR-PATTERN
handler.CONSOLE.properties=enabled,autoFlush,target
handler.CONSOLE.enabled=true
handler.CONSOLE.autoFlush=true
handler.CONSOLE.target=SYSTEM_OUT
handler.FILE=org.jboss.logmanager.handlers.PeriodicRotatingFileHandler
handler.FILE.level=ALL
handler.FILE.formatter=PATTERN
handler.FILE.properties=append,autoFlush,enabled,suffix,fileName
handler.FILE.append=true
handler.FILE.autoFlush=true
handler.FILE.enabled=true
handler.FILE.suffix=.yyyy-MM-dd
handler.FILE.fileName=/home/u24282/servers/wildfly-10.1.0.Final/standalone/log/server.log
formatter.PATTERN=org.jboss.logmanager.formatters.PatternFormatter
formatter.PATTERN.properties=pattern
formatter.PATTERN.pattern=%d{yyyy-MM-dd HH\:mm\:ss,SSS} %-5p [%c] (%t) %s%e%n
formatter.COLOR-PATTERN=org.jboss.logmanager.formatters.PatternFormatter
formatter.COLOR-PATTERN.properties=pattern
formatter.COLOR-PATTERN.pattern=%K{level}%d{HH\:mm\:ss,SSS} %-5p [%c] (%t) %s%e%n
Are you perhaps piping your WildFly process output to the log file? Or, are you running in domain mode maybe?

Java log4j No appenders could be found for logger

I am trying to make a custom logger and appender in log4j, but I am geting confusing error messages.
Here's the error:
[n.a.:n.a.] 19.Apr.2016 15:54 81 [ preRegister] ERROR stderr - log4j:WARN No appenders could be found for logger (datenImportLogger).
[n.a.:n.a.] 19.Apr.2016 15:54 81 [ preRegister] ERROR stderr - log4j:WARN Please initialize the log4j system properly.
[n.a.:n.a.] 19.Apr.2016 15:54 81 [ preRegister] ERROR stderr - log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Here's my config:
# datenImportLogger
log4j.logger.datenImportLogger=datenImportFileAppender
log4j.additivity.datenImportLogger=false
log4j.appender.datenImportFileAppender=org.apache.log4j.RollingFileAppender
log4j.appender.datenImportFileAppender.File=java/log/datenimport.log
log4j.appender.datenImportFileAppender.MaxBackupIndex=5
log4j.appender.datenImportFileAppender.MaxFileSize=5MB
log4j.appender.datenImportFileAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.datenImportFileAppender.layout.ConversionPattern=[%X{USER_CODE}:%X{CALLER_ID}] %d{dd.MMM.yyyy HH:mm:ss,SSS} - %m%n
Have I missed something?
Are there any debug Abilities which provide debug on runtime,
because -Dlog4j.debug is not posible.
Logger should be called in code like :
private static final Logger logger = Logger.getLogger("datenImportLogger");
Root Logger is already configured.
The line
log4j.logger.datenImportLogger=datenImportFileAppender is problematic, it miss the level definition
The logger definition should be:
log4j.logger.loggerName=[level|INHERITED|NULL], [appenderName1, appenderName2,...]
source: The Complete Log4j Manual
e.g.
log4j.logger.datenImportLogger=INFO, datenImportFileAppender
try placing log4j.debug=true in top of the log4.propeties file it should provide additional logging information (although it will have affect only after the configurations are parsed )

REST JAX-RS Logging

I have followed the HelloWorld example and got my fist REST done successfully. Now, I would like to add the logging capability the code. For example, I would like to have any logging frameworks (Log4j, JUL) and be able to log in the code, and have output to a file. How do I implement the logging to my REST code?
#Path("/hello")
public class HelloWorldService {
Logger log = Logger.getLogger("className");
#GET
#Path("/{param}")
public Response getMsg(#PathParam("param") String msg) {
String output = "Jersey say : " + msg;
//for example, here. hopefully to a file
log.info("Log Jersey say : " + msg);
return Response.status(200).entity(output).build();
}
}
I am using Jersey 1.19, Tomcat 8
You can use open source Apache Log4j library. Add below dependency in your pom or download it from here.
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
log4j.properties
# Root logger option
log4j.rootLogger=INFO, file
# Direct log messages to a log file
log4j.appender.file=org.apache.log4j.RollingFileAppender
#Redirect to Tomcat logs folder
#log4j.appender.file.File=${catalina.home}/logs/logging.log
log4j.appender.file.File=C:\\logigng.log
log4j.appender.file.MaxFileSize=10MB
log4j.appender.file.MaxBackupIndex=10
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
With this configuration, all logging will be redirected to your specified log file.
Source : http://www.mkyong.com/logging/log4j-log4j-properties-examples/
How to log a message using Log4j?
private static final Logger logger = Logger.getLogger(HelloWorldService.class);
Logs messages with different priorities, for example, debug, info, warn, error and fatal. Normally, you just need to use debug or error.
//logs a debug message
if(logger.isDebugEnabled()){
logger.debug("This is debug");
}
//logs an error message with parameter
logger.error("This is error : " + parameter);
//logs an exception thrown from somewhere
logger.error("This is error", exception);
To set logger in debug mode, change this in your property file
log4j.rootLogger=DEBUG, file

log4j not logging to file

I've got a simple Tomcat web service that I'd like to see the logs for. I figured log4j would be the easiest solution. So far it will log to the in my dev environment, but it won't log to a file.
Here is my log4j.properties file (located in the src/ folder):
#Add these properties to all CallRouter-->data-->ddlog4j.properties files at the bottom to configure the Transactions.jar logging for DB and WS messaging.
log4j.rootCategory=ALL, MAIN_LOG
log4j.rootLogger=DEBUG,console
#Defines the <logging level>, <appender> for custom logging.
log4j.category.com.ddvc.android.resource=INFO, SupportWebServices
#### Transactions.jar appender INFO setup
log4j.logger.com.ddvc.android.resource=INFO
log4j.appender.ResourceInfo=org.apache.log4j.DailyRollingFileAppender
log4j.appender.ResourceInfo.File=C:/test/SupportWebServices.log
log4j.appender.ResourceInfo.Append=true
log4j.appender.ResourceInfo.DatePattern='.' yyyy-MM-dd HH-mm
log4j.appender.ResourceInfo.layout=org.apache.log4j.PatternLayout
log4j.appender.ResourceInfo.layout.ConversionPattern=%d{[yyyy-MM-dd HH:mm:ss:SSS]} %p %c{1} (%M: %L) - %m%n
log4j.appender.ResourceInfo.Threshold=INFO
# Output to Console
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.target=System.out
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{[yyyy-MM-dd HH:mm:ss]} %p %c{1} (%M: %L) - %m%n
log4j.appender.CONSOLE.Threshold=CONSOLE
And in my java files I have (located in src/com/ddvc/android/resource):
import org.apache.log4j.Logger;
#Path("/pulse")
#Component
#Scope("request")
public class PulseResource {
private final static Logger LOGGER = Logger.getLogger(PulseResource.class.getName());
#GET
#Path("list")
#Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public List<Pulse> postXML() {
LOGGER.info("Start: list");
}
}
Like I said I can see the logs to the Console:
INFO [2015-02-19 15:19:34,961] [http-bio-8080-exec-3] [PulseResource] [] - Start: list
But I don't see any file created or logged to in the C:\test folder. (plan to change it to ${catalina.base}\logs\SupportWebServices.log)
Try changing
log4j.rootLogger=DEBUG,console
to
log4j.rootLogger=DEBUG,console,ResourceInfo
remove this line:
log4j.rootCategory=ALL, MAIN_LOG
edit this line:
log4j.rootLogger=DEBUG,console,ResourceInfo

How to know in log4j , that ERROR level is triggered?

How to know in log4j , that ERROR level is triggered. In my code I have written like If an exception occurs i.e if an ERROR level is triggered then I will show log file path in console and wont show any message for other levels.
In Log4j you can configure different levels in the log4j.properties or xml file which ever you choose to use.
There is some predefined pattern with the error levels and runs from lower to upper.
Lowest id Debug its in this sequence.
1.Debug
2. Warn
3. Error etc
So if you want only Error messages then configure the Error level to Error. you wot get Debug and Warn
If you configure Debug you get everything
Ex.
<logger name="org.springframework...">
<level value="error" />
</logger>
This is the point of separating the code from the configuration.
E.g., your code could look like this:
try {
someMethod();
} catch (SomeException e) {
log.error("Error!!! " + e.getMessage());
}
And in your log4j configuration, your configure your log to output only ERROR level messages:
log4j.rootLogger=error, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
# Just an example of a pattern layout
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n

Categories