jmc线程转储_使线程转储智能化
jmc線程轉儲
很久以前,我了解了一個稱為Log MDC的東西,我對此非常感興趣。 我突然意識到日志文件中發生的一切,并指出了特定的日志條目,并找到了對錯,特別是在調試生產中的錯誤時。
2013年,我受委托從事一個項目,該項目正在經歷一些麻煩的水域(幾件事的結合),幾乎每個星期我都必須經歷幾個Java線程轉儲,以弄清應用程序中發生的事情以使其停止。 另外,有時候我不得不將諸如AppDynamic,jProfiler,jConsole之類的探查器全部連接到應用程序,以試圖找出問題所在,更重要的是是什么引發了問題。 jStack是我曾經使用過的最有用的工具之一,但是顛簸的線程轉儲沒有我可以使用的上下文信息。 我被困在看到10(s)個轉儲,其中包含導致類的原因的類的堆棧跟蹤,但是沒有有關什么是什么以及導致問題的輸入的信息,并且它很快就令人沮喪。 最終,我們找到了問題,但是它們主要是經過幾輪使用各種數據集進行的深度調試之后。
一旦完成該項目,我發誓我再也不會陷入那種境地了。 我探索了可以使用類似于Log4j的NDC但在線程中使用它的方式,以便我的轉儲有意義。 而且我發現我可以更改ThreadName。 我的下一個項目確實非常有效地使用了它。 我最近遇到了一篇文章,很好地解釋了這個概念。 我不會重寫他們所說的所有內容,因此這里是他們博客文章的鏈接 。
所以上周我開始一個新項目,當我開始編碼框架時(使用Spring 4.1和Spring Boot),這是我為應用程序編寫的第一個類,并確保過濾器盡快進入代碼。幫助我們進行后期制作,但也使我的開發日志有意義。
下面是Log4j NDC和設置ThreadName的代碼副本。
import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date;import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.filter.OncePerRequestFilter;/*** This is a very Spring opinionated HTTPFilter used for intercepting all requests and decorate the thread name with additional contextual* information. We have extenced the filter from {@link OncePerRequestFilter} class provided by Spring Framework to ensure that the filter is absolutely * executd only once per request. * * The following information will be added:* <ul>* <li>Old Thread name: to ensure that we are not losing any original context with thread names;</li>* <li>Time when the request was intercepted;</li>* <li>The RequestURI that proviced information on what RestFUL endpoint was accessed as part of this request;</li>* <li>A Token that was received in the header. This token is encrypted and does not exposes any confidential information. Also, this token provides* context which helps during debugging;</li>* <li>The Payload from the token. This information will be very helpful when we have to debug for issues that may be happening with a call request* as this holds all the information sent from the called.</li>* </ul>* * This filter will also reset the ThreadName back to it's original name once the processing is complete.* * @author Kapil Viren Ahuja**/ public class DecorateThreadNameFilter extends OncePerRequestFilter {@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)throws ServletException, IOException {final Logger LOGGER = LoggerFactory.getLogger(DecorateThreadNameFilter.class);final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");Thread thread = Thread.currentThread();String threadOriginalName = thread.getName();String uri = request.getRequestURI();String time = dateFormat.format(new Date());String token = request.getHeader("authorization");try {thread.setName(String.format("%s StartTime \"%s\" RequestURI \"%s\" Token \"%s\"", threadOriginalName, time, uri, token));} catch (Exception ex) {LOGGER.error("Failed to set the thread name.", ex);// this is an internal filter and an error here should not impact// the request processing, hence eat the exception}try {filterChain.doFilter(request, response);} finally {try {thread.setName(threadOriginalName);} catch (Exception ex) {LOGGER.error("Failed to reset the thread name.", ex);// this is an internal filter and an error here should not// impact the request processing, hence eat the exception}}} }/*** Generic filter for intercepting all requests and perform the following generic tasks:* * <ul>* <li>Intercepts the request and then pushed the user domain into the session if one exists.</li>* <li> Pushes a uniquely generated request identifier to the LOG4J NDC context. This identifier will then be prepended* to all log messages generated using LOG4J. This allows tracing all log messages generated as part of the same* request; </li>* <li> Pushes the HTTP session identifier to the LOG4J NDC context. This identifier will then be prepended to all log* messages generated using LOG4J. This allows tracing all log messages generated as part of the same HTTP session;* </li>* <li> Pushes the IP address of the client to the LOG4J NDC context. The IP address will then be prepended to all log* messages generated using LOG4J. This allows tying back multiple user sessions initiated with the same logon name to* be correctly tied back to their actual origins. </li>* </ul>*/ public class RequestInterceptorFilter implements Filter {/*** <p>* <ul>* <li>Initializes the LOG4J NDC context before executing an HTTP requests.</li>* <li>Pushes the domain into the session</li>* </ul>* </p>*/public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException{HttpServletRequest httpRequest = (HttpServletRequest) request;if (httpRequest.isRequestedSessionIdFromCookie() && !httpRequest.isRequestedSessionIdValid()){// TODO: Need to define an session expiration page and redirect the application to that page// As of now this is a non-issue as we are handling session expirations on Flex (Front-end) and hence// no request will come to server in case the session timeout occurs// HttpServletResponse httpServletResponse = (HttpServletResponse) response;// httpServletResponse.sendRedirect(httpRequest.getContextPath() + "?expired");}else{// Create an NDC context string that will be prepended to all log messages written to files.org.apache.log4j.NDC.push(getContextualInformation(httpRequest));// Process the chain of filterschain.doFilter(request, response);// Clear the NDC context string so that if the thread is reused for another request, a new context string is// used.org.apache.log4j.NDC.remove();}}public void init(FilterConfig arg0) throws ServletException{}public void destroy(){}/*** <p>* Generates the Contextual information to be put in the log4j's context. This information helps in tracing requests* </p>* * @param httpRequest* @return*/private String getContextualInformation(HttpServletRequest httpRequest){String httpRequestIdentifier = UUID.randomUUID().toString();String httpSessionIdentifier = httpRequest.getSession().getId();String clientAddress = httpRequest.getRemoteAddr();StringBuffer logNDC = new StringBuffer(httpRequestIdentifier + " | " + httpSessionIdentifier + " | " + clientAddress);String userName = (String)httpRequest.getSession().getAttribute(WebConstants.USERNAME);if (userName != null){logNDC.append(" | " + userName);}String domain = (String)httpRequest.getSession().getAttribute(WebConstants.DOMAIN);if (domain != null){logNDC.append(" | " + domain);}// Create an NDC context string that will be prepended to all log messages written to files.return logNDC.toString();} }翻譯自: https://www.javacodegeeks.com/2015/08/making-thread-dumps-intelligent.html
jmc線程轉儲
總結
以上是生活随笔為你收集整理的jmc线程转储_使线程转储智能化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电视安卓助手下载(电视安卓助手)
- 下一篇: 等保 备案(等保和备案)