去除Dubbox LoggingFilter自动打印response内容

Dubbox自带日志打印问题

dubbo配置文件配置protocol引入LoggingFilter:

	<dubbo:protocol accepts="500" contextpath="xxx" name="rest" port="xxx" server="tomcat" 
	 threads="500" extension="com.alibaba.dubbo.rpc.protocol.rest.support.LoggingFilter"/>

LoggingFilter源码:

	public class LoggingFilter implements ContainerRequestFilter, ClientRequestFilter, ContainerResponseFilter, ClientResponseFilter, WriterInterceptor, ReaderInterceptor {
	// 省略其他代码
	···
	public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException {
    	ServerReaderInterceptorContext scontext =(ServerReaderInterceptorContext)context;
    	Field fd = null;
    	String path ="";
		try {
			fd = ServerReaderInterceptorContext.class.getDeclaredField("request");
			fd.setAccessible(true);
			HttpRequest rm = (HttpRequest) fd.get(scontext);
			path = rm.getUri().getPath();
		} catch (Exception e) {
			logger.warn("Get url path is exception,but your code is OK! ",e);
		}
        byte[] buffer = IOUtils.toByteArray(context.getInputStream());
        logger.info("The HTTP("+path+") request body are: \nBody:"+new String(buffer, "UTF-8"));
        context.setInputStream(new ByteArrayInputStream(buffer));
        return context.proceed();
    }

    public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
    	ServerWriterInterceptorContext scontext = (ServerWriterInterceptorContext)context;
    	Field fd = null;
    	String path ="";
		try {
			fd = ServerWriterInterceptorContext.class.getDeclaredField("request");
			fd.setAccessible(true);
			HttpRequest rm = (HttpRequest) fd.get(scontext);
			path = rm.getUri().getPath();
		} catch (Exception e) {
			logger.warn("Get url path is exception,but your code is OK! ",e);
		}
        OutputStreamWrapper wrapper = new OutputStreamWrapper(context.getOutputStream());
        context.setOutputStream(wrapper);
        context.proceed();
        logger.info("The url("+path+") of response body is: \n" + new String(wrapper.getBytes(), "UTF-8") + "\n");
    }

    protected void logHttpHeaders(String url,MultivaluedMap<String, String> headers) {
        StringBuilder msg = new StringBuilder("The HTTP("+url+") request body are: \nHeader:");
        for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
            msg.append(entry.getKey()).append(": ");
            for (int i = 0; i < entry.getValue().size(); i++) {
                msg.append(entry.getValue().get(i));
                if (i < entry.getValue().size() - 1) {
                    msg.append(", ");
                }
            }
            msg.append("\n");
        }
        logger.info(msg.toString());
    }
    // 省略其他代码
    ···
}
  1. 其中大量的log info日志打印request body和response body,在实际应用中,这些不起眼的日志有可能会撑爆整个服务的文件内存,拖垮接口的请求响应效率。如文件上传与下载接口,将文件内容打印到日志中时完全没有必要的。
  2. 因此,需要对默认的日志记录进行改造,去掉不需要的日志记录。

自定义日志记录类

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.ClientRequestFilter;
import javax.ws.rs.client.ClientResponseContext;
import javax.ws.rs.client.ClientResponseFilter;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.ReaderInterceptor;
import javax.ws.rs.ext.ReaderInterceptorContext;
import javax.ws.rs.ext.WriterInterceptor;
import javax.ws.rs.ext.WriterInterceptorContext;

import org.apache.commons.io.IOUtils;
import org.jboss.resteasy.core.interception.ServerReaderInterceptorContext;
import org.jboss.resteasy.core.interception.ServerWriterInterceptorContext;

import com.alibaba.dubbo.common.logger.Logger;
import com.alibaba.dubbo.common.logger.LoggerFactory;

public class CustomLogFilter implements ContainerRequestFilter, ClientRequestFilter, ContainerResponseFilter, ClientResponseFilter, WriterInterceptor, ReaderInterceptor {
	private Logger logger = LoggerFactory.getLogger(CustomLogFilter.class);

	public void filter(ClientRequestContext context) throws IOException {
		logHttpHeaders(context.getUri().getPath(), context.getStringHeaders());
	}

	public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException {
		logHttpHeaders(requestContext.getUri().getPath(), responseContext.getHeaders());
	}

	public void filter(ContainerRequestContext context) throws IOException {
		logHttpHeaders(context.getUriInfo().getPath(), context.getHeaders());
	}

	public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
		logHttpHeaders(requestContext.getUriInfo().getPath(), responseContext.getStringHeaders());
	}

	public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException {
		Field fd = null;
		try {
			fd = ServerReaderInterceptorContext.class.getDeclaredField("request");
			fd.setAccessible(true);
		} catch (Exception e) {
			logger.warn("Get url path is exception,but your code is OK! ", e);
		}
		byte[] buffer = IOUtils.toByteArray(context.getInputStream());
		context.setInputStream(new ByteArrayInputStream(buffer));
		return context.proceed();
	}

	public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
		Field fd = null;
		try {
			fd = ServerWriterInterceptorContext.class.getDeclaredField("request");
			fd.setAccessible(true);
		} catch (Exception e) {
			logger.warn("Get url path is exception,but your code is OK! ", e);
		}
		OutputStreamWrapper wrapper = new OutputStreamWrapper(context.getOutputStream());
		context.setOutputStream(wrapper);
		context.proceed();
	}

	protected void logHttpHeaders(String url, MultivaluedMap<String, String> headers) {
		StringBuilder msg = new StringBuilder("The HTTP(" + url + ") request body are: \nHeader:");
		for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
			msg.append(entry.getKey()).append(": ");
			for (int i = 0; i < entry.getValue().size(); i++) {
				msg.append(entry.getValue().get(i));
				if (i < entry.getValue().size() - 1) {
					msg.append(", ");
				}
			}
			msg.append("\n");
		}
		logger.info(msg.toString());
	}

	protected static class OutputStreamWrapper extends OutputStream {

		private final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
		private final OutputStream output;

		private OutputStreamWrapper(OutputStream output) {
			this.output = output;
		}

		@Override
		public void write(int i) throws IOException {
			buffer.write(i);
			output.write(i);
		}

		@Override
		public void write(byte[] b) throws IOException {
			buffer.write(b);
			output.write(b);
		}

		@Override
		public void write(byte[] b, int off, int len) throws IOException {
			buffer.write(b, off, len);
			output.write(b, off, len);
		}

		@Override
		public void flush() throws IOException {
			output.flush();
		}

		@Override
		public void close() throws IOException {
			output.close();
		}

		public byte[] getBytes() {
			return buffer.toByteArray();
		}
	}
}
  1. 为了不影响其他接口,参照LoggingFilter类,实现的类和方法内容不变,直接删除log.info部分的内容,即可去除不必要的request和response日志打印。
  2. 再将dubbo配置文件的中的extension配置替换为自定义的日志类即可。

修改dubbo配置文件

	<dubbo:protocol accepts="500" contextpath="xxx" extension="xxxxxx.CustomLogFilter"
    name="rest" port="xxx" server="tomcat" threads="500"/>

测试

找到项目的日志文件,清空内容,重新启动服务,调用接口,查看日志文件中是否还包含“request body”或“response body”内容。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值