Added fallback for host address in logging 05/45205/3
authorvempo <vitaliy.emporopulo@amdocs.com>
Sun, 29 Apr 2018 15:34:48 +0000 (18:34 +0300)
committerAvi Gaffa <avi.gaffa@amdocs.com>
Wed, 2 May 2018 05:44:36 +0000 (05:44 +0000)
In some cases Java fails to get local hostname on Linux.
Added a workaround that in such cases gets at least some
meaningful host identification.

Change-Id: Icf9b84ec6a0d6fbcbcb6a1578689b3e3be00261b
Issue-ID: SDC-1275
Signed-off-by: vempo <vitaliy.emporopulo@amdocs.com>
openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/context/HostAddressCache.java
openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/GlobalContextProvider.java
openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/context/HostAddressCacheTest.java

index afe2b0b..0930888 100644 (file)
 package org.openecomp.sdc.logging.context;
 
 import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
 import java.net.UnknownHostException;
+import java.util.Enumeration;
+import java.util.Optional;
 
 /**
  * Holds a reference to local host address as returned by Java runtime. A value of host address will be cached for the
@@ -28,7 +32,7 @@ import java.net.UnknownHostException;
  * @author evitaliy
  * @since 26 Mar 2018
  */
-@SuppressWarnings({"UseOfSystemOutOrSystemErr", "CallToPrintStackTrace", "squid:S106", "squid:S1148"})
+@SuppressWarnings({"UseOfSystemOutOrSystemErr", "CallToPrintStackTrace", "squid:S106", "squid:S1148", "squid:S1166"})
 public class HostAddressCache {
 
     private static final long DEFAULT_REFRESH_INTERVAL = 60000L; // 1 min
@@ -54,16 +58,16 @@ public class HostAddressCache {
      *
      * @return local host address or <code>null</code> if it could not be read for some reason
      */
-    public synchronized InetAddress get() {
+    public synchronized Optional<InetAddress> get() {
 
         long current = System.currentTimeMillis();
         if (current - cachedAddress.lastUpdated < interval) {
-            return cachedAddress.address;
+            return Optional.ofNullable(cachedAddress.address);
         }
 
-        InetAddress address = read();
+        InetAddress address = read(); // register the attempt even if null, i.e. failed to get a meaningful address
         cachedAddress = new CacheEntry(current, address);
-        return address;
+        return Optional.ofNullable(address);
     }
 
     private InetAddress read() {
@@ -71,9 +75,59 @@ public class HostAddressCache {
         try {
             return InetAddress.getLocalHost();
         } catch (UnknownHostException e) {
+            System.err.println(
+                    "[WARNING] Failed to get local host address. Using a fallback. If you are on Linux, make sure "
+                            + "/etc/hosts contains the host name of your machine, "
+                            + "e.g. '127.0.0.1 localhost my-host.example.com'.");
+
+            e.printStackTrace(); // can't really use logging
+            return getFallbackLocalHost();
+        }
+    }
+
+    private InetAddress getFallbackLocalHost() {
+
+        try {
+
+            Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
+
+            while (networkInterfaces.hasMoreElements()) {
+
+                InetAddress address = getAddress(networkInterfaces.nextElement());
+                if (address != null) {
+                    return address;
+                }
+            }
+
+            return null;
+
+        } catch (SocketException e) {
             e.printStackTrace(); // can't really use logging
-            return null; // let register the attempt even if failed
+            return null;
+        }
+    }
+
+    private InetAddress getAddress(NetworkInterface networkInterface) throws SocketException {
+
+        if (networkInterface.isLoopback() || networkInterface.isUp()) {
+            return null;
         }
+
+        Enumeration<InetAddress> interfaceAddresses = networkInterface.getInetAddresses();
+        while (interfaceAddresses.hasMoreElements()) {
+
+            InetAddress address = interfaceAddresses.nextElement();
+            if (isHostAddress(address)) {
+                return address;
+            }
+        }
+
+        return null;
+    }
+
+    private boolean isHostAddress(InetAddress address) {
+        return !address.isLoopbackAddress() && !address.isAnyLocalAddress() && !address.isLinkLocalAddress()
+                       && !address.isMulticastAddress();
     }
 
     private static class CacheEntry {
index 97cac2e..f6e933d 100644 (file)
@@ -19,6 +19,7 @@ package org.openecomp.sdc.logging.slf4j;
 import java.net.InetAddress;
 import java.util.EnumMap;
 import java.util.Map;
+import java.util.Optional;
 import org.openecomp.sdc.logging.context.HostAddressCache;
 import org.openecomp.sdc.logging.context.InstanceId;
 
@@ -38,11 +39,11 @@ class GlobalContextProvider implements ContextProvider {
         Map<ContextField, String> values = new EnumMap<>(ContextField.class);
         values.put(ContextField.INSTANCE_ID, InstanceId.get());
 
-        InetAddress hostAddress = HOST_ADDRESS_CACHE.get();
-        if (hostAddress != null) {
-            values.put(ContextField.SERVER, hostAddress.getHostName());
-            values.put(ContextField.SERVER_IP_ADDRESS, hostAddress.getHostAddress());
-        }
+        Optional<InetAddress> hostAddress = HOST_ADDRESS_CACHE.get();
+        hostAddress.ifPresent(address -> {
+            values.put(ContextField.SERVER, address.getHostName());
+            values.put(ContextField.SERVER_IP_ADDRESS, address.getHostAddress());
+        });
 
         return values;
     }
index 6d7a636..f75b634 100644 (file)
@@ -16,7 +16,7 @@
 
 package org.openecomp.sdc.logging.context;
 
-import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
 
 import java.net.InetAddress;
 import java.net.UnknownHostException;
@@ -37,7 +37,7 @@ public class HostAddressCacheTest extends PowerMockTestCase {
 
     @Test
     public void hostAddressIsAlwaysPopulated() {
-        assertNotNull(new HostAddressCache().get());
+        assertTrue(new HostAddressCache().get().isPresent());
     }
 
     @Test