Question: Within a java application, I have several Classes and Threads here and there. I would like them all to write their logs to one single file. How can I achieve that?

Also here's some more questions:

1. Do I receive the same instance of a logger if I define the same name for them even in different classes. To be clear, are the following two loggers the same:

```
class MyClass1 {
    Logger logger1 = Logger.getLogger("theSameName");
}
class MyClass2{
    Logger logger2 = Logger.getLogger("theSameName");
}

```
2. What happens if I define two of the `FileHandler` in two separate Threads that have the same file name?
Do both of them write to the same file?
If yes, what happens if the file is already opened by the first one, when the second one tries to open and write to it?
3. What happens if I try to add the same FielHandler to a logger more than once as in:

```
logger.addHandler(myFileHandler); // in Thread one
...
logger.addHandler(myFileHandler); // in Thread two

```

Will I receive a `RuntimeException` because of the two `FileHandler` may try to open the same file simultaneously?

I'm using `java-util-logging` not `log4j`.

Answer: 
Make a [singleton](https://en.wikipedia.org/wiki/Singleton_pattern) log class so any other class or thread tries creating a copy of it, will actually be using the same instance.

Example implementation with `java.util.logging`:

```
public class LogMe {        
    private static LogMe logMe;
    private static Logger logger;    
    private static FileHandler fh;
    private static Formatter sf;

    public LogMe() {
        //Make this class a singleton
        if (logMe != null) {
            return;
        }

        //Create the log file            
        try {
            fh = new FileHandler("../xyz/LogFile.log");
        } catch (Exception e) {
            e.printStackTrace();
        }

        sf = new SimpleFormatter();
        fh.setFormatter(sf);            
        logger.addHandler(fh);

        //Part of making this class a singleton
        logger = Logger.getLogger("LogMe");
        logMe = this;        
    }

    public Logger getLogger() {
        return LogMe.logger;
    }
}

```

Then in your classes you will be using it like this:

```
class MyClass1 {
    LogMe logMe1 = new LogMe();
    Logger logger2 = logMe1.getLogger();
    logger.info("X 01");
}

class MyClass2 {
    LogMe logMe2 = new LogMe();
    Logger logger2 = logMe2.getLogger();
    logger.info("X 02");
}

```

Notice that whatever you name the `LogMe` and its `Logger` in your classes it won't have any effect because they are referencing the same instance of `LogMe` and its `Logger`

Example output in the log file will look something like this:

```
Oct 1, 2015 10:43:47 AM 
INFO: X 01 
Oct 1, 2015 10:43:47 AM 
INFO: X 02

```

Notice that the order of these log lines will depends on the order of execution of your classes. Also you won't need any synchronization, quoting JavaDoc of Logger:

> 
> All methods on Logger are multi-thread safe.
> 
> 
>
```
package javaloggers;

import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
//singleton class logger wrapper
public class LogWrap {
    public static final Logger aLogger = Logger.getLogger("myLogger");
    private static LogWrap instance = null;
    public static LogWrap getInstance(){
        if(instance==null){
            getLoggerReady();
            instance = new LogWrap();
        }
        return instance;
    }
    private static void getLoggerReady(){
        try{
            FileHandler fh = new FileHandler("test-log.txt");
            fh.setFormatter(new SimpleFormatter());
            aLogger.addHandler(fh);
            aLogger.setUseParentHandlers(false);
            aLogger.setLevel(Level.ALL);
        } catch(Exception e){
            System.out.print("Error: Logger creation issue: "+e);
        }           
    }
}
class test {
    public static void main(String args[]){
        //usage
        LogWrap logWrap = LogWrap.getInstance();
        logWrap.aLogger.severe( "Hello world!" );
    }
}

```