New Relic React Native統合設定 - クロスプラットフォーム監視の完全ガイド

React Nativeアプリケーションでは、JavaScriptロジックとネイティブプラットフォーム(iOS・Android)の両方を包括的に監視する必要があります。New Relic React Native Agentは、この複雑な要件に対応し、統合されたパフォーマンス監視ソリューションを提供します。本ガイドでは、React Native環境での完全な導入手順から高度な設定まで、実践的な実装方法を詳しく解説します。

React Native Agent概要と監視機能

New Relic React Native Agentは、React Native 0.60以上をサポートし、JavaScriptエンジンとネイティブコードの両方を統合的に監視できる包括的なSDKです。Metro bundlerとの連携により、JavaScript実行パフォーマンスとネイティブブリッジ通信の効率性を詳細に分析できます。

React Native特有の監視項目

React Nativeアプリケーションの特性に配慮した以下の監視機能を提供します。

JavaScript実行パフォーマンスでは、Metroバンドラーによるバンドルサイズ、JavaScriptスレッドの実行時間、コンポーネントレンダリングパフォーマンスを追跡します。Redux状態管理やナビゲーション処理の効率性も測定できます。

ネイティブブリッジ通信監視により、JavaScriptとネイティブコード間のメソッド呼び出し頻度、データ転送量、通信遅延を詳細に分析します。パフォーマンスボトルネックとなりやすいブリッジ通信の最適化指針を提供します。

クロスプラットフォーム対応では、iOSとAndroidプラットフォームでの動作差異、デバイス固有の問題、OSバージョン依存の課題を統一的に把握できます。

JavaScriptエラー追跡により、未処理の例外、Promise rejection、コンポーネントエラーバウンダリーでキャッチされたエラーを包括的に収集し、詳細なスタックトレースを提供します。

ナビゲーション監視では、React Navigationやその他のルーティングライブラリによる画面遷移時間とユーザージャーニーを追跡し、アプリケーション内での使用パターンを分析できます。

事前準備とシステム要件

React Native Agent導入前の環境確認を行います。

システム要件

  • React Native 0.60以上(0.70以上を推奨)
  • Node.js 16以上
  • iOS: Xcode 12以上、iOS 10以上
  • Android: Android Studio 4.0以上、Android API 24以上
  • New Relicアカウントとアプリケーショントークン

開発環境の確認

既存のReact Nativeプロジェクトがあることを前提とし、以下のコマンドで環境を確認してください。

bash
npx react-native info

React Native CLI、Metro bundler、プラットフォーム固有の開発環境が適切に設定されていることを確認します。

アプリケーショントークンの取得

New Relicダッシュボードで「Add Data」→「Mobile」→「React Native」を選択し、新しいアプリケーションを作成します。生成されるアプリケーショントークンは、後の設定で使用するため安全に保管してください。

npm/yarnによるパッケージインストール

React Native Agentの導入を開始します。

パッケージのインストール

プロジェクトルートディレクトリで以下のコマンドを実行してください。

bash
# npmの場合
npm install @newrelic/react-native-agent

# yarnの場合
yarn add @newrelic/react-native-agent

自動リンキングの確認

React Native 0.60以降では自動リンキングが有効になっているため、追加の設定は不要です。古いバージョンを使用している場合は、手動リンキングが必要となります。

bash
# React Native 0.59以下の場合のみ
npx react-native link @newrelic/react-native-agent

プラットフォーム固有の設定

iOS・Android それぞれで必要な設定を行います。

iOS設定

ios/ディレクトリに移動し、CocoaPods依存関係をインストールします。

bash
cd ios
pod install
cd ..

Xcodeでプロジェクトを開き、ios/YourApp/AppDelegate.m(または.mm)ファイルを編集します。

objective-c
#import "AppDelegate.h"
#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import <NewRelic/NewRelic.h>

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // New Relic初期化
    [NewRelic startWithApplicationToken:@"YOUR_APPLICATION_TOKEN"];
    
    RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
    // 既存のコード
    
    return YES;
}

@end

Android設定

android/app/src/main/java/.../MainApplication.javaファイルを編集します。

java
import com.facebook.react.ReactApplication;
import com.newrelic.agent.android.NewRelic;

public class MainApplication extends Application implements ReactApplication {
    
    @Override
    public void onCreate() {
        super.onCreate();
        
        // New Relic初期化
        NewRelic.withApplicationToken("YOUR_APPLICATION_TOKEN")
               .start(this.getApplicationContext());
        
        SoLoader.init(this, /* native exopackage */ false);
        // 既存のコード
    }
}

Gradleファイル(android/app/build.gradle)にプラグインを追加します。

gradle
apply plugin: "com.android.application"
apply plugin: "com.facebook.react"
apply plugin: "newrelic"

// dependencies内に追加
dependencies {
    implementation "com.newrelic.agent.android:android-agent:+"
    // 既存の依存関係
}

プロジェクトレベルのandroid/build.gradleにもプラグインを追加します。

gradle
buildscript {
    dependencies {
        classpath "com.newrelic.agent.android:agent-gradle-plugin:+"
        // 既存のdependencies
    }
}

JavaScript/TypeScript実装

React Nativeアプリケーション内でのAgent使用方法を実装します。

基本的な初期化

App.jsまたはindex.jsファイルでAgentを初期化します。

javascript
import React from 'react';
import { NewRelic } from '@newrelic/react-native-agent';

// アプリケーション開始時の初期化
NewRelic.startAgent('YOUR_APPLICATION_TOKEN');

const App = () => {
  // アプリケーションコンポーネント
  return (
    // JSXコンテンツ
  );
};

export default App;

TypeScriptプロジェクトの場合:

typescript
import React from 'react';
import { NewRelic } from '@newrelic/react-native-agent';

// 型安全な初期化
NewRelic.startAgent('YOUR_APPLICATION_TOKEN');

const App: React.FC = () => {
  // アプリケーションコンポーネント
  return (
    // JSXコンテンツ
  );
};

export default App;

カスタムメトリクスとイベントの実装

React Nativeアプリケーション固有の監視項目を追加します。

javascript
import { NewRelic } from '@newrelic/react-native-agent';

// ユーザー属性の設定
NewRelic.setUserId('user_12345');
NewRelic.setAttribute('userSubscription', 'premium');
NewRelic.setAttribute('appVersion', '2.1.0');

// カスタムイベントの記録
const recordPurchaseEvent = (itemId, price, currency) => {
  NewRelic.recordCustomEvent('PurchaseCompleted', {
    itemId: itemId,
    price: price,
    currency: currency,
    platform: Platform.OS,
    timestamp: Date.now()
  });
};

// コンポーネント内でのイベント記録
const handlePurchase = () => {
  // 購入処理
  recordPurchaseEvent('item_123', 29.99, 'USD');
};

// メトリクスの記録
NewRelic.recordMetric('Custom/ComponentRenderTime', 45.2);
NewRelic.recordMetric('Custom/NetworkRequestCount', 15);

ナビゲーション監視の実装

React Navigationとの統合により、画面遷移の監視を実現します。

javascript
import { NewRelic } from '@newrelic/react-native-agent';
import { NavigationContainer } from '@react-navigation/native';

const Navigation = () => {
  const navigationRef = useRef();
  
  const onStateChange = (state) => {
    const currentRouteName = getActiveRouteName(state);
    
    // 画面遷移イベントの記録
    NewRelic.recordCustomEvent('ScreenView', {
      screenName: currentRouteName,
      timestamp: Date.now(),
      previousScreen: getPreviousRouteName(state)
    });
  };
  
  return (
    <NavigationContainer
      ref={navigationRef}
      onStateChange={onStateChange}
    >
      {/* ナビゲーション構造 */}
    </NavigationContainer>
  );
};

エラーハンドリングと監視

React Native特有のエラー処理と監視機能を実装します。

JavaScript例外の追跡

javascript
import { NewRelic } from '@newrelic/react-native-agent';

// グローバル例外ハンドラーの設定
const originalHandler = ErrorUtils.getGlobalHandler();
ErrorUtils.setGlobalHandler((error, isFatal) => {
  NewRelic.recordError(error);
  originalHandler(error, isFatal);
});

// Promise rejectionの処理
const unhandledRejectionHandler = (reason, promise) => {
  NewRelic.recordError(reason);
};

// React Error Boundaryとの統合
class ErrorBoundary extends React.Component {
  componentDidCatch(error, errorInfo) {
    NewRelic.recordError(error, {
      componentStack: errorInfo.componentStack,
      errorBoundary: true
    });
  }
  
  render() {
    // エラーUI表示
    return this.props.children;
  }
}

ネットワーク監視の設定

javascript
import { NewRelic } from '@newrelic/react-native-agent';

// Fetch APIの監視
const monitoredFetch = async (url, options = {}) => {
  const startTime = Date.now();
  
  try {
    const response = await fetch(url, options);
    const endTime = Date.now();
    
    // 成功時のメトリクス記録
    NewRelic.recordMetric('Custom/NetworkRequest/Success', endTime - startTime);
    
    return response;
  } catch (error) {
    const endTime = Date.now();
    
    // エラー時のメトリクス記録
    NewRelic.recordMetric('Custom/NetworkRequest/Error', endTime - startTime);
    NewRelic.recordError(error);
    
    throw error;
  }
};

// Axios interceptorとの統合
import axios from 'axios';

axios.interceptors.request.use((config) => {
  config.metadata = { startTime: Date.now() };
  return config;
});

axios.interceptors.response.use(
  (response) => {
    const endTime = Date.now();
    const duration = endTime - response.config.metadata.startTime;
    
    NewRelic.recordMetric('Custom/AxiosRequest/Success', duration);
    return response;
  },
  (error) => {
    const endTime = Date.now();
    const duration = endTime - error.config.metadata.startTime;
    
    NewRelic.recordMetric('Custom/AxiosRequest/Error', duration);
    NewRelic.recordError(error);
    
    return Promise.reject(error);
  }
);

パフォーマンス最適化

React Native特有のパフォーマンス課題に対応した最適化手法を紹介します。

Bundle分析とメトリクス

javascript
// Bundle読み込み時間の測定
const bundleStartTime = Date.now();

// アプリケーション初期化完了時
const onAppReady = () => {
  const bundleLoadTime = Date.now() - bundleStartTime;
  NewRelic.recordMetric('Custom/BundleLoadTime', bundleLoadTime);
};

// JavaScriptスレッドの監視
const measureJSThreadPerformance = () => {
  const start = Date.now();
  
  setTimeout(() => {
    const jsThreadDelay = Date.now() - start;
    NewRelic.recordMetric('Custom/JSThreadDelay', jsThreadDelay);
  }, 0);
};

メモリ使用量の監視

javascript
// メモリ使用量の定期的な監視
const monitorMemoryUsage = () => {
  if (global.performance && global.performance.memory) {
    const memoryInfo = global.performance.memory;
    
    NewRelic.recordMetric('Custom/MemoryUsed', memoryInfo.usedJSHeapSize);
    NewRelic.recordMetric('Custom/MemoryTotal', memoryInfo.totalJSHeapSize);
    NewRelic.recordMetric('Custom/MemoryLimit', memoryInfo.jsHeapSizeLimit);
  }
};

// 定期実行の設定
setInterval(monitorMemoryUsage, 30000); // 30秒間隔

トラブルシューティング

React Native環境でよく発生する問題と解決方法を説明します。

Metro bundlerとの競合

Metro bundlerの設定ファイル(metro.config.js)で競合を回避します。

javascript
module.exports = {
  resolver: {
    blacklistRE: /node_modules\/.*\/node_modules\/react-native\/.*/,
  },
  transformer: {
    getTransformOptions: async () => ({
      transform: {
        experimentalImportSupport: false,
        inlineRequires: false,
      },
    }),
  },
};

プラットフォーム固有の問題

iOS Simulatorでの制限、Androidエミュレータでの動作確認、実機での最終テストを段階的に実行し、問題を特定してください。

データ送信の確認

React Native Debugger、Flipper、またはXcode/Android Studioのコンソールでエラーメッセージを確認し、初期化とデータ送信の状況を監視してください。

まとめ

New Relic React Native Agentの適切な導入により、クロスプラットフォームモバイルアプリケーションの包括的な監視が実現できます。JavaScriptとネイティブコードの統合監視により、React Native特有のパフォーマンス課題を効果的に解決できます。

継続的な監視データの活用により、ユーザー体験の向上とアプリケーションパフォーマンスの最適化を実現してください。次のステップとして、Flutter環境での監視設定についても学習することをお勧めします。


関連記事: New Relic Flutter統合設定関連記事: New Relicモバイル監視概要