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.jaxrs;
19 import static org.openecomp.sdc.logging.LoggingConstants.DEFAULT_PARTNER_NAME_HEADER;
20 import static org.openecomp.sdc.logging.LoggingConstants.DEFAULT_REQUEST_ID_HEADER;
22 import java.util.UUID;
23 import javax.servlet.http.HttpServletRequest;
24 import javax.ws.rs.container.ContainerRequestContext;
25 import javax.ws.rs.container.ContainerRequestFilter;
26 import javax.ws.rs.core.Context;
27 import javax.ws.rs.ext.Provider;
28 import org.openecomp.sdc.logging.api.ContextData;
29 import org.openecomp.sdc.logging.api.Logger;
30 import org.openecomp.sdc.logging.api.LoggerFactory;
31 import org.openecomp.sdc.logging.api.LoggingContext;
32 import org.openecomp.sdc.logging.servlet.HttpHeader;
35 * <p>Takes care of logging initialization an HTTP request hits the application. This includes populating logging
36 * context and storing the request processing start time, so that it can be used for audit. The filter was built
37 * <b>works in tandem</b> with {@link LoggingResponseFilter} or a similar implementation.</p>
38 * <p>The filter requires a few HTTP header names to be configured. These HTTP headers are used for propagating logging
39 * and tracing information between ONAP components.</p>
40 * <p>Sample configuration for a Spring environment:</p>
42 * <jaxrs:providers>
43 * <bean class="org.openecomp.sdc.logging.ws.rs.LoggingRequestFilter">
44 * <property name="requestIdHeaders" value="X-ONAP-RequestID"/>
45 * <property name="partnerNameHeaders" value="X-ONAP-InstanceID"/>
47 * </jaxrs:providers>
49 * <p>Keep in mind that the filters does nothing in case when a request cannot be mapped to a working JAX-RS resource
50 * (implementation). For instance, when the path is invalid (404), or there is no handler for a particular method (405).
53 * @author evitaliy, katyr
56 * @see ContainerRequestFilter
59 public class LoggingRequestFilter implements ContainerRequestFilter {
61 static final String MULTI_VALUE_SEPARATOR = ",";
63 static final String START_TIME_KEY = "audit.start.time";
65 private static final Logger LOGGER = LoggerFactory.getLogger(LoggingRequestFilter.class);
67 private HttpServletRequest httpRequest;
69 private HttpHeader requestIdHeader = new HttpHeader(DEFAULT_REQUEST_ID_HEADER);
70 private HttpHeader partnerNameHeader = new HttpHeader(DEFAULT_PARTNER_NAME_HEADER);
71 private boolean includeHttpMethod = true;
74 * Injection of HTTP request object from JAX-RS context.
76 * @param httpRequest automatically injected by JAX-RS container
79 public void setHttpRequest(HttpServletRequest httpRequest) {
80 this.httpRequest = httpRequest;
84 * Configuration parameter to include the HTTP method of a request in service name.
86 public void setHttpMethodInServiceName(boolean includeHttpMethod) {
87 this.includeHttpMethod = includeHttpMethod;
91 * Configuration parameter for request ID HTTP header.
93 public void setRequestIdHeaders(String requestIdHeaders) {
94 LOGGER.debug("Valid request ID headers: {}", requestIdHeaders);
95 this.requestIdHeader = new HttpHeader(requestIdHeaders.split(MULTI_VALUE_SEPARATOR));
99 * Configuration parameter for partner name HTTP header.
101 public void setPartnerNameHeaders(String partnerNameHeaders) {
102 LOGGER.debug("Valid partner name headers: {}", partnerNameHeaders);
103 this.partnerNameHeader = new HttpHeader(partnerNameHeaders.split(MULTI_VALUE_SEPARATOR));
107 public void filter(ContainerRequestContext containerRequestContext) {
109 LoggingContext.clear();
111 containerRequestContext.setProperty(START_TIME_KEY, System.currentTimeMillis());
113 ContextData.ContextDataBuilder contextData = ContextData.builder();
114 contextData.serviceName(getServiceName());
116 String partnerName = partnerNameHeader.getAny(containerRequestContext::getHeaderString);
117 if (partnerName != null) {
118 contextData.partnerName(partnerName);
121 String requestId = requestIdHeader.getAny(containerRequestContext::getHeaderString);
122 contextData.requestId(requestId == null ? UUID.randomUUID().toString() : requestId);
124 LoggingContext.put(contextData.build());
127 private String getServiceName() {
128 return includeHttpMethod
129 ? formatServiceName(this.httpRequest.getMethod(), this.httpRequest.getRequestURI())
130 : this.httpRequest.getRequestURI();
133 static String formatServiceName(String httpMethod, String requestUri) {
134 return httpMethod + " " + requestUri;