Simplified logging code for servlets

Added and simplified unit tests, organized imports,
refactored for simplicity and reuse.

Change-Id: I4c4837447329528ae855f2e8d1a1f4b883617f33
Issue-ID: SDC-1580
Signed-off-by: vempo <vitaliy.emporopulo@amdocs.com>
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/pom.xml b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/pom.xml
index 29efa61..2bd26ed 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/pom.xml
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/pom.xml
@@ -34,29 +34,17 @@
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>org.easymock</groupId>
-            <artifactId>easymock</artifactId>
-            <version>${easymock.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.powermock</groupId>
-            <artifactId>powermock-api-easymock</artifactId>
-            <version>${powermock.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.powermock</groupId>
-            <artifactId>powermock-core</artifactId>
-            <version>${powermock.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
             <groupId>org.powermock</groupId>
             <artifactId>powermock-module-junit4</artifactId>
             <version>${powermock.version}</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.powermock</groupId>
+            <artifactId>powermock-api-mockito2</artifactId>
+            <version>${powermock.version}</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
 </project>
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/LoggerFactory.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/LoggerFactory.java
index 30517cd..96debb5 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/LoggerFactory.java
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/LoggerFactory.java
@@ -16,9 +16,8 @@
 
 package org.openecomp.sdc.logging.api;
 
-import org.openecomp.sdc.logging.spi.LoggerCreationService;
-
 import java.util.Objects;
+import org.openecomp.sdc.logging.spi.LoggerCreationService;
 
 /**
  * <a>Factory to hide a concrete, framework-specific implementation of logger creation.</a>
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/LoggingContext.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/LoggingContext.java
index 9526713..894dd2c 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/LoggingContext.java
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/LoggingContext.java
@@ -16,10 +16,9 @@
 
 package org.openecomp.sdc.logging.api;
 
-import org.openecomp.sdc.logging.spi.LoggingContextService;
-
 import java.util.Objects;
 import java.util.concurrent.Callable;
+import org.openecomp.sdc.logging.spi.LoggingContextService;
 
 /**
  * <p>Factory to hide a concrete, framework-specific implementation of diagnostic context.</p>
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/ServiceBinder.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/ServiceBinder.java
index 5aaa301..6e5b3e3 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/ServiceBinder.java
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/ServiceBinder.java
@@ -16,13 +16,12 @@
 
 package org.openecomp.sdc.logging.api;
 
-import org.openecomp.sdc.logging.spi.LoggerCreationService;
-import org.openecomp.sdc.logging.spi.LoggingContextService;
-import org.openecomp.sdc.logging.spi.LoggingServiceProvider;
-
 import java.util.Iterator;
 import java.util.Optional;
 import java.util.ServiceLoader;
+import org.openecomp.sdc.logging.spi.LoggerCreationService;
+import org.openecomp.sdc.logging.spi.LoggingContextService;
+import org.openecomp.sdc.logging.spi.LoggingServiceProvider;
 
 /**
  * <p>Binds to a concrete implementation of logging services.</p>
@@ -37,7 +36,7 @@
 
 // No advanced logging can be used here because we don't know
 // which underlying implementation will be used
-@SuppressWarnings({"UseOfSystemOutOrSystemErr", "squid:S106"})
+@SuppressWarnings({"UseOfSystemOutOrSystemErr", "squid:S106", "squid:S1166"})
 class ServiceBinder {
 
     private static final LoggingServiceProvider PROVIDER = lookupProvider();
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/AuditTracker.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/AuditTracker.java
new file mode 100644
index 0000000..af9b506
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/AuditTracker.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openecomp.sdc.logging.servlet;
+
+import java.util.Objects;
+import javax.servlet.http.HttpServletRequest;
+import org.openecomp.sdc.logging.api.AuditData;
+import org.openecomp.sdc.logging.api.Logger;
+import org.openecomp.sdc.logging.api.LoggerFactory;
+
+/**
+ * Tracks and logs audit information when a request is being processed. An instance of this class cannot be reused, and
+ * the pre- and post-request methods must be called only once.
+ *
+ * @author evitaliy
+ * @since 31 Jul 2018
+ */
+public class AuditTracker implements Tracker {
+
+    private final Logger logger;
+    private volatile long started;
+    private volatile String clientIpAddress;
+
+    /**
+     * Allows passing a class that will be used to log audit.
+     *
+     * @param resourceType audit will be logged through the logger of this class
+     */
+    public AuditTracker(Class<?> resourceType) {
+        this.logger = LoggerFactory.getLogger(resourceType);
+    }
+
+    /**
+     * Allows passing a logger that will be used to log audit.
+     *
+     * @param logger audit will be logged through this logger, cannot be null
+     */
+    public AuditTracker(Logger logger) {
+        this.logger = Objects.requireNonNull(logger);
+    }
+
+    @Override
+    public synchronized void preRequest(HttpServletRequest request) {
+
+        if (this.started > 0) {
+            throw new IllegalStateException("Pre-request has been already called");
+        }
+
+        this.started = System.currentTimeMillis();
+        this.clientIpAddress = request.getRemoteAddr();
+    }
+
+    @Override
+    public synchronized void postRequest(RequestProcessingResult result) {
+
+        if (this.started == 0) {
+            throw new IllegalStateException("Pre-request must be called first");
+        }
+
+        if (!logger.isAuditEnabled()) {
+            return;
+        }
+
+        long end = System.currentTimeMillis();
+        AuditData auditData = AuditData.builder().startTime(started).endTime(end).statusCode(result.getStatusCode())
+                                      .responseCode(Integer.toString(result.getStatus()))
+                                      .responseDescription(result.getStatusPhrase()).clientIpAddress(clientIpAddress)
+                                      .build();
+        logger.audit(auditData);
+    }
+}
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/CombinedTracker.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/CombinedTracker.java
new file mode 100644
index 0000000..2dd2c12
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/CombinedTracker.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openecomp.sdc.logging.servlet;
+
+import javax.servlet.http.HttpServletRequest;
+import org.openecomp.sdc.logging.api.Logger;
+
+/**
+ * Tracker for all the elements of ONAP logging and tracing at an entry point to an application - context and audit.
+ * The order of invocations is important, assuming the context must be kept as long as audit hasn't been finished.
+ *
+ * @author evitaliy
+ * @since 01 Aug 2018
+ */
+public class CombinedTracker implements Tracker {
+
+    private final ContextTracker context;
+    private final AuditTracker audit;
+
+    public CombinedTracker(Logger logger, HttpHeader partnerNameHeader, HttpHeader requestIdHeader) {
+        this.context = new ContextTracker(partnerNameHeader, requestIdHeader);
+        this.audit = new AuditTracker(logger);
+    }
+
+    public CombinedTracker(Class<?> resourceType, HttpHeader partnerNameHeader, HttpHeader requestIdHeader) {
+        this.context = new ContextTracker(partnerNameHeader, requestIdHeader);
+        this.audit = new AuditTracker(resourceType);
+    }
+
+    @Override
+    public void preRequest(HttpServletRequest request) {
+        this.context.preRequest(request);
+        this.audit.preRequest(request);
+    }
+
+    @Override
+    public void postRequest(RequestProcessingResult result) {
+        this.audit.postRequest(result);
+        this.context.postRequest(result);
+    }
+}
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/ContextTracker.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/ContextTracker.java
new file mode 100644
index 0000000..2334f37
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/ContextTracker.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openecomp.sdc.logging.servlet;
+
+import java.util.Objects;
+import java.util.UUID;
+import javax.servlet.http.HttpServletRequest;
+import org.openecomp.sdc.logging.api.ContextData;
+import org.openecomp.sdc.logging.api.LoggingContext;
+
+/**
+ * Populates the context before a request is processed, and cleans it after the request has been processed.
+ *
+ * @author evitaliy
+ * @since 31 Jul 2018
+ */
+public class ContextTracker implements Tracker {
+
+    private final HttpHeader partnerNameHeaders;
+    private final HttpHeader requestIdHeaders;
+
+    /**
+     * Constructs tracker to handle required logging context in Servlet-based applications. Refer to ONAP logging
+     * guidelines for fields required to be put on logging context.
+     *
+     * @param partnerNameHeaders HTTP headers to check for a partner name, cannot be null
+     * @param requestIdHeaders   HTTP headers to check for a request ID, cannot be null
+     */
+    public ContextTracker(HttpHeader partnerNameHeaders, HttpHeader requestIdHeaders) {
+        this.partnerNameHeaders = Objects.requireNonNull(partnerNameHeaders);
+        this.requestIdHeaders = Objects.requireNonNull(requestIdHeaders);
+    }
+
+    @Override
+    public void preRequest(HttpServletRequest request) {
+
+        LoggingContext.clear();
+
+        String serviceName = ServiceNameFormatter.format(request);
+        String requestId = requestIdHeaders.getAny(request::getHeader).orElse(UUID.randomUUID().toString());
+        ContextData.ContextDataBuilder contextBuilder =
+                ContextData.builder().serviceName(serviceName).requestId(requestId);
+
+        partnerNameHeaders.getAny(request::getHeader).ifPresent(contextBuilder::partnerName);
+        LoggingContext.put(contextBuilder.build());
+    }
+
+    @Override
+    public void postRequest(RequestProcessingResult result) {
+        LoggingContext.clear();
+    }
+}
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/HttpHeader.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/HttpHeader.java
index 4dcc197..db10c2e 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/HttpHeader.java
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/HttpHeader.java
@@ -16,6 +16,11 @@
 
 package org.openecomp.sdc.logging.servlet;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
 import java.util.function.Function;
 
 /**
@@ -28,28 +33,80 @@
  */
 public class HttpHeader {
 
-    private final String[] keys;
+    private static final String NAMES_CANNOT_BE_NULL = "Names cannot be null";
+    private static final String AT_LEAST_ONE_NAME_REQUIRED = "At least one name required";
 
-    public HttpHeader(String... keys) {
-        this.keys = keys;
+    private final List<String> headerNames;
+
+    /**
+     * Receives a list of accepted header names as a String array.
+     *
+     * @param headerNames cannot be null or empty
+     */
+    public HttpHeader(String[] headerNames) {
+
+        if (Objects.requireNonNull(headerNames, NAMES_CANNOT_BE_NULL).length < 1) {
+            throw new IllegalArgumentException(AT_LEAST_ONE_NAME_REQUIRED);
+        }
+
+        this.headerNames = Arrays.asList(headerNames);
+    }
+
+    /**
+     * Receives a list of accepted header names as a list of String.
+     *
+     * @param headerNames cannot be null or empty
+     */
+    public HttpHeader(List<String> headerNames) {
+
+        if (Objects.requireNonNull(headerNames, NAMES_CANNOT_BE_NULL).isEmpty()) {
+            throw new IllegalArgumentException(AT_LEAST_ONE_NAME_REQUIRED);
+        }
+
+        this.headerNames = new ArrayList<>(headerNames);
     }
 
     /**
      * Returns the value of any of the possible headers.
      *
      * @param reader function for reading an HTTP header.
-     * @return value or null if not found
+     * @return value or empty if not found
      */
-    public String getAny(Function<String, String> reader) {
+    public Optional<String> getAny(Function<String, String> reader) {
 
-        for (String k : keys) {
+        for (String k : headerNames) {
 
             String value = reader.apply(k);
             if (value != null) {
-                return value;
+                return Optional.of(value);
             }
         }
 
-        return null;
+        return Optional.empty();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+
+        if (this == o) {
+            return true;
+        }
+
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        HttpHeader that = (HttpHeader) o;
+        return Objects.equals(headerNames, that.headerNames);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(headerNames);
+    }
+
+    @Override
+    public String toString() {
+        return "HttpHeader{headerNames=" + headerNames + '}';
     }
 }
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/LoggingFilter.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/LoggingFilter.java
deleted file mode 100644
index e53f281..0000000
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/LoggingFilter.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright © 2016-2018 European Support Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.openecomp.sdc.logging.servlet;
-
-import static org.openecomp.sdc.logging.LoggingConstants.DEFAULT_PARTNER_NAME_HEADER;
-import static org.openecomp.sdc.logging.LoggingConstants.DEFAULT_REQUEST_ID_HEADER;
-
-import java.io.IOException;
-import java.util.UUID;
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import org.openecomp.sdc.logging.api.ContextData;
-import org.openecomp.sdc.logging.api.Logger;
-import org.openecomp.sdc.logging.api.LoggerFactory;
-import org.openecomp.sdc.logging.api.LoggingContext;
-import org.openecomp.sdc.logging.servlet.jaxrs.LoggingRequestFilter;
-import org.openecomp.sdc.logging.servlet.jaxrs.LoggingResponseFilter;
-
-/**
- * <p>Places logging context information. Must be configured as a servlet filter in <i>web.xml</i>. The behavior can be
- * customized via init-params.</p>
- * <p>Example:</p>
- * <pre>
- *
- *  &lt;filter&gt;
- *      &lt;filter-name&gt;LoggingServletFilter&lt;/filter-name&gt;
- *      &lt;filter-class&gt;org.openecomp.sdc.logging.servlet.LoggingFilter&lt;/filter-class&gt;
- *      &lt;init-param&gt;
- *          &lt;param-name&gt;requestIdHeaders&lt;/param-name&gt;
- *          &lt;param-value&gt;X-ONAP-RequestID&lt;/param-value&gt;
- *      &lt;/init-param&gt;
- *      &lt;init-param&gt;
- *          &lt;param-name&gt;partnerNameHeaders&lt;/param-name&gt;
- *          &lt;param-value&gt;USER_ID&lt;/param-value&gt;
- *      &lt;/init-param&gt;
- *  &lt;/filter&gt;
- *
- *  &lt;filter-mapping&gt;
- *      &lt;filter-name&gt;LoggingServletFilter&lt;/filter-name&gt;
- *      &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
- *  &lt;/filter-mapping&gt;
- *
- * </pre>
- *
- * @author evitaliy
- * @since 25 Jul 2016
- * @deprecated Kept for backward compatibility. For JAX-RS application, use
- * {@link LoggingRequestFilter} and
- * {@link LoggingResponseFilter} instead.
- */
-@Deprecated
-public class LoggingFilter implements Filter {
-
-    static final String MULTI_VALUE_SEPARATOR = ",";
-
-    static final String REQUEST_ID_HEADERS_PARAM = "requestIdHeaders";
-    static final String PARTNER_NAME_HEADERS_PARAM = "partnerNameHeaders";
-
-    private static final Logger LOGGER = LoggerFactory.getLogger(LoggingFilter.class);
-
-    private HttpHeader requestIdHeaders;
-    private HttpHeader partnerNameHeaders;
-
-    @Override
-    public void init(FilterConfig config) {
-        requestIdHeaders = getInitParam(config, REQUEST_ID_HEADERS_PARAM, DEFAULT_REQUEST_ID_HEADER);
-        partnerNameHeaders = getInitParam(config, PARTNER_NAME_HEADERS_PARAM, DEFAULT_PARTNER_NAME_HEADER);
-    }
-
-    @Override
-    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
-            throws IOException, ServletException {
-
-        HttpServletRequest httpRequest = HttpServletRequest.class.cast(request);
-
-        try {
-
-            LoggingContext.clear();
-
-            ContextData.ContextDataBuilder contextData = ContextData.builder();
-
-            contextData.serviceName(httpRequest.getRequestURI());
-
-            String requestId = requestIdHeaders.getAny(httpRequest::getHeader);
-            contextData.requestId(requestId == null ? UUID.randomUUID().toString() : requestId);
-
-            String partner = partnerNameHeaders.getAny(httpRequest::getHeader);
-            if (partner != null) {
-                contextData.partnerName(partner);
-            }
-
-            LoggingContext.put(contextData.build());
-
-            chain.doFilter(request, response);
-
-        } finally {
-            LoggingContext.clear();
-        }
-    }
-
-    @Override
-    public void destroy() {
-        // forced by the interface - not implemented
-    }
-
-    private HttpHeader getInitParam(FilterConfig config, String paramName, String defaultValue) {
-
-        String value = config.getInitParameter(paramName);
-        LOGGER.debug("Logging filter configuration param '{}' value '{}'", paramName, value);
-
-        if (value == null) {
-            return new HttpHeader(defaultValue);
-        } else {
-            return new HttpHeader(value.split(MULTI_VALUE_SEPARATOR));
-        }
-    }
-}
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/RequestProcessingResult.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/RequestProcessingResult.java
new file mode 100644
index 0000000..d3625ed
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/RequestProcessingResult.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openecomp.sdc.logging.servlet;
+
+import org.openecomp.sdc.logging.api.StatusCode;
+
+/**
+ * Interpretation of request processing results.
+ *
+ * @author evitaliy
+ * @since 02 Aug 2018
+ */
+public interface RequestProcessingResult {
+
+    /**
+     * Numeric status code.
+     *
+     * @return usually HTTP response status.
+     */
+    int getStatus();
+
+    /**
+     * Whether the response is considered success or failure.
+     *
+     * @return on of pre-defined status codes
+     */
+    StatusCode getStatusCode();
+
+    /**
+     * Human-friendly description of the numeric status.
+     *
+     * @return usually HTTP reason phrase
+     */
+    String getStatusPhrase();
+}
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/ServiceNameFormatter.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/ServiceNameFormatter.java
new file mode 100644
index 0000000..f65490b
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/ServiceNameFormatter.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openecomp.sdc.logging.servlet;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Formats a service name based on HTTP method and request URI.
+ *
+ * @author evitaliy
+ * @since 01 Aug 2018
+ */
+class ServiceNameFormatter {
+
+    private ServiceNameFormatter() {
+        // utility class, prevent instantiation
+    }
+
+    public static String format(HttpServletRequest request) {
+        return request.getMethod() + ": " + request.getRequestURI();
+    }
+}
\ No newline at end of file
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/Tracker.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/Tracker.java
new file mode 100644
index 0000000..c0337cf
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/Tracker.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openecomp.sdc.logging.servlet;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Tracks logging and tracing information through the processing of an HTTP request.
+ *
+ * @author evitaliy
+ * @since 31 Jul 2018
+ */
+public interface Tracker {
+
+    /**
+     * Will be executed before request processing has started.
+     *
+     * @param request provided by every Servlet container
+     */
+    void preRequest(HttpServletRequest request);
+
+    /**
+     * Will be executed after a request has been processed.  Results may be treated differently depending on a container
+     * and application. For instance, JAX-RS applications may take into account exception mappers before generating a
+     * response; some applications may Swagger annotations to map a response status to a human-friendly message, etc.
+     *
+     * @param result application- and container-specific request results
+     */
+    void postRequest(RequestProcessingResult result);
+}
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/jaxrs/LoggingRequestFilter.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/jaxrs/LoggingRequestFilter.java
index 0e1b7d7..f846359 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/jaxrs/LoggingRequestFilter.java
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/jaxrs/LoggingRequestFilter.java
@@ -19,25 +19,24 @@
 import static org.openecomp.sdc.logging.LoggingConstants.DEFAULT_PARTNER_NAME_HEADER;
 import static org.openecomp.sdc.logging.LoggingConstants.DEFAULT_REQUEST_ID_HEADER;
 
-import java.util.UUID;
 import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.container.ContainerRequestContext;
 import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.ResourceInfo;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.ext.Provider;
-import org.openecomp.sdc.logging.api.ContextData;
 import org.openecomp.sdc.logging.api.Logger;
 import org.openecomp.sdc.logging.api.LoggerFactory;
-import org.openecomp.sdc.logging.api.LoggingContext;
+import org.openecomp.sdc.logging.servlet.CombinedTracker;
 import org.openecomp.sdc.logging.servlet.HttpHeader;
+import org.openecomp.sdc.logging.servlet.Tracker;
 
 /**
  * <p>Takes care of logging initialization an HTTP request hits the application. This includes populating logging
- * context and storing the request processing start time, so that it can be used for audit. The filter was built
- * <b>works in tandem</b> with {@link LoggingResponseFilter} or a similar implementation.</p>
+ * context and tracking the request for audit. The filter <b>works in tandem</b> with {@link LoggingResponseFilter} or
+ * a similar implementation.</p>
  * <p>The filter requires a few HTTP header names to be configured. These HTTP headers are used for propagating logging
- * and tracing information between ONAP components.</p>
- * <p>Sample configuration for a Spring environment:</p>
+ * and tracing information between ONAP components. Sample configuration for a Spring environment:</p>
  * <pre>
  *     &lt;jaxrs:providers&gt;
  *         &lt;bean class="org.openecomp.sdc.logging.ws.rs.LoggingRequestFilter"&gt;
@@ -51,24 +50,33 @@
  * </p>
  *
  * @author evitaliy, katyr
- * @since 29 Oct 17
- *
  * @see ContainerRequestFilter
+ * @since 29 Oct 17
  */
 @Provider
 public class LoggingRequestFilter implements ContainerRequestFilter {
 
-    static final String MULTI_VALUE_SEPARATOR = ",";
+    static final String LOGGING_TRACKER_KEY = "onap.logging.tracker";
 
-    static final String START_TIME_KEY = "audit.start.time";
-
+    private static final String MULTI_VALUE_SEPARATOR = ",";
     private static final Logger LOGGER = LoggerFactory.getLogger(LoggingRequestFilter.class);
 
     private HttpServletRequest httpRequest;
 
-    private HttpHeader requestIdHeader = new HttpHeader(DEFAULT_REQUEST_ID_HEADER);
-    private HttpHeader partnerNameHeader = new HttpHeader(DEFAULT_PARTNER_NAME_HEADER);
-    private boolean includeHttpMethod = true;
+    private HttpHeader requestIdHeader = new HttpHeader(new String[] {DEFAULT_REQUEST_ID_HEADER});
+    private HttpHeader partnerNameHeader = new HttpHeader(new String[] {DEFAULT_PARTNER_NAME_HEADER});
+
+    private ResourceInfo resource;
+
+    /**
+     * Injection of a resource that matches the request from JAX-RS context.
+     *
+     * @param resource automatically injected by JAX-RS container
+     */
+    @Context
+    public void setResource(ResourceInfo resource) {
+        this.resource = resource;
+    }
 
     /**
      * Injection of HTTP request object from JAX-RS context.
@@ -81,13 +89,6 @@
     }
 
     /**
-     * Configuration parameter to include the HTTP method of a request in service name.
-     */
-    public void setHttpMethodInServiceName(boolean includeHttpMethod) {
-        this.includeHttpMethod = includeHttpMethod;
-    }
-
-    /**
      * Configuration parameter for request ID HTTP header.
      */
     public void setRequestIdHeaders(String requestIdHeaders) {
@@ -104,33 +105,10 @@
     }
 
     @Override
-    public void filter(ContainerRequestContext containerRequestContext) {
-
-        LoggingContext.clear();
-
-        containerRequestContext.setProperty(START_TIME_KEY, System.currentTimeMillis());
-
-        ContextData.ContextDataBuilder contextData = ContextData.builder();
-        contextData.serviceName(getServiceName());
-
-        String partnerName = partnerNameHeader.getAny(containerRequestContext::getHeaderString);
-        if (partnerName != null) {
-            contextData.partnerName(partnerName);
-        }
-
-        String requestId = requestIdHeader.getAny(containerRequestContext::getHeaderString);
-        contextData.requestId(requestId == null ? UUID.randomUUID().toString() : requestId);
-
-        LoggingContext.put(contextData.build());
-    }
-
-    private String getServiceName() {
-        return includeHttpMethod
-                       ? formatServiceName(this.httpRequest.getMethod(), this.httpRequest.getRequestURI())
-                       : this.httpRequest.getRequestURI();
-    }
-
-    static String formatServiceName(String httpMethod, String requestUri) {
-        return httpMethod + " " + requestUri;
+    public void filter(ContainerRequestContext requestContext) {
+        Class<?> resourceClass = resource.getResourceMethod().getDeclaringClass();
+        Tracker tracker = new CombinedTracker(resourceClass, partnerNameHeader, requestIdHeader);
+        requestContext.setProperty(LOGGING_TRACKER_KEY, tracker);
+        tracker.preRequest(httpRequest);
     }
 }
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/jaxrs/LoggingResponseFilter.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/jaxrs/LoggingResponseFilter.java
index 4609620..fa9e815 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/jaxrs/LoggingResponseFilter.java
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/jaxrs/LoggingResponseFilter.java
@@ -16,19 +16,22 @@
 
 package org.openecomp.sdc.logging.servlet.jaxrs;
 
-import org.openecomp.sdc.logging.api.*;
+import static javax.ws.rs.core.Response.Status.Family.REDIRECTION;
+import static javax.ws.rs.core.Response.Status.Family.SUCCESSFUL;
+import static org.openecomp.sdc.logging.api.StatusCode.COMPLETE;
+import static org.openecomp.sdc.logging.api.StatusCode.ERROR;
+import static org.openecomp.sdc.logging.servlet.jaxrs.LoggingRequestFilter.LOGGING_TRACKER_KEY;
 
-import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.container.ContainerRequestContext;
 import javax.ws.rs.container.ContainerResponseContext;
 import javax.ws.rs.container.ContainerResponseFilter;
-import javax.ws.rs.container.ResourceInfo;
-import javax.ws.rs.core.Context;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.ext.Provider;
-
-import static org.openecomp.sdc.logging.api.StatusCode.COMPLETE;
-import static org.openecomp.sdc.logging.api.StatusCode.ERROR;
+import org.openecomp.sdc.logging.api.Logger;
+import org.openecomp.sdc.logging.api.LoggerFactory;
+import org.openecomp.sdc.logging.api.StatusCode;
+import org.openecomp.sdc.logging.servlet.RequestProcessingResult;
+import org.openecomp.sdc.logging.servlet.Tracker;
 
 /**
  * <p>Takes care of logging when an HTTP request leaves the application. This includes writing to audit and clearing
@@ -44,123 +47,49 @@
  * due to unhandled application or container exceptions.</i></p>
  *
  * @author evitaliy
- * @since 29 Oct 17
- *
  * @see ContainerResponseFilter
+ * @since 29 Oct 17
  */
 @Provider
 public class LoggingResponseFilter implements ContainerResponseFilter {
 
-    private static final int UNKNOWN_START_TIME = 0;
-
     private static final Logger LOGGER = LoggerFactory.getLogger(LoggingResponseFilter.class);
 
-    /**
-     * Tracks reporting configuration problems to the log. We want to report them only once, and not to write to log
-     * upon every request, as the configuration will not change in runtime.
-     */
-    private boolean reportBadConfiguration = true;
-
-    private HttpServletRequest httpRequest;
-
-    private ResourceInfo resource;
-
-    /**
-     * Injection of HTTP request object from JAX-RS context.
-     *
-     * @param httpRequest automatically injected by JAX-RS container
-     */
-    @Context
-    public void setHttpRequest(HttpServletRequest httpRequest) {
-        this.httpRequest = httpRequest;
-    }
-
-    /**
-     * Injection of a resource that matches the request from JAX-RS context.
-     *
-     * @param resource automatically injected by JAX-RS container
-     */
-    @Context
-    public void setResource(ResourceInfo resource) {
-        this.resource = resource;
-    }
-
     @Override
-    public void filter(ContainerRequestContext containerRequestContext,
-            ContainerResponseContext containerResponseContext) {
+    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) {
 
-        try {
+        Tracker tracker = (Tracker) requestContext.getProperty(LOGGING_TRACKER_KEY);
 
-            if ((resource == null) || (resource.getResourceClass() == null)) {
-                LOGGER.debug("No matching resource, skipping audit.");
-                return;
-            }
-
-            writeAudit(containerRequestContext, containerResponseContext);
-
-        } finally {
-            LoggingContext.clear();
-        }
-    }
-
-    private void writeAudit(ContainerRequestContext containerRequestContext,
-            ContainerResponseContext containerResponseContext) {
-
-        Logger resourceLogger = LoggerFactory.getLogger(resource.getResourceMethod().getDeclaringClass());
-        if (!resourceLogger.isAuditEnabled()) {
+        if (tracker == null) {
+            LOGGER.debug("No logging tracker received");
             return;
         }
 
-        long start = readStartTime(containerRequestContext);
-        long end = System.currentTimeMillis();
-
-        Response.StatusType statusInfo = containerResponseContext.getStatusInfo();
-        int responseCode = statusInfo.getStatusCode();
-        StatusCode statusCode = isSuccess(responseCode) ? COMPLETE : ERROR;
-
-        AuditData auditData = AuditData.builder().startTime(start).endTime(end).statusCode(statusCode)
-                                       .responseCode(Integer.toString(responseCode))
-                                       .responseDescription(statusInfo.getReasonPhrase())
-                                       .clientIpAddress(httpRequest.getRemoteAddr()).build();
-        resourceLogger.audit(auditData);
+        tracker.postRequest(new ContainerResponseResult(responseContext.getStatusInfo()));
     }
 
-    private boolean isSuccess(int responseCode) {
-        return responseCode > 199 && responseCode < 400;
-    }
+    private static class ContainerResponseResult implements RequestProcessingResult {
 
-    private long readStartTime(ContainerRequestContext containerRequestContext) {
+        private final Response.StatusType statusInfo;
 
-        Object startTime = containerRequestContext.getProperty(LoggingRequestFilter.START_TIME_KEY);
-        if (startTime == null) {
-            return handleMissingStartTime();
+        private ContainerResponseResult(Response.StatusType statusInfo) {
+            this.statusInfo = statusInfo;
         }
 
-        return parseStartTime(startTime);
-    }
-
-    private long handleMissingStartTime() {
-        reportConfigProblem("{} key was not found in JAX-RS request context. "
-                + "Make sure you configured a request filter", LoggingRequestFilter.START_TIME_KEY);
-        return UNKNOWN_START_TIME;
-    }
-
-    private long parseStartTime(Object startTime) {
-
-        try {
-            return Long.class.cast(startTime);
-        } catch (ClassCastException e) {
-            reportConfigProblem("{} key in JAX-RS request context contains an object of type '{}', but 'java.lang.Long'"
-                    + " is expected", LoggingRequestFilter.START_TIME_KEY, startTime.getClass().getName(), e);
-            return 0;
+        @Override
+        public int getStatus() {
+            return statusInfo.getStatusCode();
         }
-    }
 
-    private void reportConfigProblem(String message, Object... arguments) {
+        @Override
+        public StatusCode getStatusCode() {
+            Response.Status.Family family = statusInfo.getFamily();
+            return family.equals(SUCCESSFUL) || family.equals(REDIRECTION) ? COMPLETE : ERROR;
+        }
 
-        if (reportBadConfiguration) {
-            reportBadConfiguration = false;
-            LOGGER.error(message, arguments);
+        @Override
+        public String getStatusPhrase() {
+            return statusInfo.getReasonPhrase();
         }
     }
 }
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/spi/LoggerCreationService.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/spi/LoggerCreationService.java
index 90aebfa..54b5be3 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/spi/LoggerCreationService.java
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/spi/LoggerCreationService.java
@@ -20,7 +20,6 @@
 import org.openecomp.sdc.logging.api.LoggerFactory;
 
 /**
- *
  * Implements a framework-specific logging, to be used by {@link LoggerFactory}.
  *
  * @author evitaliy
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/spi/LoggingContextService.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/spi/LoggingContextService.java
index 7c71465..37e212a 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/spi/LoggingContextService.java
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/spi/LoggingContextService.java
@@ -16,9 +16,8 @@
 
 package org.openecomp.sdc.logging.spi;
 
-import org.openecomp.sdc.logging.api.ContextData;
-
 import java.util.concurrent.Callable;
+import org.openecomp.sdc.logging.api.ContextData;
 
 /**
  * Should be used to implement a framework-specific mechanism of managing a per-thread diagnostic context (for instance
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/AuditTrackerTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/AuditTrackerTest.java
new file mode 100644
index 0000000..1bd13a9
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/AuditTrackerTest.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openecomp.sdc.logging.servlet;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import javax.servlet.http.HttpServletRequest;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.openecomp.sdc.logging.api.AuditData;
+import org.openecomp.sdc.logging.api.Logger;
+import org.openecomp.sdc.logging.api.StatusCode;
+
+/**
+ * Test initialization and of audit tracker and log invocation.
+ *
+ * @author evitaliy
+ * @since 01 Aug 2018
+ */
+public class AuditTrackerTest {
+
+    @Test(expected = NullPointerException.class)
+    public void throwExceptionWhenLoggerNull() {
+        new AuditTracker((Logger) null);
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void throwExceptionWhenResourceTypeNull() {
+        new AuditTracker((Class<?>) null);
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void throwExceptionWhenPreRequestCalledMoreThanOnce() {
+        AuditTracker tracker = new AuditTracker(mock(Logger.class));
+        HttpServletRequest request = mock(HttpServletRequest.class);
+        tracker.preRequest(request);
+        tracker.preRequest(request);
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void throwExceptionWhenRreRequestNeverCalled() {
+        AuditTracker tracker = new AuditTracker(mock(Logger.class));
+        tracker.postRequest(mock(RequestProcessingResult.class));
+    }
+
+    @Test
+    public void nothingHappensWhenAuditDisabled() {
+
+        Logger logger = mock(Logger.class);
+        when(logger.isAuditEnabled()).thenReturn(false);
+
+        AuditTracker tracker = new AuditTracker(logger);
+        tracker.preRequest(mock(HttpServletRequest.class));
+        tracker.postRequest(mock(RequestProcessingResult.class));
+
+        verify(logger, never()).audit(any(AuditData.class));
+    }
+
+    @Test
+    public void reportedTimePositive() {
+
+        Logger logger = mock(Logger.class);
+        when(logger.isAuditEnabled()).thenReturn(true);
+
+        AuditTracker tracker = new AuditTracker(logger);
+        tracker.preRequest(mock(HttpServletRequest.class));
+        tracker.postRequest(mock(RequestProcessingResult.class));
+
+        ArgumentCaptor<AuditData> auditDataCaptor = ArgumentCaptor.forClass(AuditData.class);
+        verify(logger).audit(auditDataCaptor.capture());
+        assertTrue(auditDataCaptor.getValue().getEndTime() > 0);
+    }
+
+    @Test
+    public void interpretedRequestResultsPassedDownToAudit() {
+
+        Logger logger = mock(Logger.class);
+        when(logger.isAuditEnabled()).thenReturn(true);
+
+        AuditTracker tracker = new AuditTracker(logger);
+        tracker.preRequest(mock(HttpServletRequest.class));
+
+        final StubRequestProcessingResult result = new StubRequestProcessingResult();
+        tracker.postRequest(result);
+
+        ArgumentCaptor<AuditData> auditDataCaptor = ArgumentCaptor.forClass(AuditData.class);
+        verify(logger).audit(auditDataCaptor.capture());
+
+        AuditData capturedAuditData = auditDataCaptor.getValue();
+        assertEquals(Integer.toString(result.getStatus()), capturedAuditData.getResponseCode());
+        assertEquals(result.getStatusCode(), capturedAuditData.getStatusCode());
+        assertEquals(result.getStatusPhrase(), capturedAuditData.getResponseDescription());
+    }
+
+    @Test
+    public void clientIpAddressPassedDownToAudit() {
+
+        Logger logger = mock(Logger.class);
+        when(logger.isAuditEnabled()).thenReturn(true);
+
+        final String address = "196.50.30.122";
+        HttpServletRequest request = mock(HttpServletRequest.class);
+        when(request.getRemoteAddr()).thenReturn(address);
+
+        AuditTracker tracker = new AuditTracker(logger);
+        tracker.preRequest(request);
+        tracker.postRequest(mock(RequestProcessingResult.class));
+
+        ArgumentCaptor<AuditData> auditDataCaptor = ArgumentCaptor.forClass(AuditData.class);
+        verify(logger).audit(auditDataCaptor.capture());
+
+        AuditData capturedAuditData = auditDataCaptor.getValue();
+        assertEquals(address, capturedAuditData.getClientIpAddress());
+    }
+
+    private static class StubRequestProcessingResult implements RequestProcessingResult {
+
+        @Override
+        public int getStatus() {
+            return 505;
+        }
+
+        @Override
+        public StatusCode getStatusCode() {
+            return StatusCode.ERROR;
+        }
+
+        @Override
+        public String getStatusPhrase() {
+            return "Test request failed";
+        }
+    }
+}
\ No newline at end of file
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/ContextTrackerTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/ContextTrackerTest.java
new file mode 100644
index 0000000..a247d11
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/ContextTrackerTest.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openecomp.sdc.logging.servlet;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.powermock.api.mockito.PowerMockito.mock;
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
+import static org.powermock.api.mockito.PowerMockito.verifyStatic;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+import javax.servlet.http.HttpServletRequest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.openecomp.sdc.logging.api.ContextData;
+import org.openecomp.sdc.logging.api.LoggingContext;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+/**
+ * Populating context from request data.
+ *
+ * @author evitaliy
+ * @since 01 Aug 2018
+ */
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(LoggingContext.class)
+public class ContextTrackerTest {
+
+    private static final String X_REQUEST_ID = "X-REQUEST-ID";
+    private static final HttpHeader REQUEST_ID_HEADER = new HttpHeader(new String[] {X_REQUEST_ID});
+
+    private static final String X_PARTNER_NAME = "X-PARTNER-NAME";
+    private static final HttpHeader PARTNER_NAME_HEADER = new HttpHeader(new String[] {X_PARTNER_NAME});
+
+    @Test(expected = NullPointerException.class)
+    public void throwExceptionWhenPartnerNamesNull() {
+        new ContextTracker(null, REQUEST_ID_HEADER);
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void throwExceptionWhenRequestIdsNull() {
+        new ContextTracker(PARTNER_NAME_HEADER, null);
+    }
+
+    @Test
+    public void requestIdCopiedWhenGiven() {
+
+        mockStatic(LoggingContext.class);
+
+        final String requestId = "request-id-for-unit-testing";
+        HttpServletRequest request = mock(HttpServletRequest.class);
+        when(request.getHeader(X_REQUEST_ID)).thenReturn(requestId);
+
+        ContextTracker tracker = new ContextTracker(PARTNER_NAME_HEADER, REQUEST_ID_HEADER);
+        tracker.preRequest(request);
+
+        ArgumentCaptor<ContextData> contextDataCaptor = ArgumentCaptor.forClass(ContextData.class);
+        verifyStatic(LoggingContext.class);
+
+        LoggingContext.put(contextDataCaptor.capture());
+
+        assertEquals(requestId, contextDataCaptor.getValue().getRequestId());
+    }
+
+    @Test
+    public void requestIdGeneratedWhenNotGiven() {
+
+        mockStatic(LoggingContext.class);
+
+        ContextTracker tracker = new ContextTracker(PARTNER_NAME_HEADER, REQUEST_ID_HEADER);
+        tracker.preRequest(mock(HttpServletRequest.class));
+
+        ArgumentCaptor<ContextData> contextDataCaptor = ArgumentCaptor.forClass(ContextData.class);
+        verifyStatic(LoggingContext.class);
+
+        LoggingContext.put(contextDataCaptor.capture());
+
+        String requestId = contextDataCaptor.getValue().getRequestId();
+        assertNotNull(requestId);
+        assertFalse(requestId.isEmpty());
+    }
+
+    @Test
+    public void partnerNameCopiedWhenGiven() {
+
+        mockStatic(LoggingContext.class);
+
+        final String partner = "partner-name-for-unit-testing";
+        HttpServletRequest request = mock(HttpServletRequest.class);
+        when(request.getHeader(X_PARTNER_NAME)).thenReturn(partner);
+
+        ContextTracker tracker = new ContextTracker(PARTNER_NAME_HEADER, REQUEST_ID_HEADER);
+        tracker.preRequest(request);
+
+        ArgumentCaptor<ContextData> contextDataCaptor = ArgumentCaptor.forClass(ContextData.class);
+        verifyStatic(LoggingContext.class);
+
+        LoggingContext.put(contextDataCaptor.capture());
+
+        assertEquals(partner, contextDataCaptor.getValue().getPartnerName());
+    }
+
+    @Test
+    public void partnerNameAbsentWhenNotGiven() {
+
+        mockStatic(LoggingContext.class);
+
+        ContextTracker tracker = new ContextTracker(PARTNER_NAME_HEADER, REQUEST_ID_HEADER);
+        tracker.preRequest(mock(HttpServletRequest.class));
+
+        ArgumentCaptor<ContextData> contextDataCaptor = ArgumentCaptor.forClass(ContextData.class);
+        verifyStatic(LoggingContext.class);
+
+        LoggingContext.put(contextDataCaptor.capture());
+
+        assertNull(contextDataCaptor.getValue().getPartnerName());
+    }
+
+    @Test
+    public void serviceNameGenerated() {
+
+        mockStatic(LoggingContext.class);
+
+        ContextTracker tracker = new ContextTracker(PARTNER_NAME_HEADER, REQUEST_ID_HEADER);
+        tracker.preRequest(mock(HttpServletRequest.class));
+
+        ArgumentCaptor<ContextData> contextDataCaptor = ArgumentCaptor.forClass(ContextData.class);
+        verifyStatic(LoggingContext.class);
+
+        LoggingContext.put(contextDataCaptor.capture());
+
+        assertNotNull(contextDataCaptor.getValue().getServiceName());
+    }
+
+    @Test
+    public void contextClearedWhenRequestFinished() {
+
+        mockStatic(LoggingContext.class);
+
+        ContextTracker tracker = new ContextTracker(PARTNER_NAME_HEADER, REQUEST_ID_HEADER);
+        tracker.postRequest(mock(RequestProcessingResult.class));
+
+        verifyStatic(LoggingContext.class);
+        LoggingContext.clear();
+    }
+}
+
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/HttpHeaderTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/HttpHeaderTest.java
new file mode 100644
index 0000000..5cbd0c0
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/HttpHeaderTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openecomp.sdc.logging.servlet;
+
+import static junit.framework.TestCase.assertTrue;
+import static org.junit.Assert.assertFalse;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import org.junit.Test;
+
+/**
+ * Unit tests multiple-option headers.
+ *
+ * @author evitaliy
+ * @since 31 Jul 2018
+ */
+public class HttpHeaderTest {
+
+    private static final Supplier<? extends Throwable> VALUE_EXPECTED = () -> new AssertionError("Value expected");
+    private static final Function<String, String> NULL_WHEN_NAME_NOT_B = k -> "B".equals(k) ? "Value" : null;
+
+    @Test(expected = NullPointerException.class)
+    public void throwExceptionWhenInputArrayNull() {
+        new HttpHeader((String[]) null);
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void throwExceptionWhenInputListNull() {
+        new HttpHeader((List<String>) null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void throwExceptionWhenInputArrayEmpty() {
+        new HttpHeader(new String[0]);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void throwExceptionWhenInputListEmpty() {
+        new HttpHeader(Collections.emptyList());
+    }
+
+    @Test
+    public void valueNotReturnedWhenNameInArrayNotRequested() {
+        HttpHeader header = new HttpHeader(new String[] {"A"});
+        assertFalse(header.getAny(NULL_WHEN_NAME_NOT_B).isPresent());
+    }
+
+    @Test
+    public void valueNotReturnedWhenNameInListNotRequested() {
+        HttpHeader header = new HttpHeader(Collections.singletonList("A"));
+        assertFalse(header.getAny(NULL_WHEN_NAME_NOT_B).isPresent());
+    }
+
+    @Test
+    public void valueReturnedWhenSinglePossibleHeaderInArrayMatches() {
+        HttpHeader header = new HttpHeader(new String[] {"B"});
+        assertTrue(header.getAny(NULL_WHEN_NAME_NOT_B).isPresent());
+    }
+
+    @Test
+    public void valueReturnedWhenSinglePossibleHeaderInListMatches() {
+        HttpHeader header = new HttpHeader(Collections.singletonList("B"));
+        assertTrue(header.getAny(NULL_WHEN_NAME_NOT_B).isPresent());
+    }
+
+    @Test
+    public void valueReturnedWhenLastHeaderInArrayMatches() throws Throwable {
+        HttpHeader header = new HttpHeader(new String[] {"A", "B"});
+        header.getAny(NULL_WHEN_NAME_NOT_B).orElseThrow(VALUE_EXPECTED);
+    }
+
+    @Test
+    public void valueReturnedWhenLastHeaderInListMatches() throws Throwable {
+        HttpHeader header = new HttpHeader(Arrays.asList("A", "B"));
+        header.getAny(NULL_WHEN_NAME_NOT_B).orElseThrow(VALUE_EXPECTED);
+    }
+
+    @Test
+    public void valueReturnedWhenFirstHeaderInArrayMatches() throws Throwable {
+        HttpHeader header = new HttpHeader(new String[] {"B", "A"});
+        header.getAny(NULL_WHEN_NAME_NOT_B).orElseThrow(VALUE_EXPECTED);
+    }
+
+    @Test
+    public void valueReturnedWhenFirstHeaderInListMatches() throws Throwable {
+        HttpHeader header = new HttpHeader(Arrays.asList("B", "A"));
+        header.getAny(NULL_WHEN_NAME_NOT_B).orElseThrow(VALUE_EXPECTED);
+    }
+
+    @Test
+    public void valueReturnedWhenMiddleHeaderInArrayMatches() throws Throwable {
+        HttpHeader header = new HttpHeader(new String[] {"A", "B", "C"});
+        header.getAny(NULL_WHEN_NAME_NOT_B).orElseThrow(VALUE_EXPECTED);
+    }
+
+    @Test
+    public void valueReturnedWhenMiddleHeaderInListMatches() throws Throwable {
+        HttpHeader header = new HttpHeader(Arrays.asList("A", "B", "C"));
+        header.getAny(NULL_WHEN_NAME_NOT_B).orElseThrow(VALUE_EXPECTED);
+    }
+}
\ No newline at end of file
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/LoggingFilterTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/LoggingFilterTest.java
deleted file mode 100644
index 1ba418f..0000000
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/LoggingFilterTest.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright © 2016-2018 European Support Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.openecomp.sdc.logging.servlet;
-
-import org.easymock.EasyMock;
-import org.junit.After;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TestName;
-import org.junit.runner.RunWith;
-import org.openecomp.sdc.logging.api.ContextData;
-import org.openecomp.sdc.logging.api.LoggingContext;
-import org.powermock.api.easymock.PowerMock;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
-
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.util.UUID;
-
-import static org.easymock.EasyMock.anyObject;
-import static org.openecomp.sdc.logging.LoggingConstants.DEFAULT_PARTNER_NAME_HEADER;
-import static org.openecomp.sdc.logging.LoggingConstants.DEFAULT_REQUEST_ID_HEADER;
-import static org.openecomp.sdc.logging.servlet.LoggingFilter.PARTNER_NAME_HEADERS_PARAM;
-import static org.openecomp.sdc.logging.servlet.LoggingFilter.REQUEST_ID_HEADERS_PARAM;
-
-/**
- * Unit-tests logging filter for initialization and data retrieval.
- *
- * @author evitaliy
- * @since 17 Aug 2016
- */
-@RunWith(PowerMockRunner.class)
-@PrepareForTest(LoggingContext.class)
-public class LoggingFilterTest {
-
-    private static final String RANDOM_REQUEST_URI = UUID.randomUUID().toString();
-    private static final String RANDOM_REQUEST_ID = UUID.randomUUID().toString();
-    private static final String RANDOM_PARTNER_NAME = UUID.randomUUID().toString();
-
-    @Rule
-    public TestName testName = new TestName();
-
-    /**
-     * Verify all mocks after each test.
-     */
-    @After
-    public void verifyMocks() {
-
-        try {
-            PowerMock.verifyAll();
-        } catch (AssertionError e) {
-            throw new AssertionError("Expectations failed in " + testName.getMethodName() + "()", e);
-        }
-    }
-
-
-    @Test
-    public void filterPopulatesValuesWhenNoInitParamsAndNoHeaders() throws IOException, ServletException {
-
-        mockLoggingContext();
-        LoggingFilter loggingFilter = new LoggingFilter();
-        loggingFilter.init(mockFilterConfig(null, null));
-        loggingFilter.doFilter(new MockRequestBuilder().build(), mockResponse(), mockChain());
-    }
-
-    @Test
-    public void filterPopulatesValuesWhenNoInitParamsAndExistingHeaders() throws IOException, ServletException {
-
-        mockLoggingContext();
-
-        LoggingFilter loggingFilter = new LoggingFilter();
-        loggingFilter.init(mockFilterConfig(null, null));
-
-        HttpServletRequest mockRequest = new MockRequestBuilder().partnerName(RANDOM_PARTNER_NAME)
-                                                                 .requestId(RANDOM_REQUEST_ID).build();
-        loggingFilter.doFilter(mockRequest, mockResponse(), mockChain());
-    }
-
-    @Test
-    public void filterPopulatesValuesWhenCustomInitParamsAndNoHeaders() throws IOException, ServletException {
-
-        mockLoggingContext();
-
-        final String requestIdHeader = "x-request";
-        final String partnerNameHeader = "x-partner";
-
-        LoggingFilter loggingFilter = new LoggingFilter();
-        FilterConfig mockConfig = mockFilterConfig(requestIdHeader, partnerNameHeader);
-        loggingFilter.init(mockConfig);
-
-        HttpServletRequest mockRequest = new MockRequestBuilder().requestIdHeader(requestIdHeader)
-                                                                 .partnerNameHeader(partnerNameHeader).build();
-        loggingFilter.doFilter(mockRequest, mockResponse(), mockChain());
-    }
-
-    @Test
-    public void filterPopulatesValuesWhenCustomInitParamsAndExistingHeaders() throws IOException, ServletException {
-
-        mockLoggingContext();
-
-        final String requestIdHeader = "x-request-id";
-        final String partnerNameHeader = "x-partner-name";
-
-        LoggingFilter loggingFilter = new LoggingFilter();
-        FilterConfig mockConfig = mockFilterConfig(requestIdHeader, partnerNameHeader);
-        loggingFilter.init(mockConfig);
-
-        HttpServletRequest mockRequest = new MockRequestBuilder()
-                .partnerNameHeader(partnerNameHeader).partnerName(RANDOM_PARTNER_NAME)
-                .requestIdHeader(requestIdHeader).requestId(RANDOM_REQUEST_ID).build();
-        loggingFilter.doFilter(mockRequest, mockResponse(), mockChain());
-    }
-
-    private FilterConfig mockFilterConfig(String requestIdHeader, String partnerNameHeader) {
-        FilterConfig config = EasyMock.mock(FilterConfig.class);
-        EasyMock.expect(config.getInitParameter(REQUEST_ID_HEADERS_PARAM)).andReturn(requestIdHeader);
-        EasyMock.expect(config.getInitParameter(PARTNER_NAME_HEADERS_PARAM)).andReturn(partnerNameHeader);
-        EasyMock.replay(config);
-        return config;
-    }
-
-    private FilterChain mockChain() throws IOException, ServletException {
-        FilterChain chain = EasyMock.mock(FilterChain.class);
-        chain.doFilter(anyObject(ServletRequest.class), anyObject(ServletResponse.class));
-        EasyMock.expectLastCall().once();
-        EasyMock.replay(chain);
-        return chain;
-    }
-
-    private ServletResponse mockResponse() {
-        HttpServletResponse servletResponse = EasyMock.mock(HttpServletResponse.class);
-        EasyMock.replay(servletResponse);
-        return servletResponse;
-    }
-
-    private void mockLoggingContext() {
-
-        PowerMock.mockStatic(LoggingContext.class);
-
-        LoggingContext.clear();
-        EasyMock.expectLastCall().times(2);
-
-        LoggingContext.put(anyObject(ContextData.class));
-        EasyMock.expectLastCall().once();
-
-        PowerMock.replay(LoggingContext.class);
-    }
-
-    private static class MockRequestBuilder {
-
-        private String requestIdHeader = DEFAULT_REQUEST_ID_HEADER;
-        private String partnerNameHeader = DEFAULT_PARTNER_NAME_HEADER;
-        private String requestId = null;
-        private String partnerName = null;
-
-        MockRequestBuilder requestIdHeader(String h) {
-            this.requestIdHeader = h;
-            return this;
-        }
-
-        MockRequestBuilder requestId(String id) {
-            this.requestId = id;
-            return this;
-        }
-
-        MockRequestBuilder partnerNameHeader(String h) {
-            this.partnerNameHeader = h;
-            return this;
-        }
-
-        MockRequestBuilder partnerName(String name) {
-            this.partnerName = name;
-            return this;
-        }
-
-        HttpServletRequest build() {
-            HttpServletRequest mockRequest = EasyMock.mock(HttpServletRequest.class);
-            EasyMock.expect(mockRequest.getRequestURI()).andReturn(RANDOM_REQUEST_URI);
-            EasyMock.expect(mockRequest.getHeader(requestIdHeader)).andReturn(requestId);
-            EasyMock.expect(mockRequest.getHeader(partnerNameHeader)).andReturn(partnerName);
-            EasyMock.replay(mockRequest);
-            return mockRequest;
-        }
-    }
-}
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/ServiceNameFormatterTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/ServiceNameFormatterTest.java
new file mode 100644
index 0000000..87fb6f7
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/ServiceNameFormatterTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openecomp.sdc.logging.servlet;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import javax.servlet.http.HttpServletRequest;
+import org.junit.Test;
+
+/**
+ * Service name formatting.
+ *
+ * @author evitaliy
+ * @since 01 Aug 2018
+ */
+public class ServiceNameFormatterTest {
+
+    @Test
+    public void includesMethodAndUri() {
+        final String method = "ABC";
+        final String uri = "/a/b/c";
+        HttpServletRequest request = mock(HttpServletRequest.class);
+        when(request.getRequestURI()).thenReturn(uri);
+        when(request.getMethod()).thenReturn(method);
+        assertEquals(method + ": " + uri, ServiceNameFormatter.format(request));
+    }
+}
\ No newline at end of file
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/jaxrs/HttpHeaderTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/jaxrs/HttpHeaderTest.java
deleted file mode 100644
index ad7be95..0000000
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/jaxrs/HttpHeaderTest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright © 2016-2018 European Support Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.openecomp.sdc.logging.servlet.jaxrs;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-
-import java.util.function.Function;
-import org.junit.Test;
-import org.openecomp.sdc.logging.servlet.HttpHeader;
-
-/**
- * Unit tests multiple-option headers.
- *
- * @author evitaliy
- * @since 25 Mar 2018
- */
-public class HttpHeaderTest {
-
-    private static final String KEY_FIRST = "First";
-    private static final String KEY_SECOND = "Second";
-
-    @Test
-    public void valueReturnedWhenSinglePossibleHeader() {
-
-        final String key = "Head";
-        final String value = "1234";
-
-        Function<String, String> reader = createReader(key, value);
-        HttpHeader header = new HttpHeader(key);
-        assertEquals(value, header.getAny(reader));
-    }
-
-    @Test
-    public void nullReturnedWhenSingleNoMatchingHeader() {
-
-        final String key = "Head";
-
-        Function<String, String> reader = createReader(key, null);
-        HttpHeader header = new HttpHeader(key);
-        assertNull(header.getAny(reader));
-    }
-
-    @Test
-    public void nullReturnedWhenNoneHeaderMatches() {
-        Function<String, String> reader = createReader("None", "Value");
-        HttpHeader header = new HttpHeader("A", "B", "C");
-        assertNull(header.getAny(reader));
-    }
-
-    @Test
-    public void valueReturnedWhenLastHeaderMatches() {
-
-        final String lastKey = "Last";
-        final String value = "1234";
-
-        Function<String, String> reader = createReader(lastKey, value);
-        HttpHeader header = new HttpHeader(KEY_FIRST, KEY_SECOND, lastKey);
-        assertEquals(value, header.getAny(reader));
-    }
-
-    @Test
-    public void valueReturnedWhenFirstHeaderMatches() {
-
-        final String value = "1234";
-        Function<String, String> reader = createReader(KEY_FIRST, value);
-        HttpHeader header = new HttpHeader(KEY_FIRST, KEY_SECOND, "Third");
-        assertEquals(value, header.getAny(reader));
-    }
-
-    @Test
-    public void valueReturnedWhenMiddleHeaderMatches() {
-
-        final String value = "1234";
-        Function<String, String> reader = createReader(KEY_SECOND, value);
-        HttpHeader header = new HttpHeader(KEY_FIRST, KEY_SECOND, "Third");
-        assertEquals(value, header.getAny(reader));
-    }
-
-    private Function<String, String> createReader(String key, String value) {
-        return  h -> h.equals(key) ? value : null;
-    }
-}
\ No newline at end of file
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/jaxrs/LoggingRequestFilterTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/jaxrs/LoggingRequestFilterTest.java
index 4098809..aa77dea 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/jaxrs/LoggingRequestFilterTest.java
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/jaxrs/LoggingRequestFilterTest.java
@@ -16,25 +16,18 @@
 
 package org.openecomp.sdc.logging.servlet.jaxrs;
 
-import static org.easymock.EasyMock.anyObject;
-import static org.easymock.EasyMock.anyString;
-import static org.openecomp.sdc.logging.servlet.jaxrs.LoggingRequestFilter.START_TIME_KEY;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.openecomp.sdc.logging.servlet.jaxrs.LoggingRequestFilter.LOGGING_TRACKER_KEY;
 
-import java.util.UUID;
 import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.container.ContainerRequestContext;
-import org.easymock.EasyMock;
-import org.junit.After;
-import org.junit.Rule;
+import javax.ws.rs.container.ResourceInfo;
 import org.junit.Test;
-import org.junit.rules.TestName;
-import org.junit.runner.RunWith;
-import org.openecomp.sdc.logging.LoggingConstants;
-import org.openecomp.sdc.logging.api.ContextData;
-import org.openecomp.sdc.logging.api.LoggingContext;
-import org.powermock.api.easymock.PowerMock;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
+import org.openecomp.sdc.logging.servlet.Tracker;
 
 
 /**
@@ -43,222 +36,25 @@
  * @author evitaliy
  * @since 19 Mar 2018
  */
-@RunWith(PowerMockRunner.class)
-@PrepareForTest({LoggingContext.class, ContextData.class})
 public class LoggingRequestFilterTest {
 
-    private static final String REQUEST_URI = "/test";
-    private static final String REQUEST_METHOD = "GET";
-    private static final String RANDOM_REQUEST_ID = UUID.randomUUID().toString();
-    private static final String RANDOM_PARTNER_NAME = UUID.randomUUID().toString();
-
-    @Rule
-    public TestName testName = new TestName();
-
-    /**
-     * Verify all mocks after each test.
-     */
-    @After
-    public void verifyMocks() {
-
-        try {
-            PowerMock.verifyAll();
-        } catch (AssertionError e) {
-            throw new AssertionError("Expectations failed in " + testName.getMethodName() + "()", e);
-        }
-    }
-
     @Test
-    public void serviceNamePopulatedWhenThereIsMatchingResource() {
+    public void trackerPushedOntoRequestContext() {
 
-        mockContextDataBuilder(null, null, LoggingRequestFilter.formatServiceName(REQUEST_METHOD, REQUEST_URI));
-        mockLoggingContext();
+        LoggingRequestFilter requestFilter = new LoggingRequestFilter();
+        requestFilter.setHttpRequest(mock(HttpServletRequest.class));
 
-        LoggingRequestFilter filter = new LoggingRequestFilter();
-        filter.setHttpRequest(mockHttpRequest(true));
+        ResourceInfo resourceInfo = mock(ResourceInfo.class);
+        when(resourceInfo.getResourceMethod()).thenReturn(Resource.class.getDeclaredMethods()[0]);
+        requestFilter.setResource(resourceInfo);
 
-        filter.filter(mockContainerRequestContext(
-                new RequestIdHeader(null),
-                new PartnerHeader(null)));
+        ContainerRequestContext requestContext = mock(ContainerRequestContext.class);
+        requestFilter.filter(requestContext);
+        verify(requestContext).setProperty(eq(LOGGING_TRACKER_KEY), any(Tracker.class));
     }
 
-    @Test
-    public void serviceNameDoesNotIncludeHttpMethodWhenHttpMethodDisabled() {
-
-        mockContextDataBuilder(null, null, REQUEST_URI);
-        mockLoggingContext();
-
-        LoggingRequestFilter filter = new LoggingRequestFilter();
-        filter.setHttpMethodInServiceName(false);
-        filter.setHttpRequest(mockHttpRequest(false));
-
-        filter.filter(mockContainerRequestContext(
-                new RequestIdHeader(null),
-                new PartnerHeader(null)));
-    }
-
-    @Test
-    public void partnerNamePopulatedWhenPresentInDefaultHeader() {
-
-        mockContextDataBuilder(null, RANDOM_PARTNER_NAME,
-                LoggingRequestFilter.formatServiceName(REQUEST_METHOD, REQUEST_URI));
-        mockLoggingContext();
-
-        LoggingRequestFilter filter = new LoggingRequestFilter();
-        filter.setHttpRequest(mockHttpRequest(true));
-
-        filter.filter(mockContainerRequestContext(
-                new RequestIdHeader(null),
-                new PartnerHeader(RANDOM_PARTNER_NAME)));
-    }
-
-    @Test
-    public void partnerNamePopulatedWhenPresentInCustomHeader() {
-
-        final String partnerHeader = "x-partner-header";
-        mockContextDataBuilder(null, RANDOM_PARTNER_NAME,
-                LoggingRequestFilter.formatServiceName(REQUEST_METHOD, REQUEST_URI));
-        mockLoggingContext();
-
-        LoggingRequestFilter filter = new LoggingRequestFilter();
-        filter.setHttpRequest(mockHttpRequest(true));
-        filter.setPartnerNameHeaders(partnerHeader);
-
-        filter.filter(mockContainerRequestContext(
-                new RequestIdHeader(null),
-                new PartnerHeader(partnerHeader, RANDOM_PARTNER_NAME)));
-    }
-
-    @Test
-    public void requestIdPopulatedWhenPresentInDefaultHeader() {
-
-        mockContextDataBuilder(RANDOM_REQUEST_ID, null,
-                LoggingRequestFilter.formatServiceName(REQUEST_METHOD, REQUEST_URI));
-        mockLoggingContext();
-
-        LoggingRequestFilter filter = new LoggingRequestFilter();
-        filter.setHttpRequest(mockHttpRequest(true));
-
-        filter.filter(mockContainerRequestContext(
-                new RequestIdHeader(RANDOM_REQUEST_ID),
-                new PartnerHeader(null)));
-    }
-
-    @Test
-    public void requestIdPopulatedWhenPresentInCustomHeader() {
-
-        final String requestIdHeader = "x-request-id";
-        mockContextDataBuilder(RANDOM_REQUEST_ID, null,
-                LoggingRequestFilter.formatServiceName(REQUEST_METHOD, REQUEST_URI));
-        mockLoggingContext();
-
-        LoggingRequestFilter filter = new LoggingRequestFilter();
-        filter.setRequestIdHeaders(requestIdHeader);
-        filter.setHttpRequest(mockHttpRequest(true));
-
-        filter.filter(mockContainerRequestContext(
-                new RequestIdHeader(requestIdHeader, RANDOM_REQUEST_ID),
-                new PartnerHeader(null)));
-    }
-
-    private HttpServletRequest mockHttpRequest(boolean includeMethod) {
-
-        HttpServletRequest servletRequest = EasyMock.mock(HttpServletRequest.class);
-        EasyMock.expect(servletRequest.getRequestURI()).andReturn(REQUEST_URI);
-
-        if (includeMethod) {
-            EasyMock.expect(servletRequest.getMethod()).andReturn(REQUEST_METHOD);
-        }
-
-        EasyMock.replay(servletRequest);
-        return servletRequest;
-    }
-
-    private ContainerRequestContext mockContainerRequestContext(Header... headers) {
-
-        ContainerRequestContext requestContext = EasyMock.mock(ContainerRequestContext.class);
-
-        for (Header h : headers) {
-            EasyMock.expect(requestContext.getHeaderString(h.key)).andReturn(h.value);
-        }
-
-        requestContext.setProperty(EasyMock.eq(START_TIME_KEY), EasyMock.anyLong());
-        EasyMock.expectLastCall();
-
-        EasyMock.replay(requestContext);
-        return requestContext;
-    }
-
-    private void mockContextDataBuilder(String requestId, String partnerName, String serviceName) {
-
-        ContextData.ContextDataBuilder mockBuilder = EasyMock.mock(ContextData.ContextDataBuilder.class);
-
-        if (requestId != null) {
-            EasyMock.expect(mockBuilder.requestId(requestId)).andReturn(mockBuilder);
-        } else {
-            EasyMock.expect(mockBuilder.requestId(anyString())).andReturn(mockBuilder);
-        }
-
-        EasyMock.expect(mockBuilder.serviceName(serviceName)).andReturn(mockBuilder);
-
-        if (partnerName != null) {
-            EasyMock.expect(mockBuilder.partnerName(partnerName)).andReturn(mockBuilder);
-        }
-
-        EasyMock.expect(mockBuilder.build()).andReturn(EasyMock.mock(ContextData.class));
-        EasyMock.replay(mockBuilder);
-
-        PowerMock.mockStatic(ContextData.class);
-
-        ContextData.builder();
-        PowerMock.expectLastCall().andReturn(mockBuilder);
-
-        PowerMock.replay(ContextData.class);
-    }
-
-    private void mockLoggingContext() {
-
-        PowerMock.mockStatic(LoggingContext.class);
-
-        LoggingContext.clear();
-        EasyMock.expectLastCall();
-
-        LoggingContext.put(anyObject(ContextData.class));
-        EasyMock.expectLastCall();
-
-        PowerMock.replay(LoggingContext.class);
-    }
-
-    private abstract static class Header {
-
-        private final String key;
-        private final String value;
-
-        private Header(String key, String value) {
-            this.key = key;
-            this.value = value;
-        }
-    }
-
-    private static class PartnerHeader extends Header {
-
-        private PartnerHeader(String value) {
-            super(LoggingConstants.DEFAULT_PARTNER_NAME_HEADER, value);
-        }
-
-        private PartnerHeader(String key, String value) {
-            super(key, value);
-        }
-    }
-
-    private static class RequestIdHeader extends Header {
-
-        private RequestIdHeader(String value) {
-            super(LoggingConstants.DEFAULT_REQUEST_ID_HEADER, value);
-        }
-
-        private RequestIdHeader(String key, String value) {
-            super(key, value);
-        }
+    private interface Resource {
+        @SuppressWarnings("unused")
+        void method();
     }
 }
\ No newline at end of file
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/jaxrs/LoggingResponseFilterTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/jaxrs/LoggingResponseFilterTest.java
index 710cf12..336840b 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/jaxrs/LoggingResponseFilterTest.java
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/jaxrs/LoggingResponseFilterTest.java
@@ -16,35 +16,18 @@
 
 package org.openecomp.sdc.logging.servlet.jaxrs;
 
-import static org.easymock.EasyMock.anyObject;
-import static org.easymock.EasyMock.anyString;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.openecomp.sdc.logging.servlet.jaxrs.LoggingRequestFilter.LOGGING_TRACKER_KEY;
 
-import java.lang.reflect.Method;
-import java.util.Comparator;
-import java.util.Objects;
-import java.util.function.Consumer;
-import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.container.ContainerRequestContext;
 import javax.ws.rs.container.ContainerResponseContext;
-import javax.ws.rs.container.ResourceInfo;
-import javax.ws.rs.core.Response;
-import org.easymock.EasyMock;
-import org.easymock.LogicalOperator;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.TestName;
-import org.junit.runner.RunWith;
-import org.openecomp.sdc.logging.api.AuditData;
-import org.openecomp.sdc.logging.api.Logger;
-import org.openecomp.sdc.logging.api.LoggerFactory;
-import org.openecomp.sdc.logging.api.LoggingContext;
-import org.openecomp.sdc.logging.api.StatusCode;
-import org.powermock.api.easymock.PowerMock;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
-
+import org.openecomp.sdc.logging.servlet.RequestProcessingResult;
+import org.openecomp.sdc.logging.servlet.Tracker;
 
 /**
  * Unit testing JAX-RS response filter.
@@ -52,277 +35,24 @@
  * @author evitaliy
  * @since 19 Mar 2018
  */
-@RunWith(PowerMockRunner.class)
 public class LoggingResponseFilterTest {
 
-    private static final Class RESOURCE_TYPE = Resource.class;
-    private static final Method RESOURCE_METHOD = Resource.class.getDeclaredMethods()[0];
-
-    @Rule
-    public TestName testName = new TestName();
-
-    @Before
-    public void prepareLoggingContext() {
-        mockLoggingContext();
-    }
-
-    /**
-     * Verify all mocks after each test.
-     */
-    @After
-    public void verifyMocks() {
-
-        try {
-            PowerMock.verifyAll();
-        } catch (AssertionError e) {
-            throw new AssertionError("Expectations failed in " + testName.getMethodName() + "()", e);
-        }
+    @Test
+    public void noExceptionsWhenTrackerNotPassed() {
+        new LoggingResponseFilter().filter(mock(ContainerRequestContext.class), mock(ContainerResponseContext.class));
     }
 
     @Test
-    @PrepareForTest({LoggingContext.class, LoggerFactory.class})
-    public void noAuditWhenNoMatchingResource() {
+    public void postRequestWhenTrackerPassed() {
 
-        PowerMock.mockStatic(LoggerFactory.class);
-        mockFilterLogger(logger -> {
-            logger.debug(anyString());
-            EasyMock.expectLastCall();
-        });
-        PowerMock.replay(LoggerFactory.class);
+        Tracker tracker = mock(Tracker.class);
+
+        ContainerRequestContext requestContext = mock(ContainerRequestContext.class);
+        when(requestContext.getProperty(LOGGING_TRACKER_KEY)).thenReturn(tracker);
 
         LoggingResponseFilter responseFilter = new LoggingResponseFilter();
-        responseFilter.filter(mockDisabledRequestContext(), mockDisabledResponseContext());
-    }
+        responseFilter.filter(requestContext, mock(ContainerResponseContext.class));
 
-    @Test
-    @PrepareForTest({LoggingContext.class, LoggerFactory.class})
-    public void noAuditWhenNullResource() {
-
-        PowerMock.mockStatic(LoggerFactory.class);
-        mockFilterLogger(logger -> {
-            logger.debug(anyString());
-            EasyMock.expectLastCall();
-        });
-        PowerMock.replay(LoggerFactory.class);
-
-        LoggingResponseFilter responseFilter = new LoggingResponseFilter();
-        responseFilter.setResource(null);
-        responseFilter.filter(mockDisabledRequestContext(), mockDisabledResponseContext());
-    }
-
-    @Test
-    @PrepareForTest({LoggingContext.class, LoggerFactory.class})
-    public void noAuditWhenAuditDisabled() {
-
-        PowerMock.mockStatic(LoggerFactory.class);
-        mockFilterLogger();
-        mockResourceLogger(false, AuditData.builder().build());
-        PowerMock.replay(LoggerFactory.class);
-
-        LoggingResponseFilter responseFilter = new LoggingResponseFilter();
-        responseFilter.setResource(mockResource());
-        responseFilter.filter(mockDisabledRequestContext(), mockDisabledResponseContext());
-    }
-
-    @Test
-    @PrepareForTest({LoggingContext.class, LoggerFactory.class})
-    public void startTimeReadWhenPresentInRequestContext() {
-
-        final String clientIp = "IP1";
-        final long startTime = 12345L;
-        final Response.Status ok = Response.Status.OK;
-
-        PowerMock.mockStatic(LoggerFactory.class);
-        mockResourceLogger(true, buildAuditData(startTime, clientIp, ok, StatusCode.COMPLETE));
-        mockFilterLogger();
-        PowerMock.replay(LoggerFactory.class);
-
-        LoggingResponseFilter filter = new LoggingResponseFilter();
-        filter.setResource(mockResource());
-        filter.setHttpRequest(mockHttpRequest(clientIp));
-
-        filter.filter(mockRequestContext(startTime), mockResponseContext(ok));
-    }
-
-    @Test
-    @PrepareForTest({LoggingContext.class, LoggerFactory.class})
-    public void startTimeZeroWhenNotPresentInRequestContext() {
-
-        final String clientIp = "IP2";
-        final Response.Status ok = Response.Status.OK;
-
-        AuditData expectedAuditData = buildAuditData(0, clientIp, ok, StatusCode.COMPLETE);
-
-        PowerMock.mockStatic(LoggerFactory.class);
-        mockResourceLogger(true, expectedAuditData);
-        mockFilterLogger(logger -> {
-            logger.error(anyString(), anyObject(Object[].class));
-            EasyMock.expectLastCall();
-        });
-        PowerMock.replay(LoggerFactory.class);
-
-        LoggingResponseFilter filter = new LoggingResponseFilter();
-        filter.setResource(mockResource());
-        filter.setHttpRequest(mockHttpRequest(clientIp));
-
-        filter.filter(mockRequestContext(null), mockResponseContext(ok));
-    }
-
-    @Test
-    @PrepareForTest({LoggingContext.class, LoggerFactory.class})
-    public void startTimeZeroWhenIncorrectObjectType() {
-
-        final String clientIp = "IP3";
-        final Response.Status accepted = Response.Status.ACCEPTED;
-
-        AuditData expectedAuditData = buildAuditData(0, clientIp, accepted, StatusCode.COMPLETE);
-
-        PowerMock.mockStatic(LoggerFactory.class);
-        mockFilterLogger(logger -> {
-            logger.error(anyString(), anyString(), anyString(), anyObject());
-            EasyMock.expectLastCall();
-        });
-        mockResourceLogger(true, expectedAuditData);
-        PowerMock.replay(LoggerFactory.class);
-
-        LoggingResponseFilter filter = new LoggingResponseFilter();
-        filter.setResource(mockResource());
-        filter.setHttpRequest(mockHttpRequest(clientIp));
-
-        filter.filter(mockRequestContext("string object"), mockResponseContext(accepted));
-    }
-
-    @Test
-    @PrepareForTest({LoggingContext.class, LoggerFactory.class})
-    public void statusErrorWhenHttpResponseGreaterThan399() {
-
-        final Response.Status error = Response.Status.BAD_REQUEST;
-        final String clientIp = "IP13";
-        final long startTime = 88668603L;
-
-        AuditData expectedAuditData = buildAuditData(startTime, clientIp, error, StatusCode.ERROR);
-
-        PowerMock.mockStatic(LoggerFactory.class);
-        mockResourceLogger(true, expectedAuditData);
-        mockFilterLogger();
-        PowerMock.replay(LoggerFactory.class);
-
-        LoggingResponseFilter filter = new LoggingResponseFilter();
-        filter.setResource(mockResource());
-        filter.setHttpRequest(mockHttpRequest(clientIp));
-
-        filter.filter(mockRequestContext(startTime), mockResponseContext(error));
-    }
-
-    private AuditData buildAuditData(long startTime, String clientIp, Response.Status responseStatus,
-            StatusCode status) {
-        return AuditData.builder().startTime(startTime).responseCode(Integer.toString(responseStatus.getStatusCode()))
-                        .responseDescription(responseStatus.getReasonPhrase()).clientIpAddress(clientIp)
-                        .statusCode(status).build();
-    }
-
-    private void mockResourceLogger(boolean enabled, AuditData auditData) {
-
-        Logger resourceLogger = EasyMock.mock(Logger.class);
-
-        EasyMock.expect(resourceLogger.isAuditEnabled()).andReturn(enabled).atLeastOnce();
-
-        if (enabled) {
-            resourceLogger.audit(EasyMock.cmp(auditData, new AuditDataComparator(), LogicalOperator.EQUAL));
-            EasyMock.expectLastCall();
-        }
-
-        EasyMock.replay(resourceLogger);
-
-        LoggerFactory.getLogger(RESOURCE_TYPE);
-        PowerMock.expectLastCall().andReturn(resourceLogger);
-    }
-
-    @SafeVarargs
-    private final void mockFilterLogger(Consumer<Logger>... expectations) {
-
-        Logger filterLogger = EasyMock.mock(Logger.class);
-
-        for (Consumer<Logger> expect : expectations) {
-            expect.accept(filterLogger);
-        }
-
-        EasyMock.replay(filterLogger);
-
-        LoggerFactory.getLogger(LoggingResponseFilter.class);
-        PowerMock.expectLastCall().andReturn(filterLogger);
-    }
-
-    private void mockLoggingContext() {
-        PowerMock.mockStatic(LoggingContext.class);
-        LoggingContext.clear();
-        EasyMock.expectLastCall();
-        PowerMock.replay(LoggingContext.class);
-    }
-
-    private ContainerRequestContext mockDisabledRequestContext() {
-        ContainerRequestContext requestContext = EasyMock.mock(ContainerRequestContext.class);
-        EasyMock.replay(requestContext);
-        return requestContext;
-    }
-
-    private ContainerResponseContext mockDisabledResponseContext() {
-        ContainerResponseContext responseContext = EasyMock.mock(ContainerResponseContext.class);
-        EasyMock.replay(responseContext);
-        return responseContext;
-    }
-
-    private HttpServletRequest mockHttpRequest(String clientIp) {
-        HttpServletRequest servletRequest = EasyMock.mock(HttpServletRequest.class);
-        EasyMock.expect(servletRequest.getRemoteAddr()).andReturn(clientIp);
-        EasyMock.replay(servletRequest);
-        return servletRequest;
-    }
-
-    private ContainerRequestContext mockRequestContext(Object startTime) {
-        ContainerRequestContext requestContext = EasyMock.mock(ContainerRequestContext.class);
-        EasyMock.expect(requestContext.getProperty(LoggingRequestFilter.START_TIME_KEY)).andReturn(startTime);
-        EasyMock.replay(requestContext);
-        return requestContext;
-    }
-
-    private ContainerResponseContext mockResponseContext(Response.StatusType statusInfo) {
-        ContainerResponseContext responseContext = EasyMock.mock(ContainerResponseContext.class);
-        EasyMock.expect(responseContext.getStatusInfo()).andReturn(statusInfo);
-        EasyMock.replay(responseContext);
-        return responseContext;
-    }
-
-    private ResourceInfo mockResource() {
-        ResourceInfo resource = EasyMock.mock(ResourceInfo.class);
-        //noinspection unchecked
-        EasyMock.expect(resource.getResourceClass()).andReturn(RESOURCE_TYPE).anyTimes();
-        EasyMock.expect(resource.getResourceMethod()).andReturn(RESOURCE_METHOD).anyTimes();
-        EasyMock.replay(resource);
-        return resource;
-    }
-
-    private static class AuditDataComparator implements Comparator<AuditData> {
-
-        @Override
-        public int compare(AuditData one, AuditData two) {
-
-            // don't compare end time as it changes
-            if (Objects.equals(one.getClientIpAddress(), two.getClientIpAddress())
-                        && Objects.equals(one.getResponseCode(), two.getResponseCode())
-                        && Objects.equals(one.getResponseDescription(), two.getResponseDescription())
-                        && one.getStartTime() == two.getStartTime()
-                        && Objects.equals(one.getStatusCode(), two.getStatusCode())) {
-
-                return 0;
-            }
-
-            return -1;
-        }
-    }
-
-    interface Resource {
-        @SuppressWarnings("unused")
-        void method();
+        verify(tracker, times(1)).postRequest(any(RequestProcessingResult.class));
     }
 }
\ No newline at end of file