2 * Copyright © 2016-2018 European Support Limited
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package org.openecomp.sdc.logging.servlet.spring;
19 import static org.openecomp.sdc.logging.api.StatusCode.COMPLETE;
20 import static org.openecomp.sdc.logging.api.StatusCode.ERROR;
21 import static org.springframework.http.HttpStatus.Series.REDIRECTION;
22 import static org.springframework.http.HttpStatus.Series.SUCCESSFUL;
24 import java.util.Objects;
25 import javax.servlet.http.HttpServletRequest;
26 import javax.servlet.http.HttpServletResponse;
27 import org.openecomp.sdc.logging.api.Logger;
28 import org.openecomp.sdc.logging.api.LoggerFactory;
29 import org.openecomp.sdc.logging.api.StatusCode;
30 import org.openecomp.sdc.logging.servlet.AuditTracker;
31 import org.openecomp.sdc.logging.servlet.CombinedTracker;
32 import org.openecomp.sdc.logging.servlet.ContextTracker;
33 import org.openecomp.sdc.logging.servlet.HttpHeader;
34 import org.openecomp.sdc.logging.servlet.RequestProcessingResult;
35 import org.openecomp.sdc.logging.servlet.Tracker;
36 import org.springframework.http.HttpStatus;
37 import org.springframework.stereotype.Component;
38 import org.springframework.web.method.HandlerMethod;
39 import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
42 * <p><b>IMPORTANT</b>: For this interceptor to work, all exceptions must be properly handled before being returned to a
43 * client. Any unexpected, automatically handled exception bypasses the interceptor and will not be logged.</p>
44 * <p>The interceptor must be either registered in Spring configuration XML as a bean, or programmatically as described
45 * in <a href="https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-config-interceptors">
46 * Spring MVC Config: Interceptors</a>.</p>
52 public class LoggingInterceptor extends HandlerInterceptorAdapter {
54 static final String LOGGING_TRACKER_KEY = "onap.logging.tracker";
56 private static final Logger LOGGER = LoggerFactory.getLogger(LoggingInterceptor.class);
58 private final HttpHeader partnerNameHeader;
59 private final HttpHeader requestIdHeader;
61 public LoggingInterceptor(HttpHeader partnerNameHeader, HttpHeader requestIdHeader) {
62 this.partnerNameHeader = Objects.requireNonNull(partnerNameHeader);
63 this.requestIdHeader = Objects.requireNonNull(requestIdHeader);
67 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
68 Class<?> resourceClass = getResourceType(handler);
69 Tracker tracker = new CombinedTracker(
70 new ContextTracker(partnerNameHeader, requestIdHeader),
71 new AuditTracker(resourceClass));
72 request.setAttribute(LOGGING_TRACKER_KEY, tracker);
73 tracker.preRequest(request);
78 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
81 Tracker tracker = (Tracker) request.getAttribute(LOGGING_TRACKER_KEY);
83 if (tracker == null) {
84 LOGGER.debug("No logging tracker received");
88 tracker.postRequest(new ServletResponseResult(response.getStatus()));
91 private Class<?> getResourceType(Object handler) {
93 if (handler instanceof HandlerMethod) {
94 return ((HandlerMethod) handler).getMethod().getDeclaringClass();
97 return LoggingInterceptor.class;
100 static class ServletResponseResult implements RequestProcessingResult {
102 private final StatusInfo statusInfo;
104 ServletResponseResult(int status) {
105 this.statusInfo = init(status);
108 private StatusInfo init(int status) {
111 return new StatusInfo(HttpStatus.valueOf(status));
112 } catch (IllegalArgumentException e) {
113 return new StatusInfo(status, "Non-standard HTTP status", HttpStatus.Series.valueOf(status));
118 public int getStatus() {
119 return statusInfo.getStatus();
123 public StatusCode getStatusCode() {
124 return statusInfo.getStatusCode();
128 public String getStatusPhrase() {
129 return statusInfo.getReasonPhrase();
133 private static class StatusInfo {
135 private final int status;
136 private final String reasonPhrase;
137 private final HttpStatus.Series series;
139 private StatusInfo(HttpStatus httpStatus) {
140 this(httpStatus.value(), httpStatus.getReasonPhrase(), httpStatus.series());
143 private StatusInfo(int status, String reasonPhrase, HttpStatus.Series series) {
144 this.status = status;
145 this.reasonPhrase = reasonPhrase;
146 this.series = series;
149 private int getStatus() {
153 private String getReasonPhrase() {
157 private StatusCode getStatusCode() {
158 return series.equals(SUCCESSFUL) || series.equals(REDIRECTION) ? COMPLETE : ERROR;