Java アプリケーションのRUM-APM-LOG連携分析¶
ユースケースの紹介¶
企業にとって最も重要な収益源はビジネスであり、現代のほとんどの企業のビジネスは対応するITシステムによって支えられています。では、企業のビジネスをいかに安定させるかという問題は、最終的には企業内のITシステムをいかに安定させるかという問題に帰着します。業務システムに異常や障害が発生した場合、多くの場合、ビジネス、アプリケーション開発、運用などの様々な部門の担当者が連携して問題の調査にあたる必要があり、プラットフォーム横断、部門横断、専門分野横断といった様々な課題があり、調査には時間と労力がかかります。
この問題を解決するために、現在業界で一般的に用いられている方法は、インフラストラクチャーモニタリングに加えて、アプリケーション層とログ層を深く監視し、RUM+APM+LOG によって業務システム全体の中核となるフロントエンド・バックエンドアプリケーションとログを統合管理することです。さらに高度なモニタリングでは、これらの3種類のデータをキーフィールドで連携させることで連携分析を実現し、関係者の作業効率を向上させ、システムの安定稼働を支えます。
- APM:アプリケーションパフォーマンスモニタリング(APM)
- RUM:リアルユーザーモニタリング(RUM)
- LOG:ログ
現在、Guance はこのような機能を備えています。本稿では、RuoYi オフィスシステムをデモとして使用し、RUM+APM+LOG の3つのモニタリングをどのように導入するか、そしてGuanceを使用して連携分析を行う方法について説明します。
DataKit のインストール¶
1 インストールコマンドのコピー¶
Guance に登録してログインし、「統合」 - 「DataKit」を選択し、ご自身の環境に適したインストールコマンドを選択してコピーします。
2 サーバーへの DataKit のインストール¶
3 DataKit の状態確認¶
コマンド systemctl status datakit を実行します。
4 データの確認¶
DataKit がインストールされると、デフォルトで以下の内容が収集されます。Guance の「インフラストラクチャー」 - 「ホスト」で関連データを確認できます。
| 収集器名 | 説明 |
|---|---|
| cpu | ホストのCPU使用率を収集 |
| disk | ディスク使用量を収集 |
| diskio | ホストのディスクIO状況を収集 |
| mem | ホストのメモリ使用状況を収集 |
| swap | Swapメモリ使用状況を収集 |
| system | ホストのOS負荷を収集 |
| net | ホストのネットワークトラフィックを収集 |
| host_process | ホスト上の常駐プロセス (10分以上生存)のリストを収集 |
| hostobject | ホストの基本情報 (OS情報、ハードウェア情報など)を収集 |
| docker | ホスト上のコンテナオブジェクトとコンテナログを収集 |
異なる統合 inputs 名を選択すると、対応するモニタリングビューを表示できます。モニタリングビューの下では、ログ、プロセス、コンテナなどの他のデータも確認できます。
RUM¶
詳細な手順はドキュメント Webアプリケーションモニタリング(RUM)ベストプラクティス を参照してください。
1 JSコードのコピー¶
Guance にログインし、「リアルユーザーモニタリング(RUM)」 - 「アプリケーションを作成」 - 「Web」を選択し、読み込みタイプで「同期読み込み」を選択します。
2 JSの埋め込み¶
フロントエンドページ /usr/local/ruoyi/dist/index.html の head 内にJSを貼り付けます。
<script src="https://static.guance.com/browser-sdk/v2/dataflux-rum.js" type="text/javascript"></script>
<script>
window.DATAFLUX_RUM &&
window.DATAFLUX_RUM.init({
applicationId: 'appid_9c7fd257fd824300ba70f7e6d3f5083e',
datakitOrigin: 'http://112.124.52.73:9529',
env: 'dev',
version: '1.0',
trackInteractions: true,
traceType: 'ddtrace',
allowedTracingOrigins: ['http://112.124.52.73']
})
</script>
パラメータ説明
- datakitOrigin:データ転送アドレス。本番環境でドメイン名を設定している場合は、ドメイン名のリクエストを datakit-9529 ポートがインストールされた任意の1台のサーバーに転送できます。フロントエンドのアクセス量が多すぎる場合は、ドメイン名と DataKit が存在するサーバーの間にSLBを追加できます。フロントエンドのJSはデータをSLBに送信し、SLBはリクエストを datakit-9529 がインストールされた複数のサーバーに転送します。複数のDataKitがRUMデータを処理しますが、フロントエンドリクエストの再利用により、セッションデータが中断されることはなく、RUMデータの表示にも影響はありません。
- allowedTracingOrigins:フロントエンドとバックエンド(APMとRUM)の連携を実現します。このシナリオは、フロントエンドにRUMを、バックエンドにAPMをデプロイしている場合にのみ有効です。ここには、フロントエンドページとインタラクションのあるバックエンドアプリケーションサーバーに対応するドメイン名(本番環境)またはIP(テスト環境)を入力する必要があります。ユースケース:フロントエンドのユーザーアクセスが遅い場合、その原因がバックエンドのコードロジックの異常にある可能性があります。フロントエンドのRUMの遅いリクエストデータから直接APMデータにジャンプして、その時点のバックエンドコードの呼び出し状況を確認し、遅延の根本原因を特定できます。実装原理:ユーザーがフロントエンドアプリケーションにアクセスすると、フロントエンドアプリケーションはリソースとリクエストの呼び出しを行い、rum-js がパフォーマンスデータの収集をトリガーします。rum-js は trace-id を生成し、リクエストの request_header に書き込みます。リクエストがバックエンドに到達すると、バックエンドの ddtrace がこの trace_id を読み取り、自身のトレースデータに記録します。これにより、同じ trace_id を介してアプリケーションパフォーマンスモニタリング(APM)とリアルユーザーモニタリング(RUM)のデータを連携させることができます。
- env:必須。アプリケーションが属する環境。test、product、またはその他の値を指定します。
- version:必須。アプリケーションのバージョン番号。
- trackInteractions:ユーザー行動の分析。例えば、ボタンのクリックや情報の送信などのアクションを記録します。
3 公開¶
ページを保存、検証して公開します。
ブラウザで対象のページにアクセスし、F12 開発者ツールを使用して、ページのネットワークリクエストに rum 関連のリクエストが存在し、ステータスコードが 200 であることを確認します。
Warning
F12 開発者ツールでデータが送信されず、ポートが refused と表示される場合は、telnet IP:9529 でポートが開いているか確認してください。
開いていない場合は、/usr/local/datakit/conf.d/datakit.conf を編集し、先頭行の http_listen を 0.0.0.0 に変更します。
それでも開かない場合は、セキュリティグループで 9529 ポートが開放されているか確認してください。
4 RUMデータの確認¶
「リアルユーザーモニタリング(RUM)」でRUM関連データを確認できます。
APM¶
詳細な手順はドキュメント 分散型トレーシング(APM)ベストプラクティス を参照してください。
Guance がサポートするAPMの導入方法には、ddtrace、SkyWalking、Zipkin、Jaeger など、OpenTracing プロトコルをサポートするさまざまなAPMツールがあります。ここでは、ddtrace を使用したAPMの可観測性の実現例を示します。
1 inputs の修正¶
DataKit で APM(ddtrace)の inputs を修正します。
デフォルトでは jvm の inputs を修正する必要はなく、conf ファイルをコピーして作成するだけで済みます。
$ cd /usr/local/datakit/conf.d/ddtrace/
$ cp ddtrace.conf.sample ddtrace.conf
$ vim ddtrace.conf
# デフォルトでは修正不要
2 Javaアプリケーションの起動スクリプトの修正¶
APMの可観測性を実現するには、Javaアプリケーションにエージェントを追加する必要があります。このエージェントは、アプリケーションの起動時にバイトコードインジェクション技術を使用して、アプリケーション内部のメソッド呼び出し、SQL呼び出し、外部システム呼び出しなどのパフォーマンスデータを収集し、アプリケーションシステムのコード品質の可観測性を実現します。
# 元のアプリケーション起動スクリプト
$ cd /usr/local/ruoyi/
$ nohup java -Dfile.encoding=utf-8 -jar ruoyi-gateway.jar > logs/gateway.log 2>&1 &
$ nohup java -Dfile.encoding=utf-8 -jar ruoyi-auth.jar > logs/auth.log 2>&1 &
$ nohup java -Dfile.encoding=utf-8 -jar ruoyi-modules-system.jar > logs/system.log 2>&1 &
——————————————————————————————————————————————————————————————————————————————————————————
# ddtrace-agent 追加後のアプリケーション起動スクリプト
$ cd /usr/local/ruoyi/
$ nohup java -Dfile.encoding=utf-8 -javaagent:dd-java-agent-0.80.0.jar -XX:FlightRecorderOptions=stackdepth=256 -Ddd.logs.injection=true -Ddd.service.name=ruoyi-gateway -Ddd.service.mapping=redis:redis_ruoyi -Ddd.agent.port=9529 -Ddd.jmxfetch.enabled=true -Ddd.jmxfetch.check-period=1000 -Ddd.jmxfetch.statsd.port=8125 -Ddd.version=1.0 -jar ruoyi-gateway.jar > logs/gateway.log 2>&1 &
$ nohup java -Dfile.encoding=utf-8 -javaagent:dd-java-agent-0.80.0.jar -XX:FlightRecorderOptions=stackdepth=256 -Ddd.logs.injection=true -Ddd.service.name=ruoyi-auth -Ddd.service.mapping=redis:redis_ruoyi -Ddd.env=staging -Ddd.agent.port=9529 -Ddd.jmxfetch.enabled=true -Ddd.jmxfetch.check-period=1000 -Ddd.jmxfetch.statsd.port=8125 -Ddd.version=1.0 -jar ruoyi-auth.jar > logs/auth.log 2>&1 &
$ nohup java -Dfile.encoding=utf-8 -javaagent:dd-java-agent-0.80.0.jar -XX:FlightRecorderOptions=stackdepth=256 -Ddd.logs.injection=true -Ddd.service.name=ruoyi-modules-system -Ddd.service.mapping=redis:redis_ruoyi,mysql:mysql_ruoyi -Ddd.env=dev -Ddd.agent.port=9529 -Ddd.jmxfetch.enabled=true -Ddd.jmxfetch.check-period=1000 -Ddd.jmxfetch.statsd.port=8125 -Ddd.version=1.0 -jar ruoyi-modules-system.jar > logs/system.log 2>&1 &
ddtrace 関連の環境変数(起動パラメータ)の説明:
- Ddd.env:カスタム環境タイプ。オプションです。
- Ddd.tags:カスタムアプリケーションタグ。オプションです。
- Ddd.service.name:カスタムアプリケーション名。必須です。
- Ddd.agent.port:データアップロードポート(デフォルトは9529)。必須です。
- Ddd.version:アプリケーションバージョン。オプションです。
- Ddd.trace.sample.rate:サンプリングレートの設定(デフォルトは全件サンプリング)。オプションです。サンプリングが必要な場合は、0~1の間の数値(例:0.6 は60%サンプリング)を設定します。
- Ddd.service.mapping:現在のアプリケーションが呼び出す redis、mysql などに、エイリアスを追加するためのパラメータです。他のアプリケーションが呼び出す redis、mysql と区別するために使用します。オプションです。ユースケース:例えば、プロジェクトAとプロジェクトBの両方が mysql を呼び出しており、それぞれ mysql-a、mysql-b を呼び出している場合、mapping 設定項目を追加しないと、df プラットフォーム上ではプロジェクトAとプロジェクトBの両方が同じ名前の mysql データベースを呼び出しているように表示されます。mapping 設定項目を追加して mysql-a、mysql-b と設定すると、df プラットフォーム上ではプロジェクトAが mysql-a を、プロジェクトBが mysql-b を呼び出しているように表示されます。
- Ddd.agent.host:データ転送先IP。デフォルトはローカルホスト localhost。オプションです。
3 APMデータの確認¶
APM はGuanceのデフォルトの組み込みモジュールであり、シーンやビューを作成しなくても確認できます。
ビュー例:
このビューを使用すると、アプリケーションの呼び出し状況、トポロジービュー、異常データ、その他のAPM関連データをすばやく確認できます。
呼び出しチェーンの問題追跡:
インターフェースやデータベースなどの問題を調査できます。
LOG¶
1 標準ログ収集¶
例:Nginx、MySQL、Redis など
DataKit に組み込まれているさまざまな inputs を有効にすることで、関連するログ収集を直接開始できます。例えば、Nginx、Redis、コンテナ、ES などです。
例:Nginx
$ cd /usr/local/datakit/conf.d/nginx/
$ cp nginx.conf.sample nginx.conf
$ vim nginx.conf
## ログパスを正しい nginx パスに修正
$ [inputs.nginx.log]
$ files = ["/usr/local/nginx/logs/access.log","/usr/local/nginx/logs/error.log"]
$ pipeline = "nginx.p"
## pipeline は grok ステートメントで、テキストログの切り出しに使用します。datakit には nginx、mysql などの複数の pipeline が組み込まれています。pipeline のデフォルトディレクトリは /usr/local/datakit/pipeline/ です。ここで pipeline パスを修正する必要はなく、datakit がデフォルトで自動的に読み取ります。
ビュー表示:
2 カスタムログ収集¶
例:アプリケーションログ、ビジネスログなど
例:アプリケーションログ Pipeline(ログ grok 切り出し)公式ドキュメント
$ cd /usr/local/datakit/conf.d/log/
$ cp logging.conf.sample system-logging.conf
$ vim system-logging.conf
## ログパスを正しいアプリケーションログのパスに修正
## source と service は必須フィールドです。アプリケーション名を直接使用して、異なるログ名を区別できます。
[[inputs.logging]]
## required
logfiles = [
"/usr/local/java/ruoyi/logs/ruoyi-system/info.log",
"/usr/local/java/ruoyi/logs/ruoyi-system/error.log",
]
## glob filteer
ignore = [""]
## your logging source, if it's empty, use 'default'
source = "system-log"
## add service tag, if it's empty, use $source.
service = "system-log"
## grok pipeline script path
pipeline = "log_demo_system.p"
## optional status:
## "emerg","alert","critical","error","warning","info","debug","OK"
ignore_status = []
## optional encodings:
## "utf-8", "utf-16le", "utf-16le", "gbk", "gb18030" or ""
character_encoding = ""
## The pattern should be a regexp. Note the use of '''this regexp'''
## regexp link: https://golang.org/pkg/regexp/syntax/#hdr-Syntax
multiline_match = '''^\d{4}-\d{2}-\d{2}'''
## removes ANSI escape codes from text strings
remove_ansi_escape_codes = false
## pipeline は grok ステートメントで、テキストログの切り出しに使用します。この設定を行わない場合、デフォルトでは df プラットフォーム上にログの元のテキスト内容が表示されます。設定を行うと、対応するログが grok で切り出されます。ここで指定する .p ファイルは、手動で作成する必要があります。
$ /usr/local/datakit/pipeline/
$ vim ruoyi_system.p
grok(_, "%{TIMESTAMP_ISO8601:time} %{NOTSPACE:thread_name} %{LOGLEVEL:status}%{SPACE}%{NOTSPACE:class_name} - \\[%{NOTSPACE:method_name},%{N
UMBER:line}\\] - %{DATA:service1} %{DATA:trace_id} %{DATA:span_id} - %{GREEDYDATA:msg}")
default_time(time)
3 ログデータの確認¶
RUM と APM のデータ連携デモ¶
原理説明:ユーザーがフロントエンドアプリケーションにアクセスすると(RUMモニタリングが追加され、allowedTracingOrigins フィールドが設定されている場合)、フロントエンドアプリケーションはリソースとリクエストの呼び出しを行い、rum-js がパフォーマンスデータの収集をトリガーします。rum-js は trace-id を生成し、リクエストの request_header に書き込みます。リクエストがバックエンドに到達すると、バックエンドの ddtrace がこの trace_id を読み取り、自身のトレースデータに記録します。これにより、同じ trace_id を介してアプリケーションパフォーマンスモニタリング(APM)とリアルユーザーモニタリング(RUM)のデータの連携分析を実現します。
ユースケース:フロントエンドとバックエンドの関連付け。フロントエンドリクエストとバックエンドメソッドの実行パフォーマンスデータを一対一でバインドすることで、フロントエンドとバックエンドに関連する問題をより簡単に特定できます。例えば、フロントエンドのユーザーログインが遅い場合、その原因がバックエンドサービスがデータベースにユーザー情報を問い合わせるのに時間がかかりすぎることにある場合、フロントエンドとバックエンドの連携分析により、チームや部門を超えて迅速に問題を特定できます。例は以下の通りです。
設定方法:Webアプリケーションモニタリング(RUM)ベストプラクティス
1 フロントエンドのRUMデータ¶
2 バックエンドのAPMデータへのジャンプ¶
APM と LOG のデータ連携デモ¶
1 APMモニタリングの有効化¶
Kubernetes アプリケーションのRUM-APM-LOG連携分析 のAPM部分を参照してください。追加の操作は必要ありません。
2 アプリケーションログの出力形式の修正¶
この手順は開発者の介入が必要です。アプリケーションログの出力形式のファイル logback/log4j を修正します。
<!-- ログ出力形式 -->
<property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] %X{dd.service} %X{dd.trace_id} %X{dd.span_id} - %msg%n" />
この xml ファイルを保存し、アプリケーションを再公開します。
3 ログモニタリングの有効化¶
例:
$ cd /usr/local/datakit/conf.d/log/
$ cp log.conf.sample ruoyi-system.conf
$ vim ruoyi-system.conf
## 以下の内容を修正
## logfiles はアプリケーションログの絶対パス
## service と source は必須フィールドで、df プラットフォーム上で検索するために使用します
## Pipeline は必要に応じて設定します。pipeline は主にログのフィールド切り出しに使用され、切り出したログの内容はメトリクスとして保存し、可視化できます。trace-id 関連の内容は可視化する必要がないため、切り出す必要はありません。
4 APM & LOG 連携分析¶
- 順方向関連付け [APM → ログ]
APM トレースデータ内で、下部のログモジュールから直接trace_idを検索すると、このトレース呼び出しに対応するアプリケーションログを表示できます。
- 逆方向関連付け [ログ → APM]
異常ログを確認し、ログ内のtrace_idをコピーします。分散型トレーシングのページの検索ボックスでそのtrace_idを直接検索すると、その id に関連するすべてのトレースとスパンデータが表示されるので、クリックして確認できます。

























