Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8509525
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 11, 20262026-06-11T03:27:28+00:00 2026-06-11T03:27:28+00:00

Disclaimer: I apologize that this question is so long. I have added code as

  • 0

Disclaimer: I apologize that this question is so long. I have added code as I have explored suggestions made here and done additional research since asking my original question.

I am working on an open source project in Java and want to implement logging in my application to facilitate bug tracking and debugging when/if users report problems with the app. I am looking at the java.util.logging package from the standard Java API. I’ve already added some logging code when exceptions are caught. For example, I have

Logger.getLogger(FindCardsPanel.class.getName()).log(Level.SEVERE, "Storage I/O error", ex);

The only difference in each line of code is the class name and the message string.

I have read that the proper way to use a logger is using one for each class name string. This makes a little bit of sense since it allows a lot of flexibility in filtering log messages.

My current problem is that all of the logging messages currently go to stderr. I need to write them to a file instead. I have found the FileHandler class which facilitates this. However, since I have dozens of classes, I have dozens of logger names. Do I need to add the FileHandler to each of these? That seems like it will take a lot of work, especially when I decide to add another class to my code base.

I understand that there is some kind of tree hierarchy of loggers. Does this happen automatically? If not, how do I create my own hierarchy? And whether or not it’s automatic, where in the hierarchy do I add my FileHandler so that all logging goes to the same file?

Edit:

Based on the link given by @spdaley, I have created the following SSCCE:

LoggingSSCCE.java:

package loggingsscce;

import java.io.IOException;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;

public class LoggingSSCCE {
    private static String LOG_FILE_NAME = "loggingsscce.log";

    public static void main(String[] args) throws IOException {
        LoggingSSCCE.initLogger();

        LogTest lta = new LogTestA();
        lta.doLog();

        LogTest ltb = new LogTestB();
        ltb.doLog();
    }

    private static void initLogger() throws IOException {
        FileHandler handler = null;

        try {
            boolean append = true;
            handler = new FileHandler(LoggingSSCCE.LOG_FILE_NAME, append);
            handler.setFormatter(new SimpleFormatter());

            Logger logger = Logger.getLogger("");
            logger.setLevel(Level.ALL);
            logger.addHandler(handler);
        } finally {
            handler.close();
        }
    }
}

LogTest.java:

package loggingsscce;

interface LogTest {
    public void doLog();
}

LogTestA.java:

package loggingsscce;

import java.util.logging.Level;
import java.util.logging.Logger;

class LogTestA implements LogTest {
    @Override
    public void doLog() {
        Logger.getLogger(LogTestA.class.getName()).log(Level.INFO, "LogTestA.doLog()");
    }
}

LogTestB.java:

package loggingsscce;

import java.util.logging.Level;
import java.util.logging.Logger;

class LogTestB implements LogTest {
    @Override
    public void doLog() {
        Logger.getLogger(LogTestA.class.getName()).log(Level.INFO, "LogTestB.doLog()");
    }
}

When I run this in NetBeans, the output window shows

run:
Sep 09, 2012 5:36:56 PM loggingsscce.LogTestA doLog
INFO: LogTestA.doLog()
Sep 09, 2012 5:36:56 PM loggingsscce.LogTestB doLog
INFO: LogTestB.doLog()
BUILD SUCCESSFUL (total time: 0 seconds)

but the “loggingsscce.log” file is empty.

So what am I missing?

Another edit:

I found an example at http://onjava.com/pub/a/onjava/2002/06/19/log.html?page=2 which I modified:

import java.io.IOException;
import java.util.logging.FileHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.LogManager;
import java.util.logging.SimpleFormatter;

public class HelloWorld {
  private static Logger theLogger = Logger.getLogger(HelloWorld.class.getName());

  public static void main( String[] args ) throws IOException {
    Logger rootLogger = Logger.getLogger("");
    Handler handler = new FileHandler("hello.log");

    handler.setFormatter(new SimpleFormatter());
    rootLogger.addHandler(handler);

    // The root logger's handlers default to INFO. We have to
    // crank them up. We could crank up only some of them
    // if we wanted, but we will turn them all up.
    Handler[] handlers = Logger.getLogger( "" ).getHandlers();
    for ( int index = 0; index < handlers.length; index++ ) {
      handlers[index].setLevel( Level.FINE );
    }

    // We also have to set our logger to log finer-grained
    // messages
    theLogger.setLevel(Level.FINE);
    HelloWorld hello = new HelloWorld("Hello world!");
    hello.sayHello();
  }

  private String theMessage;

  public HelloWorld(String message) {
    theMessage = message;
  }

  public void sayHello() {
    theLogger.fine("Hello logging!");
    System.err.println(theMessage);
  }
}

This produces the following output from the command-line:

lib_lab_ref08@LBP-REF87XVMDP1 /e/devel/src/java/stackoverflow
$ javac HelloWorld.java

lib_lab_ref08@LBP-REF87XVMDP1 /e/devel/src/java/stackoverflow
$ java HelloWorld
Sep 09, 2012 6:13:33 PM HelloWorld sayHello
FINE: Hello logging!
Hello world!

lib_lab_ref08@LBP-REF87XVMDP1 /e/devel/src/java/stackoverflow
$ cat hello.log
Sep 09, 2012 6:13:33 PM HelloWorld sayHello
FINE: Hello logging!

lib_lab_ref08@LBP-REF87XVMDP1 /e/devel/src/java/stackoverflow
$

So this single class example works just fine. What is the difference when I have multiple classes in multiple files as in my previous code?

Modifications to LoggingSSCCE class:

I added a static field:

private static FileHandler HANDLER = null;

And changed the initLogger() method:

private static void initLogger() throws IOException {
    LoggingSSCCE.HANDLER = new FileHandler(LoggingSSCCE.LOG_FILE_NAME);
    LoggingSSCCE.HANDLER.setFormatter(new SimpleFormatter());

    Logger logger = Logger.getLogger("");
    logger.setLevel(Level.ALL);
    logger.addHandler(LoggingSSCCE.HANDLER);
}

This works great with the following contents of “loggingsscce.log”:

Sep 09, 2012 6:50:16 PM loggingsscce.LogTestA doLog
INFO: LogTestA.doLog()
Sep 09, 2012 6:50:16 PM loggingsscce.LogTestB doLog
INFO: LogTestB.doLog()

I’m still having trouble making this all work in my more complicated Swing project. I suspect my FileHandler is being closed, perhaps by the garbage collector?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-11T03:27:30+00:00Added an answer on June 11, 2026 at 3:27 am

    Edit:

    The problem in your original code is that you’re closing the handler early.

    Original Text:

    I see two problems with your (original) code:

    Problem one, you’re calling getLogger("") in your init, but calling getLogger(xxx.class.getName()) in your implementations. Each of those loggers is a different logger, and you’re only setting the file handler for the "" one.

    Problem two, which was being masked by problem one, you’re closing the handler early.

    Here’s something you can try for multiple classes in one file:

    LoggingSSCCE.java:

    package loggingsscce;
    
    import java.io.IOException;
    import java.util.Hashtable;
    import java.util.logging.FileHandler;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    
    public class LoggingSSCCE {
        private static String LOG_FILE_NAME = "loggingsscce.log";
        Hashtable<String, Logger> loggers = new Hastable<String, Logger>();
        FileHandler handler = null;
    
        public static void main(String[] args) throws IOException {
    
            LogTest lta = new LogTestA();
            lta.doLog();
    
            LogTest ltb = new LogTestB();
            ltb.doLog();
        }
    
        public static Logger getLogger(String loggerName) throws IOException {
            if ( loggers.get(loggerName) != null )
                return loggers.get(loggerName);
    
            if ( handler == null ) {
                boolean append = true;
                handler = new FileHandler(LoggingSSCCE.LOG_FILE_NAME, append);
                handler.setFormatter(new SimpleFormatter());
            }
    
            Logger logger = Logger.getLogger(loggerName);
            logger.setLevel(Level.ALL);
            logger.addHandler(handler);
            loggers.put(loggerName, logger);
            return logger;
        }
    }
    

    LogTest.java:

    package loggingsscce;
    
    interface LogTest {
        public void doLog();
    }
    

    LogTestA.java:

    package loggingsscce;
    
    import java.util.logging.Level;
    import java.util.logging.Logger;
    
    class LogTestA implements LogTest {
        @Override
        public void doLog() {
            LoggingSSCCE.getLogger(LogTestA.class.getName()).log(Level.INFO, "LogTestA.doLog()");
        }
    }
    

    LogTestB.java:

    package loggingsscce;
    
    import java.util.logging.Level;
    import java.util.logging.Logger;
    
    class LogTestB implements LogTest {
        @Override
        public void doLog() {
            LoggingSSCCE.getLogger(LogTestB.class.getName()).log(Level.INFO, "LogTestB.doLog()");
        }
    }
    

    If you want this to work for one file per class, or some other criteria, simply modify LoggingSSCCE.getLogger to compute an appropriate file name for each case.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Disclaimer: I apologize if this is not an appropriate question to ask here... I
Disclaimer, I'm not a PHP programmer, so you might find this question trivial. That's
( Disclaimer: This question is not specific to ASP.NET) I have a control which
Disclaimer: i have searched genericly (Google) and here for some information on this topic,
Disclaimer: this question may not have practical value, it's more of a puzzle/curiosity question.
Disclaimer: I know this type of question has been asked here before, I just
Disclaimer This question is a repost. I originally asked it here . While there
Disclaimer: this question is driven by my personal curiosity more than an actual need
Disclaimer: JS novice I have a JS widget that depends on JQuery. The widget's
Disclaimer : this is a strange issue that only happens in a Kindle Fire

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.