Elastic APMでリアルユーザー監視(RUM)を実行 | Elastic Blog
エンジニアリング

Elastic RUM(Real User Monitoring)の概要

著者

RUMと聞いて、ラム酒で作られた素敵なカクテルを一杯飲みたいという気分になったでしょうか。残念ながら、私が話しているRUMはラム酒のことではありません。ただし、Elastic RUMも同じように素敵なものです。早速、見ていきましょう。このブログで詳細な内容を説明するには時間が必要なため、少し長くなることにご注意ください。

RUMとは

Elasticのリアルユーザー監視(real user monitoring)は、Webブラウザでのユーザーインタラクションをキャプチャし、パフォーマンスの観点から、Webアプリケーションの「リアルユーザーエクスペリエンス」の詳細なビューを提供します。ElasticのRUMエージェントは、任意のJavaScriptベースアプリケーションをサポートするJavaScriptエージェントです。RUMは、アプリケーションに関する貴重なインサイトを提供します。RUMの一般的な利点には次のようなものがあります。

  • RUMのパフォーマンスデータは、ボトルネックの特定と、サイトのパフォーマンスに関する問題が訪問者のエクスペリエンスにどのような影響を与えるかを把握するために役立ちます。
  • RUMによってキャプチャされたユーザーエージェント情報により、お客様が最もよく使用しているブラウザ、デバイス、プラットフォームを特定することができ、その情報を基にしてアプリケーションを最適化することができます。
  • RUMによって収集した各ユーザーのパフォーマンスデータを、場所の情報とともに使用することで、世界中の各地域でのWebサイトのパフォーマンスを把握できます。
  • RUMは、アプリケーションのサービスレベル契約(SLA)に関するインサイトおよび計測結果を提供します。

Elastic APMでRUMを開始する

このブログでは、ReactフロントエンドとSpring BootバックエンドのシンプルなWebアプリケーションのインストルメントプロセス全体を手順ごとに説明します。そうすることで、RUMエージェントが簡単に使用できることが分かるようになります。またボーナスとして、Elastic APMでフロントエンドおよびバックエンドのパフォーマンス情報を1つの包括的な分散トレースビューにまとめる方法についても説明します。詳細についてご興味がある場合は、Elastic APMと分散トレーシングの概要を説明した私の前回のブログをご覧ください。

Elastic APMリアルユーザー監視を使用するには、APMサーバーがインストールされたElastic Stackが必要です。もちろん、最新のElastic StackとAPMサーバーをダウンロードして、コンピューターでローカルにインストールすることもできますが、最も簡単なアプローチは、 Elastic Cloudのトライアルアカウントを作成することです。この場合は数分でクラスターを準備できます。APMはデフォルトのI/O最適化テンプレートで有効化されます。以降の説明は、クラスターが準備できているものとして進めます。

サンプルアプリケーション

インストルメントするアプリケーションは、Reactフロントエンドと、インメモリの自動車データベースへのAPIアクセスを提供するSpring Bootバックエンドで構成される、シンプルな自動車データベースアプリケーションです。このアプリケーションは意図的にシンプルにしてあります。以下と同じ手順に従ってご自身のアプリケーションをインストルメントできるように、詳細なインストルメンテーション手順をゼロから示していきます。

ReactフロントエンドとSpringバックエンドのシンプルなアプリケーション

ラップトップの任意の場所に、「CarApp」という名前のディレクトリを作成します。そして、そのディレクトリに、フロントエンドおよびバックエンドアプリケーションの両方のクローンを作成します。

git clone https://github.com/adamquan/carfront.git
git clone https://github.com/adamquan/cardatabase.git

ご覧のとおり、アプリケーションはきわめてシンプルです。Reactフロントエンドにいくつかのコンポーネントがあり、バックエンドのSpring Bootアプリケーションにいくつかのクラスがあるのみです。フロントエンドとバックエンドの両方について、GitHubのインストラクションに従ってアプリケーションを構築し、実行すると、次のように表示されるはずです。ブラウズ、自動車のフィルター、およびデータに対するCRUDオプションの実行ができます。

シンプルなReactユーザーインターフェイス

このようにアプリケーションを実行すると、RUMエージェントを使用したインストルメンテーションの準備が整ったことになります。

RUMですぐに使える豊富なインストルメンテーション機能

まずはRUMエージェントをインストールし、構成します。それには2つの方法があります。

  1. サーバーサイドアプリケーションの場合、RUMエージェントを依存関係としてインストールし、初期化します。

    npm install @elastic/apm-rum --save
        
  2. HTML構成でRUMエージェントをインストールします。

    <script src="https://unpkg.com/@elastic/apm-rum@4.0.1/dist/bundles/elastic-apm-rum.umd.min.js">
    </script>
    <script>
      elasticApm.init({
        serviceName: 'carfront',
        serverUrl: 'http://localhost:8200',
        serviceVersion:'0.90'
      })
    </script>
        

ここでは、フロントエンドがReactアプリケーションであるため、上記1のアプローチを使用します。index.jsと同じディレクトリの下に、次のコードを含んでいるrum.jsという名前のファイルがあります。

import { init as initApm } from '@elastic/apm-rum'
var apm = initApm({
 // 必要なサービス名を設定します(使用可能な文字は a-z、A-Z、0-9、-、_、スペースです)
 serviceName: 'carfront',
 // APMサーバーで使用されるアプリケーションのバージョンを設定し、
 // 適切なソースマップを見つけられるようにします
 serviceVersion:'0.90',
 // カスタムのAPMサーバーURLを設定します(デフォルト:http://localhost:8200)
 serverUrl: 'https://aba7c3d90b0b4820b05b0a9df44c096d.apm.us-central1.gcp.cloud.es.io:443',
 // distributedTracingOrigins: ['http://localhost:8080'],
})
export default apm;

RUMエージェントの初期化に必要な手順はこれだけです。以下に、構成のいくつかについて簡単に説明します。

  1. サービス名: サービス名を設定する必要があります。APM UIでアプリケーションを表します。意味のある名前にしましょう。
  2. サービスバージョン: アプリケーションのバージョンです。このバージョン番号は、適切なソースマップを見つけるためにAPMサーバーでも使用されます。ソースマップの詳細についてはのちほど説明します。
  3. サーバーURL: APMサーバーのURLです。APMサーバーURLは通常、公共インターネットからアクセスできることに注意してください。RUMエージェントはインターネット上のエンドユーザーのブラウザから、データをAPMサーバーにレポートするからです。
  4. distributedTracingOriginsについてはのちほど説明します。

Elastic APMバックエンドエージェントについて精通している方は、ここでAPMトークンが渡されていないことを不思議に思うかもしれません。その理由は、RUMエージェントが実際には秘密のAPMトークンを使用していないからです。トークンはバックエンドエージェントでのみ使用されます。フロントエンドコードはパブリックであり、秘密のトークンでは追加のセキュリティは提供されないからです。

次に、アプリケーションがロードされるときにこのJavaScriptファイルをロードし、それを、カスタムインストルメンテーションを実行する場所に含めます。ここでは、カスタムインストルメンテーションを含める前の、何も設定を追加していない状態から見ておきましょう。そのためには、rum.jsindex.jsに含める必要があるだけです。index.jsファイルはrum.jsをインポートして、ページロード名を設定します。ページロード名を設定しない場合、APM UIにページロードが「Unknown」(不明)としてリストされるため、分かりにくくなってしまいます。index.jsは次のようになります。

import apm from './rum'
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
apm.setInitialPageLoadName("Car List")
ReactDOM.render(<App />, document.getElementById('root'));
serviceWorker.unregister();

アプリケーションへの少量のトラフィックを生成します。Kibanaにログインし、APM UIをクリックします。「carfront」という名前のサービスがリストされているはずです。そのサービス名をクリックすると、トランザクションページが表示されます。デフォルトの「page-load」リストが表示され、「car list」ページロードが表示されるはずです。表示されない場合は、タイムピッカーで「Last 15 minutes」(最近15分)の時間範囲を選択します。[car list]リンクをクリックすると、次のようにブラウザインタラクションのウォーターフォールビューが表示されます。

Elastic APMでのサンプルトランザクション

RUMエージェントによってデフォルトでキャプチャされている情報量に驚きませんか?特に、timeToFirstBytedomInteractivedomComplete、およびfirstContentfulPaintなどのマーカーに注目しましょう。黒の点にマウスを合わせて名前を見ます。コンテンツの取得およびそれらのコンテンツのブラウザレンダリングについて、きわめて詳細な情報が提示されます。また、ブラウザからのリソースのローディングに関するすべてのパフォーマンスデータについても注目してください。カスタムインストルメンテーションなしで、RUMエージェントを初期化するだけで、これらすべての詳細なパフォーマンスメトリックを入手することができます。パフォーマンスに問題がある場合、その問題の原因はバックエンドサービスが遅いからなのか、ネットワークが遅いからなのか、または単にクライアントブラウザが遅いからなのかが、これらのメトリックによって簡単に判断できるため、非常に便利です。

確認が必要な方のために、以下にWebパフォーマンスのメトリックについて簡単に説明します。注意が必要なのは、Reactのような最新のWebアプリケーションフレームワークにおいて、これらのメトリックはWebページの「静的」な部分を表すだけの場合があることです。Reactは非同期だからです。たとえば、動的コンテンツの場合、domInteractiveの後にもまだロードされる可能性があります(のちほど説明します)。

  • timeToFirstByte:情報をリクエストした後、Webサーバーから最初の情報を受信するまでの待機時間です。これは、ネットワークおよびサーバーサイドの処理スピードの組み合わせとなります。
  • domInteractive:ユーザーエージェントが現在のドキュメントの準備状況を「interactive」(インタラクティブ)に設定する直前の時間です。そのように設定されたということは、ブラウザですべてのHTMLおよびDOM構造のパースが完了したことを意味します。
  • domComplete: ユーザーエージェントが現在のドキュメントの準備状況を「complete」(完了)に設定する直前の時間です。そのように設定されたということは、ページおよびそれらのサブリソース(画像など)のダウンロードが完了し、準備が整ったことを意味します。ローディングのスピナーが停止します。
  • firstContentfulPaint:DOMからの最初のコンテンツをブラウザがレンダリングする時間です。これは、ページが実際にロードされていることのフィードバックとなるため、ユーザーにとって重要なマイルストーンです。

柔軟なカスタムインストルメンテーション

すでに見たとおり、RUMエージェントは、何も設定しない状態で、 ブラウザインタラクションについての詳細なインストルメンテーションを提供します。必要な場合は、カスタムインストルメンテーションを実行することもできます。たとえば、Reactアプリケーションはシングルページアプリケーションのため、自動車を削除しても「ページロード」はトリガーされず、RUMはデフォルトではこの自動車の削除に関するパフォーマンスデータをキャプチャすることはありません。このような場合にカスタムトランザクションを使用することができます。

最新のリリース(APM Real User Monitoring JavaScriptエージェント4.x)では、ユーザーはページロードをトリガーしないAJAXコールおよびシングルページアプリケーション(SPA)コールのトランザクションを手動で作成する必要があります。JSFなど、JavaScriptに対する制御があまりできないフレームワークもあるため、AJAXリクエストを開始するボタンクリックのトランザクションを手動で作成することは現実的ではありません。開発者がAJAXリクエストを直接制御できたとしても、大規模なアプリケーションのインストルメントには多大な労力が必要です。ElasticではRUMエージェントを強化する予定です。つまり、RUMエージェントが自動的にこれらのリクエスト向けのトランザクションを作成(有効なトランザクションが存在していない場合)するようにと考えています。これにより、開発者がプログラミングして追跡ロジックをアプリケーションに追加する必要なく、自動によるインストルメンテーションでさらに多くのアプリケーションに対応できるようになります。

フロントエンドアプリケーションの[New Car]ボタンにより、データベースに新しい自動車を追加することができます。自動車の新たな追加に関するパフォーマンスをキャプチャするために、そのコードをインストルメントします。コンポーネントのディレクトリでCarlist.jsファイルを開きます。次のようなコードがあります。

// 新しい自動車を追加します
addCar(car) {
    // カスタムトランザクションを作成します
    var transaction = apm.startTransaction("Add Car", "Car");
    apm.addTags(car);
    fetch(SERVER_URL + 'api/cars',
        {
            method:'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body:JSON.stringify(car)
        })
        .then(res => this.fetchCars())
        .catch(err => console.error(err))
}
fetchCars = () => {
    fetch(SERVER_URL + 'api/cars')
        .then((response) => response.json())
        .then((responseData) => {
            this.setState({
                cars: responseData._embedded.cars,
            });
        })
        .catch(err => console.error(err));
        // 現在のトランザクションを応答コールバックの最後で終了させます
        var transaction = apm.getCurrentTransaction()
        if (transaction) transaction.end()
}

このコードによって、「Car」タイプの「Add Car」という名前の新しいトランザクションが作成されました。そして、コンテキスト情報を提供するために、自動車にトランザクションがタグ付けされます。トランザクションは応答コールバックの最後で終了します。

アプリケーションWeb UIから新たに自動車を追加します。KibanaのAPM UIをクリックします。「Add Car」トランザクションがリストされているはずです。[Filter by type]ドロップダウンで[Car]を選択していることを確認します。デフォルトでは「page-load」トランザクションが表示されます。

Elastic APMでタイプでフィルター

[Add Car]トランザクションリンクをクリックします。カスタムトランザクション「Add Car」のパフォーマンス情報が表示されるはずです。

Elastic APMでの「car」タイプでフィルターしたトランザクションサンプル

[Tags]タブをクリックします。追加したタグが表示されます。タグとログは、APMトレースに貴重なコンテキスト情報を追加します。

Elastic APMでタイプタグで探索

カスタムインストルメンテーションを実行するために必要な作業はこれだけです。作業は簡単ですがその機能は強力です。詳細に関しては、APIドキュメントを参照してください。

Kibanaを使用した強力なカスタムAPMビジュアライゼーション

Elastic APMは、 洗練されたAPM UIと内蔵のAPMダッシュボードを提供します。これにより、何も設定を加えていない状態のエージェントによってキャプチャされたすべてのAPMデータを可視化できます。また、独自のカスタムビジュアライゼーションを作成することもできます。たとえば、RUMエージェントによってキャプチャされたユーザーIPおよびユーザーエージェントデータは、お客様に関するきわめて豊富な情報となります。ユーザーIPとユーザーエージェントに関するすべての情報があれば、以下のようなビジュアライゼーションを作成することが可能です。以下では、Webトラフィックがどこから来ているのかが地図上に示されており、また、お客様がどのオペレーティングシステムおよびブラウザを使用しているかが示されています。ingestノードパイプラインを使用して、APMデータをエンリッチ化および変換できます。これらすべての情報により、アプリケーションをよりインテリジェントに最適化することが可能になります。

KibanaダッシュボードでElastic APMデータを可視化

分散トレーシングで全体像を見る

ボーナスポイントとして、ここでバックエンドのSpring Bootアプリケーションもインストルメントします。そうすることで、Webブラウザからバックエンドデータベースまでの全体のトランザクションを1つのビューで包括的に見ることができます。Elastic APMの分散トレーシングならそれが可能です。

RUMエージェントで分散トレーシングを構成

分散トレーシングは、RUMエージェントでデフォルトで有効化されます。ただし、同じオリジンに対して行われたリクエストのみが含まれます。オリジン間リクエストを含めるためには、distributedTracingOrigins構成オプションを設定する必要があります。また、バックエンドアプリケーションにCORSポリシーを設定する必要もあります。これについては次のセクションで説明します。

ここでのアプリケーションでは、フロントエンドは http://localhost:3000から提供されます。http://localhost:8080へのリクエストを含めるためには、distributedTracingOrigins構成をReactアプリケーションに追加する必要があります。これはrum.js内でできます。すでにそこにコードがあります。単にコメントアウトを解除するだけです。

var apm = initApm({
  ...
  distributedTracingOrigins: ['http://localhost:8080']
})

これにより、http:// localhost:8080へのリクエストに分散トレースHTTPヘッダー(elastic-apm-traceparent)を追加するよう、エージェントに効果的に指示されます。

何も設定を加えていないデフォルトのインストルメンテーションをサーバーサイドで使用するには、Javaエージェントをダウンロードし、それとともにアプリケーションを起動する必要があります。以下は、バックエンドのSpring Bootアプリケーションを実行するために、私がEclipseプロジェクトを構成した方法です。ご自身のAPM URLとAPMトークンを使用して構成してください。

-javaagent:/Users/aquan/Downloads/elastic-apm-agent-1.4.0.jar 
-Delastic.apm.service_name=cardatabase 
-Delastic.apm.application_packages=com.packt.cardatabase
-Delastic.apm.server_urls=https://aba7c3d90b0b4820b05b0a9df44c096d.apm.us-central1.gcp.cloud.es.io:443 
-Delastic.apm.secret_token=jeUWQhFtU9e5Jv836F

バックエンドデータをElastic APMに送信するようにEclipseを構成

では、ブラウザで自動車のリスト(car list)を更新して新たにリクエストを生成します。Kibana APM UIにアクセスし、最新の「car list」ページロードを確認します。次のスクリーンショットのように表示されるはずです。ご覧のとおり、JDBCアクセスを含む、ブラウザからのクライアントサイドのパフォーマンスデータとサーバーサイドのパフォーマンスデータがすべて、1つの分散トレースできれいに表示されます。異なる色が、分散トレースの異なる部分に使用されています。これは、アプリケーションとエージェントを起動しているだけであって、サーバーサイドで何もカスタムインストルメンテーションを追加していないデフォルトのトレーシングであることにご注意ください。Elastic APMと分散トレーシングの力を感じることができます。

Elastic APMでの分散トレーシング(バックエンドおよびフロントエンド)

上記のタイムラインのビジュアライゼーションに注目している方は、バックエンドからまだデータが提供されているのに、なぜ「Car List」ページロードトランザクションがdomInteractiveの時間の193 msで終了しているのかについて疑問があるかもしれません。良い質問です。これは、デフォルトでは取得の呼び出しが非同期だからです。Webサーバーから提供される「静的」なHTMLコンテンツのすべてをロードしたため、ブラウザはすべてのHTMLおよびDOM構造の解析が193 msで完了したとみなします。一方、Reactはまだバックエンドサーバーから非同期にデータをロードし続けています。

オリジン間リソース共有(CORS)

RUMエージェントは、分散トレースのパズルの1ピースに過ぎません。分散トレーシングを使用するためには、その他のコンポーネントも適切に構成する必要があります。通常、構成する必要のあるものの1つはオリジン間リソース共有、つまり「悪名高い」CORSです。この構成が必要なのは、フロントエンドおよびバックエンドサービスは通常、別々に展開されているからです。same-originポリシーを使用すると、CORSが適切に構成されていない場合、異なるオリジンからバックエンドへのフロントエンドリクエストは失敗します。基本的にCORSは、異なるオリジンからのリクエストが許可されているかどうかをサーバーサイドで確認する方法です。オリジン間リクエストの詳細について、およびこのプロセスが必要な理由については、オリジン間リソース共有に関するMDNのページをご確認ください。

CORSは具体的に何を意味するのでしょうか。それは次の2つを意味します。

  1. distributedTracingOrigins構成オプションを設定する必要があります。これはすでに完了しています。
  2. その構成により、RUMエージェントは実際のHTTP要求の前にHTTP OPTIONS要求も送信して、すべてのヘッダーとHTTPメソッドがサポートされていること、およびオリジンが許可されていることを確認します。具体的には、http://localhost:8080は以下のヘッダーを使用することで OPTIONSリクエストを受信します。

    Access-Control-Request-Headers: elastic-apm-traceparent
    Access-Control-Request-Method: [request-method]
    Origin: [request-origin]
        
    そして、APMサーバーは以下のヘッダーと200ステータスコードで応答します。

    Access-Control-Allow-Headers: elastic-apm-traceparent
    Access-Control-Allow-Methods: [allowed-methods]
    Access-Control-Allow-Origin: [request-origin]
        

Spring BootアプリケーションのMyCorsConfigurationクラスは、これとは異なります。このためのSpring Bootの構成方法は異なるものであり、ここではフィルターベースのアプローチを使用します。これは、任意のオリジンからの任意のHTTPヘッダーおよび任意のHTTPメソッドによるリクエストを許可するように、サーバーサイドのSpring Bootアプリケーションを構成するものです。本番アプリケーションで開かないことを推奨します。

@Configuration
public class MyCorsConfiguration {
    @Bean
    public FilterRegistrationBean<CorsFilter> corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<CorsFilter>(new CorsFilter(source));
        bean.setOrder(0);
        return bean;
    }
}

最後に、RUMエージェントのもう1つの強力な機能について触れておきましょう。それはソースマップです。ソースマップは、暗号のような縮小されたコードではなく、オリジナルのソースコードのどこでエラーが発生したかを的確に示します。これにより、アプリケーションのエラーを簡単にデバッグできるようになります。

ソースマップで簡単にデバッグ

パフォーマンスのために実稼働環境でJavaScriptバンドルを縮小することはよくあります。しかし、縮小されたデバッグコードは本質的に理解が困難です。下記のスクリーンショットは、RUMエージェントが本番環境のビルドに関してキャプチャしたエラーのメッセージです。見てのとおり、例外のスタックトレースはコードが縮小されているためあまり意味が分かりません。すべてのエラー行は、2.5e9f7401.chunk.jsなどのようにJavaScriptファイルを示しており、常に「1行目」を指しています。これは縮小方法によるものです。開発時に具体的なソースコードを知ることができれば素晴らしいと思いませんか?

Elastic APMでの縮小コードはソースマップで解決可能

そこで役立つのがソースマップです。バンドルに関してソースマップを生成し、APMサーバーにアップロードすることができます。そうすることでAPMサーバーは、エラーを縮小されたコードからオリジナルのソースコードに変換し、非常に分かりやすいエラーメッセージを提示します。

その方法をフロントエンドのReactアプリケーションで見てみましょう。アプリケーション用の本番環境のビルドを構築し、ソースマップをアップロードします。以下のコマンドを使用して本番環境のビルドを作成できます。

npm run build

ビルドの最後に次のメッセージが表示されるはずです。

The build folder is ready to be deployed.
You may serve it with a static server:
  serve -s build

本番環境のビルドの詳細については、https://facebook.github.io/create-react-app/docs/production-buildをご覧ください。

必ずserveをインストールしてください(インストールしていない場合)。

npm install -g serve

次のコマンドで、Reactアプリケーションを本番モードに提供します。

serve -s build

Reactアプリケーションが本番モードの場合、React Developer Tools for Chromeのアイコンは背景が暗い色になります。Reactアプリケーションが開発モードの場合、アイコンの背景色は赤になります。必ず本番モードで実行してください。

次に、エラーボタンをクリックしてエラーを生成し、Kibana APM UIから確認すると、上記のスクリーンショットのような縮小されたエラースタックが表示されます。

ここでソースマップをロードすると魔法が起こります。ソースマップは、$APP-PATH/carfront/build/static/jsディレクトリの下に生成されます。そこにアクセスすると、3つのJavaScriptファイルについての3つのソースマップファイルがあります。以下のコマンドを実行して、それらをAPMサーバーにアップロードします。アプリケーションのバージョン、ビルド、環境に一致するように、URL、ファイル名、その他のパラメーターを必ず変更してください。また、APMサーバーからの認証トークンを使用していることを確認してください。

curl https://aba7c3d90b0b4820b05b0a9df44c096d.apm.us-central1.gcp.cloud.es.io:443/v1/rum/sourcemaps -X POST \
  -F sourcemap="@./main.b81677b7.chunk.js.map" \
  -F service_version="0.90" \
  -F bundle_filepath="http://localhost:5000/static/js/main.b81677b7.chunk.js" \
  -F service_name="carfront" \
  -H "Authorization:Bearer jeUWQhFtU9e5Jv836F"
curl https://aba7c3d90b0b4820b05b0a9df44c096d.apm.us-central1.gcp.cloud.es.io:443/v1/rum/sourcemaps -X POST \
  -F sourcemap="@./runtime~main.fdfcfda2.js.map" \
  -F service_version="0.90" \
  -F bundle_filepath="http://localhost:5000/static/js/runtime~main.fdfcfda2.js" \
  -F service_name="carfront" \
  -H "Authorization:Bearer jeUWQhFtU9e5Jv836F"
curl https://aba7c3d90b0b4820b05b0a9df44c096d.apm.us-central1.gcp.cloud.es.io:443/v1/rum/sourcemaps -X POST \
  -F sourcemap="@./2.5e9f7401.chunk.js.map" \
  -F service_version="0.90" \
  -F bundle_filepath="http://localhost:5000/static/js/2.5e9f7401.chunk.js" \
  -F service_name="carfront" \
  -H "Authorization:Bearer jeUWQhFtU9e5Jv836F"

サービスバージョンが文字列であり、Reactアプリケーションで構成したサービスバージョンと正確に一致していることに特に注意してください。ここでは、service_version="0.90"でアップロードしており、アプリケーションでサービスバージョンは"0.90"と設定されています。ソースマップをservice_version="0.9"(最後の0がない)でロードしようとしてもできません。

サービスマップがAPMサーバーにロードされたら、Dev Toolsからのこのリクエストですべてのソースマップを見つけることができます(バージョンが異なっている場合があります)。

GET apm-6.6.1-sourcemap/_search

別のエラーを生成して、再度APM UIエラータブからスタックトレースをチェックしてみましょう。以下のスクリーンショットのようなスタックトレースが表示されます。元のソースコードが分かりやすく反映されています。これで問題をより簡単に識別し、デバッグできるようになりました。

ソースマップの実行後、Elastic APMで実際のコードを確認できる

まとめ

Elastic RUMでアプリケーションをインストルメントする方法はシンプルかつ簡単でありながら、機能はパワフルです。本ブログ記事で、その点をお伝えできれば幸いです。バックエンドサービス向けに他のAPMエージェントを組み合わせて使うことにより、分散トレーシングを通じて、エンドユーザーの視点によるアプリケーションパフォーマンスの包括的なビューを獲得できます。

もう一度お伝えしておきますが、Elastic APMサーバーをダウンロードしてローカルで実行、またはElastic Cloudトライアルアカウントを作成して数分でクラスターを準備することで、Elastic APMの使用を開始できます。

ディスカッションを開始する場合またはご質問がある場合は、Elastic APMフォーラムをご利用ください。RUMを是非ご活用ください。