This may actually be a bug in the JVM (Sun/Oralce 1.7.0) or the Linux
distribution TZ data files (Debian 6.0.4), but it is impacting OpenNMS.

After upgrading to 1.10 we noticed all outages were starting at 20hrs.
The time in the webUI, the time on the machine, the time returned by
Date() in java and the time returned by now() in postgresql were all
correct.

Looking deeper the times in the outages tables were all out by 20hrs.

So I decided to investigate where these times were coming from.

Java is not my native language and I have not looked at the OpenNMS
internals before, so apologies if this is wrong or slightly off somewhere:

It appears opennms uses Date() to get the current local time at the time
of an outage/event and then converts it to GMT to store in memory, but
is converted back to local time when it used (or written to the outages
table in the DB).

Looking at src/main/java/org/opennms/netmgt/EventConstants.java there is
the following two functions (erm.. methods..) that the time is passed
through (sorry pasting this in email is going to garble the formating):

1133     static final ThreadLocal<DateFormat> FORMATTER_LONG_GMT = new
ThreadLocal<DateFormat>() {
1134         protected synchronized DateFormat initialValue() {
1135             final DateFormat formatter =
DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.LONG);
1136             formatter.setLenient(true);
1137             formatter.setTimeZone(TimeZone.getTimeZone("GMT"));
1138             return formatter;
1139         }
1140     };
1141

and

1104     static final ThreadLocal<DateFormat> FORMATTER_LONG = new
ThreadLocal<DateFormat>() {
1105         protected synchronized DateFormat initialValue() {
1106             final DateFormat formatter =
DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.LONG);
1107             formatter.setLenient(true);
1108             return formatter;
1109         }
1110     };


So, constructing a small test program like the following:

import java.util.*;
import java.text.DateFormat;

public class DateTest {
   static final ThreadLocal<DateFormat> FORMATTER_LONG_GMT = new
ThreadLocal<DateFormat>() {
        protected synchronized DateFormat initialValue() {
            final DateFormat formatter =
DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.LONG);
            formatter.setLenient(true);
            formatter.setTimeZone(TimeZone.getTimeZone("GMT"));
            return formatter;
        }
    };


     static final ThreadLocal<DateFormat> FORMATTER_LONG = new
ThreadLocal<DateFormat>() {
         protected synchronized DateFormat initialValue() {
             final DateFormat formatter =
DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.LONG);
             formatter.setLenient(true);
             return formatter;
         }
     };

  public static void main(String[] args) throws Exception {
    System.out.println("Date (Local):  " + new Date());
    String timestr = FORMATTER_LONG_GMT.get().format(new Date());
    System.out.println("Date (GMT): " + timestr);
    System.out.println("Date (Local): " +
FORMATTER_LONG.get().parse(timestr));
  }
}

And running it, yields some very interesting results.
It appears that in our default locale (we are in Sydney), the conversion
from GMT->Local time is not adjusting for the timezone.

Running it with LANG=C the results are as expected.

Observe:

gmollett@onms:~$ locale
LANG=en_AU.UTF-8
LANGUAGE=
LC_CTYPE="en_AU.UTF-8"
LC_NUMERIC="en_AU.UTF-8"
LC_TIME="en_AU.UTF-8"
LC_COLLATE="en_AU.UTF-8"
LC_MONETARY="en_AU.UTF-8"
LC_MESSAGES="en_AU.UTF-8"
LC_PAPER="en_AU.UTF-8"
LC_NAME="en_AU.UTF-8"
LC_ADDRESS="en_AU.UTF-8"
LC_TELEPHONE="en_AU.UTF-8"
LC_MEASUREMENT="en_AU.UTF-8"
LC_IDENTIFICATION="en_AU.UTF-8"
LC_ALL=

gmollett@onms:~$ java DateTest
Date (Local):  Thu Apr 12 14:35:06 EST 2012
Date (GMT): Thursday, 12 April 2012 4:35:06 AM
Date (Local): Thu Apr 12 04:35:06 EST 2012

And:

gmollett@onms:~$ export LANG=C
gmollett@onms:~$ locale
LANG=C
LANGUAGE=
LC_CTYPE="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_COLLATE="C"
LC_MONETARY="C"
LC_MESSAGES="C"
LC_PAPER="C"
LC_NAME="C"
LC_ADDRESS="C"
LC_TELEPHONE="C"
LC_MEASUREMENT="C"
LC_IDENTIFICATION="C"
LC_ALL=

gmollett@onms:~$ java DateTest
Date (Local):  Thu Apr 12 14:37:35 EST 2012
Date (GMT): Thursday, April 12, 2012 4:37:35 AM GMT
Date (Local): Thu Apr 12 14:37:35 EST 2012


And sure enough, running OpenNMS with LANG=C added to the environment,
everything works normally again, and the times in the outages table are
correct.

I will leave this with you guys, please let me know if you want any more
information or if there is anything more I can do to help.

Thanks,
Garth.

------------------------------------------------------------------------------
For Developers, A Lot Can Happen In A Second.
Boundary is the first to Know...and Tell You.
Monitor Your Applications in Ultra-Fine Resolution. Try it FREE!
http://p.sf.net/sfu/Boundary-d2dvs2
_______________________________________________
Please read the OpenNMS Mailing List FAQ:
http://www.opennms.org/index.php/Mailing_List_FAQ

opennms-devel mailing list

To *unsubscribe* or change your subscription options, see the bottom of this 
page:
https://lists.sourceforge.net/lists/listinfo/opennms-devel

Reply via email to