2 * Copyright © 2016-2017 European Support Limited
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package org.openecomp.sdc.logging;
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.io.InputStreamReader;
22 import java.net.InetAddress;
23 import java.net.UnknownHostException;
24 import java.nio.charset.StandardCharsets;
25 import java.util.Properties;
26 import java.util.UUID;
27 import java.util.concurrent.atomic.AtomicLong;
28 import java.util.prefs.BackingStoreException;
29 import java.util.prefs.Preferences;
32 * Collect information the is required for logging, but should not concern the business code of an application. For
33 * example, host name and IP address.
38 @SuppressWarnings({"UseOfSystemOutOrSystemErr", "CallToPrintStackTrace", "squid:S106", "squid:S1148"})
39 public class GlobalLoggingContext {
41 private static final String APPLICATION_ID_KEY = "ApplicationId";
43 private static final String CONFIGURATION_RESOURCE = "META-INF/logging/logger.properties";
45 @SuppressWarnings("squid:S1075")
46 private static final String ID_PREFERENCES_PATH = "/logging/instance/uuid";
48 private static final String APP_DISTINGUISHER_KEY = "app.distinguisher";
50 // should be cashed to avoid low-level call, but with a timeout to account for IP or FQDN changes
51 private static final HostAddressCache HOST_ADDRESS = new HostAddressCache();
53 private static final String DISTINGUISHER;
55 private static final String APPLICATION_ID;
57 private static final String INSTANCE_ID;
60 APPLICATION_ID = System.getProperty(APPLICATION_ID_KEY);
61 DISTINGUISHER = readDistinguisher();
62 INSTANCE_ID = readInstanceId();
65 private GlobalLoggingContext() { /* prevent instantiation */ }
67 public static String getApplicationId() {
68 return APPLICATION_ID;
72 * A distinguisher to allow separation of logs created by applications running with the same configuration, but
73 * different class-loaders. For instance, when multiple web application are running in the same container and their
74 * logger configuration is passed at the JVM level.
76 * @return application distinguisher defined in a properties file
78 public static String getDistinguisher() {
83 * A unique ID of the logging entity. Is useful to distinguish between different nodes of the same application. It
84 * is assumed, that the node can be re-started, in which case the unique ID must be retained.
86 * @return unique logging entity ID
88 public static String getInstanceId() {
93 * Local host address as returned by Java runtime. A value of host address will be cached for the interval specified
94 * in {@link HostAddressCache#REFRESH_TIME}
96 * @return local host address, may be null if could not be read for some reason
98 public static InetAddress getHostAddress() {
99 return HOST_ADDRESS.get();
102 private static String readInstanceId() {
104 String appId = System.getProperty(APPLICATION_ID_KEY);
105 String key = ID_PREFERENCES_PATH + (appId == null ? "" : "/" + appId);
109 // By default, this will be ~/.java/.userPrefs/prefs.xml
110 final Preferences preferences = Preferences.userRoot();
111 String existingId = preferences.get(key, null);
112 if (existingId != null) {
116 String newId = UUID.randomUUID().toString();
117 preferences.put(key, newId);
121 } catch (BackingStoreException e) {
123 // don't fail if there's a problem to use the store for some unexpected reason
124 return UUID.randomUUID().toString();
128 private static String readDistinguisher() {
131 Properties properties = loadConfiguration();
132 return properties.getProperty(APP_DISTINGUISHER_KEY, "");
133 } catch (IOException e) {
134 e.printStackTrace(); // can't write to a log
139 private static Properties loadConfiguration() throws IOException {
141 Properties properties = new Properties();
143 try (InputStream is = Thread.currentThread().getContextClassLoader()
144 .getResourceAsStream(CONFIGURATION_RESOURCE)) {
150 try (InputStreamReader reader = new InputStreamReader(is, StandardCharsets.UTF_8)) {
151 properties.load(reader);
157 private static class HostAddressCache {
159 private static final long REFRESH_TIME = 60000L;
161 private final AtomicLong lastUpdated = new AtomicLong(0L);
162 private InetAddress hostAddress;
164 public InetAddress get() {
166 long current = System.currentTimeMillis();
167 if (current - lastUpdated.get() > REFRESH_TIME) {
169 synchronized (this) {
172 // set now to register the attempt even if failed
173 lastUpdated.set(current);
174 hostAddress = InetAddress.getLocalHost();
175 } catch (UnknownHostException e) {
176 e.printStackTrace(); // can't really use logging