Multiple logging files - java

I want to make multiple logging files (For each day), the code I have is this:
public class LoggingInkrement {
static final Logger logger = Logger.getLogger(LoggingInkrement.class.getName());
public static void main(String[] args) {
LogManager manager = LogManager.getLogManager();
try {
FileHandler fhandler = new FileHandler("C:/Users/Administrator/Desktop/Logging%g.txt", 1024*1024,10, true);
SimpleFormatter sformatter = new SimpleFormatter();
fhandler.setFormatter(sformatter);
logger.addHandler(fhandler);
} catch (IOException | SecurityException ex) {
logger.log(Level.SEVERE, ex.getMessage(), ex);
}
try {
((Object) null).toString();
}
catch ( Exception e ) {
logger.log( Level.SEVERE, "oh oh", e );
}
logger.info( "Hat funktioniert" );
}
}
my problem is that:
First run: logging0.txt is created
Second run: nothing happens
the changes are unnoticed (it stays on "Hat funktioniert") regardless of the changes i made in logger.info
but my desired outcome is:
You can make logging files with a set size
the files append and dont overwrite till they're full limit
The files are automatically deleted when outdated
logging0.txt
logging1.txt
logging2.txt
and so on
but I have no idea how I could do it

The FileHandler doesn't support daily file rotation. However, you can always trigger a rotation by creating a throw away FileHandler with the limit set to zero and append set to false.
if (isNewDay()) { //then rotate and close.
new FileHandler("C:/Users/Administrator/Desktop/Logging%g.txt",0,5, false).close();
}
//Open the log file.
FileHandler fhandler = new FileHandler("C:/Users/Administrator/Desktop/Logging%g.txt", 1024*1024,10, true);

Related

java.util.logging: where does handler output go when running from Windows comand prompt?

Just getting to grips with this logging module.
When I run it in Eclipse the console output goes where I expect: console handler to console, file handler to file.
When I run from the command prompt I have no idea where the console output or the file output is going.
This is how I configure it:
Handler consoleHandler = null;
Handler fileHandler = null;
try {
logger.setUseParentHandlers(false);
// Creating consoleHandler and fileHandler
consoleHandler = new DualConsoleHandler();
// 1000 bytes max, 5 files max, append mode = true
fileHandler = new FileHandler("./output/logging/log%g.xml", 10000, 5, true);
// Assigning handlers to logger object
logger.addHandler(consoleHandler);
logger.addHandler(fileHandler);
// Setting levels to handlers and logger
consoleHandler.setLevel(Level.ALL);
fileHandler.setLevel(Level.ALL);
logger.setLevel(Level.ALL);
} catch (IOException exception) {
logger.log(Level.SEVERE, "Error occur in FileHandler.", exception);
}
The DualConsoleHandler looks like this (found in another SO question), the idea being to print INFO or lower to stdout, but WARNING or higher to stderr:
public class DualConsoleHandler extends StreamHandler {
private final ConsoleHandler stderrHandler = new ConsoleHandler();
public DualConsoleHandler() {
super(System.out, new SimpleFormatter());
}
#Override
public void publish(LogRecord record) {
if (record.getLevel().intValue() <= Level.INFO.intValue()) {
super.publish(record);
super.flush();
} else {
stderrHandler.publish(record);
stderrHandler.flush();
}
}
}
When I run from the command prompt I have no idea where the console output or the file output is going.
The console output goes to the console.
The file output goes to the path you gave it. i.e. ./output/logging/log%g.xml
Look in the directory under where you ran it for a output/logging directory.

Java Log File creates multiple copies

I am trying to create a logs file in a Java swings application that will contain all the messages generated by the code. But unfortunately it does not create 1 single log file but creates a structure as shown. I need 1 single log file.
My code:
//get the logger object
logger = Logger.getLogger("MyLog");
try {
// This block configure the logger with handler and formatter
loggerFH = new FileHandler(System.getProperty("user.dir") + "\\resources\\logs\\logs.txt",true);
logger.addHandler(loggerFH);
SimpleFormatter formatter = new SimpleFormatter();
loggerFH.setFormatter(formatter);
} catch (IOException | SecurityException ex) {
logger.severe(ex.getMessage());
outputArea.append(ex.getMessage());
}
Your files are being rotated.
Did you try solution from this:
Java FileHandler disable log rotation
FileHandler fh = new FileHandler( "path" , 0, 1, false);
I realized my Logger file was used by several instances at a time. So when 1 instance of filehandler locked the access to the file a new file was getting created. So I created a Synchronized class to handle all logging. And it worked great.
public class SynchronizedLogger {
//Logger to put error logs and messages in the log file
public static Logger logger = Logger.getLogger("MyLog");
//Logger Filehandler
private static FileHandler loggerFH;
public SynchronizedLogger() {
}
public static synchronized void writeLog(String message) {
logger.info(message);
}
public SynchronizedLogger(int i) {
try {
synchronized (this) {
// This block configures the logger with handler and formatter
loggerFH = new FileHandler(System.getProperty("user.dir") + "\\resources\\logs\\logs.txt", 0, 1, true);
logger.setUseParentHandlers(false);
logger.addHandler(loggerFH);
SimpleFormatter formatter = new SimpleFormatter();
loggerFH.setFormatter(formatter);
}
} catch (IOException | SecurityException ex) {
writeLog(ex.getMessage());
outputArea.append("\n\n" + ex.getMessage());
}
}
}

java.util.logging.SimpileFormatter system property configuration

I'm learning Java logging recently, and in the javadoc, it says the SimpleFormatter can be configured using property "java.util.logging.SimpleFormatter.format".
In below code, I tried to "set the format" twice with System.setProperty(), but it seems won't work in the second attempt, the "formatterB" in below code will still use the format defined in "formatterA".
What's the reason for this, thanks.
public class Test {
public static void main(String[] args) {
try {
Logger loggerA = Logger.getLogger("A");
System.setProperty("java.util.logging.SimpleFormatter.format", "A: %1$tc %2$s%n%4$s: %5$s%6$s%n"); // first attempt
Handler handlerA = new FileHandler("A.log", 0, 1, true);
SimpleFormatter formatterA = new SimpleFormatter();
handlerA.setFormatter(formatterA);
loggerA.addHandler(handlerA);
loggerA.info("Logger A info message");
Logger loggerB = Logger.getLogger("B");
System.setProperty("java.util.logging.SimpleFormatter.format", "B: %1$tc %2$s%n%4$s: %5$s%6$s%n"); // second attempt
Handler handlerB = new FileHandler("B.log", 0, 1, true);
SimpleFormatter formatterB = new SimpleFormatter();
handlerB.setFormatter(formatterB);
loggerB.addHandler(handlerB);
loggerB.info("Logger B info message");
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
The SimpleFormatter stores the format in a static field that is stored once on class load. The format is used for all instances of the SimpleFormatter class.
You'll have to roll your own formatter class or classes to support multiple formats.

New log and lock files created when redeploying app

I'm logging in a JSF and ejb enviroment and every time I redeploy my app, the .lck files don't get deleted and a new log (and lock) file is created (logfilename.log.2, logfilename.log.3 ...)
This is how I get the log and add a filehandler in a JSF managed bean:
static {
// (...)
logger = Logger.getLogger("registrations");
FileHandler fh;
try {
// (...)
fh = new FileHandler(registerLogPath, true);
fh.setFormatter(new Formatter() {
#Override
public String format(LogRecord record) {
return ...
}
});
logger.addHandler(fh);
} catch (IOException | SecurityException ex) {
logger.log(Level.SEVERE, null, ex);
}
}
I tried to remove the handlers in the contextDestroyed method of ServletContextListener, but it seems that it is too late since Logger.getLogger("registrations").getHandlers() returns an empty array, so nothing to remove.
Can you help me how to make the logger use the file it used before redeploying?
I finally managed to solve this. Removing a handler is not enough, you have to call close() on the handler itself. Also, logger.getHandlers() works in a contextDestroyed method:
for (Handler h : logger.getHandlers()) {
h.close();
}

Problem with java.util.logging and Lock file

I have an application that scans a set of files. And this scanning take place parallely. I mean if I upload 5 files, five process will be created and start executing the job parallely. Now For logging the exceptions for the jobs running, there is only one log file. The problem that is coming is, the logger creates a lot of logs files as -
mylogfile.log(actual log file)
mylogfile.log.1
mylogfile.log.2
mylogfile.log.3
mylogfile.log.4
mylogfile.log.5
...
with their respective lock files.
Below is the code snippet that I used:
public static Logger getLogger(final String className) {
final Logger logger = Logger.getLogger(className);
FileHandler fh;
try {
// This block configure the logger with handler and formatter
fh = new FileHandler("mylogfile.log", true);
logger.addHandler(fh);
logger.setLevel(Level.ALL);
logger.setUseParentHandlers(false);
fh.setFormatter(new SimpleFormatter());
} catch (final SecurityException e) {
// }
} catch (final IOException e) {
//
}
return logger;
}
How do I make sure that only one log file should be used to write the exception of all the jobs running parallely..??
Thanks,
Anish
I face the same problem and what I was missing is an standard programming practice that I should close the filehandler after I finish the logging.
So you can create multiple loggers but make sure you close them at the end.
Following 2 lines in below example:
successLogFileHandler.close();
failureLogFileHandler.close();
class LoggerExample {
private Logger loggerFailure;
private Logger loggerSuccess;
public void myLogger() {
// some code block
FileHandler successLogFileHandler = new FileHandler(successLogFile.getAbsolutePath());
FileHandler failureLogFileHandler = new FileHandler(failureLogFile.getAbsolutePath());
// Create loggers
loggerFailure = createLogger(STR_FAILURE_LOG_FILE, failureLogFileHandler, Level.INFO, customFormatter);
loggerSuccess = createLogger(STR_SUCCESS_LOG_FILE, successLogFileHandler, Level.INFO, customFormatter);
// Write messages into loggers
// and at the end close the file handlers
successLogFileHandler.close();
failureLogFileHandler.close();
}
public static Logger createLogger(String strLoggerName, FileHandler handler, Level level, Formatter formatter) throws Exception
{
Logger logger = Logger.getLogger(strLoggerName);
logger.setLevel(level);
handler.setFormatter(formatter);
logger.addHandler(handler);
return logger;
}
}
You can use a singlton locator class that you can retrieve the logger from, that would force your application to use one logger (which means you'll have one log file)
class LoggerLocator {
private static LoggerLocator locator = new LoggerLocator();
private Logger logger;
/**
*
*/
private LoggerLocator() {
initLogger();
}
/**
* #return
*/
public static LoggerLocator getLocator(){
return locator;
}
/**
* #return
*/
public Logger getLogger() {
return logger;
}
/**
*
*/
private void initLogger() {
logger = Logger.getLogger("My General Logger");
FileHandler fh;
try {
// This block configure the logger with handler and formatter
fh = new FileHandler("mylogfile.log", true);
logger.addHandler(fh);
logger.setLevel(Level.ALL);
logger.setUseParentHandlers(false);
fh.setFormatter(new SimpleFormatter());
} catch (final SecurityException e) {
// }
} catch (final IOException e) {
//
}
}
}
In your jobs you will get the logger by the following call:
Logger logger = LoggerLocator.getLocator().getLogger();
This does not have much to do with parallel calls. As well from single thread with each call to your getLogger (even with same string as argument) you create a new FileHandler and add it to existing logger.Maybe you do not want to do all of the setup each time when you call your getLogger-method.
//now we will create new Filehandler and set it to logger
getLogger("identifier").log(Level.SEVERE, "Log to one file");
//now we have already one filehandler, but lets add one more
getLogger("identifier").log(Level.SEVERE, "Log to two files");
//now we have already two filehandlers, but lets add one more
getLogger("identifier").log(Level.SEVERE, "Log to three files");
Configure logging once and after that you can get reference to logger via java.util.loggingLogger.getLogger. Overview from Sun gives more ideas how to configure logging via properties files.

Categories

Resources