高效访问 HttpServletRequest 以进行调试打印

发布于 2024-09-08 18:16:32 字数 1075 浏览 0 评论 0原文

为了调试失败的请求,我想打印来自 HttpServletRequest 的所有信息。

现在,请求可能会部分失败(例如,几个匹配成功,但一个匹配失败),在这种情况下,我想捕获失败的内部方法中的异常,打印错误 + ServletUtil.toStringHttpServletRequest( )并继续提供服务(降级但仍然有用与完全请求失败)。

我们当前的实现要么捕获异常并打印愚蠢的信息(“getRules failed”),要么将异常一直抛出到 doGet() (有效地取消用户的服务),就像在 doGet() 中一样,我可以访问 HttpServletRequest ,我可以打印相关的调试信息(标题、参数...)。

将 HttpServletRequest 传递给请求期间调用的每个可能失败的函数似乎有点难看,如果没有其他优雅的解决方案出现,我会这样做。

制作一个 before head ServletUtil.toStringHttpServletRequest() 并将其存储在 ThreadLocal 映射中会浪费内存和 CPU 时间。由于某种原因,将 HttpServletRequest 对象存储在 ThreadLocal 中感觉不对(如果我错了,请纠正)。

调试信息既写入本地计算机日志,又直接通过电子邮件发送给开发人员(伟大的工作 log4j TLSSMTPAppender),因此在多个地方登录是不切实际的(需要组合几封电子邮件才能了解发生了什么)并且 ssh'ing 到服务器已经过时了: )(我们这里都是阴天...当我查看错误时服务器可能不存在)

所以,我的解决方案是访问“PrintErrorUtility”(TODO:更好地命名它)。这将接收 (String errorMsg, Throwable t, HttpServletRequest) ,它将打印错误以及所有相关信息...这将从内部 try {} catch 块调用,它将通知错误但不会取消请求,因为它的。

显然我正在考虑在生产中运行的服务器。

评论?请指教。

谢谢你,马克西姆。

In order to debug failing requests I would like to print all information coming from HttpServletRequest.

Now, it's possible that a request will partially fail (for ex. Several matches are successful, yet one has failed) in which case I would like to catch the exception in the internal method that failed, print the error + the ServletUtil.toStringHttpServletRequest() and continue providing service (degraded but still useful vs. complete request failure).

Our current implementation either catches the exception and prints dumb info ("getRules failed") or throws the exception all the way to doGet() (effectively canceling service for the user) where as in doGet() I have access to HttpServletRequest where I can print at the relevant debug info (headers, parameters...).

Passing HttpServletRequest to every function called during the request that might fail seems a bit ugly, I will do it if no other elegant solution will pop up.

Making a before head ServletUtil.toStringHttpServletRequest() and storing it in a ThreadLocal map would be wasteful both in memory and CPU time. For some reason it feels wrong to store the HttpServletRequest object in ThreadLocal (please correct if I'm wrong).

Debug information is written both to local machine log and is emailed directly to devs (Great work log4j TLSSMTPAppender), so logging in several places won't be practical (Will need to assemble several emails to understand what's going on) and ssh'ing into the server is old age :) (We're all cloudy here... server might not exist by the time I get to look at the error)

So, my solution is gaining access to a "PrintErrorUtility" (TODO: better name it). That will receive (String errorMsg, Throwable t, HttpServletRequest) which will print the error together will all the relevant info... This will be called from internal try {} catch blocks that will notify about the error but will not cancel the request because of it.

Obviously I'm taking about servers running in production.

Comments? Please advise.

Thank you, Maxim.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

始终不够 2024-09-15 18:16:32

FilterChain#doFilter() 调用之后的 Filter 中执行此任务。 ServletRequest 对象已经存在。在要优雅地抑制此异常的业务代码中,将异常存储为请求属性,然后让 Filter 从请求中检查/抓取它。


更新:根据评论,这里有一个示例:

public class Context { 
    private static ThreadLocal<Context> instance = new ThreadLocal<Context>();
    private HttpServletRequest request;
    private List<Exception> exceptions = new ArrayList<Exception>();

    private Context(HttpServletRequest request) {
        this.request = request;
        this.request.setAttribute("exceptions", exceptions);
    }

    public static Context getCurrentInstance() {
        return instance.get();
    }

    public static Context newInstance(HttpServletRequest request) {
        Context context = new Context(request);
        instance.set(context);
        return context;
    }

    public void release() {
        instance.remove();
    }

    public void addException(Exception exception) {
        exceptions.add(exception);
    }
}

以下是如何在控制器 servlet 中使用它:

Context context = Context.newInstance(request);
try {
    executeBusinessCode();
} finally {
    context.release();
}

以下是如何在执行的业务代码中使用它:

} catch (Exception e) {
    Context.getCurrentInstance().addException(e);
}

Do this task in a Filter after the FilterChain#doFilter() call. The ServletRequest object is already there. In the business code where this exception is to be suppressed gracefully, store the exception as a request attribute and just let the Filter check/grab it from the request.


Update: as per the comments, here's an example:

public class Context { 
    private static ThreadLocal<Context> instance = new ThreadLocal<Context>();
    private HttpServletRequest request;
    private List<Exception> exceptions = new ArrayList<Exception>();

    private Context(HttpServletRequest request) {
        this.request = request;
        this.request.setAttribute("exceptions", exceptions);
    }

    public static Context getCurrentInstance() {
        return instance.get();
    }

    public static Context newInstance(HttpServletRequest request) {
        Context context = new Context(request);
        instance.set(context);
        return context;
    }

    public void release() {
        instance.remove();
    }

    public void addException(Exception exception) {
        exceptions.add(exception);
    }
}

And here's how to use it in your controller servlet:

Context context = Context.newInstance(request);
try {
    executeBusinessCode();
} finally {
    context.release();
}

And here's how you could use it in the executed business code:

} catch (Exception e) {
    Context.getCurrentInstance().addException(e);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文