AppInsights と Power BI を使って Java Web アプリの例外発生をリアルタイム監視する
前回の記事である Application Insights と Power BI を使って Java の Web アプリの PageView を監視する にて、Application Insights の連続エクスポート/Stream Analytics の Power BI 出力を活用して PageView のログが簡単に可視化できることが分かった。
今回は Application Insights に例外ログを出力して Power BI に可視化するまでの手順を紹介する。なお、Application Insights の連続エクスポート、Stream Analytics の設定、Power BI 設定の細かな手順については前回の記事を参照してほしい。
Java アプリケーションの記載
以下の様に入力文字列が空の場合に IllegalArgumentException を出力するコードを作成する。
- index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8" /> <script type="text/javascript"> var appInsights=window.appInsights||function(config){ function r(config){t[config]=function(){var i=arguments;t.queue.push(function(){t[config].apply(t,i)})}}var t={config:config},u=document,e=window,o="script",s=u.createElement(o),i,f;for(s.src=config.url||"//az416426.vo.msecnd.net/scripts/a/ai.0.js",u.getElementsByTagName(o)[0].parentNode.appendChild(s),t.cookie=u.cookie,t.queue=[],i=["Event","Exception","Metric","PageView","Trace"];i.length;)r("track"+i.pop());return r("setAuthenticatedUserContext"),r("clearAuthenticatedUserContext"),config.disableExceptionTracking||(i="onerror",r("_"+i),f=e[i],e[i]=function(config,r,u,e,o){var s=f&&f(config,r,u,e,o);return s!==!0&&t["_"+i](config,r,u,e,o),s}),t }({ instrumentationKey:"<my instrumentation key>" }); window.appInsights=appInsights; appInsights.trackPageView(); </script> <title>AppInsights-site index page</title> </head> <body> <h2>ポストしてみる</h2> <form method="post" action="<%=request.getContextPath()%>/home"> 文字列: <input name="message" type="text" placeholder="文字列を入力してください" /> <br /> <input type="submit" value="送信 " /> </form> </body> </html>
- HomeServlet.java
package com.mydomain; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import com.microsoft.applicationinsights.TelemetryClient; @WebServlet("/home") public class HomeServlet extends HttpServlet { private static final long serialVersionUID = 1L; private static final Logger logger = LogManager.getLogger(HomeServlet.class); /** * @see HttpServlet#HttpServlet() */ public HomeServlet() { super(); // TODO Auto-generated constructor stub } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse * response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse * response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { TelemetryClient telemetryClient = new TelemetryClient(); String message = request.getParameter("message"); if (message == null || message.length() == 0) { IllegalArgumentException ex = new IllegalArgumentException("please input message"); telemetryClient.trackException(ex); logger.warn("input warning"); } RequestDispatcher dispatch = request.getRequestDispatcher("/second.jsp"); dispatch.forward(request, response); } }
非常にシンプルなコードなので、特に解説は不要だと思う。
Stream Analytics を設定する
前回の記事を参考にインプットに BLOB ストレージ、アウトプットに Power BI を指定する。特に Stream Analytics のインプットのパターンは以下となる。
- プレフィックスのパターン: forpowerbiappinsights_
/Exceptions/{date}/{time} - 日付形式: YYYY-MM-DD
- 時刻形式: HH
そんな BLOB の格納される Exception のログは以下になる。
{ "basicException":[ { "assembly":"Unknown", "exceptionType":"java.lang.IllegalArgumentException", "outerExceptionType":"java.lang.IllegalArgumentException", "outerExceptionThrownAtMethod":"com.mydomain.HomeServlet.doPost", "outerExceptionThrownAtAssembly":"", "failedUserCodeMethod":"com.mydomain.HomeServlet.doPost", "failedUserCodeAssembly":"", "exceptionGroup":"java.lang.IllegalArgumentException at com.mydomain.HomeServlet.doPost", "id":"Representative", "typeName":"java.lang.IllegalArgumentException", "handledAt":"UserCode", "count":1, "method":"com.mydomain.HomeServlet.doPost", "problemId":"", "outerExceptionMessage":"please input message" }, { "parsedStack":[ { "method":"com.mydomain.HomeServlet.doPost", "fileName":"HomeServlet.java", "level":0, "line":78 }, { "method":"javax.servlet.http.HttpServlet.service", "fileName":"HttpServlet.java", "level":1, "line":648 }, <中略>
上記の "basicException" 内にある "exceptionType" を取得するクエリは以下となる。"parsedStack" 部分をスキップしないと空白の count(*) が出力されるため、HAVING 句で "basicException" の無い項目はスキップしている。
SELECT flat.ArrayValue.exceptionType, count(*) INTO [pbi-exception-output] FROM [export-input] A OUTER APPLY GetElements(A.[basicException]) as flat GROUP BY TumblingWindow(minute, 1), flat.ArrayValue.exceptionType HAVING LEN(flat.ArrayValue.exceptionType) > 0
Power BI でのリアルタイム表示
Power BI にログインし、Stream Analytics のアウトプットで指定したデータセットが表示されていることを確認する。ポータルから表示方法を設定し、"以下の様に ダッシュボード" にレポートを作成する*1。
体感値として、1分弱の時間で Application Insights の連続エクスポートが永続ログを吐き出し、2分~3分で Power BI 側に情報が反映される様だ。
*1:ダッシュボードに保存しないと、リアルタイムでの更新が確認できない