Update Logging
[so.git] / common / src / main / java / org / onap / so / logging / jaxrs / filter / JaxRsClientLogging.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
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.onap.so.logging.jaxrs.filter;
22
23
24 import org.apache.commons.io.IOUtils;
25 import org.onap.logging.ref.slf4j.ONAPLogConstants;
26 import org.onap.so.utils.TargetEntity;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29 import org.slf4j.MDC;
30 import org.slf4j.MarkerFactory;
31 import org.springframework.stereotype.Component;
32 import javax.annotation.Priority;
33 import javax.ws.rs.client.ClientRequestContext;
34 import javax.ws.rs.client.ClientRequestFilter;
35 import javax.ws.rs.client.ClientResponseContext;
36 import javax.ws.rs.client.ClientResponseFilter;
37 import javax.ws.rs.container.ContainerRequestContext;
38 import javax.ws.rs.container.ContainerResponseContext;
39 import javax.ws.rs.core.Context;
40 import javax.ws.rs.core.MediaType;
41 import javax.ws.rs.core.MultivaluedMap;
42 import javax.ws.rs.core.Response;
43 import javax.ws.rs.ext.MessageBodyWriter;
44 import javax.ws.rs.ext.Providers;
45 import java.io.*;
46 import java.lang.annotation.Annotation;
47 import java.lang.reflect.Type;
48 import java.time.ZoneOffset;
49 import java.time.ZonedDateTime;
50 import java.time.format.DateTimeFormatter;
51 import java.util.Map;
52 import java.util.UUID;
53
54 @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
55 @Component
56 @Priority(0)
57 public class JaxRsClientLogging implements ClientRequestFilter,ClientResponseFilter {
58     
59     @Context 
60     private Providers providers;
61
62     private static final String TRACE = "trace-#";
63     private static final String SO = "SO";
64     private static Logger logger = LoggerFactory.getLogger(JaxRsClientLogging.class);
65
66     public void setTargetService(TargetEntity targetEntity){
67         MDC.put(ONAPLogConstants.MDCs.TARGET_ENTITY, targetEntity.toString());
68     }
69
70     @Override
71     public void filter(ClientRequestContext clientRequest) {
72         try{
73             setupMDC(clientRequest);
74             setupHeaders(clientRequest);
75             logger.info(ONAPLogConstants.Markers.INVOKE, "Invoke");
76         } catch (Exception e) {
77             logger.warn("Error in incoming JAX-RS Inteceptor", e);
78         }
79     }
80
81     private void setupHeaders(ClientRequestContext clientRequest) {
82         MultivaluedMap<String, Object> headers = clientRequest.getHeaders();
83         headers.add(ONAPLogConstants.Headers.REQUEST_ID, extractRequestID(clientRequest));
84         headers.add(ONAPLogConstants.Headers.INVOCATION_ID, MDC.get(ONAPLogConstants.MDCs.INVOCATION_ID));
85         headers.add(ONAPLogConstants.Headers.PARTNER_NAME, SO);
86     }
87
88     private void setupMDC(ClientRequestContext clientRequest) {
89         MDC.put(ONAPLogConstants.MDCs.INVOKE_TIMESTAMP, ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT));
90         MDC.put(ONAPLogConstants.MDCs.TARGET_SERVICE_NAME, clientRequest.getUri().toString());
91         MDC.put(ONAPLogConstants.MDCs.RESPONSE_STATUS_CODE, ONAPLogConstants.ResponseStatus.INPROGRESS.toString());
92         setInvocationId();
93         MDC.put(ONAPLogConstants.MDCs.TARGET_ENTITY,MDC.get(ONAPLogConstants.MDCs.TARGET_ENTITY));
94     }
95
96     private String extractRequestID(ClientRequestContext clientRequest) {
97         String requestId = MDC.get(ONAPLogConstants.MDCs.REQUEST_ID);
98         if(requestId == null || requestId.isEmpty() || requestId.equals(TRACE)){
99             requestId = UUID.randomUUID().toString();
100             logger.warn("Could not Find Request ID Generating New One: {}",clientRequest.getUri().getPath());
101         }
102         return requestId;
103     }   
104
105     private void setInvocationId() {
106         String invocationId = MDC.get(ONAPLogConstants.MDCs.INVOCATION_ID);
107         if(invocationId == null || invocationId.isEmpty())
108             invocationId =UUID.randomUUID().toString();
109         MDC.put(ONAPLogConstants.MDCs.INVOCATION_ID, invocationId);
110     }
111
112
113     @Override
114     public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) {
115
116         try {
117             String statusCode;
118             if(Response.Status.Family.familyOf(responseContext.getStatus()).equals(Response.Status.Family.SUCCESSFUL)){         
119                 statusCode=ONAPLogConstants.ResponseStatus.COMPLETED.toString();
120             }else{                                                      
121                 statusCode=ONAPLogConstants.ResponseStatus.ERROR.toString();                            
122             }
123             MDC.put(ONAPLogConstants.MDCs.RESPONSE_CODE, String.valueOf(responseContext.getStatus()));
124             MDC.put(ONAPLogConstants.MDCs.RESPONSE_DESCRIPTION,getStringFromInputStream(responseContext));
125             MDC.put(ONAPLogConstants.MDCs.RESPONSE_STATUS_CODE, statusCode);
126             logger.info(ONAPLogConstants.Markers.INVOKE_RETURN, "InvokeReturn");
127             clearClientMDCs();
128         } catch ( Exception e) {
129             logger.warn("Error in outgoing JAX-RS Inteceptor", e);
130         }
131     }
132
133     private void clearClientMDCs() {
134         MDC.remove(ONAPLogConstants.MDCs.INVOCATION_ID);
135         MDC.remove(ONAPLogConstants.MDCs.RESPONSE_DESCRIPTION);
136         MDC.remove(ONAPLogConstants.MDCs.RESPONSE_STATUS_CODE);
137         MDC.remove(ONAPLogConstants.MDCs.RESPONSE_DESCRIPTION);
138         MDC.remove(ONAPLogConstants.MDCs.RESPONSE_CODE);
139         MDC.remove(ONAPLogConstants.MDCs.TARGET_ENTITY);
140         MDC.remove(ONAPLogConstants.MDCs.PARTNER_NAME);
141         MDC.remove(ONAPLogConstants.MDCs.TARGET_SERVICE_NAME);
142         MDC.remove(ONAPLogConstants.MDCs.INVOKE_TIMESTAMP);
143     }
144
145     private static String getStringFromInputStream(ClientResponseContext clientResponseContext) {
146
147         InputStream is = clientResponseContext.getEntityStream();
148         ByteArrayOutputStream boas = new ByteArrayOutputStream();
149
150         try {
151             IOUtils.copy(is,boas);
152             InputStream copiedStream = new ByteArrayInputStream(boas.toByteArray());
153             clientResponseContext.setEntityStream(copiedStream);
154             return boas.toString();
155
156         } catch (IOException e) {
157             logger.warn("Failed to read response body", e);
158         }
159         return "Unable to read input stream";
160     }
161
162 }