Skip to content

Commit

Permalink
[#1321] add logger request server serviceName/ip/port (#1322) (#1380)
Browse files Browse the repository at this point in the history
  • Loading branch information
chengyouling authored Aug 16, 2024
1 parent 117cd6f commit 99906fb
Show file tree
Hide file tree
Showing 9 changed files with 223 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ public class GovernanceProperties {

public static final int WEB_FILTER_SERVICE_AUTH_ORDER = -60000;

public static final int WEB_FILTER_REQUEST_LOGGER_ORDER = -35000;

private static final int WEB_CLIENT_LOAD_BALANCE_BASE = 0;

public static final int WEB_CLIENT_FAULT_INJECTION_ORDER =
Expand All @@ -56,6 +58,9 @@ public class GovernanceProperties {
public static final String WEBCLIENT_FAULT_INJECTION_ENABLED =
PREFIX + "." + "webclient.faultInjection.enabled";

public static final String WEBCLIENT_REQUEST_LOGGER_ENABLED =
PREFIX + "." + "webclient.requestLogger.enabled";

public static final String GATEWAY_GOVERNANCE_ENABLED = PREFIX + "." + "gateway.governance.enabled";

public static final String GATEWAY_RETRY_ENABLED = PREFIX + "." + "gateway.retry.enabled";
Expand All @@ -78,6 +83,12 @@ public class GovernanceProperties {
public static final String WEBFLUX_CONTEXT_MAPPER_ENABLED =
PREFIX + "." + "webflux.contextMapper.enabled";

public static final String WEBFLUX_REQUEST_LOGGER_ENABLED =
PREFIX + "." + "webflux.requestLogger.enabled";

public static final String WEBMVC_REQUEST_LOGGER_ENABLED =
PREFIX + "." + "webmvc.requestLogger.enabled";

public static final String WEBMVC_RATE_LIMITING_ENABLED =
PREFIX + "." + "webmvc.rateLimiting.enabled";

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright (C) 2020-2024 Huawei Technologies Co., Ltd. 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.
*/

package com.huaweicloud.governance.adapters;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.ServiceInstance;

import com.huaweicloud.common.context.InvocationContext;
import com.huaweicloud.governance.GovernanceConst;

public class RequestServiceInfoLoggerUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(RequestServiceInfoLoggerUtil.class);

public static void logServiceInfo(InvocationContext context, Throwable e) {
if (context != null && context.getLocalContext(GovernanceConst.CONTEXT_CURRENT_INSTANCE) != null) {
ServiceInstance instance = context.getLocalContext(GovernanceConst.CONTEXT_CURRENT_INSTANCE);
LOGGER.error("request >>>>>>>>>>>>>> service {}[{}:{}] failed", instance.getServiceId(), instance.getHost(),
instance.getPort(), e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright (C) 2020-2024 Huawei Technologies Co., Ltd. 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.
*/
package com.huaweicloud.governance.adapters.webclient;

import java.util.Optional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.core.Ordered;
import org.springframework.web.reactive.function.client.ClientRequest;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.ExchangeFunction;

import com.huaweicloud.governance.adapters.loadbalancer.RetryContext;

import reactor.core.publisher.Mono;

public class ServiceInfoLoggerExchangeFilterFunction implements ExchangeFilterFunction, Ordered {
private static final Logger LOGGER = LoggerFactory.getLogger(ServiceInfoLoggerExchangeFilterFunction.class);

@Override
public Mono<ClientResponse> filter(ClientRequest request, ExchangeFunction next) {
return next.exchange(request).map(response -> logServiceInfo(response, request));
}

private ClientResponse logServiceInfo(ClientResponse response, ClientRequest request) {
if (response.statusCode().value() != 200) {
Optional<Object> invocationContext = request.attribute(RetryContext.RETRY_SERVICE_INSTANCE);
if (invocationContext.isPresent() && invocationContext.get() instanceof ServiceInstance) {
ServiceInstance instance = (ServiceInstance) invocationContext.get();
LOGGER.error("request >>>>>>>>>>>>>> service {}[{}:{}] failed", instance.getServiceId(), instance.getHost(),
instance.getPort());
}
}
return response;
}

@Override
public int getOrder() {
return Integer.MAX_VALUE;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,11 @@ public ExchangeFilterFunction faultInjectionExchangeFilterFunction(FaultInjectio
public StatusCodeExtractor clientResponseStatusCodeExtractor(Environment environment) {
return new ClientResponseStatusCodeExtractor(environment);
}

@Bean
@ConditionalOnProperty(value = GovernanceProperties.WEBCLIENT_REQUEST_LOGGER_ENABLED,
havingValue = "true", matchIfMissing = true)
public ServiceInfoLoggerExchangeFilterFunction serviceInfoLoggerExchangeFilterFunction() {
return new ServiceInfoLoggerExchangeFilterFunction();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (C) 2020-2024 Huawei Technologies Co., Ltd. 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.
*/

package com.huaweicloud.governance.adapters.webflux;

import org.springframework.boot.web.reactive.filter.OrderedWebFilter;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilterChain;

import com.huaweicloud.common.configration.dynamic.GovernanceProperties;
import com.huaweicloud.common.context.InvocationContext;
import com.huaweicloud.common.context.InvocationContextHolder;
import com.huaweicloud.governance.adapters.RequestServiceInfoLoggerUtil;

import reactor.core.publisher.Mono;

public class RequestServiceInfoLoggerWebFilter implements OrderedWebFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
return chain.filter(exchange).onErrorResume(Exception.class, (t) -> {
InvocationContext context = exchange.getAttribute(InvocationContextHolder.ATTRIBUTE_KEY);
RequestServiceInfoLoggerUtil.logServiceInfo(context, t);
return Mono.error(t);
});
}

@Override
public int getOrder() {
return GovernanceProperties.WEB_FILTER_REQUEST_LOGGER_ORDER;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,11 @@ public WebFilter identifierRateLimitingWebFilter(IdentifierRateLimitingHandler i
public WebFilter contextMapperWebFilter(@Qualifier("contextMapperHandler") MapperHandler mapperHandler) {
return new ContextMapperWebFilter(mapperHandler);
}

@Bean
@ConditionalOnProperty(value = GovernanceProperties.WEBFLUX_REQUEST_LOGGER_ENABLED,
havingValue = "true", matchIfMissing = true)
public WebFilter requestServiceInfoLoggerWebFilter() {
return new RequestServiceInfoLoggerWebFilter();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,7 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha
if (e instanceof RequestNotPermitted) {
((HttpServletResponse) response).setStatus(429);
response.getWriter().print("rate limited.");
LOGGER.warn("the request is rate limit by policy : {}",
e.getMessage());
LOGGER.warn("the request is rate limit by policy : {}", e.getMessage());
} else {
throw e;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (C) 2020-2024 Huawei Technologies Co., Ltd. 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.
*/
package com.huaweicloud.governance.adapters.webmvc;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import com.huaweicloud.common.context.InvocationContextHolder;
import com.huaweicloud.governance.adapters.RequestServiceInfoLoggerUtil;

public class RequestServiceInfoLoggerFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
try {
if (WebMvcUtils.isNotHttpServlet(request, response)) {
chain.doFilter(request, response);
return;
}
chain.doFilter(request, response);
} catch (Throwable e) {
RequestServiceInfoLoggerUtil.logServiceInfo(InvocationContextHolder.getOrCreateInvocationContext(), e);
throw e;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,18 @@ public FilterRegistrationBean<RateLimitingFilter> rateLimitingFilter(
return registrationBean;
}

@Bean
@ConditionalOnProperty(value = GovernanceProperties.WEBMVC_REQUEST_LOGGER_ENABLED,
havingValue = "true", matchIfMissing = true)
public FilterRegistrationBean<RequestServiceInfoLoggerFilter> requestServiceInfoLoggerFilter() {
FilterRegistrationBean<RequestServiceInfoLoggerFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new RequestServiceInfoLoggerFilter());
registrationBean.addUrlPatterns("/*");
registrationBean.setOrder(GovernanceProperties.WEB_FILTER_REQUEST_LOGGER_ORDER);

return registrationBean;
}

@Bean
@ConditionalOnProperty(value = GovernanceProperties.WEBMVC_IDENTIFIER_RATE_LIMITING_ENABLED,
havingValue = "true", matchIfMissing = true)
Expand Down

0 comments on commit 99906fb

Please sign in to comment.