Skip to Content

ステップ4:CloudWatchによる配信監視・管理システムの構築

今回のステップの概要とライブ配信アプリとの関連について

このステップでは、これまで構築したライブ配信アプリケーションにAmazon CloudWatchを使用した包括的な監視・管理システムを実装します。具体的には、IVSメトリクスの監視ダッシュボード、DynamoDBを使用した配信履歴管理、Lambda関数による自動アラート機能、配信統計の分析機能を構築します。

ライブ配信アプリケーションにとって、監視・管理システムは「テレビ局のディレクターが放送状況をリアルタイムで確認し、番組を管理する制御室」のような役割を果たします。テレビ局では、放送品質、視聴率、音声レベル、機器の状態などを常時監視し、問題が発生した際に即座に対応します。同様に、ライブ配信でも視聴者数、配信品質、チャット活動、システムの健康状態を監視し、最適な配信体験を提供する必要があります。

このステップで学ぶこと

リソースの関わりと構成説明

ステップ4で作成するリソースは、ライブ配信アプリケーションの運用管理機能を構築するものです。それぞれのリソースがライブ配信アプリケーションにどのように関わるのかを説明します。

Amazon CloudWatchとライブ配信アプリの関わり

Amazon CloudWatch「監視制御システム」は、ライブ配信アプリケーションの「放送制御室の監視画面」のような役割を果たします。同時視聴者数、配信品質、チャット活動量、システムリソース使用量などをリアルタイムで監視し、グラフやダッシュボードで視覚化します。これにより、配信者や運営者は配信の健康状態を一目で把握でき、問題の早期発見と迅速な対応が可能になります。

Amazon DynamoDBとライブ配信アプリの関わり

Amazon DynamoDB「配信データ保管庫」は、ライブ配信アプリケーションの「放送ログ保管システム」のような役割を果たします。配信開始・停止時刻、最大視聴者数、チャットメッセージ数、配信品質データなどを永続的に保存します。これにより、配信履歴の分析、トレンドの把握、改善点の発見、レポート作成などが可能になり、長期的な配信品質向上に貢献します。

CloudWatch Alarmsとライブ配信アプリの関わり

CloudWatch Alarms「自動警報システム」は、ライブ配信アプリケーションの「緊急事態対応システム」のような役割を果たします。配信品質の低下、視聴者数の異常な変動、システムエラーの発生などを自動検知し、即座に管理者に通知します。これにより、問題が深刻化する前に対処でき、視聴者への影響を最小限に抑えることができます。

実際の手順

実際の手順では、たくさんの設定値を入力することになります。 本文中に設定値が指定されていない場合は、デフォルト値のまま作業を進めてください。

1. DynamoDBテーブルによる配信データ管理

配信履歴とパフォーマンスデータを保存するDynamoDBテーブルを作成します。

Note

AWSでの役割

Amazon DynamoDBは、NoSQL形式の高性能データベースサービスです。

特徴:

  • 自動スケーリングで大量のデータ読み書きに対応
  • 低遅延(ミリ秒レベル)でのデータアクセス
  • サーバーレス運用でインフラ管理が不要
  • グローバルテーブルによる地理的分散対応

オンプレミスでの対応

オンプレミス環境では「MongoDB + Redis」が対応します。

  • MongoDBでのドキュメント型データベース構築
  • Redisでの高速キャッシュ層の実装
  • レプリケーション設定とシャーディング設計

1-1. 配信履歴テーブルの作成

  1. AWSマネジメントコンソールで「Amazon DynamoDB」サービスにアクセスします

  2. 「テーブルを作成」ボタンをクリックします

  3. 以下の設定で配信履歴テーブルを作成:

    • テーブル名: StreamingSessions
    • パーティションキー: sessionId (文字列)
    • ソートキー: timestamp (数値)
    • テーブル設定: デフォルト設定 を選択(オンデマンドキャパシティモード)

    注意: デフォルト設定では、キャパシティモードは「オンデマンド」に設定され、自動的にスケールします。プロビジョニングされたキャパシティを使用する場合は、「テーブル設定をカスタマイズ」を選択してください。

1-2. 配信メトリクステーブルの作成

  1. 配信の詳細メトリクスを保存するテーブルを作成:

    • テーブル名: StreamingMetrics
    • パーティションキー: sessionId (文字列)
    • ソートキー: metricTimestamp (数値)
  2. テーブル作成後、グローバルセカンダリインデックス(GSI)を追加:

    • テーブルの「インデックス」タブを選択
    • 「インデックスを作成」をクリック
    • インデックス名: ChannelIdIndex
    • パーティションキー: channelId (文字列)
    • ソートキー: metricTimestamp (数値)
    • 「インデックスを作成」をクリック

ヒント: GSIを使用することで、チャンネルID別にメトリクスを効率的にクエリできます。これにより「特定のチャンネルの過去1週間の配信統計」のような検索が高速に行えます。

DynamoDBテーブル作成画面

1-3. 配信データ記録用Lambda関数の作成

配信イベントをDynamoDBに記録するLambda関数を作成します:

import json import boto3 import time from decimal import Decimal from datetime import datetime, timezone dynamodb = boto3.resource('dynamodb') sessions_table = dynamodb.Table('StreamingSessions') metrics_table = dynamodb.Table('StreamingMetrics') cloudwatch = boto3.client('cloudwatch') def lambda_handler(event, context): """ 配信イベントの処理とDynamoDBへの記録 """ try: event_type = event.get('eventType') session_id = event.get('sessionId') channel_id = event.get('channelId') timestamp = int(time.time()) if event_type == 'stream_start': handle_stream_start(session_id, channel_id, timestamp, event) elif event_type == 'stream_end': handle_stream_end(session_id, channel_id, timestamp, event) elif event_type == 'metrics_update': handle_metrics_update(session_id, channel_id, timestamp, event) return { 'statusCode': 200, 'body': json.dumps({ 'message': f'Successfully processed {event_type}', 'sessionId': session_id }) } except Exception as e: print(f"Error processing event: {str(e)}") return { 'statusCode': 500, 'body': json.dumps({ 'error': str(e) }) } def handle_stream_start(session_id, channel_id, timestamp, event): """配信開始イベントの処理""" # 配信セッション情報をDynamoDBに記録 sessions_table.put_item( Item={ 'sessionId': session_id, 'timestamp': timestamp, 'channelId': channel_id, 'eventType': 'stream_start', 'streamerUserId': event.get('streamerUserId'), 'streamTitle': event.get('streamTitle', ''), 'streamQuality': event.get('streamQuality', '720p'), 'status': 'live' } ) # CloudWatchカスタムメトリクスを送信 cloudwatch.put_metric_data( Namespace='LiveStreaming/Sessions', MetricData=[ { 'MetricName': 'StreamsStarted', 'Value': 1, 'Unit': 'Count', 'Timestamp': datetime.fromtimestamp(timestamp, timezone.utc), 'Dimensions': [ { 'Name': 'ChannelId', 'Value': channel_id } ] } ] ) print(f"Stream started: {session_id}") def handle_stream_end(session_id, channel_id, timestamp, event): """配信終了イベントの処理""" duration = event.get('duration', 0) peak_viewers = event.get('peakViewers', 0) total_chat_messages = event.get('totalChatMessages', 0) # 配信終了情報をDynamoDBに記録 sessions_table.put_item( Item={ 'sessionId': session_id, 'timestamp': timestamp, 'channelId': channel_id, 'eventType': 'stream_end', 'duration': duration, 'peakViewers': peak_viewers, 'totalChatMessages': total_chat_messages, 'avgBitrate': event.get('avgBitrate', 0), 'status': 'ended' } ) # CloudWatchカスタムメトリクスを送信 cloudwatch.put_metric_data( Namespace='LiveStreaming/Sessions', MetricData=[ { 'MetricName': 'StreamsEnded', 'Value': 1, 'Unit': 'Count', 'Timestamp': datetime.fromtimestamp(timestamp, timezone.utc), 'Dimensions': [ { 'Name': 'ChannelId', 'Value': channel_id } ] }, { 'MetricName': 'StreamDuration', 'Value': duration, 'Unit': 'Seconds', 'Timestamp': datetime.fromtimestamp(timestamp, timezone.utc), 'Dimensions': [ { 'Name': 'ChannelId', 'Value': channel_id } ] }, { 'MetricName': 'PeakViewers', 'Value': peak_viewers, 'Unit': 'Count', 'Timestamp': datetime.fromtimestamp(timestamp, timezone.utc), 'Dimensions': [ { 'Name': 'ChannelId', 'Value': channel_id } ] } ] ) print(f"Stream ended: {session_id}, Duration: {duration}s, Peak viewers: {peak_viewers}") def handle_metrics_update(session_id, channel_id, timestamp, event): """配信メトリクス更新の処理""" current_viewers = event.get('currentViewers', 0) bitrate = event.get('bitrate', 0) frame_rate = event.get('frameRate', 0) chat_messages_per_minute = event.get('chatMessagesPerMinute', 0) # メトリクスデータをDynamoDBに記録 metrics_table.put_item( Item={ 'sessionId': session_id, 'metricTimestamp': timestamp, 'channelId': channel_id, 'currentViewers': current_viewers, 'bitrate': Decimal(str(bitrate)), 'frameRate': Decimal(str(frame_rate)), 'chatMessagesPerMinute': chat_messages_per_minute, 'cpuUsage': event.get('cpuUsage', 0), 'memoryUsage': event.get('memoryUsage', 0) } ) # CloudWatchカスタムメトリクスを送信 cloudwatch.put_metric_data( Namespace='LiveStreaming/Metrics', MetricData=[ { 'MetricName': 'CurrentViewers', 'Value': current_viewers, 'Unit': 'Count', 'Timestamp': datetime.fromtimestamp(timestamp, timezone.utc), 'Dimensions': [ { 'Name': 'ChannelId', 'Value': channel_id } ] }, { 'MetricName': 'StreamBitrate', 'Value': bitrate, 'Unit': 'Bits/Second', 'Timestamp': datetime.fromtimestamp(timestamp, timezone.utc), 'Dimensions': [ { 'Name': 'ChannelId', 'Value': channel_id } ] }, { 'MetricName': 'ChatActivity', 'Value': chat_messages_per_minute, 'Unit': 'Count/Minute', 'Timestamp': datetime.fromtimestamp(timestamp, timezone.utc), 'Dimensions': [ { 'Name': 'ChannelId', 'Value': channel_id } ] } ] ) > **注意**: CloudWatchカスタムメトリクスには明示的なタイムスタンプを含めることで、データの正確性が向上します。タイムスタンプはUTC時間で指定する必要があります。 print(f"Metrics updated for session: {session_id}")
Tip

【解説】DynamoDBのデータ設計について

DynamoDBでは、アクセスパターンに基づいたテーブル設計が重要です。配信履歴テーブルでは、セッションIDをパーティションキー、タイムスタンプをソートキーとすることで、特定の配信の時系列データを効率的に取得できます。

グローバルセカンダリインデックス(GSI)を使用することで、チャンネル別の配信履歴検索も高速に行えます。これにより、「特定の配信者の過去1ヶ月の配信統計」のような複雑なクエリも効率的に処理できます。

CloudWatchカスタムメトリクスとの連携により、DynamoDBに保存した詳細データとCloudWatchの監視機能を組み合わせた包括的な分析が可能になります。

2. CloudWatchダッシュボードの構築

配信状況を視覚的に監視できるダッシュボードを作成します。

2-1. カスタムダッシュボードの作成

  1. AWSマネジメントコンソールで「CloudWatch」サービスにアクセスします
  2. 左側メニューから「ダッシュボード」を選択します
  3. 「ダッシュボードの作成」をクリックし、以下を設定:
    • ダッシュボード名: LiveStreamingDashboard

2-2. 監視ウィジェットの追加

以下のウィジェットを追加してダッシュボードを構成します:

1. 現在の視聴者数(リアルタイム)

  • ウィジェット種類: 数値
  • メトリクス: LiveStreaming/Metrics > CurrentViewers
  • 期間: 最新の値

2. 視聴者数の推移(時系列グラフ)

  • ウィジェット種類: 線グラフ
  • メトリクス: LiveStreaming/Metrics > CurrentViewers
  • 期間: 過去24時間

3. 配信品質メトリクス

  • ウィジェット種類: 線グラフ
  • メトリクス:
    • LiveStreaming/Metrics > StreamBitrate
    • AWS/IVS > IngestFramerate
    • AWS/IVS > KeyframeInterval

4. チャット活動量

  • ウィジェット種類: 線グラフ
  • メトリクス: LiveStreaming/Metrics > ChatActivity
  • 期間: 過去6時間

5. 配信セッション統計

  • ウィジェット種類: 数値
  • メトリクス:
    • LiveStreaming/Sessions > StreamsStarted
    • LiveStreaming/Sessions > StreamsEnded
    • LiveStreaming/Sessions > StreamDuration

CloudWatchダッシュボード

3. CloudWatch Alarmsによる自動監視

異常な状況を自動検知してアラートを送信するアラームを設定します。

3-1. SNSトピックの作成

アラート通知用のSNSトピックを作成します:

  1. AWSマネジメントコンソールで「Amazon SNS」サービスにアクセスします

  2. 「トピックの作成」をクリックし、以下を設定:

    • タイプ: スタンダード
    • 名前: LiveStreamingAlerts
    • 表示名: ライブ配信アラート
  3. 作成したトピックに通知先(メールアドレス、Slack Webhook等)をサブスクライブします

3-2. 配信品質監視アラームの設定

  1. CloudWatchで「アラーム」を選択し、「アラームの作成」をクリックします
  2. 以下のアラームを作成:

視聴者数急減アラーム

  • メトリクス: LiveStreaming/Metrics > CurrentViewers
  • 統計: 平均
  • 期間: 5分
  • 条件: 前の期間と比較して50%以上減少
  • アクション: SNSトピック LiveStreamingAlerts に通知

配信品質低下アラーム

  • メトリクス: AWS/IVS > IngestFramerate
  • 統計: 平均
  • 期間: 2分
  • 条件: 20fps未満
  • アクション: SNSトピック LiveStreamingAlerts に通知

チャット活動異常アラーム

  • メトリクス: LiveStreaming/Metrics > ChatActivity
  • 統計: 合計
  • 期間: 10分
  • 条件: 100メッセージ/分を超過(スパム検知)
  • アクション: SNSトピック LiveStreamingAlerts に通知

4. 配信分析レポート機能の実装

配信データを分析してレポートを生成する機能を実装します。

4-1. 分析用Lambda関数の作成

import json import boto3 from datetime import datetime, timedelta from decimal import Decimal import statistics dynamodb = boto3.resource('dynamodb') sessions_table = dynamodb.Table('StreamingSessions') metrics_table = dynamodb.Table('StreamingMetrics') s3 = boto3.client('s3') def lambda_handler(event, context): """ 配信分析レポートの生成 """ try: report_type = event.get('reportType', 'daily') channel_id = event.get('channelId') if report_type == 'daily': report_data = generate_daily_report(channel_id) elif report_type == 'weekly': report_data = generate_weekly_report(channel_id) elif report_type == 'monthly': report_data = generate_monthly_report(channel_id) else: return { 'statusCode': 400, 'body': json.dumps({'error': 'Invalid report type'}) } # レポートをS3に保存 report_key = f"reports/{channel_id}/{report_type}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json" s3.put_object( Bucket='live-streaming-metadata-reports', Key=report_key, Body=json.dumps(report_data, default=decimal_default), ContentType='application/json' ) return { 'statusCode': 200, 'body': json.dumps({ 'message': f'{report_type} report generated successfully', 'reportUrl': f's3://live-streaming-metadata-reports/{report_key}', 'reportData': report_data }, default=decimal_default) } except Exception as e: print(f"Error generating report: {str(e)}") return { 'statusCode': 500, 'body': json.dumps({'error': str(e)}) } def generate_daily_report(channel_id): """日次レポートの生成""" # 過去24時間のデータを取得 end_time = datetime.now() start_time = end_time - timedelta(days=1) # 配信セッション情報を取得 sessions = get_sessions_in_period(channel_id, start_time, end_time) # メトリクスデータを取得 metrics = get_metrics_in_period(channel_id, start_time, end_time) # レポートデータを生成 report = { 'reportType': 'daily', 'channelId': channel_id, 'period': { 'start': start_time.isoformat(), 'end': end_time.isoformat() }, 'summary': { 'totalSessions': len(sessions), 'totalStreamTime': sum([s.get('duration', 0) for s in sessions]), 'avgSessionDuration': calculate_avg_duration(sessions), 'maxConcurrentViewers': max([m.get('currentViewers', 0) for m in metrics]) if metrics else 0, 'totalChatMessages': sum([s.get('totalChatMessages', 0) for s in sessions]) }, 'sessions': sessions[:10], # 最新10セッション 'hourlyBreakdown': generate_hourly_breakdown(metrics), 'qualityMetrics': calculate_quality_metrics(metrics), 'chatAnalytics': analyze_chat_activity(sessions, metrics) } return report def get_sessions_in_period(channel_id, start_time, end_time): """期間内の配信セッションを取得""" start_timestamp = int(start_time.timestamp()) end_timestamp = int(end_time.timestamp()) response = sessions_table.query( IndexName='ChannelIdIndex', KeyConditionExpression='channelId = :channel_id AND #ts BETWEEN :start_ts AND :end_ts', ExpressionAttributeNames={ '#ts': 'timestamp' }, ExpressionAttributeValues={ ':channel_id': channel_id, ':start_ts': start_timestamp, ':end_ts': end_timestamp } ) return response['Items'] def get_metrics_in_period(channel_id, start_time, end_time): """期間内のメトリクスデータを取得""" start_timestamp = int(start_time.timestamp()) end_timestamp = int(end_time.timestamp()) response = metrics_table.query( IndexName='ChannelIdIndex', KeyConditionExpression='channelId = :channel_id AND metricTimestamp BETWEEN :start_ts AND :end_ts', ExpressionAttributeValues={ ':channel_id': channel_id, ':start_ts': start_timestamp, ':end_ts': end_timestamp } ) return response['Items'] def calculate_avg_duration(sessions): """平均配信時間の計算""" durations = [s.get('duration', 0) for s in sessions if s.get('duration', 0) > 0] return statistics.mean(durations) if durations else 0 def generate_hourly_breakdown(metrics): """時間別の視聴者数推移を生成""" hourly_data = {} for metric in metrics: timestamp = metric['metricTimestamp'] hour = datetime.fromtimestamp(timestamp).strftime('%Y-%m-%d %H:00') if hour not in hourly_data: hourly_data[hour] = { 'viewers': [], 'bitrate': [], 'chatActivity': [] } hourly_data[hour]['viewers'].append(metric.get('currentViewers', 0)) hourly_data[hour]['bitrate'].append(float(metric.get('bitrate', 0))) hourly_data[hour]['chatActivity'].append(metric.get('chatMessagesPerMinute', 0)) # 各時間の平均値を計算 breakdown = [] for hour, data in sorted(hourly_data.items()): breakdown.append({ 'hour': hour, 'avgViewers': statistics.mean(data['viewers']) if data['viewers'] else 0, 'avgBitrate': statistics.mean(data['bitrate']) if data['bitrate'] else 0, 'avgChatActivity': statistics.mean(data['chatActivity']) if data['chatActivity'] else 0 }) return breakdown def calculate_quality_metrics(metrics): """配信品質メトリクスの計算""" if not metrics: return {} bitrates = [float(m.get('bitrate', 0)) for m in metrics] frame_rates = [float(m.get('frameRate', 0)) for m in metrics] return { 'avgBitrate': statistics.mean(bitrates) if bitrates else 0, 'minBitrate': min(bitrates) if bitrates else 0, 'maxBitrate': max(bitrates) if bitrates else 0, 'avgFrameRate': statistics.mean(frame_rates) if frame_rates else 0, 'bitrateStability': calculate_stability(bitrates), 'qualityScore': calculate_quality_score(bitrates, frame_rates) } def analyze_chat_activity(sessions, metrics): """チャット活動の分析""" total_messages = sum([s.get('totalChatMessages', 0) for s in sessions]) total_duration = sum([s.get('duration', 0) for s in sessions]) chat_rates = [m.get('chatMessagesPerMinute', 0) for m in metrics] return { 'totalMessages': total_messages, 'messagesPerMinute': total_messages / (total_duration / 60) if total_duration > 0 else 0, 'peakChatRate': max(chat_rates) if chat_rates else 0, 'avgChatRate': statistics.mean(chat_rates) if chat_rates else 0, 'chatEngagementScore': calculate_chat_engagement(total_messages, total_duration) } def calculate_stability(values): """数値の安定性を計算(変動係数)""" if not values or len(values) < 2: return 1.0 mean_val = statistics.mean(values) if mean_val == 0: return 0.0 std_dev = statistics.stdev(values) return max(0, 1 - (std_dev / mean_val)) # 変動が少ないほど1に近い def calculate_quality_score(bitrates, frame_rates): """配信品質スコアの計算(0-100)""" if not bitrates or not frame_rates: return 0 avg_bitrate = statistics.mean(bitrates) avg_framerate = statistics.mean(frame_rates) bitrate_stability = calculate_stability(bitrates) framerate_stability = calculate_stability(frame_rates) # 品質スコア計算(独自のアルゴリズム) bitrate_score = min(100, (avg_bitrate / 5000) * 40) # 5Mbpsで40点 framerate_score = min(100, (avg_framerate / 30) * 30) # 30fpsで30点 stability_score = (bitrate_stability + framerate_stability) * 15 # 安定性で30点 return min(100, bitrate_score + framerate_score + stability_score) def calculate_chat_engagement(total_messages, total_duration): """チャットエンゲージメントスコアの計算""" if total_duration == 0: return 0 messages_per_minute = total_messages / (total_duration / 60) # エンゲージメントスコア(0-10) if messages_per_minute >= 50: return 10 # 非常に高い elif messages_per_minute >= 20: return 8 # 高い elif messages_per_minute >= 10: return 6 # 中程度 elif messages_per_minute >= 5: return 4 # やや低い elif messages_per_minute >= 1: return 2 # 低い else: return 1 # 非常に低い def decimal_default(obj): """DecimalをJSONシリアライズ可能な形式に変換""" if isinstance(obj, Decimal): return float(obj) raise TypeError
Tip

【解説】配信分析の重要性

配信分析機能は、単なる数値の記録以上の価値を提供します。視聴者数の推移から最適な配信時間を発見したり、チャット活動量から視聴者エンゲージメントを測定したり、配信品質の安定性から技術的な改善点を特定できます。

品質スコアやエンゲージメントスコアのような独自メトリクスにより、配信者は自分のパフォーマンスを客観的に評価できます。これは、YouTubeアナリティクスやTwitchアナリティクスと同等の機能を独自システムで実現することを意味します。

時系列データの蓄積により、長期的なトレンド分析や季節性の発見、A/Bテストの効果測定なども可能になります。

このステップで何をしたのか

このステップでは、Amazon CloudWatchとDynamoDBを使用してライブ配信アプリケーションに包括的な監視・管理システムを構築しました。具体的には、配信履歴とメトリクスデータを保存するDynamoDBテーブル、リアルタイム監視を行うCloudWatchダッシュボード、異常検知を行うCloudWatchアラーム、詳細な分析レポートを生成するLambda関数を実装しました。また、カスタムメトリクスの送信により、AWS標準メトリクスでは取得できない独自の指標も監視できるようになりました。

ライブ配信アプリでどのような影響があるのか

この構成により、ライブ配信アプリケーションは単なる配信プラットフォームから、データ駆動型の運営が可能な本格的なサービスに進化しました。配信者は自分の配信パフォーマンスを詳細に分析でき、視聴者により良い体験を提供するための改善点を発見できます。運営者はシステム全体の健康状態をリアルタイムで監視し、問題の早期発見と迅速な対応が可能になります。また、蓄積されたデータを活用して、最適な配信時間の提案、人気コンテンツの傾向分析、収益最大化のための戦略立案なども行えます。これは、Netflix、YouTube、Twitchなどの大手プラットフォームが持つデータ分析能力を、個人や小規模組織でも活用できることを意味します。

技術比較まとめ表

技術領域AWSオンプレミス
監視・メトリクスCloudWatch + カスタムメトリクス
リアルタイム監視とアラート
Prometheus + Grafana
監視インフラの構築・運用
データ保存DynamoDB
自動スケーリングNoSQLデータベース
MongoDB + InfluxDB
時系列データ用データベース設計
アラート・通知CloudWatch Alarms + SNS
統合アラートシステム
Alertmanager + Slack/Email
独自通知システムの構築

学習において重要な技術的違い

1. 監視データの収集方法

  • AWS:CloudWatchエージェントとカスタムメトリクスで自動収集
  • オンプレミス:Prometheusエクスポーターやログ収集エージェントの設定

2. データの永続化戦略

  • AWS:DynamoDBの自動スケーリングで大量データに対応
  • オンプレミス:時系列データベースの容量計画とパーティショニング設計

3. アラートの管理

  • AWS:CloudWatch Alarmsで統合的なアラート管理
  • オンプレミス:複数の監視ツールからのアラート統合とノイズ除去

4. 分析とレポート

  • AWS:Lambdaによるサーバーレス分析処理
  • オンプレミス:定期実行バッチジョブとレポート生成システム

実践チェック:画面キャプチャで証明しよう

下記のチェック項目について、実際にAWSマネジメントコンソールで設定ができていることを確認し、各項目ごとに該当画面のスクリーンショットを撮影して提出してください。

  • DynamoDBに2つのテーブル(StreamingSessions、StreamingMetrics)が作成され、適切なキー設計とインデックスが設定されている

  • CloudWatchダッシュボードが作成され、視聴者数、配信品質、チャット活動などの主要メトリクスが表示されている

  • CloudWatch Alarmsが設定され、視聴者数急減、配信品質低下、チャット異常の3つのアラームが有効になっている

  • SNSトピックが作成され、アラート通知の配信先(メールアドレス等)が設定されている

  • 配信データ記録用Lambda関数が作成され、DynamoDBへのデータ保存とCloudWatchメトリクス送信が実装されている

  • 配信分析レポート生成Lambda関数が作成され、日次・週次・月次レポートの生成機能が実装されている

提出方法: 各項目ごとにスクリーンショットを撮影し、まとめて提出してください。 ファイル名やコメントで「どの項目か」が分かるようにしてください。

構成図による理解度チェック

ステップ3の構成図に、このステップで作成したリソースを追記して、最終的なインフラ構成を完成させましょう。

なぜ構成図を更新するのか?

監視・管理システムの追加により、システム全体の運用面が完成します。データの流れ、監視の仕組み、アラートの流れを理解することで、本格的な運用に必要な要素がすべて揃ったことを確認できます。また、障害発生時の影響範囲や復旧手順を事前に把握することで、安定した運用が可能になります。

  • データフローの理解: 配信データから分析レポートまでの一連の流れ
  • 監視ポイントの理解: どこで何を監視し、どのような異常を検知するか
  • 運用プロセスの理解: 日常運用から障害対応までの全体像

構成図の書き方

ステップ3で作成した構成図をベースに、以下のリソースを追記してみましょう。

  1. DynamoDB テーブル: 配信データの永続化、履歴管理とメトリクス保存
  2. CloudWatch ダッシュボード: リアルタイム監視、メトリクス可視化
  3. CloudWatch Alarms: 異常検知、自動アラート機能
  4. SNS: 通知配信、アラートの送信先管理
  5. Lambda関数: データ処理、分析レポート生成

💡 ヒント: データの流れ(配信→メトリクス収集→保存→分析→アラート)を時系列で表現し、監視・運用の全体像を明確にしましょう。

理解度チェック:なぜ?を考えてみよう

AWSの各リソースや設計には、必ず”理由”や”目的”があります。 下記の「なぜ?」という問いに自分なりの言葉で答えてみてください。 仕組みや設計意図を自分で説明できることが、真の理解につながります。 ぜひ、単なる暗記ではなく「なぜそうなっているのか?」を意識して考えてみてください。

Q. なぜ配信メトリクスをDynamoDBに保存するのでしょうか?RDSのような関係データベースではなくNoSQLデータベースを選択する理由を、ライブ配信の特性と合わせて説明してください。

Q. なぜCloudWatchアラームで複数の条件(視聴者数減少、配信品質低下、チャット異常)を監視するのでしょうか?それぞれのアラームが検知する問題と、早期対応の重要性について説明してください。

Q. なぜ配信分析でカスタムメトリクス(品質スコア、エンゲージメントスコア)を計算するのでしょうか?AWS標準メトリクスだけでは不十分な理由と、独自指標の価値について説明してください。

今回のステップで利用したAWSサービス名一覧

  • Amazon CloudWatch:リアルタイム監視とメトリクス収集、ダッシュボードによる可視化
  • Amazon DynamoDB:配信履歴とメトリクスデータの高性能保存、時系列データ管理
  • CloudWatch Alarms:異常検知と自動アラート、配信品質の監視
  • Amazon SNS:アラート通知の配信、マルチチャネル通知システム
  • AWS Lambda:配信データ処理と分析レポート生成、サーバーレス分析基盤
Last updated on