b0e1742f6f3f861dd2c69bff9ba4e33bd8e7ee84
[aai/aai-service.git] / ajsc-aai / src / main / java / org / openecomp / aai / interceptors / AAILogJAXRSInInterceptor.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * org.openecomp.aai
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
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
21 package org.openecomp.aai.interceptors;
22
23 import java.io.InputStream;
24 import java.text.DateFormat;
25 import java.text.SimpleDateFormat;
26 import java.util.ArrayList;
27 import java.util.Collections;
28 import java.util.Date;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.UUID;
32 import java.util.regex.Matcher;
33 import java.util.regex.Pattern;
34
35 import javax.ws.rs.core.MediaType;
36
37 import org.apache.commons.io.IOUtils;
38 import org.apache.cxf.helpers.CastUtils;
39 import org.apache.cxf.interceptor.Fault;
40 import org.apache.cxf.interceptor.LoggingMessage;
41 import org.apache.cxf.jaxrs.ext.MessageContext;
42 import org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor;
43 import org.apache.cxf.message.Message;
44 import org.openecomp.aai.exceptions.AAIException;
45 import org.openecomp.aai.logging.AAILogger;
46 import org.openecomp.aai.logging.LogLine;
47 import org.openecomp.aai.rest.util.EchoResponse;
48 import org.openecomp.aai.util.AAIConfig;
49 import org.openecomp.aai.util.AAIConstants;
50 import org.openecomp.aai.util.HbaseSaltPrefixer;
51
52 public class AAILogJAXRSInInterceptor extends JAXRSInInterceptor {
53
54         protected final String COMPONENT = "aairest";
55         protected final String CAMEL_REQUEST ="CamelHttpUrl";
56         private static final Pattern uuidPattern = Pattern.compile("^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$");
57         
58         /**
59          * {@inheritDoc}
60          */
61         public void handleMessage(Message message) {
62                 boolean go = false;
63                 AAILogger aaiLogger = new AAILogger(AAILogJAXRSInInterceptor.class.getName());
64                 LogLine logline = new LogLine();
65                 LogLine auditLogline = new LogLine();
66                 String uri = null;
67                 String query = null;
68                 try {
69                 
70                         uri = (String)message.get(CAMEL_REQUEST);
71                         if (uri != null) { 
72                                 query = (String)message.get(Message.QUERY_STRING);
73                         }
74                         
75                         if (AAIConfig.get(AAIConstants.AAI_LOGGING_HBASE_INTERCEPTOR).equalsIgnoreCase("true") &&
76                                         AAIConfig.get(AAIConstants.AAI_LOGGING_HBASE_ENABLED).equalsIgnoreCase("true")) {
77                                 go = true;
78                                 message.getExchange().put("AAI_LOGGING_HBASE_ENABLED", 1);
79                                 if (AAIConfig.get(AAIConstants.AAI_LOGGING_HBASE_LOGREQUEST).equalsIgnoreCase("true") ) {
80                                         message.getExchange().put("AAI_LOGGING_HBASE_LOGREQUEST", 1);
81                                 }
82                                 if (AAIConfig.get(AAIConstants.AAI_LOGGING_HBASE_LOGRESPONSE).equalsIgnoreCase("true") ) {
83                                         message.getExchange().put("AAI_LOGGING_HBASE_LOGRESPONSE", 1);
84                                 }
85                         }
86                         if (AAIConfig.get(AAIConstants.AAI_LOGGING_TRACE_ENABLED).equalsIgnoreCase("true") ) {
87                                 go = true;
88                                 message.getExchange().put("AAI_LOGGING_TRACE_ENABLED", 1);
89                                 if (AAIConfig.get(AAIConstants.AAI_LOGGING_TRACE_LOGREQUEST).equalsIgnoreCase("true") ) {
90                                         message.getExchange().put("AAI_LOGGING_TRACE_LOGREQUEST", 1);
91                                 }
92                                 if (AAIConfig.get(AAIConstants.AAI_LOGGING_TRACE_LOGRESPONSE).equalsIgnoreCase("true") ) {
93                                         message.getExchange().put("AAI_LOGGING_TRACE_LOGRESPONSE", 1);
94                                 }
95                         }
96                 } catch (AAIException e1) {
97                         logline.add("Property", AAIConstants.AAI_LOGGING_TRACE_ENABLED);
98                         logline.add("Property", AAIConstants.AAI_LOGGING_HBASE_ENABLED);
99                         aaiLogger.error(e1.getErrorObject(), logline);
100                 }
101                 
102                 if (uri.contains(EchoResponse.echoPath)) {
103                         // if it's a health check, we don't want to log ANYTHING if it's a lightweight one
104                         if (query == null) {
105                                 if (message.getExchange().containsKey("AAI_LOGGING_HBASE_ENABLED")) {
106                                         message.getExchange().remove("AAI_LOGGING_HBASE_ENABLED");
107                                 }
108                                 if (message.getExchange().containsKey("AAI_LOGGING_TRACE_ENABLED")) { 
109                                         message.getExchange().remove("AAI_LOGGING_TRACE_ENABLED");
110                                 }
111                                 go = false;
112                         }
113                 }
114                 else if (uri.contains("/translog/")) {
115                         // if it's a translog query, we don't want to log the responses
116                         if (message.getExchange().containsKey("AAI_LOGGING_HBASE_LOGRESPONSE")) {
117                                 message.getExchange().remove("AAI_LOGGING_HBASE_LOGRESPONSE");
118                         }
119                         if (message.getExchange().containsKey("AAI_LOGGING_TRACE_LOGRESPONSE")) {
120                                 message.getExchange().remove("AAI_LOGGING_TRACE_LOGRESPONSE");
121                         }
122                 }
123                 
124                 if (go == false) { // there's nothing to do 
125                         return;
126                 }
127
128                 // DONE: get a TXID based on hostname, time (YYYYMMDDHHMMSSMILLIS,  and LoggingMessage.nextId(); 20150326145301-1
129                 String now = genDate(aaiLogger, logline);
130
131                 message.getExchange().put("AAI_RQST_TM", now);
132
133                 String id = (String)message.getExchange().get(LoggingMessage.ID_KEY);
134
135                 String fullId = null;
136                 try {
137                         if (id == null) {
138                                 id = LoggingMessage.nextId();
139                         }
140                         fullId = AAIConfig.get(AAIConstants.AAI_NODENAME) + "-" + now + "-" + id;
141                         fullId = HbaseSaltPrefixer.getInstance().prependSalt(fullId);
142                         message.getExchange().put(LoggingMessage.ID_KEY, fullId);
143                 } catch (AAIException e1) {
144                         aaiLogger.debug(logline, "config problem", e1);
145                 }
146                 if (fullId == null) { 
147                         fullId = now + "-" + id;
148                         fullId = HbaseSaltPrefixer.getInstance().prependSalt(fullId);
149                 }
150                 message.put(LoggingMessage.ID_KEY, fullId);
151                 final LoggingMessage buffer = new LoggingMessage("Message", fullId);
152
153                 Integer responseCode = (Integer)message.get(Message.RESPONSE_CODE);
154                 if (responseCode != null) {
155                         buffer.getResponseCode().append(responseCode);
156                 }
157
158                 String encoding = (String)message.get(Message.ENCODING);
159
160                 if (encoding != null) {
161                         buffer.getEncoding().append(encoding);
162                 }
163                 String httpMethod = (String)message.get(Message.HTTP_REQUEST_METHOD);
164                 if (httpMethod != null) {
165                         buffer.getHttpMethod().append(httpMethod);
166                 }
167
168                 String ct = (String)message.get(Message.CONTENT_TYPE);
169                 if (ct != null) {
170                         if ("*/*".equals(ct)) {
171                                 message.put(Message.CONTENT_TYPE, MediaType.APPLICATION_JSON);
172                                 ct = MediaType.APPLICATION_JSON;
173                         }
174                         buffer.getContentType().append(ct);
175
176                 }
177                 Object headers = message.get(Message.PROTOCOL_HEADERS);
178                 if (headers != null) {
179                         buffer.getHeader().append(headers);
180                         
181                         Map<String, List<String>> headersList = CastUtils.cast((Map<?, ?>)message.get(Message.PROTOCOL_HEADERS));
182                         String transId = "";
183                         String fromAppId = null;
184                         List<String> xt = headersList.get("X-TransactionId");
185                         String newTransId = transId;
186                         boolean missingTransId = false;
187                         boolean replacedTransId = false;
188                         String logMsg = null;
189                         if (xt != null) {
190                                 for (String transIdValue : xt) {
191                                         transId = transIdValue;
192                                 }       
193                                 Matcher matcher = uuidPattern.matcher(transId);
194                                 if (!matcher.find()) {
195                                         replacedTransId = true;
196                                         // check if there's a colon, and check the first group?
197                                         if (transId.contains(":")) {
198                                                 String[] uuidParts = transId.split(":");
199                                                 Matcher matcher2 = uuidPattern.matcher(uuidParts[0]);
200                                                 if (matcher2.find()) { 
201                                                         newTransId = uuidParts[0];
202                                                 } else {
203                                                         // punt, we tried to find it, it has a colon but no UUID-1
204                                                         newTransId = UUID.randomUUID().toString();
205                                                 }
206                                         } else {
207                                                 newTransId = UUID.randomUUID().toString();
208                                         }
209                                 }
210                         } else { 
211                                 newTransId = UUID.randomUUID().toString();
212                                 missingTransId = true;
213                         }
214                                                 
215                         if (missingTransId || replacedTransId) {
216                                 List<String> txList = new ArrayList<String>();
217                                 txList.add(newTransId);
218                                 headersList.put("X-TransactionId", txList);
219                                 if (missingTransId) { 
220                                         logMsg = "Missing requestID. Assigned " + newTransId;
221                                 } else if (replacedTransId) { 
222                                         logMsg = "Replaced invalid requestID of " + transId + " Assigned " + newTransId;
223                                 }
224                         } 
225                         
226                         
227                         List<String> fa = headersList.get("X-FromAppId");
228                         if (fa != null) {
229                                 for (String fromAppIdValue : fa) {
230                                         fromAppId = fromAppIdValue;
231                                 }
232                         }
233                         
234                         List<String> contentType = headersList.get("Content-Type");
235                         if (contentType == null) {
236                                 ct = (String)message.get(Message.CONTENT_TYPE);
237                                 headersList.put(Message.CONTENT_TYPE, Collections.singletonList(ct));
238                         }
239                         logline.init(COMPONENT, newTransId, fromAppId, "interceptIn");
240                         auditLogline.init(COMPONENT, newTransId, fromAppId, "REST " + httpMethod + " "
241                                         + ((query != null)? uri+"?"+query : uri));
242                         if (logMsg != null) {
243                                 logline.add(logMsg, true);
244                         }
245                         logline.add("HbaseTxId", fullId);
246                         aaiLogger.info(logline, true, "0");
247                 }
248
249
250                 if (uri != null) {
251                         buffer.getAddress().append(uri);
252                         if (query != null) {
253                                 buffer.getAddress().append("?").append(query);
254                         }
255                 }
256
257                 InputStream is = message.getContent(InputStream.class);
258                 if (is != null) {
259                         try {
260                                 String currentPayload = IOUtils.toString(is, "UTF-8");
261                                 IOUtils.closeQuietly(is);
262                                 buffer.getPayload().append(currentPayload);
263                                 is = IOUtils.toInputStream(currentPayload, "UTF-8");
264                                 message.setContent(InputStream.class, is);
265                                 IOUtils.closeQuietly(is);
266                         } catch (Exception e) { 
267                                 // It's ok to not have request input content
268                                 // throw new Fault(e); 
269                         }
270                 }
271
272                 // this will be saved in the message exchange, and can be pulled out later...
273                 message.getExchange().put(fullId + "_REQUEST", buffer.toString());
274                 message.getExchange().put("AUDIT_LOGLINE", auditLogline);
275
276         }
277
278         /**
279          * Gen date.
280          *
281          * @param aaiLogger the aai logger
282          * @param logline the logline
283          * @return the string
284          */
285         protected String genDate(AAILogger aaiLogger, LogLine logline) {
286                 Date date = new Date();
287                 DateFormat formatter = null;
288                 try {
289                         formatter = new SimpleDateFormat(AAIConfig.get(AAIConstants.HBASE_TABLE_TIMESTAMP_FORMAT));
290                 } catch (AAIException ex) {
291                         logline.add("Property", AAIConstants.HBASE_TABLE_TIMESTAMP_FORMAT);
292                         aaiLogger.error(ex.getErrorObject(), logline);
293                 } finally {
294                         if (formatter == null) {
295                                 formatter = new SimpleDateFormat("YYMMdd-HH:mm:ss:SSS");
296                         }
297                 }
298
299                 return formatter.format(date);
300         }
301
302 }