every Tech Blog

株式会社エブリーのTech Blogです。

amazon-quicksight-embedding-sdkを利用したQuickSightの埋め込み

エブリーでデータエンジニアを担当している塚田です。

QuickSightを活用したビジュアライズを進めていますが、そのビジュアルの埋め込みで外部のサイトで表示する部分を検証しています。

今回はその検証過程で利用したamazon-quicksight-embedding-sdkについて、使用方法などを紹介します。

Amazon QuickSightとは

Amazon QuickSightは、AWSが提供するビジネスインテリジェンス (BI) サービスです。AWSとの連携が容易で、比較的簡単に利用を開始することができます。

QuickSightの大きな特徴として、SPICEと呼ばれるインメモリエンジンがあります。SPICEはカラムナフォーマットでデータを保存することで、高速なクエリ処理を実現しています。これにより、大量のデータを高速に分析し、ダッシュボードに表示することができます。

QuickSightダッシュボードをアプリケーションに埋め込むことで、自社サービスの一機能として活用できます。

例えば:

  • 社内ポータルサイトに組み込んで、従業員が必要なデータに簡単にアクセス
  • 顧客向けポータルサイトに統合して、利用状況の分析機能を提供
  • 既存のWebアプリケーションにシームレスに統合してデータビジュアライゼーション機能を追加

埋め込みの実装手順

今回は、認証済みユーザーでQuickSightダッシュボードにアクセスする実装例を紹介します。

なお、QuickSightでは以下のような他の埋め込みオプションも用意されています。

  • 匿名ユーザーによるアクセス
  • ダッシュボード以外のビジュアルの埋め込み

環境

  • npmとNext.js、Reactがインストールされていること
  • 必要なパッケージがインストールされていること
    • @aws-sdk/client-quicksight
    • amazon-quicksight-embedding-sdk

埋め込みQuickSightのURL取得

QuickSightダッシュボードの埋め込みURLを取得します。 AWS CLIやAWS SDKを使用して生成できます。

一例としてAWS SDK for JavaScriptを使った場合のURL取得サンプルを示します UserArnはListUsersCommandなどを利用することで確認ができます。

import { QuickSightClient, GenerateEmbedUrlForRegisteredUserCommand, GenerateEmbedUrlForRegisteredUserCommandInput } from '@aws-sdk/client-quicksight';

// QuickSight クライアントの作成
const quicksightClient = new QuickSightClient({
  region: "ap-northeast-1" // QuickSightを利用しているリージョンを指定
});

// 埋め込み用 URL の取得
const params: GenerateEmbedUrlForRegisteredUserCommandInput = {
  AwsAccountId: "123456789012", // QuickSightを利用しているAWSアカウントIDを指定
  SessionLifetimeInMinutes: 600,
  UserArn: "arn:aws:quicksight:ap-northeast-1:123456789012:user/default/xxxxxxxxxx", // 利用するQuickSightのユーザーARNを指定
  ExperienceConfiguration: {
    Dashboard: {
      InitialDashboardId: "xxxxxxxx-1111-xxxx-1111-xxxxxxxxxxxx", // 利用したいダッシュボードIDを指定
      FeatureConfigurations: {
        StatePersistence: { Enabled: false },
        SharedView: { Enabled: false },
        Bookmarks: { Enabled: false },
      }
    }
  },
};
const command = new GenerateEmbedUrlForRegisteredUserCommand(params);
try {
  const data = await quicksightClient.send(command)
  const embedUrl = data.EmbedUrl || ''
  console.log(embedUrl)
} catch (error) {
  console.error('Error generating embed URL:', error);
}

amazon-quicksight-embedding-sdkを利用した埋め込み処理

先のURLへそのままアクセスすることで埋め込み用のダッシュボードにアクセスすることが可能です。 ただ、システム内で利用する際にはそのURLを伝えて見てもらうような運用は考えられないので、Webページに埋め込んでアクセスできるようにしたいと思います。

すでにNext.jsなどを利用してサーバーが起動しており、ブラウザからアクセス可能な状態を前提にします。

注意事項

  • QuickSightの管理画面でドメイン許可の設定が必要です
  • 埋め込み先のサーバーはHTTPSである必要があります
    • 開発環境ではnext dev --experimental-httpsを使用できます
"use client";
import { useEffect, useRef, useState } from 'react';
import { createEmbeddingContext } from 'amazon-quicksight-embedding-sdk';

export default function QuickSightDashboard() {
  const containerRef = useRef<HTMLDivElement>(null);
  const [embeddingContext, setEmbeddingContext] = useState<any>(null);
  const [embeddedDashboard, setEmbeddedDashboard] = useState<any>(null);
  const [dashboardParameter, setDashboardParameter] = useState<string | null>(null);

  useEffect(() => {
    const fetchEmbeddingContext = async () => {
      const context = await createEmbeddingContext();
      setEmbeddingContext(context);
    };
    fetchEmbeddingContext();
  }, []);

  useEffect(() => {
    if (embeddingContext) {
      embed();
    }
  }, [embeddingContext]);

  useEffect(() => {
    if (embeddedDashboard && dashboardParameter) {
      embeddedDashboard.setParameters(dashboardParameter);
    }
  }, [embeddedDashboard, dashboardParameter]);

  const embed = async () => {
    const frameOptions = {
      url: "https://xxxxxxxxxxxx", // 前の手順で作成された埋め込み用URLを指定
      container: containerRef.current,
      width: "100%",
      height: "100%",
      resizeHeightOnSizeChangedEvent: true,
      onChange: (changeEvent: any) => {
        switch (changeEvent.eventName) {
          case 'FRAME_MOUNTED': {
            console.log("Do something when the experience frame is mounted.");
            break;
          }
        }
      },
    };

    const contentOptions = {
      parameters: dashboardParameter,
      locale: "ja-JP",
      sheetOptions: {
        singleSheet: false
      },
      toolbarOptions: {
        export: true,
        undoRedo: false,
        reset: true
      },
      attributionOptions: {
        overlayContent: false,
      },
      themeOptions: {
        "themeOverride": {
          "UIColorPalette": {
            SecondaryBackground: '#FFFFFF',
            SecondaryForeground: '#000000'
          },
          "DataColorPalette": {
            "Colors": [
              "#E6194B",
              "#3CB44B",
              "#FFE119",
              "#4363D8",
              "#F58231"
            ]
          },
          "Typography": {
            "FontFamilies": [
              {"FontFamily":"Comic Neue"}
            ]
          }
        }
      },

      onMessage: async (messageEvent: any) => {
        switch (messageEvent.eventName) {
          case 'CONTENT_LOADED': {
            console.log("コンテンツのロードが完了しました:", messageEvent.message.title);
            break;
          }
          case 'PARAMETERS_CHANGED': {
            console.log("パラメータが変更されました:", messageEvent.message.changedParameters);
            break;
          }
        }
      },
    };

    const embedDashboard = await embeddingContext.embedDashboard(frameOptions, contentOptions);
    setEmbeddedDashboard(embedDashboard);
  };

  return (
    <div ref={containerRef}></div>
  );
};

今回はサンプルなのでframeOptionscontentOptionsは設定できるものの中からよく使いそうなものを指定しています。

他にもREADMEなどで指定できる内容が記載されているので、利用用途に合わせて変更することで目的にあった表現に近づくと思います。

実際に利用することを見据えた対応

  • 埋め込み用URL生成ロジックをAPI化し、アクセス時にURL発行->embedUrlの設定を行うことで柔軟に表示できるようにする
  • 今回は用意しかしていませんがdashboardParameterを変化させることで、QuickSight外からのパラメータの入れ込みができるようになるのでデザインの自由度が上がる

まとめ

マネージドなBIの良さを生かしながらプロダクトに組み込むにはという視点で今回は埋め込み処理の方法を取り上げました。

埋め込むことによって表現できる幅の広がりやデザインの統一感も生まれると思うので、必要に応じてこういった機能の利用をしていくべきと感ました。