LoginSignup
2
1

More than 3 years have passed since last update.

ApplicationInsightsのjavaagentを仕込んで実行されたSQLをトレース

Posted at

ドキュメントにある内容をやっただけです。

こんな感じになります。

image.png

黒塗りばかりのこの画像は所要時間が5分かかった謎のリクエストを調べたときのものです。
4回SQLクエリが実行されている様子と、2個ほどクソクエリがある様子が分かります。クエリのどれかをクリックすると、右のコマンドにSQLが出てきます。

SQLの内容はPreparedStatementを使っているためかPreparedなSQLになっており、パラメータは「?」になっているまでは見れないようです。(逆に埋められても機密情報が見えかねないのでこれはこれで良いと思います)
呼び出されたコードの位置もわかりません。でも実装者なら十分役立つことでしょう。

もちろん、DBクエリの情報をApplicationInsightsに送るため、転送量がかかるのでその点は注意してください。

前提

  • Javaアプリ
  • ApplicationInsightsは導入済み

仕組み

JavaAgentを使って、クラスローダでクラスを読み込む際にクラスファイルに手を加え、テレメトリを書き出す仕組みになっているようです。

JavaAgentを組み込むだけでよいので、動いているコードには手を加えずに利用できます。

導入

  • javaagentファイルをダウンロード
  • 同じ場所にAI-Agent.xmlを作成
  • JVM引数に-javaagent:...を追加
  • アプリケーション再起動

導入手順はAzure WebApp上を想定していますが、JavaのWebアプリケーションならAzure WebAppに限らずちょっと読み替えるだけで導入できます。

ApplicationInsightsのjavaagentを導入する

https://github.com/microsoft/ApplicationInsights-Java/releases/ で公開されているので、導入済みのApplicationInsightsのバージョンにあったagentを入れます。

Azure WebAppなら、kudu上でこんな感じに操作。D:\home\data 辺りなら邪魔にならないかと思いますが、適宜変更してください。


cd D:\home\data
curl -LO https://github.com/microsoft/ApplicationInsights-Java/releases/download/2.1.1/applicationinsights-agent-2.1.1.jar

AI-Agent.xmlファイルを作成

AI-Agent.xmlというファイルを先ほどダウンロードしたjarファイルがある場所と同じ場所に作成してください。

内容は以下をコピペで良いです。

AI-Agent.xml
<?xml version="1.0" encoding="utf-8"?>
<ApplicationInsightsAgent>
    <Instrumentation>
        <BuiltIn enabled="true"> <!-- ここのenabled属性も見ているため忘れずに。 -->
            <JDBC enabled="true" /> <!-- JDBCでクエリを投げた時にクエリの実行時間とPreparedなSQLのテレメトリを送信 -->
        </BuiltIn>
    </Instrumentation>
</ApplicationInsightsAgent>

今回はJDBCのみですが、設定でいくつかのHTTP呼び出しなどもトレースできるようです。

JVM引数に-javaagent:...を追加

JVM引数に以下を追加します。ファイルパスは適宜置き換えます。

-javaagent:D:/home/data/applicationinsights-agent-2.1.1.jar

Tomcatで動かすアプリなら環境変数JAVA_OPTSCATALINA_OPTSでよいです。

Azure WebAppならアプリケーション設定かkudu上からweb.configで。ただし、アプリケーション設定の方が優先されるので、その点を考慮してください。

アプリケーション再起動

javaagentを読み込ませるために再起動が必要です。

以上。

その他

冗長なテレメトリを抑制したい

現状、時間がかかった場合だけ送る、といったことは出来ないようです。

例えば、十分に早いことが分かっているクエリや、コネクションプーリングを使っているとプールから取り出したときに腐ってないかチェックするときのSELECT 1でもテレメトリが送られてしまいます。
もし防ぎたい場合は、フィルタを書く必要があります。以下のIssueにTelemetryProcessorの実装例があります。

参考: https://github.com/microsoft/ApplicationInsights-Java/issues/837#issuecomment-471610584

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1