Skip to content

Commit

Permalink
Entry and Exit Logging
Browse files Browse the repository at this point in the history
Issue-ID: CCSDK-4040
Change-Id: I0dc6a7d398b4d414a5c82bb31f61e36be31134a0
Signed-off-by: Raviteja Karumuri <raviteja.karumuri@est.tech>
  • Loading branch information
ravitejakarumuri committed Nov 15, 2024
1 parent e76775d commit 3477cf3
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 0 deletions.
2 changes: 2 additions & 0 deletions a1-policy-management/config/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ app:
lifecycle:
timeout-per-shutdown-phase: "20s"
logging:
# Reactive logging filter
reactive-entry-exit-filter-enabled: true
# Configuration of logging
file:
name: /var/log/policy-agent/application.log
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.onap.ccsdk.oran.a1policymanagementservice.configuration;

import org.onap.ccsdk.oran.a1policymanagementservice.util.v3.ReactiveEntryExitFilter;
import org.onap.ccsdk.oran.a1policymanagementservice.util.v3.ReactiveEntryExitFilterCondition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.server.WebFilter;

@Configuration
public class ReactiveEntryExitFilterConfig {
@Bean
@Conditional(ReactiveEntryExitFilterCondition.class)
public WebFilter reactiveEntryExitFilter() {
return new ReactiveEntryExitFilter();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*-
* ========================LICENSE_START=================================
* ONAP : ccsdk oran
* ======================================================================
* Copyright (C) 2024 OpenInfra Foundation Europe. All rights reserved.
* ======================================================================
* 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.
* ========================LICENSE_END===================================
*/

package org.onap.ccsdk.oran.a1policymanagementservice.util.v3;

import org.reactivestreams.Publisher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.nio.channels.Channels;
import java.nio.charset.StandardCharsets;

public class ReactiveEntryExitFilter implements WebFilter {

private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
ServerHttpRequest httpRequest = exchange.getRequest();
ServerHttpResponse httpResponse = exchange.getResponse();
MultiValueMap<String, String> queryParams = httpRequest.getQueryParams();
logger.info("Request received with path: {} and the Request Id: {}", httpRequest.getPath(), exchange.getRequest().getId());
if (!queryParams.isEmpty())
logger.trace("For the request Id: {}, the Query parameters are: {}", exchange.getRequest().getId(), queryParams);

ServerHttpRequestDecorator loggingServerHttpRequestDecorator = new ServerHttpRequestDecorator(exchange.getRequest()) {
String requestBody = "";
@Override
public Flux<DataBuffer> getBody() {
return super.getBody().doOnNext(dataBuffer -> {
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
Channels.newChannel(byteArrayOutputStream).write(dataBuffer.asByteBuffer().asReadOnlyBuffer());
requestBody = byteArrayOutputStream.toString(StandardCharsets.UTF_8);
if (requestBody != null)
logger.trace("For the request ID: {} the received request body: {}", exchange.getRequest().getId(), requestBody);
} catch (IOException e) {
logger.info("For the request ID: {} we got the error during processing: {}", exchange.getRequest().getId(), e.getMessage());
logger.trace("For the request ID: {} the received request body: {}", exchange.getRequest().getId(), requestBody);
}
});
}
};

ServerHttpResponseDecorator loggingServerHttpResponseDecorator = new ServerHttpResponseDecorator(exchange.getResponse()) {
String responseBody = "";
@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
Flux<DataBuffer> buffer = Flux.from(body);
return super.writeWith(buffer.doOnNext(dataBuffer -> {
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
Channels.newChannel(byteArrayOutputStream).write(dataBuffer.toByteBuffer().asReadOnlyBuffer());
responseBody = byteArrayOutputStream.toString(StandardCharsets.UTF_8);
logger.info("For the request ID: {} the Status code of the response: {}", exchange.getRequest().getId(), httpResponse.getStatusCode());
logger.trace("For the request ID: {} the response is: {} ", exchange.getRequest().getId(), responseBody);
} catch (Exception e) {
logger.info("For the request ID: {} we got an Error during processing: {}", exchange.getRequest().getId(), e.getMessage());
logger.trace("For the request ID: {} the response body :: {}", exchange.getRequest().getId(), responseBody);
}
}));
}
};
return chain.filter(exchange.mutate().request(loggingServerHttpRequestDecorator).response(loggingServerHttpResponseDecorator).build());
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.onap.ccsdk.oran.a1policymanagementservice.util.v3;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

import java.lang.invoke.MethodHandles;

public class ReactiveEntryExitFilterCondition implements Condition {

private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String reactiveFilterEnabled = context.getEnvironment().getProperty("logging.reactive-entry-exit-filter-enabled", "false");
logger.info("Reactive Entry Exit filter is enabled: {}", reactiveFilterEnabled);
return Boolean.parseBoolean(reactiveFilterEnabled);
}
}

0 comments on commit 3477cf3

Please sign in to comment.