🔍

「なんかMeet重いんだけど」を撲滅!GWS監査ログとLooker Studioで作るネットワーク品質ダッシュボード

に公開

🚀 はじめに

「最近、Google Meetの調子悪いんだけど…」
「XXさんの声、ブツブツ切れてますよ」

コーポレートエンジニアやネットワーク担当者の皆さん、こんなフワッとした社員からの申告に頭を悩ませていませんか?

原因が「社員の自宅回線」なのか、「会社のVPN」なのか、はたまた「特定のオフィスのWi-Fiが詰まっ
てる」のか…。原因の切り分けができず、具体的なアクションが取れないのはツラいですよね。

この記事では、Google Workspace Enterprise プラン以上で利用できる「BigQueryへのログエクスポート機能」を使い、Google Meetのネットワーク品質(レイテンシ、ジッター、パケットロス)を Looker Studio で可視化する 方法を紹介します。

この記事を読めば、「ネットワークが悪い」という主観的な申告を、客観的なデータ(p95レイテンシなど)で裏付けられるダッシュボードが手に入ります。しかも、ほぼ安価で!
(※BigQueryのストレージ・スキャン費用はかかります)


🎯 この記事で実現すること

  • Google Meetのネットワーク品質(レイテンシ、ジッター、パケットロス)を日次で可視化する
  • 特定のIPアドレス(オフィスの固定IPなど) に絞り込み、客観的なデータに基づきネットワーク品質の劣化を早期に検知する
  • Looker Studio を使い、情シスやネットワーク担当者がいつでも状況を確認できるダッシュボードを構築する

🤔 なぜGoogle Workspaceの生ログをイジるのか?

「え、Google Workspaceの管理コンソールにもレポート機能あるじゃん」と思うかもしれません。
確かに「品質に関する問題」レポートはありますが、以下のような限界があります。

  • 集計の柔軟性が低い: 独自の切り口(例: 拠点ごと、時間帯ごと)での集計や、長期的なトレンド分析が難しい。
  • 生データへのアクセスが面倒: 結局、CSVエクスポートしてExcelでこねこね…なんてことになりがち。
  • BIツールとの連携: 標準機能では、Looker Studio や Tableau のようなBIツールに直接データを渡せません。

そこで登場するのが、BigQueryへのログエクスポートです。
Google Workspaceの監査ログ(今回は meet ログ)をBigQueryに流し込むことで、以下のメリットが得られます。

  1. SQLで自由に分析: 強力なSQLを使って、必要なデータを思いのままに集計できます。
  2. BIツールと直結: Looker Studio とはネイティブ連携。ほぼリアルタイムでデータをダッシュボードに反映できます。
  3. 安価な長期保存: 履歴データをBigQueryに安価に蓄積し、過去との比較も容易です。

🏗️ 全体像(アーキテクチャ)

構成は非常にシンプルです。社員がGoogle Meetを使い、Google Workspace が吐き出すログを BigQuery が受け止め、それを Looker Studio が読みに行くだけ。

🛠️ ステップ1:GWSからBigQueryへのログエクスポート設定

この記事の前提条件です。 すでに設定済みの方は、ステップ2まで飛ばしてください。

  1. Google Workspace の特権管理者アカウントで、管理コンソールにログインします。
  2. [レポート] > [監査] > [BigQuery Export] に移動します。
  3. [BigQuery Export] カードで、ログをエクスポートしたい Google Cloud プロジェクトIDを指定します。
  4. 「アクティビティ ログ」のエクスポートを有効化します。
  • この設定を行うと、GoogleWorkspaceExportData (または指定した名前) というデータセットが BigQuery に自動で作成されます。
  • データセット内には、ログの種類ごと(activity、drive、meetなど)にパーティション化されたテーブルが作られますが、今回のクエリでは、meet の情報が含まれる activity テーブルを使います。 (※環境によっては meet テーブルが別途作られる場合もあります。ご自身の環境のテーブル構成を確認してください)

実施方法ですが、一部分かりづらい部分もありますので以下も合わせてご確認ください。
https://blog.g-gen.co.jp/entry/BigQueryExport

📊 ステップ2:Looker Studio で可視化する (キモのSQL解説)

ここがこの記事のメインディッシュです。 Looker Studio で新しいデータソースを作成し、「カスタムクエリ」として以下のSQLを貼り付けます。

#standardSQL
-- Google Meetの品質指標、通話数、平均経過時間を日次で集計するクエリ
-- X軸: 日本時間 (activity_date)
-- Y軸: 各種指標
-- 条件: 2025/1/1(JST)以降、120秒以上の通話のみを対象、call_countが5件未満の日を除外
-- IPアドレス「meet.ip_address」でフィルタリング (IPv6対応済)

WITH
  -- 1. 必要なデータを抽出
  FormattedData AS (
    SELECT
      -- 集計日を抽出 (日本時間)
      DATE(TIMESTAMP_MICROS(time_usec), 'Asia/Tokyo') AS activity_date,
      -- 測定対象の指標
      meet.network_rtt_msec_mean AS avg_latency_ms,
      meet.network_recv_jitter_msec_mean AS avg_jitter_ms,
      meet.audio_recv_packet_loss_mean AS avg_audio_packet_loss_percent,
      meet.video_recv_packet_loss_mean AS avg_video_packet_loss_percent,
      meet.duration_seconds
    FROM
      -- ↓↓↓ ご自身のプロジェクトIDとデータセット名に合わせてください
      `your-project-id.GoogleWorkspaceExportData.activity`
    WHERE
      record_type = 'meet'
      AND event_name = 'call_ended'
      AND email IS NOT NULL
      -- PC (デスクトップ) での会議品質にフォーカス
      AND meet.device_type NOT IN ('ios', 'android')
      AND meet.network_rtt_msec_mean IS NOT NULL -- LatencyがNULLのデータは除外
      -- 120秒未満のテスト通話や即切りを除外
      AND meet.duration_seconds >= 120
      
      -- ↓↓↓ ここが最重要!自社のオフィスIPアドレスやVPNのIPレンジに合わせて絞り込む
      -- (※ IPアドレスはダミーのサンプルです)
      AND (
        -- IPv4アドレス(例: オフィスAの固定IP)
        meet.ip_address = '203.0.113.10'
        -- IPv4アドレス(例: オフィスBの固定IP)
        OR meet.ip_address = '203.0.113.20'
        -- IPv4サブネット(例: VPNのIPレンジ 198.51.100.0/24)
        OR STARTS_WITH(meet.ip_address, '198.51.100.') 
        
        -- IPv6 サブネット(例: オフィスのv6プラス回線 の /64 プレフィックス)
        OR (
          -- IPv6 (16バイト長) かどうかを先に判定
          LENGTH(NET.SAFE_IP_FROM_STRING(meet.ip_address)) = 16
          -- /64 のプレフィックスで絞り込み
          AND NET.IP_TRUNC(NET.SAFE_IP_FROM_STRING(meet.ip_address), 64) = NET.SAFE_IP_FROM_STRING('2001:db8:1234:abcd::')
        )
      )
      
      -- データの取得期間を限定
      AND time_usec >= UNIX_MICROS(TIMESTAMP('2025-01-01', 'Asia/Tokyo'))
      AND time_usec < UNIX_MICROS(TIMESTAMP(DATE_ADD(CURRENT_DATE('Asia/Tokyo'), INTERVAL 1 DAY)))
  )

-- 2. 日次で各種指標を集計
SELECT
  activity_date,
  -- 通話数と平均経過時間
  COUNT(*) AS call_count, -- このcall_countは既に120秒以上の通話のみ
  ROUND(AVG(duration_seconds/60), 1) AS avg_duration_minutes,
  
  -- === ここからが品質指標のキモ ===
  
  -- Latency (p95, p99.5)
  APPROX_QUANTILES(avg_latency_ms, 1000)[OFFSET(950)] AS p95_latency_ms,
  APPROX_QUANTILES(avg_latency_ms, 1000)[OFFSET(995)] AS p995_latency_ms,
  
  -- Jitter (p95, p99.5)
  APPROX_QUANTILES(avg_jitter_ms, 1000)[OFFSET(950)] AS p95_jitter_ms,
  APPROX_QUANTILES(avg_jitter_ms, 1000)[OFFSET(995)] AS p995_jitter_ms,
  
  -- Audio Packet Loss (p95, p99.5)
  APPROX_QUANTILES(avg_audio_packet_loss_percent, 1000)[OFFSET(950)] AS p95_audio_packet_loss_percent,
  APPROX_QUANTILES(avg_audio_packet_loss_percent, 1000)[OFFSET(995)] AS p995_audio_packet_loss_percent,
  
  -- Video Packet Loss (p95, p99.5)
  APPROX_QUANTILES(avg_video_packet_loss_percent, 1000)[OFFSET(950)] AS p95_video_packet_loss_percent,
  APPROX_QUANTILES(avg_video_packet_loss_percent, 1000)[OFFSET(995)] AS p995_video_packet_loss_percent
FROM
  FormattedData
GROUP BY
  activity_date
-- データが少なすぎる日(例: 休日)を除外し、グラフのノイズを減らす
HAVING
  COUNT(*) >= 5
ORDER BY
  activity_date

☕ カスタムクエリ(SQL)の解説

このクエリが何をやっているのか、ポイントを解説します。

  • FormattedData (CTE: 共通テーブル式)

    • まず、WITH FormattedData AS (...) の部分で、分析に必要な生データを絞り込んでいます。
    • record_type = 'meet' / event_name = 'call_ended': Google Meet の「通話終了」ログだけに絞り込みます。ここに品質レポートが含まれています。
  • meet.device_type NOT IN ('ios', 'android'):

    • スマホアプリからの接続を除外しています。オフィスのネットワーク品質や、PCでの会議体験にフォーカスするためです。
  • meet.duration_seconds >= 120:

    • 2分未満の短い通話(テストや間違い電話など)はノイズになるため除外します。
  • AND (meet.ip_address = ...):

    • ここが最重要カスタマイズポイントです!
    • 以前は meet.location_region(IPアドレスからの推定位置)で絞り込むしかありませんでしたが、meet.ip_address(実際の接続元IP)が取得できるようになったため、こちらを使うことで格段に精度が上がりました。ここには、監視したいオフィスの固定IPv4アドレスや、VPNのIPアドレスを OR で繋げて指定します。
    • IPv6にも対応しています。NET.SAFE_IP_FROM_STRING でIP文字列をバイトに変換し、LENGTH でIPv6 (16バイト) かを判定、NET.IP_TRUNC でIPv6のプレフィックス(この例では /64)が一致するかを見ています。
    • これにより、特定の拠点(=特定のIPアドレス群)からの接続品質だけを正確に抜き出すことができます。
  • メインSELECT (日次集計)

    • FormattedData で絞り込んだデータを、activity_date (日付) ごとに集計します。
  • APPROX_QUANTILES(..., 1000)[OFFSET(950)] AS p95_latency_ms:

    • ここがこの記事で一番伝えたかった部分です。
    • ネットワーク品質を見るとき、平均値 (AVG) はほとんど役に立ちません。なぜなら、たった一回の極端な遅延(外れ値)で、平均値は簡単に悪化してしまうからです。
    • 品質を測るには「パーセンタイル」を使います。p95 (95パーセンタイル) とは、「95%の通話は、この値以下でしたよ」という指標です。
    • つまり、p95_latency_ms が 200ms だった場合、「最も通信品質が悪かった5%の通話を除けば、残りの95%はレイテンシ200ms以下で快適だった」と(ざっくり)解釈できます。
    • この p95 や p99.5 の値が跳ね上がった日は、ネットワークで何かしらの問題が起きていた可能性が高い、と判断できます。
  • HAVING COUNT(*) >= 5:

    • 1日の通話数が5件未満の日は、データとして信頼性が低いため除外しています(例: 週末や祝日など)。

📈 ステップ3:ダッシュボードの作成 (作例)

SQLをデータソースとして登録したら、あとはLooker Studioでグラフを配置するだけです。

[グラフを追加] > [時系列グラフ] を選択します。

  • ディメンション (X軸):

    • activity_date
  • 指標 (Y軸):

    • p95_latency_ms
    • p995_latency_ms

これで、「いつ(activity_date)」ネットワーク品質(p95_latency_ms など)が悪化したかが一目瞭然のダッシュボードが完成します。

サンプルとして、latency のダッシュボードはこちらになります。
通信遅延が大きい日が一目瞭然になりました。

応用編: SQLの AND (meet.ip_address = ...) の部分を @ パラメータ(例: @office_ip_list)に置き換えることで、Looker Studio側でIPアドレスを動的に入力・変更できるダッシュボードを作ることも可能です。

⚠️ 注意点とハマりどころ

  • Enterpriseプラン必須

    • 悲しいですが、このBigQueryログエクスポート機能は Google Workspace Enterprise プラン(Standard / Plus)以上が必要です。
  • データの反映ラグ

    • BigQueryへのログエクスポートは準リアルタイムです。監査ログの場合、数時間〜最大半日程度の遅延が発生することがあります。「今すぐ」の障害調査には向きませんが、日次の傾向把握には十分です。
  • IPアドレスリストの運用

    • meet.ip_address を使うことで、location_region よりもはるかに正確な拠点判定が可能になりました。
      • ただし、クエリに書いたIPアドレスリストは「運用」が必要です。オフィスの回線契約を変更してIPアドレスが変わった場合、このクエリも修正しないとデータが取れなくなります。
      • 「このダッシュボードのデータが0件になったら、IPアドレスの変更を疑う」くらいの運用ルールは決めておくと良いでしょう。

✅ まとめ

  • Google Workspace Enterprise のログを BigQuery に連携すれば、SQLで柔軟な品質分析が可能になります。
  • meet.ip_address フィールドを活用し、オフィスの固定IPやVPNのIPレンジで絞り込むことで、精度の高い拠点別分析ができます。
  • ネットワーク品質は「平均 (AVG)」ではなく「パーセンタイル (p95)」で見るのが鉄則です。
  • APPROX_QUANTILES 関数は、BigQueryでパーセンタイルを計算する際の強力な武器です。
  • Looker Studio で可視化・共有することで、「なんか調子悪い」という主観的な声から脱却し、データに基づいたネットワーク改善の第一歩を踏み出せます。

面倒なログ集計は自動化して、エンジニアにしかできない価値ある仕事(ネットワークの改善提案など)に集中していきましょう!

📚 参考

Discussion