リモート監視ソリューション アクセラレータをカスタマイズする

この記事では、ソース コードにアクセスし、リモート監視ソリューション アクセラレータ UI をカスタマイズする方法について説明します。

Azure Cloud Shell を使用する

Azure では、ブラウザーを介して使用できる対話型のシェル環境、Azure Cloud Shell がホストされています。 Cloud Shell で Bash または PowerShell を使用して、Azure サービスを操作できます。 ローカル環境に何もインストールしなくても、Cloud Shell にプレインストールされているコマンドを使用して、この記事のコードを実行できます。

Azure Cloud Shell を開始するには:

オプション 例とリンク
コード ブロックの右上隅にある [使ってみる] を選択します。 [使ってみる] を選択しても、コードは Cloud Shell に自動的にコピーされません。 Azure Cloud Shell の [使ってみる] の例
https://shell.azure.com に移動するか、[Cloud Shell を起動する] ボタンを選択して、ブラウザーで Cloud Shell を開きます。 新しいウィンドウで Cloud Shell を起動する
Azure portal の右上にあるメニュー バーの [Cloud Shell] ボタンを選択します。 Azure Portal の [Cloud Shell] ボタン

Azure Cloud Shell でこの記事のコードを実行するには:

  1. Cloud Shell を開始します。

  2. [コピー] ボタンを選択して、コード ブロックをコードにコピーします。

  3. Windows と Linux では CtrlShiftV キーを選択し、macOS では CmdShiftV キーを選択して、コードを Cloud Shell セッションに貼り付けます。

  4. Enter キーを選択して、コードを実行します。

UI のローカル開発環境を準備する

リモート監視ソリューション アクセラレータ UI のコードは、React.js フレームワークを使用して実装されます。 azure-iot-pcs-remote-monitoring-webui GitHub リポジトリでソース コードを見つけることができます。

UI を変更するために、そのコピーをローカルで実行できます。 テレメトリの取得などのアクションを実行するために、ローカル コピーはソリューションのデプロイ済みのインスタンスに接続します。

次の手順に、UI 開発のためのローカル環境を設定するプロセスを説明します。

  1. pcs CLI を使用して、ソリューション アクセラレータの基本インスタンスをデプロイします。 デプロイの名前と仮想マシンに提供した資格情報をメモしておきます。 詳しくは、CLI を使用したデプロイに関するページをご覧ください。

  2. ソリューションでマイクロサービスをホストする仮想マシンへの SSH アクセスを有効にするには、Azure portal または Azure Cloud Shell を使用します。 次に例を示します。

    az network nsg rule update --name SSH --nsg-name {your solution name}-nsg --resource-group {your solution name} --access Allow
    

    SSH アクセスを有効にするのはテストおよび開発中のみにしてください。 SSH を有効にした場合、使用し終えたらできるだけ早く無効にする必要があります

  3. Azure Portal または Azure Cloud Shell を使用して、仮想マシンの名前とパブリック IP アドレスを検索します。 次に例を示します。

    az resource list --resource-group {your solution name} -o table
    az vm list-ip-addresses --name {your vm name from previous command} --resource-group {your solution name} -o table
    
  4. SSH を使用して仮想マシンに接続します。 前の手順で取得した IP アドレスと、ソリューションをデプロイするために、pcs を実行したときに提供した資格情報を使用します。 ssh コマンドは Azure Cloud Shell で使用できます。

  5. ローカル UX で接続できるようにするには、仮想マシンの bash シェルで、次のコマンドを実行します。

    cd /app
    sudo ./start.sh --unsafe
    
  6. コマンドが完了し、Web サイトが起動したことを確認したら、仮想マシンから切断できます。

  7. azure-iot-pcs-remote-monitoring-webui リポジトリのローカル コピーで、.env ファイルを編集し、デプロイ済みのソリューションの URL を追加します。

    NODE_PATH = src/
    REACT_APP_BASE_SERVICE_URL=https://{your solution name}.azurewebsites.net/
    
  8. コマンド プロンプトで、azure-iot-pcs-remote-monitoring-webui フォルダーのローカル コピーに移動します。

  9. 必要なライブラリをインストールして UI をローカルで実行するには、次のコマンドを実行します。

    npm install
    npm start
    
  10. 前のコマンドでは、ローカルで UI を実行します。 http://localhost:3000/dashboard. サイトの実行中にコードを編集し、動的に更新されることを確認できます。

レイアウトのカスタマイズ

リモート監視ソリューションの各ページは、ソース コードでパネルと呼ばれる一連のコントロールから構成されます。 ダッシュボード ページは、概要、マップ、アラート、テレメトリ、分析の 5 つのパネルで構成されています。 各ページとそのパネルを定義するソース コードを、pcs-remote-monitoring-webui GitHub リポジトリで見つけることができます。 たとえば、Dashboard ページ、そのレイアウト、およびページ上のパネルを定義するコードは、src/components/pages/dashboard フォルダーにあります。

パネルがその独自のレイアウトとサイズを管理するため、ユーザーはページのレイアウトを簡単に変更できます。 次のことを行うために、src/components/pages/dashboard/dashboard.js ファイルの PageContent 要素に以下の変更を加えます。

  • マップ パネルとテレメトリ パネルの位置を交換します。
  • マップ パネルと分析パネルの相対的な幅を変更します。
<PageContent className="dashboard-container">
  <Grid>
    <Cell className="col-1 devices-overview-cell">
      <OverviewPanel
        activeDeviceGroup={activeDeviceGroup}
        openWarningCount={openWarningCount}
        openCriticalCount={openCriticalCount}
        onlineDeviceCount={onlineDeviceCount}
        offlineDeviceCount={offlineDeviceCount}
        isPending={analyticsIsPending || devicesIsPending}
        error={deviceGroupError || devicesError || analyticsError}
        t={t} />
    </Cell>
    <Cell className="col-6">
      <TelemetryPanel
        timeSeriesExplorerUrl={timeSeriesParamUrl}
        telemetry={telemetry}
        isPending={telemetryIsPending}
        lastRefreshed={lastRefreshed}
        error={deviceGroupError || telemetryError}
        theme={theme}
        colors={chartColorObjects}
        t={t} />
    </Cell>
    <Cell className="col-3">
      <AlertsPanel
        alerts={currentActiveAlertsWithName}
        isPending={analyticsIsPending || rulesIsPending}
        error={rulesError || analyticsError}
        t={t}
        deviceGroups={deviceGroups} />
    </Cell>
    <Cell className="col-4">
      <PanelErrorBoundary msg={t('dashboard.panels.map.runtimeError')}>
        <MapPanel
          analyticsVersion={analyticsVersion}
          azureMapsKey={azureMapsKey}
          devices={devices}
          devicesInAlert={devicesInAlert}
          mapKeyIsPending={azureMapsKeyIsPending}
          isPending={devicesIsPending || analyticsIsPending}
          error={azureMapsKeyError || devicesError || analyticsError}
          t={t} />
      </PanelErrorBoundary>
    </Cell>
    <Cell className="col-6">
      <AnalyticsPanel
        timeSeriesExplorerUrl={timeSeriesParamUrl}
        topAlerts={topAlertsWithName}
        alertsPerDeviceId={alertsPerDeviceType}
        criticalAlertsChange={criticalAlertsChange}
        isPending={analyticsIsPending || rulesIsPending || devicesIsPending}
        error={devicesError || rulesError || analyticsError}
        theme={theme}
        colors={chartColorObjects}
        t={t} />
    </Cell>
    {
      Config.showWalkthroughExamples &&
      <Cell className="col-4">
        <ExamplePanel t={t} />
      </Cell>
    }
  </Grid>
</PageContent>

パネル レイアウトの変更

パネルを複製して、カスタマイズする場合は、同じパネルのいくつかのインスタンスやいくつかのバージョンを追加することもできます。 次の例は、テレメトリ パネルの 2 つのインスタンスを追加する方法を示しています。 これらの変更を行うには、src/components/pages/dashboard/dashboard.js ファイルを編集します。

<PageContent className="dashboard-container">
  <Grid>
    <Cell className="col-1 devices-overview-cell">
      <OverviewPanel
        activeDeviceGroup={activeDeviceGroup}
        openWarningCount={openWarningCount}
        openCriticalCount={openCriticalCount}
        onlineDeviceCount={onlineDeviceCount}
        offlineDeviceCount={offlineDeviceCount}
        isPending={analyticsIsPending || devicesIsPending}
        error={deviceGroupError || devicesError || analyticsError}
        t={t} />
    </Cell>
    <Cell className="col-3">
      <TelemetryPanel
        timeSeriesExplorerUrl={timeSeriesParamUrl}
        telemetry={telemetry}
        isPending={telemetryIsPending}
        lastRefreshed={lastRefreshed}
        error={deviceGroupError || telemetryError}
        theme={theme}
        colors={chartColorObjects}
        t={t} />
    </Cell>
    <Cell className="col-3">
      <TelemetryPanel
        timeSeriesExplorerUrl={timeSeriesParamUrl}
        telemetry={telemetry}
        isPending={telemetryIsPending}
        lastRefreshed={lastRefreshed}
        error={deviceGroupError || telemetryError}
        theme={theme}
        colors={chartColorObjects}
        t={t} />
    </Cell>
    <Cell className="col-3">
      <AlertsPanel
        alerts={currentActiveAlertsWithName}
        isPending={analyticsIsPending || rulesIsPending}
        error={rulesError || analyticsError}
        t={t}
        deviceGroups={deviceGroups} />
    </Cell>
    <Cell className="col-4">
      <PanelErrorBoundary msg={t('dashboard.panels.map.runtimeError')}>
        <MapPanel
          analyticsVersion={analyticsVersion}
          azureMapsKey={azureMapsKey}
          devices={devices}
          devicesInAlert={devicesInAlert}
          mapKeyIsPending={azureMapsKeyIsPending}
          isPending={devicesIsPending || analyticsIsPending}
          error={azureMapsKeyError || devicesError || analyticsError}
          t={t} />
      </PanelErrorBoundary>
    </Cell>
    <Cell className="col-6">
      <AnalyticsPanel
        timeSeriesExplorerUrl={timeSeriesParamUrl}
        topAlerts={topAlertsWithName}
        alertsPerDeviceId={alertsPerDeviceType}
        criticalAlertsChange={criticalAlertsChange}
        isPending={analyticsIsPending || rulesIsPending || devicesIsPending}
        error={devicesError || rulesError || analyticsError}
        theme={theme}
        colors={chartColorObjects}
        t={t} />
    </Cell>
    {
      Config.showWalkthroughExamples &&
      <Cell className="col-4">
        <ExamplePanel t={t} />
      </Cell>
    }
  </Grid>
</PageContent>

各パネルでさまざまなテレメトリを表示できます。

複数のテレメトリ パネル

既存のコントロールの複製とカスタマイズ

次の手順では、既存のパネルを複製し、それを変更して、変更済みのバージョンを使用する方法を説明します。 この手順では例として alerts パネルを使用します。

  1. リポジトリのローカル コピーで、src/components/pages/dashboard/panels フォルダー内の alerts フォルダーのコピーを作成します。 新しいコピーに cust_alerts と名付けます。

  2. cust_alerts フォルダー内の alertsPanel.js ファイルで、クラスの名前を CustAlertsPanel に編集します。

    export class CustAlertsPanel extends Component {
    
  3. 次の行を src/components/pages/dashboard/panels/index.js ファイルに追加します。

    export * from './cust_alerts';
    
  4. src/components/pages/dashboard/dashboard.js ファイル内の alertsPanelCustAlertsPanel で置き換えます。

    import {
      OverviewPanel,
      CustAlertsPanel,
      TelemetryPanel,
      KpisPanel,
      MapPanel,
      transformTelemetryResponse,
      chartColors
    } from './panels';
    
    ...
    
    <Cell className="col-3">
      <CustAlertsPanel
        alerts={currentActivealertsWithName}
        isPending={kpisIsPending || rulesIsPending}
        error={rulesError || kpisError}
        t={t} />
    </Cell>
    

これで、元の alerts パネルを CustAlerts というコピーで置き換えました。 このコピーは元のものと同じです。 これでコピーを変更できます。 たとえば、alerts パネルの列の順序を変更するには、次の手順を実行します。

  1. src/components/pages/dashboard/panels/cust_alerts/alertsPanel.js ファイルを開きます。

  2. 列定義を次のコード スニペットに示すように変更します。

    this.columnDefs = [
      rulesColumnDefs.severity,
      {
        headerName: 'rules.grid.count',
        field: 'count'
      },
      {
        ...rulesColumnDefs.ruleName,
        minWidth: 200
      },
      rulesColumnDefs.explore
    ];
    

次のスクリーン ショットは、alerts パネルの新しいバージョンを示しています。

更新済みの alerts パネル

テレメトリ グラフのカスタマイズ

ダッシュ ボード ページのテレメトリ グラフは、src/components/pages/dashboard/panels/telemtry フォルダー内のファイルによって定義されます。 UI は、src/services/telemetryService.js ファイル内のソリューション バックエンドから、テレメトリを取得します。 次の手順では、テレメトリ グラフに表示される期間を 15 分から 5 分に変更する方法を示します。

  1. src/services/telemetryService.js ファイルで、getTelemetryByDeviceIdP15M という関数を見つけます。 この関数のコピーを作成し、コピーを次のように変更します。

    static getTelemetryByDeviceIdP5M(devices = []) {
      return TelemetryService.getTelemetryByMessages({
        from: 'NOW-PT5M',
        to: 'NOW',
        order: 'desc',
        devices
      });
    }
    
  2. この新しい関数を使用して、テレメトリ グラフに入力するには、src/components/pages/dashboard/dashboard.js ファイルを開きます。 テレメトリ ストリームを初期化する行を見つけて、それを次のように変更します。

    const getTelemetryStream = ({ deviceIds = [] }) => TelemetryService.getTelemetryByDeviceIdP5M(deviceIds)
    

テレメトリ グラフに、5 分間のテレメトリ データが表示されるようになりました。

1 日を示すテレメトリ グラフ

新しい KPI の追加

ダッシュボード ページには、Analytics パネルの KPI が表示されます。 これらの KPI は、src/components/pages/dashboard/dashboard.js ファイルで計算されます。 KPI は src/components/pages/dashboard/panels/analytics/analyticsPanel.js ファイルによってレンダリングされます。 次の手順で、新しい KPI 値を計算して、ダッシュ ボード ページにレンダリングする方法について説明します。 示している例では、警告アラート KPI に新しいパーセンテージの変更を追加しています。

  1. src/components/pages/dashboard/dashboard.js ファイルを開きます。 initialState オブジェクトを次のように warningAlertsChange プロパティを含めるように変更します。

    const initialState = {
      ...
    
      // Analytics data
      analyticsVersion: 0,
      currentActiveAlerts: [],
      topAlerts: [],
      alertsPerDeviceId: {},
      criticalAlertsChange: 0,
      warningAlertsChange: 0,
      analyticsIsPending: true,
      analyticsError: null
    
      ...
    };
    
  2. currentAlarmsStats オブジェクトを totalWarningCount をプロパティとして含めるように変更します。

    return {
      openWarningCount: (acc.openWarningCount || 0) + (isWarning && isOpen ? 1 : 0),
      openCriticalCount: (acc.openCriticalCount || 0) + (isCritical && isOpen ? 1 : 0),
      totalWarningCount: (acc.totalWarningCount || 0) + (isWarning ? 1 : 0),
      totalCriticalCount: (acc.totalCriticalCount || 0) + (isCritical ? 1 : 0),
      alertsPerDeviceId: updatedAlertsPerDeviceId
    };
    
  3. 新しい KPI を計算します。 重大なアラート数の計算を見つけます。 コードをコピーし、次のようにコピーを変更します。

    // ================== Warning Alerts Count - START
    const currentWarningAlerts = currentAlertsStats.totalWarningCount;
    const previousWarningAlerts = previousAlerts.reduce(
      (cnt, { severity }) => severity === Config.ruleSeverity.warning ? cnt + 1 : cnt,
      0
    );
    const warningAlertsChange = ((currentWarningAlerts - previousWarningAlerts) / currentWarningAlerts * 100).toFixed(2);
    // ================== Warning Alerts Count - END
    
  4. KPI ストリームに新しい warningAlertsChange を含めます。

    return ({
      analyticsIsPending: false,
      analyticsVersion: this.state.analyticsVersion + 1,
    
      // Analytics data
      currentActiveAlerts,
      topAlerts,
      criticalAlertsChange,
      warningAlertsChange,
      alertsPerDeviceId: currentAlertsStats.alertsPerDeviceId,
    
      ...
    });
    
  5. UI のレンダリングに使用される状態データに新しい warningAlertsChange を含めます。

    const {
      ...
    
      analyticsVersion,
      currentActiveAlerts,
      topAlerts,
      alertsPerDeviceId,
      criticalAlertsChange,
      warningAlertsChange,
      analyticsIsPending,
      analyticsError,
    
      ...
    } = this.state;
    
  6. KPI パネルに渡されるデータを更新します。

    <AnalyticsPanel
      timeSeriesExplorerUrl={timeSeriesParamUrl}
      topAlerts={topAlertsWithName}
      alertsPerDeviceId={alertsPerDeviceType}
      criticalAlertsChange={criticalAlertsChange}
      warningAlertsChange={warningAlertsChange}
      isPending={analyticsIsPending || rulesIsPending || devicesIsPending}
      error={devicesError || rulesError || analyticsError}
      theme={theme}
      colors={chartColorObjects}
      t={t} />
    

これで、src/components/pages/dashboard/dashboard.js ファイルの変更が完了しました。 次の手順では、新しい KPI を表示するために、src/components/pages/dashboard/panels/analytics/analyticsPanel.js ファイルに行う変更について説明します。

  1. 次のように新しい KPI 値を取得するために、次のコードの行を変更します。

    const { t, isPending, criticalAlertsChange, warningAlertsChange, alertsPerDeviceId, topAlerts, timeSeriesExplorerUrl, error } = this.props;
    
  2. 次のように、新しい KPI 値を表示するために、マークアップを変更します。

    <div className="analytics-cell">
      <div className="analytics-header">{t('dashboard.panels.analytics.criticalAlerts')}</div>
      <div className="critical-alerts">
        {
          !showOverlay &&
            <div className="analytics-percentage-container">
              <div className="analytics-value">{ !isNaN(criticalAlertsChange) ? criticalAlertsChange : 0 }</div>
              <div className="analytics-percentage-sign">%</div>
            </div>
        }
      </div>
      <div className="critical-alerts">
        {
          !showOverlay &&
            <div className="analytics-percentage-container">
              <div className="analytics-value">{ !isNaN(warningAlertsChange) ? warningAlertsChange : 0 }</div>
              <div className="analytics-percentage-sign">%</div>
            </div>
        }
      </div>
    </div>
    

これで、ダッシュボード ページに、新しい KPI 値が表示されるようになります。

警告 KPI

マップをカスタマイズする

ソリューションのマップ コンポーネントの詳細については、GitHub のマップのカスタマイズに関するページをご覧ください。

その他のカスタマイズのオプション

リモート監視ソリューションのプレゼンテーションおよび視覚化レイヤーをさらに変更するために、コードを編集します。 関連する GitHub リポジトリは次のとおりです。

次のステップ

この記事では、リモート監視ソリューション アクセラレータの Web UI のカスタマイズに役立つように使用できるリソースについて説明します。 UI のカスタマイズに関する詳細については、次の記事を参照してください。

リモート監視ソリューション アクセラレータの概念に関する詳細については、リモート監視のアーキテクチャに関するページをご覧ください

リモート監視ソリューション マイクロサービスのカスタマイズの詳細については、「マイクロサービスをカスタマイズして再展開する」をご覧ください。