2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.openecomp.aai.logging;
23 import java.net.InetAddress;
24 import java.net.UnknownHostException;
25 import java.util.HashMap;
26 import java.util.Iterator;
28 import java.util.UUID;
29 import java.util.concurrent.TimeUnit;
31 import org.json.JSONArray;
32 import org.json.JSONException;
33 import org.json.JSONObject;
36 import com.att.eelf.configuration.EELFLogger;
37 import com.att.eelf.configuration.EELFManager;
39 public class LoggingContext {
41 public enum StatusCode {
46 private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(LoggingContext.class);
48 private static final String PREVIOUS_CONTEXTS_KEY = "_PREVIOUS_CONTEXTS";
50 //ECOMP Specific Log Event Fields
51 public static enum LoggingField {
52 START_TIME("startTime"),
53 REQUEST_ID("requestId"),
54 SERVICE_INSTANCE_ID("serviceInstanceId"),
55 SERVER_NAME("serverName"),
56 SERVICE_NAME("serviceName"),
57 PARTNER_NAME("partnerName"),
58 STATUS_CODE("statusCode"),
59 RESPONSE_CODE("responseCode"),
60 RESPONSE_DESCRIPTION("responseDescription"),
61 INSTANCE_UUID("instanceUUID"),
63 SERVER_IP_ADDRESS("serverIpAddress"),
64 ELAPSED_TIME("elapsedTime"),
66 CLIENT_IP_ADDRESS("clientIpAddress"),
68 PROCESS_KEY("processKey"),
69 CUSTOM_FIELD_1("customField1"),
70 CUSTOM_FIELD_2("customField2"),
71 CUSTOM_FIELD_3("customField3"),
72 CUSTOM_FIELD_4("customField4"),
74 //ECOMP Specific Metric Log Event Fields
75 TARGET_ENTITY("targetEntity"),
77 //A&AI Specific Log Event Fields
78 COMPONENT("component"),
79 STOP_WATCH_START("stopWatchStart");
81 private final String text;
83 private LoggingField(final String text) {
87 public String toString() {
93 public static void init() {
94 LoggingContext.clear();
95 LoggingContext.startTime();
96 LoggingContext.server();
97 LoggingContext.serverIpAddress();
100 private static void startTime() {
101 MDC.put(LoggingField.START_TIME.toString(), LogFormatTools.getCurrentDateTime());
104 public static UUID requestId() {
105 final String sUuid = MDC.get(LoggingField.REQUEST_ID.toString());
107 if (sUuid == null) return null;
109 return UUID.fromString(sUuid);
112 public static void requestId(UUID requestId) {
113 MDC.put(LoggingField.REQUEST_ID.toString(), requestId.toString());
116 public static void requestId(String requestId) {
118 MDC.put(LoggingField.REQUEST_ID.toString(), UUID.fromString(requestId).toString());
119 } catch (IllegalArgumentException e) {
120 final UUID generatedRequestUuid = UUID.randomUUID();
121 MDC.put(LoggingField.REQUEST_ID.toString(), generatedRequestUuid.toString());
122 LOGGER.warn("Unable to use UUID " + requestId + " (Not formatted properly). Using generated UUID=" + generatedRequestUuid);
126 public static void serviceInstanceId(String serviceInstanceId) {
127 MDC.put(LoggingField.SERVICE_INSTANCE_ID.toString(), serviceInstanceId);
130 public static void serverName(String serverName) {
131 MDC.put(LoggingField.SERVER_NAME.toString(), serverName);
134 public static void serviceName(String serviceName) {
135 MDC.put(LoggingField.SERVICE_NAME.toString(), serviceName);
138 public static void partnerName(String partnerName) {
139 MDC.put(LoggingField.PARTNER_NAME.toString(), partnerName);
142 public static void statusCode(LoggingContext.StatusCode statusCode) {
143 MDC.put(LoggingField.STATUS_CODE.toString(), statusCode.toString());
146 public static String responseCode() {
147 return (String) MDC.get(LoggingField.RESPONSE_CODE.toString());
150 public static void responseCode(String responseCode) {
151 MDC.put(LoggingField.RESPONSE_CODE.toString(), responseCode);
154 public static void responseDescription(String responseDescription) {
155 MDC.put(LoggingField.RESPONSE_DESCRIPTION.toString(), responseDescription);
158 public static Object instanceUuid() {
159 return UUID.fromString(MDC.get(LoggingField.INSTANCE_UUID.toString()));
162 public static void instanceUuid(UUID instanceUuid) {
163 MDC.put(LoggingField.INSTANCE_UUID.toString(), instanceUuid.toString());
166 public static void severity(int severity) {
167 MDC.put(LoggingField.SEVERITY.toString(), String.valueOf(severity));
170 private static void serverIpAddress() {
172 MDC.put(LoggingField.SERVER_IP_ADDRESS.toString(), InetAddress.getLocalHost().getHostAddress());
173 } catch (UnknownHostException e) {
174 LOGGER.warn("Unable to resolve server IP address - will not be displayed in logged events");
178 public static void elapsedTime(long elapsedTime, TimeUnit timeUnit) {
179 MDC.put(LoggingField.ELAPSED_TIME.toString(), String.valueOf(TimeUnit.MILLISECONDS.convert(elapsedTime, timeUnit)));
182 private static void server() {
184 MDC.put(LoggingField.SERVER.toString(), InetAddress.getLocalHost().getCanonicalHostName());
185 } catch (UnknownHostException e) {
186 LOGGER.warn("Unable to resolve server IP address - hostname will not be displayed in logged events");
190 public static void clientIpAddress(InetAddress clientIpAddress) {
191 MDC.put(LoggingField.CLIENT_IP_ADDRESS.toString(), clientIpAddress.getHostAddress());
194 public static void clientIpAddress(String clientIpAddress) {
196 MDC.put(LoggingField.CLIENT_IP_ADDRESS.toString(), InetAddress.getByName(clientIpAddress).getHostAddress());
197 } catch (UnknownHostException e) {
198 //Ignore, will not be thrown since InetAddress.getByName(String) only
199 //checks the validity of the passed in string
203 public static void unused(String unused) {
204 LOGGER.warn("Using field '" + LoggingField.UNUSED + "' (seems like this should go unused...)");
205 MDC.put(LoggingField.UNUSED.toString(), unused);
208 public static void processKey(String processKey) {
209 MDC.put(LoggingField.PROCESS_KEY.toString(), processKey);
212 public static String customField1() {
213 return MDC.get(LoggingField.CUSTOM_FIELD_1.toString());
216 public static void customField1(String customField1) {
217 MDC.put(LoggingField.CUSTOM_FIELD_1.toString(), customField1);
220 public static void customField2(String customField2) {
221 MDC.put(LoggingField.CUSTOM_FIELD_2.toString(), customField2);
224 public static void customField3(String customField3) {
225 MDC.put(LoggingField.CUSTOM_FIELD_3.toString(), customField3);
228 public static void customField4(String customField4) {
229 MDC.put(LoggingField.CUSTOM_FIELD_4.toString(), customField4);
232 public static void component(String component) {
233 MDC.put(LoggingField.COMPONENT.toString(), component);
236 public static void targetEntity(String targetEntity) {
237 MDC.put(LoggingField.TARGET_ENTITY.toString(), targetEntity);
240 public static void stopWatchStart() {
241 MDC.put(LoggingField.STOP_WATCH_START.toString(), String.valueOf(System.nanoTime()));
244 public static double stopWatchStop() {
245 final long stopWatchEnd = System.nanoTime();
246 final String rawStopWatchStart = MDC.get(LoggingField.STOP_WATCH_START.toString());
248 if (rawStopWatchStart == null) throw new StopWatchNotStartedException();
250 final Long stopWatchStart = Long.valueOf(rawStopWatchStart);
252 MDC.remove(LoggingField.STOP_WATCH_START.toString());
254 final double elapsedTimeMillis = (stopWatchEnd - stopWatchStart) / 1000.0 / 1000.0;
256 LoggingContext.elapsedTime((long) elapsedTimeMillis, TimeUnit.MILLISECONDS);
258 return elapsedTimeMillis;
261 public static void put(String key, String value) {
265 public static void clear() {
269 public static void remove(String key) {
273 public static void save() {
274 final JSONObject context = new JSONObject();
276 for (LoggingField field : LoggingField.values()) {
277 if (field == LoggingField.ELAPSED_TIME) continue;
280 context.put(field.toString(), MDC.get(field.toString()));
281 } catch (JSONException e) {
282 //Ignore - only occurs when the key is null (which can't happen)
283 // or the value is invalid (everything is converted to a string
284 // before it get put() to the MDC)
288 final String rawJsonArray = MDC.get(PREVIOUS_CONTEXTS_KEY);
290 if (rawJsonArray == null) {
291 final JSONArray stack = new JSONArray()
294 MDC.put(PREVIOUS_CONTEXTS_KEY, stack.toString());
297 final JSONArray stack = new JSONArray(rawJsonArray)
300 MDC.put(PREVIOUS_CONTEXTS_KEY, stack.toString());
301 } catch (JSONException e) {
307 public static void restore() {
309 final String rawPreviousContexts = MDC.get(PREVIOUS_CONTEXTS_KEY);
311 if (rawPreviousContexts == null) {
312 throw new LoggingContextNotExistsException();
316 final JSONArray previousContexts = new JSONArray(rawPreviousContexts);
317 final JSONObject previousContext = previousContexts.getJSONObject(previousContexts.length() - 1);
319 @SuppressWarnings("unchecked")
320 final Iterator<String> keys = previousContext.keys();
322 while (keys.hasNext()) {
323 final String key = keys.next();
326 MDC.put(key, previousContext.getString(key));
327 } catch (JSONException e) {
328 //Ignore, only occurs when the key is null (cannot happen)
329 // or the value is invalid (they are all strings)
333 MDC.put(PREVIOUS_CONTEXTS_KEY, removeLast(previousContexts).toString());
334 } catch (JSONException e) {
335 //Ignore, the previousContext is serialized from a JSONObject
340 * AJSC declares an ancient version of org.json:json in one of the parent POMs of this project.
341 * I tried to update our version of that library in our POM, but it's ignored because of the way
342 * AJSC has organized their <dependencies>. Had they put it into the <dependencyManagement> section,
343 * this method would not be necessary.
345 private static JSONArray removeLast(JSONArray previousContexts) {
346 final JSONArray result = new JSONArray();
348 for (int i = 0; i < previousContexts.length() - 1; i++) {
350 result.put(previousContexts.getJSONObject(i));
351 } catch (JSONException e) {
352 //Ignore - not possible
359 public static Map<String, String> getCopy() {
360 final Map<String, String> copy = new HashMap<String, String> ();
362 for (LoggingField field : LoggingField.values()) {
363 final String value = MDC.get(field.toString());
365 if (value != null) copy.put(field.toString(), value);