NutzCN Logo
精华 有没有好的接口日志输出方案
发布于 2435天前 作者 文涛(wentao) 2723 次浏览 复制 上一个帖子 下一个帖子
标签:

NutBoot,想统一处理所有接口的入参、出参日志打印,请问有没有什么好的解决方案
另外,有没有判断对象非空的注解

33 回复
public class LogTimeProcessor  extends AbstractProcessor {
    private static final Log log = Logs.get();

    @Override
    public void process(ActionContext ac) throws Throwable {
        Stopwatch sw = Stopwatch.begin();
        try {
            doNext(ac);
        } finally {
            sw.stop();
            if (log.isDebugEnabled()) {
                HttpServletRequest req = ac.getRequest();
                log.debugf("[%4s]URI=%s %sms", req.getMethod(), req.getRequestURI(), sw.getDuration());
            }
        }
    }
}

用这个例子实现了,但是有没有办法可以把接口内的入参和出参回传回来就好了

放在MethodInvoke之前,然后仔细看ActionContext有哪些方法

嗯,看到了, 谢谢

getMethodArgs()
getMethodReturn()

@wendal 如果接口是入参是json,且是使用@Param("..")接收的对象参数,貌似在这里也没办法做到通用打印哦

不知道你想如何"通用"

我现在是在MainLauncher添加ChainBy进行日志打印
想实现无论接口是GET请求,POST的form请求、json请求
统一打印 请求类型|参数|结果
如:

[GET] | params:a=1&b=2 | ok
[POST] | params:a=1&b=2 | ok
[POST] | params: {a:1,b:2} | ok

Json.toJson(ac.getMethodArgs()), 也许

你是想把json请求的内容完全打印出来?

嗯,包括get请求的普通参数,我试了Json.toJson可以打印json,但是get请求的数据只打印了value没打印name

简单说,我就是要统一打印所有接口的接口名、出入参、耗时 接口名、出参、耗时都可以了,就差入参了

入参不是入口方法的参数吗?

现在是放在MethodInvokeProcessor之后吗?

// 正常处理的列表
        List<Processor> list = new ArrayList<>();
        list.add(new LogTimeProcessor()); // 设置日志处理类
        list.add(new UpdateRequestAttributesProcessor()); // 设置base/msg等内置属性
        list.add(new EncodingProcessor()); // 设置编码信息@Encoding
        list.add(new ModuleProcessor()); // 获取入口类的对象,从ioc或直接new
        list.add(new ActionFiltersProcessor()); // 处理@Filters
        list.add(new AdaptorProcessor()); // 处理@Adaptor
        list.add(new MethodInvokeProcessor()); // 执行入口方法
        list.add(new ViewProcessor()); // 对入口方法进行渲染@Ok

是放在最前面的,入参是指所有请求参数,无论是get post form json

那拿不到json类的参数的,得放到AdaptorProcessor之后才有可能

稍微改一下AdaptorProcessor也许更好

主要是json是从req.getInputStream读取,但它只能读取一次

主要是json是从req.getInputStream读取,但它只能读取一次

文件上传也类似

json类的反而现在能拿到呢

Json.toJson(ac.getMethodArgs(), JsonFormat.full())

放到AdaptorProcessor之后是可以的

可是我是放在它之前的,上面的代码就是

我现在是普通表单提交,只能拿到value,拿不到name

贴你的代码看看

表单和json要根据content type区分的,不能一行通杀

    public void process(ActionContext ac) throws Throwable {
        Stopwatch sw = Stopwatch.begin();
        try {
            doNext(ac);
        } finally {
            sw.stop();
            if (log.isDebugEnabled()) {
                HttpServletRequest req = ac.getRequest();
                String path = ac.getPath();
                List<String> params = new ArrayList<>();
                String result = ac.getMethodReturn().toString();
                switch (req.getMethod().trim()) {
                    case "GET":
                        Enumeration<String> parameterNames = req.getParameterNames();
                        while(parameterNames.hasMoreElements()) {
                            String name = parameterNames.nextElement();
                            String value = req.getParameter(name);
                            params.add(name + "=" + value);
                        }
                        log.infof("[%s]|%s|params:[%s] result:[%s]", "GET", path, StringUtils.join(params, "&"), result);
                        break;
                    case "POST":
                        log.infof("[%s]|%s|params:[%s] result:[%s]", "POST", path, Json.toJson(ac.getMethodArgs(), JsonFormat.compact()), result);
                        break;
                }
            }
        }
    }

@wendal 用fliter实现,copy一个req对象,是不是就可以实现了呢?

@qq_b1ca03f7 post里面再判断content type

@Wizzercn 在我看来就浪费计算资源。。。 日志内容巨多的。。。

然后话说回来,应该是稍微改一下AdaptorProcessor,把json/upload的refer object放入ActionContext,这样就能拿到完整的json/文件上传的数据了,然后把req.getParams和refer object输出到日志

@wendal 判断content-type好说,可是怎么获取post的参数名就不知道怎么操作了

req.getParamters得到全部

可以了,跟get的获取方式一样

把最后代码放在这里,留给有需要的人

public class LogTimeProcessor  extends AbstractProcessor {
    private static final Log log = Logs.get();

    @Override
    public void process(ActionContext ac) throws Throwable {
        Stopwatch sw = Stopwatch.begin();
        try {
            doNext(ac);
        } finally {
            sw.stop();
            HttpServletRequest req = ac.getRequest();
            String path = ac.getPath();
            String result = Json.toJson(ac.getMethodReturn(), JsonFormat.tidy());
            switch (req.getMethod().trim()) {
                case "GET":
                    log.infof("[%s] url:%s params:%s result:%s time:%sms", "GET", path, getParameters(req), result, sw.getDuration());
                    break;
                case "POST":
                    if(req.getContentType().contains("json")) {
                        log.infof("[%s] url:%s params:%s result:%s time:%sms", "POST JSON", path, Json.toJson(ac.getMethodArgs(), JsonFormat.tidy()), result, sw.getDuration());
                    } else {
                        log.infof("[%s] url:%s params:%s result:%s time:%sms", "POST FORM", path, getParameters(req), result, sw.getDuration());
                    }
                    break;
            }
        }
    }

    private String getParameters(HttpServletRequest req) {
        // 按json格式返回参数
        return Json.toJson(req.getParameterMap(), JsonFormat.tidy());
        // 下面是按pv模式组织参数
        // List<String> params = new ArrayList<>();
        // Map map = req.getParameterMap();
        // for (Object o : map.keySet()) {
        //     params.add(o.toString() + "=" + req.getParameter(o.toString()));
        // }
        // return StringUtils.join(params, "&");
    }
}
添加回复
请先登陆
回到顶部