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;
52 public class AAILogJAXRSInInterceptor extends JAXRSInInterceptor {
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}$");
61 public void handleMessage(Message message) {
63 AAILogger aaiLogger = new AAILogger(AAILogJAXRSInInterceptor.class.getName());
64 LogLine logline = new LogLine();
65 LogLine auditLogline = new LogLine();
70 uri = (String)message.get(CAMEL_REQUEST);
72 query = (String)message.get(Message.QUERY_STRING);
75 if (AAIConfig.get(AAIConstants.AAI_LOGGING_HBASE_INTERCEPTOR).equalsIgnoreCase("true") &&
76 AAIConfig.get(AAIConstants.AAI_LOGGING_HBASE_ENABLED).equalsIgnoreCase("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);
82 if (AAIConfig.get(AAIConstants.AAI_LOGGING_HBASE_LOGRESPONSE).equalsIgnoreCase("true") ) {
83 message.getExchange().put("AAI_LOGGING_HBASE_LOGRESPONSE", 1);
86 if (AAIConfig.get(AAIConstants.AAI_LOGGING_TRACE_ENABLED).equalsIgnoreCase("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);
92 if (AAIConfig.get(AAIConstants.AAI_LOGGING_TRACE_LOGRESPONSE).equalsIgnoreCase("true") ) {
93 message.getExchange().put("AAI_LOGGING_TRACE_LOGRESPONSE", 1);
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);
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
105 if (message.getExchange().containsKey("AAI_LOGGING_HBASE_ENABLED")) {
106 message.getExchange().remove("AAI_LOGGING_HBASE_ENABLED");
108 if (message.getExchange().containsKey("AAI_LOGGING_TRACE_ENABLED")) {
109 message.getExchange().remove("AAI_LOGGING_TRACE_ENABLED");
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");
119 if (message.getExchange().containsKey("AAI_LOGGING_TRACE_LOGRESPONSE")) {
120 message.getExchange().remove("AAI_LOGGING_TRACE_LOGRESPONSE");
124 if (go == false) { // there's nothing to do
128 // DONE: get a TXID based on hostname, time (YYYYMMDDHHMMSSMILLIS, and LoggingMessage.nextId(); 20150326145301-1
129 String now = genDate(aaiLogger, logline);
131 message.getExchange().put("AAI_RQST_TM", now);
133 String id = (String)message.getExchange().get(LoggingMessage.ID_KEY);
135 String fullId = null;
138 id = LoggingMessage.nextId();
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);
146 if (fullId == null) {
147 fullId = now + "-" + id;
148 fullId = HbaseSaltPrefixer.getInstance().prependSalt(fullId);
150 message.put(LoggingMessage.ID_KEY, fullId);
151 final LoggingMessage buffer = new LoggingMessage("Message", fullId);
153 Integer responseCode = (Integer)message.get(Message.RESPONSE_CODE);
154 if (responseCode != null) {
155 buffer.getResponseCode().append(responseCode);
158 String encoding = (String)message.get(Message.ENCODING);
160 if (encoding != null) {
161 buffer.getEncoding().append(encoding);
163 String httpMethod = (String)message.get(Message.HTTP_REQUEST_METHOD);
164 if (httpMethod != null) {
165 buffer.getHttpMethod().append(httpMethod);
168 String ct = (String)message.get(Message.CONTENT_TYPE);
170 if ("*/*".equals(ct)) {
171 message.put(Message.CONTENT_TYPE, MediaType.APPLICATION_JSON);
172 ct = MediaType.APPLICATION_JSON;
174 buffer.getContentType().append(ct);
177 Object headers = message.get(Message.PROTOCOL_HEADERS);
178 if (headers != null) {
179 buffer.getHeader().append(headers);
181 Map<String, List<String>> headersList = CastUtils.cast((Map<?, ?>)message.get(Message.PROTOCOL_HEADERS));
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;
190 for (String transIdValue : xt) {
191 transId = transIdValue;
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];
203 // punt, we tried to find it, it has a colon but no UUID-1
204 newTransId = UUID.randomUUID().toString();
207 newTransId = UUID.randomUUID().toString();
211 newTransId = UUID.randomUUID().toString();
212 missingTransId = true;
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;
227 List<String> fa = headersList.get("X-FromAppId");
229 for (String fromAppIdValue : fa) {
230 fromAppId = fromAppIdValue;
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));
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);
245 logline.add("HbaseTxId", fullId);
246 aaiLogger.info(logline, true, "0");
251 buffer.getAddress().append(uri);
253 buffer.getAddress().append("?").append(query);
257 InputStream is = message.getContent(InputStream.class);
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);
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);
281 * @param aaiLogger the aai logger
282 * @param logline the logline
285 protected String genDate(AAILogger aaiLogger, LogLine logline) {
286 Date date = new Date();
287 DateFormat formatter = null;
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);
294 if (formatter == null) {
295 formatter = new SimpleDateFormat("YYMMdd-HH:mm:ss:SSS");
299 return formatter.format(date);