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.interceptors;
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;
31 import java.util.UUID;
32 import java.util.regex.Matcher;
33 import java.util.regex.Pattern;
35 import javax.ws.rs.core.MediaType;
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;
53 public class AAILogJAXRSInInterceptor extends JAXRSInInterceptor {
55 protected final String COMPONENT = "aairest";
56 protected final String CAMEL_REQUEST ="CamelHttpUrl";
57 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}$");
62 public void handleMessage(Message message) {
64 AAILogger aaiLogger = new AAILogger(AAILogJAXRSInInterceptor.class.getName());
65 LogLine logline = new LogLine();
66 LogLine auditLogline = new LogLine();
71 uri = (String)message.get(CAMEL_REQUEST);
73 query = (String)message.get(Message.QUERY_STRING);
76 if (AAIConfig.get(AAIConstants.AAI_LOGGING_HBASE_INTERCEPTOR).equalsIgnoreCase("true") &&
77 AAIConfig.get(AAIConstants.AAI_LOGGING_HBASE_ENABLED).equalsIgnoreCase("true")) {
79 message.getExchange().put("AAI_LOGGING_HBASE_ENABLED", 1);
80 if (AAIConfig.get(AAIConstants.AAI_LOGGING_HBASE_LOGREQUEST).equalsIgnoreCase("true") ) {
81 message.getExchange().put("AAI_LOGGING_HBASE_LOGREQUEST", 1);
83 if (AAIConfig.get(AAIConstants.AAI_LOGGING_HBASE_LOGRESPONSE).equalsIgnoreCase("true") ) {
84 message.getExchange().put("AAI_LOGGING_HBASE_LOGRESPONSE", 1);
87 if (AAIConfig.get(AAIConstants.AAI_LOGGING_TRACE_ENABLED).equalsIgnoreCase("true") ) {
89 message.getExchange().put("AAI_LOGGING_TRACE_ENABLED", 1);
90 if (AAIConfig.get(AAIConstants.AAI_LOGGING_TRACE_LOGREQUEST).equalsIgnoreCase("true") ) {
91 message.getExchange().put("AAI_LOGGING_TRACE_LOGREQUEST", 1);
93 if (AAIConfig.get(AAIConstants.AAI_LOGGING_TRACE_LOGRESPONSE).equalsIgnoreCase("true") ) {
94 message.getExchange().put("AAI_LOGGING_TRACE_LOGRESPONSE", 1);
97 } catch (AAIException e1) {
98 logline.add("Property", AAIConstants.AAI_LOGGING_TRACE_ENABLED);
99 logline.add("Property", AAIConstants.AAI_LOGGING_HBASE_ENABLED);
100 aaiLogger.error(e1.getErrorObject(), logline);
103 if (uri.contains(EchoResponse.echoPath)) {
104 // if it's a health check, we don't want to log ANYTHING if it's a lightweight one
106 if (message.getExchange().containsKey("AAI_LOGGING_HBASE_ENABLED")) {
107 message.getExchange().remove("AAI_LOGGING_HBASE_ENABLED");
109 if (message.getExchange().containsKey("AAI_LOGGING_TRACE_ENABLED")) {
110 message.getExchange().remove("AAI_LOGGING_TRACE_ENABLED");
115 else if (uri.contains("/translog/")) {
116 // if it's a translog query, we don't want to log the responses
117 if (message.getExchange().containsKey("AAI_LOGGING_HBASE_LOGRESPONSE")) {
118 message.getExchange().remove("AAI_LOGGING_HBASE_LOGRESPONSE");
120 if (message.getExchange().containsKey("AAI_LOGGING_TRACE_LOGRESPONSE")) {
121 message.getExchange().remove("AAI_LOGGING_TRACE_LOGRESPONSE");
125 if (go == false) { // there's nothing to do
129 // DONE: get a TXID based on hostname, time (YYYYMMDDHHMMSSMILLIS, and LoggingMessage.nextId(); 20150326145301-1
130 String now = genDate(aaiLogger, logline);
132 message.getExchange().put("AAI_RQST_TM", now);
134 String id = (String)message.getExchange().get(LoggingMessage.ID_KEY);
136 String fullId = null;
139 id = LoggingMessage.nextId();
141 fullId = AAIConfig.get(AAIConstants.AAI_NODENAME) + "-" + now + "-" + id;
142 fullId = HbaseSaltPrefixer.getInstance().prependSalt(fullId);
143 message.getExchange().put(LoggingMessage.ID_KEY, fullId);
144 } catch (AAIException e1) {
145 aaiLogger.debug(logline, "config problem", e1);
147 if (fullId == null) {
148 fullId = now + "-" + id;
149 fullId = HbaseSaltPrefixer.getInstance().prependSalt(fullId);
151 message.put(LoggingMessage.ID_KEY, fullId);
152 final LoggingMessage buffer = new LoggingMessage("Message", fullId);
154 Integer responseCode = (Integer)message.get(Message.RESPONSE_CODE);
155 if (responseCode != null) {
156 buffer.getResponseCode().append(responseCode);
159 String encoding = (String)message.get(Message.ENCODING);
161 if (encoding != null) {
162 buffer.getEncoding().append(encoding);
164 String httpMethod = (String)message.get(Message.HTTP_REQUEST_METHOD);
165 if (httpMethod != null) {
166 buffer.getHttpMethod().append(httpMethod);
169 String ct = (String)message.get(Message.CONTENT_TYPE);
171 if ("*/*".equals(ct)) {
172 message.put(Message.CONTENT_TYPE, MediaType.APPLICATION_JSON);
173 ct = MediaType.APPLICATION_JSON;
175 buffer.getContentType().append(ct);
178 Object headers = message.get(Message.PROTOCOL_HEADERS);
179 if (headers != null) {
180 buffer.getHeader().append(headers);
182 Map<String, List<String>> headersList = CastUtils.cast((Map<?, ?>)message.get(Message.PROTOCOL_HEADERS));
184 String fromAppId = null;
185 List<String> xt = headersList.get("X-TransactionId");
186 String newTransId = transId;
187 boolean missingTransId = false;
188 boolean replacedTransId = false;
189 String logMsg = null;
191 for (String transIdValue : xt) {
192 transId = transIdValue;
194 Matcher matcher = uuidPattern.matcher(transId);
195 if (!matcher.find()) {
196 replacedTransId = true;
197 // check if there's a colon, and check the first group?
198 if (transId.contains(":")) {
199 String[] uuidParts = transId.split(":");
200 Matcher matcher2 = uuidPattern.matcher(uuidParts[0]);
201 if (matcher2.find()) {
202 newTransId = uuidParts[0];
204 // punt, we tried to find it, it has a colon but no UUID-1
205 newTransId = UUID.randomUUID().toString();
208 newTransId = UUID.randomUUID().toString();
212 newTransId = UUID.randomUUID().toString();
213 missingTransId = true;
216 if (missingTransId || replacedTransId) {
217 List<String> txList = new ArrayList<String>();
218 txList.add(newTransId);
219 headersList.put("X-TransactionId", txList);
220 if (missingTransId) {
221 logMsg = "Missing requestID. Assigned " + newTransId;
222 } else if (replacedTransId) {
223 logMsg = "Replaced invalid requestID of " + transId + " Assigned " + newTransId;
225 MDC.put("RequestId",newTransId);
228 MDC.put("RequestId",transId);
232 List<String> fromAppIdList = headersList.get("X-FromAppId");
233 if (fromAppIdList != null) {
234 for (String fromAppIdValue : fromAppIdList) {
235 fromAppId = fromAppIdValue;
237 MDC.put("PartnerName",fromAppId);
240 List<String> contentType = headersList.get("Content-Type");
241 if (contentType == null) {
242 ct = (String)message.get(Message.CONTENT_TYPE);
243 headersList.put(Message.CONTENT_TYPE, Collections.singletonList(ct));
245 logline.init(COMPONENT, newTransId, fromAppId, "interceptIn");
246 auditLogline.init(COMPONENT, newTransId, fromAppId, "REST " + httpMethod + " "
247 + ((query != null)? uri+"?"+query : uri));
248 if (logMsg != null) {
249 logline.add(logMsg, true);
251 logline.add("HbaseTxId", fullId);
252 aaiLogger.info(logline, true, "0");
257 buffer.getAddress().append(uri);
259 buffer.getAddress().append("?").append(query);
263 InputStream is = message.getContent(InputStream.class);
266 String currentPayload = IOUtils.toString(is, "UTF-8");
267 IOUtils.closeQuietly(is);
268 buffer.getPayload().append(currentPayload);
269 is = IOUtils.toInputStream(currentPayload, "UTF-8");
270 message.setContent(InputStream.class, is);
271 IOUtils.closeQuietly(is);
272 } catch (Exception e) {
273 // It's ok to not have request input content
274 // throw new Fault(e);
278 // this will be saved in the message exchange, and can be pulled out later...
279 message.getExchange().put(fullId + "_REQUEST", buffer.toString());
280 message.getExchange().put("AUDIT_LOGLINE", auditLogline);
287 * @param aaiLogger the aai logger
288 * @param logline the logline
291 protected String genDate(AAILogger aaiLogger, LogLine logline) {
292 Date date = new Date();
293 DateFormat formatter = null;
295 formatter = new SimpleDateFormat(AAIConfig.get(AAIConstants.HBASE_TABLE_TIMESTAMP_FORMAT));
296 } catch (AAIException ex) {
297 logline.add("Property", AAIConstants.HBASE_TABLE_TIMESTAMP_FORMAT);
298 aaiLogger.error(ex.getErrorObject(), logline);
300 if (formatter == null) {
301 formatter = new SimpleDateFormat("YYMMdd-HH:mm:ss:SSS");
305 return formatter.format(date);