I have a simple question where I still can not find any answer. I want to log messages into a separate log file. I am using Java logging and not log4j.
I have the following class:
package org.imixs.workflow;
public class MailPlugin {
....
private static Logger logger = Logger.getLogger(MailPlugin.class.getName());
...
logger.info("some info...");
}
I am using GlassFish server. So I need to customize the settings in the logger.properties file from GlassFish.
What entries need to be added to the GlassFish logger.properties file to log all messages from my class 'MailPlugin' into a separate log file?
You can create a file appender and apply a Filter to it that only returns true when it the logging is coming from the MailPlugin
Related
I use websphere 9 application server to deploy war's and ear's, and use java.util.logging to generate logs into applications. I try to use properties file to configure the FileHandler of the LogManager, but websphere write ALL other logs on my file.
I not use log4j because i can't set log levels at runtime.
Is possible make differents file logs by application over websphere with java.util.logging ?
This is my properties file Logger.properties
handlers= java.util.logging.FileHandler
#java.util.logging.ConsoleHandler.level = INFO
#java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
# Set the default formatter to be the simple formatter
java.util.logging.FileHandler.formatter =java.util.logging.SimpleFormatter
# Use UTF-8 encoding
java.util.logging.FileHandler.encoding = UTF-8
# Write the log files to some file pattern
java.util.logging.FileHandler.pattern = C:/Users/pmendez/Documents/Log/testLogs.log
# Limit log file size to 5 Kb
java.util.logging.FileHandler.limit = 5000
# Keep 10 log files
java.util.logging.FileHandler.count = 10
#Customize the SimpleFormatter output format
java.util.logging.SimpleFormatter.format = %d [%t] %-5p (%F:%L) - %m%n
I try to use properties file to configure the FileHandler of the LogManager, but websphere write ALL other logs on my file.
Per your logging.properties you are attaching the FileHandler to the root logger. It would be expected to see log records from WebSphere because by default Logger::setUseParentHandlers is set to true.
Is possible make differents file logs by application over websphere with java.util.logging ?
You have to do one of the following:
Attach your FileHandler to the root logger of your application so the FileHandler is not attached to parent of the WebSphere application. Say application package is com.my.app.rules you can add entry of tocom.my.app.rules.handlers=java.util.logging.FileHandler and remove the attachment to the root logger. Next you demand the logger from code and pin it to memory so this package becomes the new root logger of your application code.
Create java.util.logging.Filter and install it on the FileHandler.
Turn off the logging for WebSphere. You can do this by setting the root logger to off and forcing all of your loggers to say info.
.level=OFF
com.my.app.rules.class1.level=INFO
com.my.app.rules.class2.level=INFO
com.my.app.rules.class3.level=INFO
It's possible set one FileHandler by app ?
The default java.util.logging.LogManager only supports one set of FileHandler settings. You can attach instances to various loggers but it doesn't allow for instances with different settings via the logging.properties. However, the LogManager does support per the documentation:
A property "config". This property is intended to allow arbitrary configuration code to be run. The property defines a whitespace or comma separated list of class names. A new instance will be created for each named class. The default constructor of each class may execute arbitrary code to update the logging configuration, such as setting logger levels, adding handlers, adding filters, etc.
So what you need to do is bundle a configuration class with your application that performs the needed FileHandler and logger configuration and modify your logging.properties to load it. One issue with this approach is that the LogManager can only see classes from the system class loader.
From jmehrens answer you can see it might be a bit difficult. Maybe you should consider switching logging to High Performance Extensible Logging (HPEL). It is just setting in the application server, so no changes in the applications code.
Then you could query logs for the given application using command line tool:
logViewer.sh -includeExtensions appName=PlantsByWebSphere
This would be much easier, if it fits your purpose. Moreover, generating separate log files is now not recommended, if you plan to move your apps in the future into containers/cloud or refactor them into microservices.
My solution to this isue was create a PersonalFileHandler to use on all Logger's. Properties are read from properties file called "Logger.properties", and invoque read this programmatically, same like this:
//Read config file
LogManager.getLogManager().readConfiguration(LoggerJUL.class.getResourceAsStream("/Logger.properties"));
//Add handler to logger
Logger.getLogger(clazz)).addHandler(new PersonalFileHandler());
PersonalFileHandler extends FileHandler, and properties are set by configure method on FileHandler class on runtime.
The application I am working with has log calls in the catch blocks auto-generated by NetBeans only and no other kind of logging:
Logger.getLogger(SomeClass.class.getName()).log(Level.SEVERE, null, ex);
What steps should be taken to redirect log output from the console to for example a text file?
I read Lars Vogel tutoriral http://www.vogella.com/tutorials/Logging/article.html and for the most part understand what he is doing, but apparently when he wanted to log an event, he would call a method from an instance of his own logger LOGGER.
NetBeans developers probably intended to auto-generate the log calls the way they did for a reason. Does their logging have to be replaced as in the tutorial, or can it be simply configured to use another logging destination?
My confusion stems from the fact that Logger.getLogger is a static method.
What steps should be taken to redirect log output from the console to for example a text file?
From the Java Logging Overview Examples:
public static void main(String[] args) {
Handler fh = new FileHandler("%t/wombat.log");
Logger.getLogger("").addHandler(fh);
Logger.getLogger("com.wombat").setLevel(Level.FINEST);
...
}
That example creates a wombat.log file in the temp directory.
Otherwise you can modify or specify a logging.properties entry to install a FileHandler. Here is a modified entry of the 'lib/logging.properties' located in your Java Home directory.
############################################################
# Global properties
############################################################
# "handlers" specifies a comma separated list of log Handler
# classes. These handlers will be installed during VM startup.
# Note that these classes must be on the system classpath.
# By default we only configure a ConsoleHandler, which will only
# show messages at the INFO and above levels.
#
#handlers= java.util.logging.ConsoleHandler
# To also add the FileHandler, use the following line instead.
handlers=java.util.logging.FileHandler, java.util.logging.ConsoleHandler
You can use the 'java.util.logging.config.file' system property on launch to specify alternate log configuration files.
if getLogger() is a static method, which executes without an instance of Logger class being created,
Contained in the Java Logging Overview listed above there is a link to the Java SE API Specification. That is the contract for how all this works.
If you look up Logger.getLogger you'll see:
Find or create a logger for a named subsystem. If a logger has already been created with the given name it is returned. Otherwise a new logger is created.
If a new logger is created its log level will be configured based on the LogManager configuration and it will configured to also send logging output to its parent's Handlers. It will be registered in the LogManager global namespace.
The getLogger method is creating or locating a logger.
than where does addHandler() persist its result?
Handlers are store on the logger instance. The output type depends on the handler. The properties of each handler are described in the API spec.
The Logging Hierarchy and Record Forwarding might help you understand what is happening in the example code.
log4j has a property, log4j.debug, which will helpfully provide the user with an indication of which configuration file was actually used to configure the logging system.
I haven't been able to find anything equivalent with the (otherwise superior) Logback logging framework. Is there any way to print (for diagnostic purposes) at runtime, which configuration file Logback used to bootstrap itself?
[edit]
To clarify, I'd ideally like a solution that doesn't require me to modify the configuration file itself (since a badly assembled third-party JAR, for example, may be picked up incorrectly, and prior to my logback configuration XML).
You can set a Java system property to output Logback debugging info:
java -Dlogback.statusListenerClass=ch.qos.logback.core.status.OnConsoleStatusListener
This is further explained by the Logback documentation for automatic status printing (very bottom mentions forcing status output) and the logback.statusListenerClass property:
In the absence of status messages, tracking down a rogue logback.xml configuration file can be difficult, especially in production where the application source cannot be easily modified. To help identify the location of a rogue configuration file, you can set a StatusListener via the "logback.statusListenerClass" system property (defined below) to force output of status messages. The "logback.statusListenerClass" system property can also be used to silence output automatically generated in case of errors.
If you want to go deep into Logback, you can do the following
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.core.joran.util.ConfigurationWatchListUtil;
public class Main {
private static final Logger logger = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) throws Exception {
LoggerContext loggerContext = ((ch.qos.logback.classic.Logger)logger).getLoggerContext();
URL mainURL = ConfigurationWatchListUtil.getMainWatchURL(loggerContext);
System.out.println(mainURL);
// or even
logger.info("Logback used '{}' as the configuration file.", mainURL);
}
}
It will print the URL of the loaded configuration file.
you can set debug="true" in a logback.xml file that you control like this:
<configuration debug="true">
(...)
</configuration
and tho make sure that file is going to be used by logback add following VM argument when you start your program:
-Dlogback.configurationFile=/path/to/yourlogback.xml
This does not really answer to your question but gives you a work around solution.
Not very scientific, but it works if you just want a quick confirmation.
I simply changed the log entry pattern and observed whether or not it changed in my console/log file.
I have developed an spring mvc application which is executing perfectly on tomcat , but the logs I am getting of the server tomcat is on console , I want that logs to be stored in a file ,in other words I want tomcat logs and events that are shown on console to be get stored on a file , I have tried log 4j of apache and below is the properties file I am using ...
### direct messages to file or.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=C:/logs/springmvc.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1} - %m%n
log4j.appender.file.append=true
### set log levels - for more verbose logging change 'info' to 'debug' ##
log4j.rootCategory=ALL, file
log4j.logger.Demo=\=debug
log4j.logger.org.eclipse=debug
and the main class.. on which I want log.info statements to be get recorded..
public class HelloWorldController extends AbstractController{
protected final Log logger = LogFactory.getLog(getClass());
#Override
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throws Exception {
logger.info("Returning hello view");
ModelAndView model = new ModelAndView("HelloWorldPage");
model.addObject("msg", "saral saxreva");
return model;
}
}
but still the logs are not generated in separate file , please advise as I am stuck up on this.
I think for enabling logging in web app you need some listener (or servlet) that will initialize it. For example in Spring you need to define in your web.xml such listener:
<!-- This listener is necessary to enable log4j logging -->
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
In internet there are a lot of info about this. Here is the firs link from google. Here is another one link where describet how to init logger in servlet or in listener without Spring.
And also it is better to use log4j.rootLogger instead of log4j.rootCategory because last is deprecated.
Does the springmvc.log file even created when your program starts? That's a first indication of whether or not the log4j is being picked up properly.
Make Sure the log4j properties file is in the correct location and are picked up properly
Double check the import statement for your logger and LogFactory classes (just to make sure they are using the log4j ones
If the log4j is set up properly, you'll see springmvc.log file created when the app starts.
Then in the log4j properties, try:
log4j.rootLogger=DEBUG,file
and also get rid of the other 2 that you have
log4j.logger.Demo=\=debug
log4j.logger.org.eclipse=debug
By default slf4j, when using with jdk (slf4j-jdk14-1.6.1.jar), does not log debug messages.
How do I enable them?
I can’t find info neither in the official docs, the web or here on how to enable it.
I found some info on (failed though) creating a file in %JDK_HOME%/lib and defining the level there, in a config file.
However, I would like to define the level at compile-/run-time so I can both run and debug my app from my IDE with different logging levels.
Isn’t there some environment variable I can set, or VM arg?
Why do you think it does not log DEBUG messages?
If you mean that your log.debug(String) logging calls do not end up in java.util.logging log files, then I guess you have to configure the logging.properties configuration file to allow log messages at FINE level.
If you do not want to mess with the global %JRE_HOME%/lib/logging.properties, then you can just pass in -Djava.util.logging.config.file=logging.properties on the command line - this will force the logging system to look for that configuration file in the current directory.
Or use some other (programmatic) way to configure java.util.logging, see below for tutorial.
This has nothing to do with configuring SLF4J; in fact, SLF4J does not have any configuration, everything is configured by simply swapping JAR files.
For your reference:
JDK14LoggerAdapter
Java Logging API tutorial
If you are using slf4j SimpleLogger implementation read this.
There you can see that simpleLogger use INFO as default log level. You can change it by using a system property. This is usefull for non-production evironments:
static {
System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "trace");
}
You can add -Dorg.slf4j.simpleLogger.defaultLogLevel=debug to the VM options.
I just put my logging.properties file in my applications WEB-INF/classes file (or use the command line argument identified by Neeme Praks if you're not deploying in a war), and have the properties file open in eclipse so I can fine tune it to log the packages and at the level I'm interested in.
In the logging.properties file, you need to make sure that both the logger level and the handler level are set to the level you want. For example, if you want your output to go to the console, you need to have at least the following:
#logging.properties file contents
#Define handlers
handlers=java.util.logging.ConsoleHandler
#Set handler log level
java.util.logging.ConsoleHandler.level=FINE
#Define your logger level
com.company.application.package.package.level=FINE
#Assign your handler to your logger
com.company.application.package.package.handlers=java.util.logging.ConsoleHandler
You mentioned the slf4j-jdk14-1.6.1.jar. This provides the slf4j binding to java.util.logging. You need to have that in your classpath, but make sure you also have the slf4j api (slf4j-api-1.7.12.jar) in your classpath as well.
I find the example logging.properties file in this link useful for creating a variety of loggers and handlers, to give you fine-grained control over what logs go to the console, and what logs go to a file:.
And here's the slf4j manual.
if you are using lombok Slf4j
package com.space.slf4j;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* #author anson
* #date 2019/6/18 16:17
*/
#Slf4j
#RestController
public class TestController {
#RequestMapping("/log")
public String testLog(){
log.info("######### info #########");
log.debug("######### debug #########");
log.error("######### error #########");
return null;
}
}
application.yml
logging:
level:
root: debug
In runtime with the default configuration you can enable it with this code:
public class MyTest {
static {
Logger rootLogger = Logger.getLogger("");
rootLogger.setLevel(Level.ALL);
rootLogger.getHandlers()[0].setLevel(Level.ALL);
}
I'm using this code inside TestNG Unit.