1e61c6598f2ca3c4ca536af21c479b8ee5693edd
[aai/aai-common.git] / aai-core / src / main / java / org / onap / aai / logging / LoggingContext.java
1 /**
2  * ============LICENSE_START=======================================================
3  * org.onap.aai
4  * ================================================================================
5  * Copyright © 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
10  *
11  *    http://www.apache.org/licenses/LICENSE-2.0
12  *
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=========================================================
19  *
20  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
21  */
22 package org.onap.aai.logging;
23
24 import java.net.InetAddress;
25 import java.net.UnknownHostException;
26 import java.util.HashMap;
27 import java.util.Iterator;
28 import java.util.Map;
29 import java.util.UUID;
30 import java.util.concurrent.TimeUnit;
31
32 import org.json.JSONArray;
33 import org.json.JSONException;
34 import org.json.JSONObject;
35 import org.onap.aai.exceptions.AAIException;
36 import org.slf4j.MDC;
37
38 import com.att.eelf.configuration.EELFLogger;
39 import com.att.eelf.configuration.EELFManager;
40
41 public class LoggingContext {
42
43         public enum StatusCode {
44                 COMPLETE,
45                 ERROR
46         }
47
48         private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(LoggingContext.class);
49
50         private static final String PREVIOUS_CONTEXTS_KEY = "_PREVIOUS_CONTEXTS";
51
52         //ECOMP Specific Log Event Fields
53         public static enum LoggingField {
54                 START_TIME("startTime"),
55                 REQUEST_ID("requestId"),
56                 SERVICE_INSTANCE_ID("serviceInstanceId"),
57                 SERVER_NAME("serverName"),
58                 SERVICE_NAME("serviceName"),
59                 PARTNER_NAME("partnerName"),
60                 STATUS_CODE("statusCode"),
61                 RESPONSE_CODE("responseCode"),
62                 RESPONSE_DESCRIPTION("responseDescription"),
63                 INSTANCE_UUID("instanceUUID"),
64                 SEVERITY("severity"),
65                 SERVER_IP_ADDRESS("serverIpAddress"),
66                 ELAPSED_TIME("elapsedTime"),
67                 SERVER("server"),
68                 CLIENT_IP_ADDRESS("clientIpAddress"),
69                 UNUSED("unused"),
70                 PROCESS_KEY("processKey"),
71                 CUSTOM_FIELD_1("customField1"),
72                 CUSTOM_FIELD_2("customField2"),
73                 CUSTOM_FIELD_3("customField3"),
74                 CUSTOM_FIELD_4("customField4"),
75                 
76                 //ECOMP Specific Metric Log Event Fields
77                 TARGET_ENTITY("targetEntity"),
78
79                 //A&AI Specific Log Event Fields
80                 COMPONENT("component"),
81                 STOP_WATCH_START("stopWatchStart");
82
83                 private final String text;
84
85                 private LoggingField(final String text) {
86                         this.text = text;
87                 }
88
89                 public String toString() {
90                         return text;
91                 }
92         }
93
94
95         public static void init() {
96                 LoggingContext.clear();
97                 LoggingContext.startTime();
98                 LoggingContext.server();
99                 LoggingContext.serverIpAddress();
100         }
101
102         private static void startTime() {
103                 MDC.put(LoggingField.START_TIME.toString(), LogFormatTools.getCurrentDateTime());
104         }
105
106         public static UUID requestId() {
107                 final String sUuid = MDC.get(LoggingField.REQUEST_ID.toString());
108
109                 if (sUuid == null) return null;
110
111                 return UUID.fromString(sUuid);
112         }
113
114         public static void requestId(UUID requestId) {
115                 MDC.put(LoggingField.REQUEST_ID.toString(), requestId.toString());
116         }
117
118         public static void requestId(String requestId) throws AAIException {
119
120                 try {
121                         if(requestId == null){
122                                 throw new IllegalArgumentException();
123                         }
124                         if (requestId.contains(":")) {
125                                 String[] uuidParts = requestId.split(":");
126                                 requestId = uuidParts[0];
127                         }
128                         MDC.put(LoggingField.REQUEST_ID.toString(), UUID.fromString(requestId).toString());
129                 } catch (IllegalArgumentException e) {
130                         final UUID generatedRequestUuid = UUID.randomUUID();
131                         MDC.put(LoggingField.REQUEST_ID.toString(), generatedRequestUuid.toString());
132                         LOGGER.warn("Unable to use UUID " + requestId + " (Not formatted properly). Using generated UUID=" + generatedRequestUuid);
133                 }
134         }
135
136         public static void serviceInstanceId(String serviceInstanceId) {
137                 MDC.put(LoggingField.SERVICE_INSTANCE_ID.toString(), serviceInstanceId);
138         }
139
140         public static void serverName(String serverName) {
141                 MDC.put(LoggingField.SERVER_NAME.toString(), serverName);
142         }
143
144         public static void serviceName(String serviceName) {
145                 MDC.put(LoggingField.SERVICE_NAME.toString(), serviceName);
146         }
147
148         public static void partnerName(String partnerName) {
149                 MDC.put(LoggingField.PARTNER_NAME.toString(), partnerName);
150         }
151
152         public static void statusCode(LoggingContext.StatusCode statusCode) {
153                 MDC.put(LoggingField.STATUS_CODE.toString(), statusCode.toString());
154         }
155
156         public static String responseCode() {
157                 return (String) MDC.get(LoggingField.RESPONSE_CODE.toString());
158         }
159
160         public static void responseCode(String responseCode) {
161                 MDC.put(LoggingField.RESPONSE_CODE.toString(), responseCode);
162         }
163
164         public static void responseDescription(String responseDescription) {
165                 MDC.put(LoggingField.RESPONSE_DESCRIPTION.toString(), responseDescription);
166         }
167
168         public static Object instanceUuid() {
169                 return UUID.fromString(MDC.get(LoggingField.INSTANCE_UUID.toString()));
170         }
171
172         public static void instanceUuid(UUID instanceUuid) {
173                 MDC.put(LoggingField.INSTANCE_UUID.toString(), instanceUuid.toString());
174         }
175
176         public static void severity(int severity) {
177                 MDC.put(LoggingField.SEVERITY.toString(), String.valueOf(severity));
178         }
179
180         private static void serverIpAddress() {
181                 try {
182                         MDC.put(LoggingField.SERVER_IP_ADDRESS.toString(), InetAddress.getLocalHost().getHostAddress());
183                 } catch (UnknownHostException e) {
184                         LOGGER.warn("Unable to resolve server IP address - will not be displayed in logged events");
185                 }
186         }
187
188         public static void elapsedTime(long elapsedTime, TimeUnit timeUnit) {
189                 MDC.put(LoggingField.ELAPSED_TIME.toString(), String.valueOf(TimeUnit.MILLISECONDS.convert(elapsedTime, timeUnit)));
190         }
191
192         private static void server() {
193                 try {
194                         MDC.put(LoggingField.SERVER.toString(),  InetAddress.getLocalHost().getCanonicalHostName());
195                 } catch (UnknownHostException e) {
196                         LOGGER.warn("Unable to resolve server IP address - hostname will not be displayed in logged events");
197                 }
198         }
199
200         public static void clientIpAddress(InetAddress clientIpAddress) {
201                 MDC.put(LoggingField.CLIENT_IP_ADDRESS.toString(), clientIpAddress.getHostAddress());
202         }
203
204         public static void clientIpAddress(String clientIpAddress) {
205                 try {
206                         MDC.put(LoggingField.CLIENT_IP_ADDRESS.toString(), InetAddress.getByName(clientIpAddress).getHostAddress());
207                 } catch (UnknownHostException e) {
208                         //Ignore, will not be thrown since InetAddress.getByName(String) only
209                         //checks the validity of the passed in string
210                 }
211         }
212
213         public static void unused(String unused) {
214                 LOGGER.warn("Using field '" + LoggingField.UNUSED + "' (seems like this should go unused...)");
215                 MDC.put(LoggingField.UNUSED.toString(), unused);
216         }
217
218         public static void processKey(String processKey) {
219                 MDC.put(LoggingField.PROCESS_KEY.toString(), processKey);
220         }
221
222         public static String customField1() {
223                 return MDC.get(LoggingField.CUSTOM_FIELD_1.toString());
224         }
225
226         public static void customField1(String customField1) {
227                 MDC.put(LoggingField.CUSTOM_FIELD_1.toString(), customField1);
228         }
229
230         public static void customField2(String customField2) {
231                 MDC.put(LoggingField.CUSTOM_FIELD_2.toString(), customField2);
232         }
233
234         public static void customField3(String customField3) {
235                 MDC.put(LoggingField.CUSTOM_FIELD_3.toString(), customField3);
236         }
237
238         public static void customField4(String customField4) {
239                 MDC.put(LoggingField.CUSTOM_FIELD_4.toString(), customField4);
240         }
241
242         public static void component(String component) {
243                 MDC.put(LoggingField.COMPONENT.toString(), component);
244         }
245
246         public static void targetEntity(String targetEntity) {
247                 MDC.put(LoggingField.TARGET_ENTITY.toString(), targetEntity);
248         }
249
250         public static void stopWatchStart() {
251                 MDC.put(LoggingField.STOP_WATCH_START.toString(), String.valueOf(System.nanoTime()));
252         }
253
254         public static double stopWatchStop() {
255                 final long stopWatchEnd = System.nanoTime();
256                 final String rawStopWatchStart = MDC.get(LoggingField.STOP_WATCH_START.toString());
257
258                 if (rawStopWatchStart == null) throw new StopWatchNotStartedException();
259
260                 final Long stopWatchStart = Long.valueOf(rawStopWatchStart);
261
262                 MDC.remove(LoggingField.STOP_WATCH_START.toString());
263
264                 final double elapsedTimeMillis = (stopWatchEnd - stopWatchStart) / 1000.0 / 1000.0;
265
266                 LoggingContext.elapsedTime((long) elapsedTimeMillis, TimeUnit.MILLISECONDS);
267
268                 return elapsedTimeMillis;
269         }
270
271         public static void put(String key, String value) {
272                 MDC.put(key, value);
273         }
274
275         public static void clear() {
276                 MDC.clear();
277         }
278
279         public static void remove(String key) {
280                 MDC.remove(key);
281         }
282
283         public static void save() {
284                 final JSONObject context = new JSONObject();
285
286                 for (LoggingField field : LoggingField.values()) {
287                         if (field == LoggingField.ELAPSED_TIME) continue;
288
289                         try {
290                                 context.put(field.toString(), MDC.get(field.toString()));
291                         } catch (JSONException e) {
292                                 //Ignore - only occurs when the key is null (which can't happen)
293                                 //                      or the value is invalid (everything is converted to a string
294                                 //                      before it get put() to the MDC)
295                         }
296                 }
297
298                 final String rawJsonArray = MDC.get(PREVIOUS_CONTEXTS_KEY);
299
300                 if (rawJsonArray == null) {
301                         final JSONArray stack = new JSONArray()
302                                                                                         .put(context);
303
304                         MDC.put(PREVIOUS_CONTEXTS_KEY, stack.toString());
305                 } else {
306                         try {
307                                 final JSONArray stack = new JSONArray(rawJsonArray)
308                                                                                                 .put(context);
309
310                                 MDC.put(PREVIOUS_CONTEXTS_KEY, stack.toString());
311                         } catch (JSONException e) {
312                                 //Ignore
313                         }
314                 }
315         }
316
317         public static void restore() {
318                 
319                 final String rawPreviousContexts = MDC.get(PREVIOUS_CONTEXTS_KEY);
320         
321                 if (rawPreviousContexts == null) {
322                         throw new LoggingContextNotExistsException();
323                 }
324
325                 try {
326                         final JSONArray previousContexts = new JSONArray(rawPreviousContexts);
327                         final JSONObject previousContext = previousContexts.getJSONObject(previousContexts.length() - 1);
328
329                         @SuppressWarnings("unchecked")
330                         final Iterator<String> keys = previousContext.keys();
331         
332                         while (keys.hasNext()) {
333                                 final String key = keys.next();
334
335                                 try {
336                                         MDC.put(key, previousContext.getString(key));
337                                 } catch (JSONException e) {
338                                         //Ignore, only occurs when the key is null (cannot happen)
339                                         //                      or the value is invalid (they are all strings)
340                                 }
341                         }
342
343                         MDC.put(PREVIOUS_CONTEXTS_KEY, removeLast(previousContexts).toString());
344                 } catch (JSONException e) {
345                         //Ignore, the previousContext is serialized from a JSONObject
346                 }
347         }
348
349         /**
350          * AJSC declares an ancient version of org.json:json in one of the parent POMs of this project.
351          * I tried to update our version of that library in our POM, but it's ignored because of the way
352          * AJSC has organized their <dependencies>.  Had they put it into the <dependencyManagement> section,
353          * this method would not be necessary.
354          */
355         private static JSONArray removeLast(JSONArray previousContexts) {
356                 final JSONArray result = new JSONArray();
357
358                 for (int i = 0; i < previousContexts.length() - 1; i++) {
359                         try {
360                                 result.put(previousContexts.getJSONObject(i));
361                         } catch (JSONException e) {
362                                 //Ignore - not possible
363                         }
364                 }
365
366                 return result;
367         }
368
369         public static Map<String, String> getCopy() {
370                 final Map<String, String> copy = new HashMap<String, String> ();
371
372                 for (LoggingField field : LoggingField.values()) {
373                         final String value = MDC.get(field.toString());
374
375                         if (value != null) copy.put(field.toString(), value);
376                 }
377
378                 return copy;
379         }
380 }