a168ad9edfa92a3a8f20374744314f6baa76a79f
[aai/traversal.git] / aai-traversal / src / main / java / org / openecomp / aai / interceptors / AAILogJAXRSOutInterceptor.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.OutputStream;
24 import java.util.Collections;
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.Map;
28
29 import org.apache.cxf.helpers.CastUtils;
30 import org.apache.cxf.interceptor.LoggingMessage;
31 import org.apache.cxf.io.CacheAndWriteOutputStream;
32 import org.apache.cxf.io.CachedOutputStream;
33 import org.apache.cxf.io.CachedOutputStreamCallback;
34 import org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor;
35 import org.apache.cxf.message.Message;
36 import org.openecomp.aai.exceptions.AAIException;
37 import org.openecomp.aai.logging.ErrorLogHelper;
38 import org.openecomp.aai.util.AAIConfig;
39 import org.openecomp.aai.util.AAIConstants;
40 import org.openecomp.aai.util.FormatDate;
41
42 import com.att.eelf.configuration.EELFLogger;
43 import com.att.eelf.configuration.EELFManager;
44
45 // right after the request is complete, there may be content
46 public class AAILogJAXRSOutInterceptor extends JAXRSOutInterceptor {
47
48         private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(AAILogJAXRSOutInterceptor.class);
49         
50         protected final String COMPONENT = "aairest";
51         protected final String CAMEL_REQUEST = "CamelHttpUrl";
52
53         /**
54          * {@inheritDoc}
55          */
56         public void handleMessage(Message message) {
57
58                 String fullId = (String) message.getExchange().get(LoggingMessage.ID_KEY);
59
60                 Map<String, List<String>> headers = CastUtils.cast((Map<?, ?>) message.get(Message.PROTOCOL_HEADERS));
61                 if (headers == null) {
62                         headers = new HashMap<String, List<String>>();
63                 }
64
65                 headers.put("X-AAI-TXID", Collections.singletonList(fullId));
66                 message.put(Message.PROTOCOL_HEADERS, headers);
67
68                 Message outMessage = message.getExchange().getOutMessage();
69                 final OutputStream os = outMessage.getContent(OutputStream.class);
70                 if (os == null) {
71                         return;
72                 }
73
74                 // we only want to register the callback if there is good reason for it.
75                 if (message.getExchange().containsKey("AAI_LOGGING_HBASE_ENABLED") || message.getExchange().containsKey("AAI_LOGGING_TRACE_ENABLED")) {
76
77                         final CacheAndWriteOutputStream newOut = new CacheAndWriteOutputStream(os);
78                         message.setContent(OutputStream.class, newOut);
79                         newOut.registerCallback(new LoggingCallback(message, os));
80                 }
81
82         }
83
84         class LoggingCallback implements CachedOutputStreamCallback {
85
86                 private final Message message;
87                 private final OutputStream origStream;
88
89                 public LoggingCallback(final Message msg, final OutputStream os) {
90                         this.message = msg;
91                         this.origStream = os;
92                 }
93
94                 public void onFlush(CachedOutputStream cos) {
95
96                 }
97
98                 public void onClose(CachedOutputStream cos) {
99
100                         String getValue = "";
101                         String postValue = "";
102                         String logValue = "";
103
104                         try {
105                                 logValue = AAIConfig.get("aai.transaction.logging");
106                                 getValue = AAIConfig.get("aai.transaction.logging.get");
107                                 postValue = AAIConfig.get("aai.transaction.logging.post");
108                         } catch (AAIException e) {
109                                 // TODO Auto-generated catch block
110                                 e.printStackTrace();
111                         }
112
113                         if (!message.getExchange().containsKey("AAI_LOGGING_HBASE_ENABLED") && !message.getExchange().containsKey("AAI_LOGGING_TRACE_ENABLED")) {
114                                 return;
115                         }
116
117                         String fullId = (String) message.getExchange().get(LoggingMessage.ID_KEY);
118
119                         Message inMessage = message.getExchange().getInMessage();
120                         String transId = null;
121                         String fromAppId = null;
122
123                         Map<String, List<String>> headersList = CastUtils.cast((Map<?, ?>) inMessage.get(Message.PROTOCOL_HEADERS));
124                         if (headersList != null) {
125                                 List<String> xt = headersList.get("X-TransactionId");
126                                 if (xt != null) {
127                                         for (String transIdValue : xt) {
128                                                 transId = transIdValue;
129                                         }
130                                 }
131                                 List<String> fa = headersList.get("X-FromAppId");
132                                 if (fa != null) {
133                                         for (String fromAppIdValue : fa) {
134
135                                                 fromAppId = fromAppIdValue;
136                                         }
137                                 }
138                         }
139
140                         String httpMethod = (String) inMessage.get(Message.HTTP_REQUEST_METHOD);
141
142                         String uri = (String) inMessage.get(CAMEL_REQUEST);
143                         String fullUri = uri;
144                         if (uri != null) {
145                                 String query = (String) message.get(Message.QUERY_STRING);
146                                 if (query != null) {
147                                         fullUri = uri + "?" + query;
148                                 }
149                         }
150
151                         String request = (String) message.getExchange().get(fullId + "_REQUEST");
152
153                         Message outMessage = message.getExchange().getOutMessage();
154
155                         final LoggingMessage buffer = new LoggingMessage("OUTMessage", fullId);
156
157                         // should we check this, and make sure it's not an error?
158                         Integer responseCode = (Integer) outMessage.get(Message.RESPONSE_CODE);
159                         if (responseCode == null) {
160                                 responseCode = 200; // this should never happen, but just in
161                                                                         // case we don't get one
162                         }
163                         buffer.getResponseCode().append(responseCode);
164
165                         String encoding = (String) outMessage.get(Message.ENCODING);
166
167                         if (encoding != null) {
168                                 buffer.getEncoding().append(encoding);
169                         }
170
171                         String ct = (String) outMessage.get(Message.CONTENT_TYPE);
172                         if (ct != null) {
173                                 buffer.getContentType().append(ct);
174                         }
175
176                         Object headers = outMessage.get(Message.PROTOCOL_HEADERS);
177                         if (headers != null) {
178                                 buffer.getHeader().append(headers);
179                         }
180
181                         Boolean ss = false;
182                         if (responseCode >= 200 && responseCode <= 299) {
183                                 ss = true;
184                         }
185                         String response = buffer.toString();
186
187                         // this should have been set by the in interceptor
188                         String rqstTm = (String) message.getExchange().get("AAI_RQST_TM");
189
190                         // just in case it wasn't, we'll put this here. not great, but it'll
191                         // have a val.
192                         if (rqstTm == null) {
193                                 rqstTm = genDate();
194                         }
195
196
197                         String respTm = genDate();
198
199                         try {
200                                 String actualRequest = request;
201                                 StringBuilder builder = new StringBuilder();
202                                 cos.writeCacheTo(builder, 100000);
203                                 // here comes my xml:
204                                 String payload = builder.toString();
205
206                                 String actualResponse = response;
207                                 if (payload == null) {
208
209                                 } else {
210                                         actualResponse = response + payload;
211                                 }
212
213                                 // we only log to AAI log if it's eanbled in the config props
214                                 // file
215                                 if (message.getExchange().containsKey("AAI_LOGGING_TRACE_ENABLED")) {
216
217                                         if (message.getExchange().containsKey("AAI_LOGGING_TRACE_LOGREQUEST")) {
218
219                                                 // strip newlines from request
220                                                 String traceRequest = actualRequest;
221                                                 traceRequest = traceRequest.replace("\n", " ");
222                                                 traceRequest = traceRequest.replace("\r", "");
223                                                 traceRequest = traceRequest.replace("\t", "");
224                                                 LOGGER.debug(traceRequest);
225                                         }
226                                         if (message.getExchange().containsKey("AAI_LOGGING_TRACE_LOGRESPONSE")) {
227                                                 // strip newlines from response
228                                                 String traceResponse = actualResponse;
229                                                 traceResponse = traceResponse.replace("\n", " ");
230                                                 traceResponse = traceResponse.replace("\r", "");
231                                                 traceResponse = traceResponse.replace("\t", "");
232
233                                                 LOGGER.debug(traceResponse);
234                                         }
235                                 }
236
237                                 // we only log to HBASE if it's enabled in the config props file
238                                 // TODO: pretty print XML/JSON. we might need to get the payload
239                                 // and envelope seperately
240                                 if (message.getExchange().containsKey("AAI_LOGGING_HBASE_ENABLED")) {
241                                         if (!message.getExchange().containsKey("AAI_LOGGING_HBASE_LOGREQUEST")) {
242                                                 actualRequest = "loggingDisabled";
243                                         }
244                                         if (!message.getExchange().containsKey("AAI_LOGGING_HBASE_LOGRESPONSE")) {
245                                                 actualResponse = "loggingDisabled";
246                                         }
247
248                                         LOGGER.debug("action={}, urlin={}, HbTransId={}", httpMethod, fullUri, fullId);
249
250                                         if (logValue.equals("false")) {
251                                         } else if (getValue.equals("false") && httpMethod.equals("GET")) {
252                                         } else if (postValue.equals("false") && httpMethod.equals("POST")) {
253                                         } else {
254                                                 putTransaction(transId, responseCode.toString(), rqstTm, respTm, fromAppId + ":" + transId, fullUri, httpMethod, request, response, actualResponse);
255
256                                         }
257                                 }
258                         } catch (Exception ex) {
259                                 // ignore
260                         }
261
262                         message.setContent(OutputStream.class, origStream);
263                         
264                         LOGGER.auditEvent("HTTP Response Code: {}", responseCode.toString());
265                 }
266
267         }
268
269         protected String genDate() {
270                 FormatDate fd = new FormatDate("YYMMdd-HH:mm:ss:SSS");
271                 return fd.getDateTime();
272         }
273
274         public String putTransaction(String tid, String status, String rqstTm, String respTm, String srcId, String rsrcId, String rsrcType, String rqstBuf, String respBuf, String actualResponse) {
275                 String tm = null;
276
277                 if (tid == null || "".equals(tid)) {
278                         tm = this.genDate();
279                         tid = tm + "-";
280                 }
281
282                 String htid = tid;
283
284                 if (rqstTm == null || "".equals(rqstTm)) {
285                         rqstTm = tm;
286                 }
287
288                 if (respTm == null || "".equals(respTm)) {
289                         respTm = tm;
290                 }
291
292                 try {
293                         LOGGER.debug(" transactionId:" + tid + " status: " + status + " rqstDate: " + rqstTm + " respDate: " + respTm + " sourceId: " + srcId + " resourceId: "
294                                         + rsrcId + " resourceType: " + rsrcType + " payload rqstBuf: " + rqstBuf + " payload respBuf: " + respBuf + " Payload Error Messages: " + actualResponse);
295                         return htid;
296                 } catch (Exception e) {
297                         ErrorLogHelper.logError("AAI_4000", "Exception updating HBase:");
298                         return htid;
299                 }
300
301         }
302 }