0

The following code creates a directory with name as current date and stores the log files in that directory. But next the log files of the next days keep are also stored in same directory. I want create a new directory every day having the same name as current date and store new log file in it.

private static Date dir1 = new java.util.Date(System.currentTimeMillis());
private static Date dir = new java.util.Date(System.currentTimeMillis());
private static String baseDir1 = "/home/gaurav/flinklogs/";
private static String newDir1 = createDateBasedDirectory(baseDir1, dir1);

private static FileHandler fh1;

static {
    try {
        fh1 = new FileHandler(newDir1 + "/data.log", 0, 1, true);
    } catch (IOException | SecurityException e) {

    }
}

public static void main(String args[]) throws Exception {
    Logger logger = Logger.getLogger("MyLog");
    // This block configure the logger with handler and formatter
    logger.addHandler(fh);

    SimpleFormatter formatter = new SimpleFormatter();
    fh.setFormatter(formatter);

    // the following statement is used to log any messages
    logger.info(e.getMessage());
}

public static String createDateBasedDirectory(String baseDirectory, Date argDate) {
    String newDir = null;
    if (baseDirectory != null && argDate != null) {
        try {
            String format = "yyyy-MM-dd";
            DateFormat dateFormatter = new SimpleDateFormat(format);
            String date = dateFormatter.format(argDate);

            // check if the directory exists:
            String todaysLogDir = baseDirectory + "\\" + date;

            Path todaysDirectoryPath = Paths.get(todaysLogDir);
            // and check if this Path exists
            if (Files.exists(todaysDirectoryPath)) {
                // if present, just return it in order to write (into) a log file there
                return todaysDirectoryPath.toUri().toString();
            } else {
                newDir = baseDirectory + date;
                new File(newDir).mkdir();
                return newDir.toString();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    return newDir;
}
aboger
  • 2,214
  • 6
  • 33
  • 47
Gaurav
  • 173
  • 1
  • 13
  • You should probably take a look at log4j or logback. These frameworks can easily be configured to achieve log rotation as you described it – Rea Sand Jun 22 '18 at 06:00
  • @Rea Sand Thanks but i have tried it...there are so many problems with log4j.properpties file and other thing... i want to do it this way only.. any solution with this?? – Gaurav Jun 22 '18 at 06:14
  • Try [*Logback*](https://logback.qos.ch) a modern logging framework by the man who originally made *log4j*. The *Logback* project directly implements the [*slf4j*](https://www.slf4j.org) façade API. – Basil Bourque Jun 22 '18 at 06:26

2 Answers2

2

Your date-time handling could use some help.

First, you are using troublesome old date-time classes (Date, SimpleDateFormat) that were supplanted years ago by the java.time classes. And you are ignoring the crucial issue of time zone (discussed further down below).

  • java.util.Date is replaced by java.time.Instant
  • SimpleDateFormat is replaced by java.time.format.DateTimeFormatter

Your desired format of YYYY-MM-DD is defined by the ISO 8601 standard. The java.time classes use the standard formats by default when generating/parsing strings. So no need to specify a formatting pattern.

Instant

new java.util.Date(System.currentTimeMillis())

That code of yours is redundant. Simply calling new Date() has the same effect, capturing a count of the number of milliseconds since the epoch reference of first moment of 1970 UTC, 1970-01-01T00:00:00Z.

Modern code replaces Date with Instant. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).

Instant instant = Instant.now() ;  // Capture the current moment in UTC.

But we really do not need Instant for your Question. Use LocalDate instead.

LocalDate

The LocalDate class represents a date-only value without time-of-day and without time zone.

A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.

If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment during runtime(!), so your results may vary. Better to specify your [desired/expected time zone][2] explicitly as an argument.

Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).

ZoneId z = ZoneId.of( "America/Montreal" ) ;  
LocalDate today = LocalDate.now( z ) ;

If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the JVM’s current default is applied implicitly. Better to be explicit, as the default may be changed at any moment during runtime by any code in any thread of any app within the JVM.

ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.

Or you might choose to always use UTC, as the people do running Stack Overflow. Notice how your daily reputation points roll-over, for example around 4 PM if on west coast US time.

LocalDate today = LocalDate.now( ZoneOffset.UTC ) ;

String

To generate a String in standard ISO 8601 format, simply call LocalDate::toString.

String output = today.toString() ; 

Logging framework

As other suggested, you should not use your valuable time re-inventing a logging framework to rollover folders daily. Any decent logging framework can do that for you.

In particular, I suggest you consider first using the slf4j façade API. In your code where you want to make send info to logs, make calls to slf4j. Behind slf4j sits any of many different logging frameworks. You can later switch out one logging framework for another without changing your app’s code.

If not already using a logging framework, adopt Logback. The Logback project is a direct implementation of the slf4j API. So no need for an adapter.

Both slf4j and Logback were written by the same man who invented log4j. So he has much experience in this field.


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
1

The problem here is you have declared all your variables as static and performing file handler assignment in static block as well.

static {

        try {

            fh1 = new FileHandler(newDir1 + "/data.log", 0, 1, true);

        } catch (IOException | SecurityException e) {

        }
    }

So, once your program starts it initialises everything and then next day there is no re-initialisation as the program is already running from previous day. You need to reassign the file-handler with change of day.

Also, may I suggest having a look at log4j as you can easily configure it as per your requirement.

skelwa
  • 575
  • 1
  • 7
  • 17
  • thanks, how do i reassign the file-handler with change of day – Gaurav Jun 22 '18 at 06:26
  • Try with a cron job that runs daily at midnight and reassigns the new handler. – skelwa Jun 22 '18 at 06:32
  • Sorry will you elaborate it plz...how to use cron job – Gaurav Jun 22 '18 at 06:47
  • 1
    If you are not sure how cron jobs work, i would highly discourage you from writing your own logging framework. Please try to re-use existing frameworks as others suggested that will do this job for you already. – skelwa Jun 22 '18 at 06:56
  • i have used log4j but there is problem in that when i run my jar file on server it is unable to find the log4j.properties file, thats why i am using this.... – Gaurav Jun 22 '18 at 11:53
  • @Gaurav your log4j config should reside in `src/main/resources` to be picked up automatically by the framework. But you may (and probably have to) provide any other path when starting you application via `-Dlog4j.configurationFile` (or smth similar). – Rea Sand Jun 25 '18 at 22:18
  • @Rea Sand suppose i have created a jar file of my application and i want to run it on server then where should i provide this -Dlog4j.configurationFile?? – Gaurav Jun 26 '18 at 05:33
  • @Gaurav You should consider consulting the [official log4j documentation](https://logging.apache.org/log4j/2.x/manual/configuration.html) as it contains examples for the different usecases, including yours. For you to get started though: put your log4j configuration file at smth like `/etc/` or `/usr/local/etc/` and reference the config like so: `java -Dlog4j.configurationFile=/path/to/log4j2.xml -jar /path/to/your/jar` – Rea Sand Jun 27 '18 at 09:43