Skip to content

非公式本サイトは非公式の日本語ドキュメントであり、Cloudflare 公式サイトではありません。最新情報はdevelopers.cloudflare.comをご確認ください。

エンドツーエンドのデータパイプラインを構築する

Cloudflare Pipelines、R2 Data Catalog、R2 SQL を使い、リアルタイムのトランザクション分析向けのエンドツーエンドデータパイプラインを作成します。

最終更新 Markdown で表示Agent セットアップ

このチュートリアルでは、Cloudflare Pipelines、R2 Data Catalog、R2 SQL を使って、一連のデータパイプラインを構築します。不正パターンを含む金融トランザクションデータを作成し、Pipeline へ送るサンプル Python スクリプトも含みます。送ったデータは、R2 SQL または任意の Apache Iceberg 互換クエリエンジンでクエリできます。

このチュートリアルでは、次を行います。

  • R2 Data Catalog をセットアップし、トランザクションイベントを Apache Iceberg テーブルに保存する
  • Cloudflare Pipeline をセットアップする
  • 不正パターンを含むトランザクションデータを作成し、Pipeline へ送る
  • 不正分析のために R2 SQL でデータをクエリする

前提条件

  1. Cloudflare アカウント に登録します。
  2. Wrangler がサポートするバージョンの Node.js をインストールします。
  3. データ生成スクリプト用に Python 3.8+ をインストールします。

1. 認証をセットアップする

Cloudflare の各サービスを操作するには、API トークンが必要です。

  1. Cloudflare ダッシュボードで API tokens ページを開きます。

    Account API tokens を開く ↗
  2. Create Token を選びます。

  3. Create Custom Token の横にある Get started を選びます。

  4. API トークンの名前を入力します。

  5. Permissions で、次を選びます。

    • Workers Pipelines に Read、Send、Edit の権限
    • Workers R2 Data Catalog に Read と Edit の権限
    • Workers R2 SQL に Read の権限
    • Workers R2 Storage に Read と Edit の権限
  6. 任意で、このトークンに TTL を追加します。

  7. Continue to summary を選びます。

  8. Create Token を選びます。

  9. Token value を控えます。

新しいトークンを環境変数としてエクスポートします。

export WRANGLER_R2_SQL_AUTH_TOKEN= #paste your token here

Wrangler を初めて使う場合は、ログインしてください。

npx wrangler login

2. R2 バケットを作成し、R2 Data Catalog を有効にする

R2 バケットを作成します。

npx wrangler r2 bucket create fraud-pipeline
  1. Cloudflare ダッシュボードで R2 object storage ページを開きます。

    Overview を開く ↗
  2. Create bucket を選びます。

  3. バケット名を入力します: fraud-pipeline

  4. Create bucket を選びます。

R2 バケットでカタログを有効にします。

npx wrangler r2 bucket catalog enable fraud-pipeline

このコマンドを実行したら、「Warehouse」と「Catalog URI」を控えてください。あとで使います。

  1. Cloudflare ダッシュボードで R2 object storage ページを開きます。

    Overview を開く ↗
  2. バケット fraud-pipeline を選びます。

  3. Settings タブに切り替え、R2 Data Catalog までスクロールし、Enable を選びます。

  4. 有効にしたら、Catalog URIWarehouse name を控えます。

export WAREHOUSE= #Paste your warehouse here

(任意)R2 Data Catalog でコンパクションを有効にする

R2 Data Catalog は、テーブルのコンパクションを自動で行えます。本番のイベントストリーミングでは小さなファイルがたくさん残ることが多いため、コンパクションの有効化を推奨します。このチュートリアルはサンプル用途のため、この手順は任意です。

npx wrangler r2 bucket catalog compaction enable fraud-pipeline --token $WRANGLER_R2_SQL_AUTH_TOKEN
  1. Cloudflare ダッシュボードで R2 object storage ページを開きます。

    Overview を開く ↗
  2. バケット fraud-pipeline を選びます。

  3. Settings タブに切り替え、R2 Data Catalog までスクロールし、編集アイコンをクリックして Enable を選びます。

  4. ターゲットのファイルサイズを選ぶか、デフォルトのままにします。保存します。

3. パイプライン基盤をセットアップする

3.1. Pipeline の stream を作成する

まず、次の json スキーマで raw_transactions_schema.json というスキーマファイルを作成します。

{
	"fields": [
		{ "name": "transaction_id", "type": "string", "required": true },
		{ "name": "user_id", "type": "int64", "required": true },
		{ "name": "amount", "type": "float64", "required": false },
		{ "name": "transaction_timestamp", "type": "string", "required": false },
		{ "name": "location", "type": "string", "required": false },
		{ "name": "merchant_category", "type": "string", "required": false },
		{ "name": "is_fraud", "type": "bool", "required": false }
	]
}

不正検知イベントを受け取る stream を作成します。

npx wrangler pipelines streams create raw_events_stream \
  --schema-file raw_transactions_schema.json \
  --http-enabled true \
  --http-auth false
# The http ingest endpoint from the output (see example below)
export STREAM_ENDPOINT= #the http ingest endpoint from the output (see example below)

出力は次のようになります。

🌀 Creating stream 'raw_events_stream'...
 Successfully created stream 'raw_events_stream' with id 'stream_id'.

Creation Summary:
General:
  Name:  raw_events_stream

HTTP Ingest:
  Enabled:         Yes
  Authentication:  Yes
  Endpoint:        https://stream_id.ingest.cloudflare.com
  CORS Origins:    None

Input Schema:
┌───────────────────────┬────────┬────────────┬──────────┐
 Field Name Type Unit/Items Required
├───────────────────────┼────────┼────────────┼──────────┤
 transaction_id string Yes
├───────────────────────┼────────┼────────────┼──────────┤
 user_id int64 Yes
├───────────────────────┼────────┼────────────┼──────────┤
 amount                │float64 No
├───────────────────────┼────────┼────────────┼──────────┤
 transaction_timestamp string No
├───────────────────────┼────────┼────────────┼──────────┤
 location string No
├───────────────────────┼────────┼────────────┼──────────┤
 merchant_category string No
├───────────────────────┼────────┼────────────┼──────────┤
 is_fraud bool No
└───────────────────────┴────────┴────────────┴──────────┘

3.2. データシンクを作成する

データを Apache Iceberg テーブルとして R2 バケットへ書き込む sink を作成します。

npx wrangler pipelines sinks create raw_events_sink \
  --type "r2-data-catalog" \
  --bucket "fraud-pipeline" \
  --roll-interval 30 \
  --namespace "fraud_detection" \
  --table "transactions" \
  --catalog-token $WRANGLER_R2_SQL_AUTH_TOKEN

3.3. pipeline を作成する

SQL で stream と sink を接続します。

npx wrangler pipelines create raw_events_pipeline \
  --sql "INSERT INTO raw_events_sink SELECT * FROM raw_events_stream"
  1. Cloudflare ダッシュボードで Pipelines > Pipelines を開きます。

    Pipelines を開く ↗
  2. Create Pipeline を選びます。

  3. Connect to a Stream:

    • Pipeline name: raw_events
    • Enable HTTP endpoint for sending data: Enabled
    • HTTP authentication: Disabled(デフォルト)
    • Next を選びます
  4. Define Input Schema:

    • JSON editor を選びます

    • 次のスキーマをコピーします。

      {
      	"fields": [
      		{ "name": "transaction_id", "type": "string", "required": true },
      		{ "name": "user_id", "type": "int64", "required": true },
      		{ "name": "amount", "type": "float64", "required": false },
      		{
      			"name": "transaction_timestamp",
      			"type": "string",
      			"required": false
      		},
      		{ "name": "location", "type": "string", "required": false },
      		{ "name": "merchant_category", "type": "string", "required": false },
      		{ "name": "is_fraud", "type": "bool", "required": false }
      	]
      }
    • Next を選びます

  5. Define Sink:

    • R2 バケットを選びます: fraud-pipeline
    • Storage type: R2 Data Catalog
    • Namespace: fraud_detection
    • Table name: transactions
    • Advanced Settings: Maximum Time Interval30 seconds に変更します
    • Next を選びます
  6. Credentials:

    • Automatically create an Account API token for your sink を無効にします
    • 手順 1 の Catalog Token を入力します
    • Next を選びます
  7. Pipeline Definition:

    • デフォルトの SQL クエリのままにします。
      INSERT INTO raw_events_sink SELECT * FROM raw_events_stream;
    • Create Pipeline を選びます
  8. パイプライン作成後、次の手順用に Stream ID を控えます。

4. 不正検知のサンプルデータを生成する

不正パターンを含む現実的なトランザクションデータを生成する Python スクリプトを作成します。

fraud_data_generator.pypython
import requests
import json
import uuid
import random
import time
import os
from datetime import datetime, timezone, timedelta

# Configuration - exported from the prior steps
STREAM_ENDPOINT = os.environ["STREAM_ENDPOINT"]# From the stream you created
API_TOKEN = os.environ["WRANGLER_R2_SQL_AUTH_TOKEN"] #the same one created earlier
EVENTS_TO_SEND = 1000 # Feel free to adjust this

def generate_transaction():
    """Generate some random transactions with occasional fraud"""

    # User IDs
    high_risk_users = [1001, 1002, 1003, 1004, 1005]
    normal_users = list(range(1006, 2000))

    user_id = random.choice(high_risk_users + normal_users)
    is_high_risk_user = user_id in high_risk_users

    # Generate amounts
    if random.random() < 0.05:
        amount = round(random.uniform(5000, 50000), 2)
    elif random.random() < 0.03:
        amount = round(random.uniform(0.01, 1.00), 2)
    else:
        amount = round(random.uniform(10, 500), 2)

    # Locations
    normal_locations = ["NEW_YORK", "LOS_ANGELES", "CHICAGO", "MIAMI", "SEATTLE", "SAN FRANCISCO"]
    high_risk_locations = ["UNKNOWN_LOCATION", "VPN_EXIT", "MARS", "BAT_CAVE"]

    if is_high_risk_user and random.random() < 0.3:
        location = random.choice(high_risk_locations)
    else:
        location = random.choice(normal_locations)

    # Merchant categories
    normal_merchants = ["GROCERY", "GAS_STATION", "RESTAURANT", "RETAIL"]
    high_risk_merchants = ["GAMBLING", "CRYPTO", "MONEY_TRANSFER", "GIFT_CARDS"]

    if random.random() < 0.1:  # 10% high-risk merchants
        merchant_category = random.choice(high_risk_merchants)
    else:
        merchant_category = random.choice(normal_merchants)

    # Series of checks to either increase fraud score by a certain margin
    fraud_score = 0
    if amount > 2000: fraud_score += 0.4
    if amount < 1: fraud_score += 0.3
    if location in high_risk_locations: fraud_score += 0.5
    if merchant_category in high_risk_merchants: fraud_score += 0.3
    if is_high_risk_user: fraud_score += 0.2

    # Compare the fraud scores
    is_fraud = random.random() < min(fraud_score * 0.3, 0.8)

    # Generate timestamps (some fraud happens at unusual hours)
    base_time = datetime.now(timezone.utc)
    if is_fraud and random.random() < 0.4:  # 40% of fraud at night
        hour = random.randint(0, 5)  # Late night/early morning
        transaction_time = base_time.replace(hour=hour)
    else:
        transaction_time = base_time - timedelta(
            hours=random.randint(0, 168)  # Last week
        )

    return {
        "transaction_id": str(uuid.uuid4()),
        "user_id": user_id,
        "amount": amount,
        "transaction_timestamp": transaction_time.isoformat(),
        "location": location,
        "merchant_category": merchant_category,
        "is_fraud": True if is_fraud else False
    }

def send_batch_to_stream(events, batch_size=100):
    """Send events to Cloudflare Stream in batches"""

    headers = {
        "Authorization": f"Bearer {API_TOKEN}",
        "Content-Type": "application/json"
    }

    total_sent = 0
    fraud_count = 0

    for i in range(0, len(events), batch_size):
        batch = events[i:i + batch_size]
        fraud_in_batch = sum(1 for event in batch if event["is_fraud"] == True)

        try:
            response = requests.post(STREAM_ENDPOINT, headers=headers, json=batch)

            if response.status_code in [200, 201]:
                total_sent += len(batch)
                fraud_count += fraud_in_batch
                print(f"Sent batch of {len(batch)} events (Total: {total_sent})")
            else:
                print(f"Failed to send batch: {response.status_code} - {response.text}")

        except Exception as e:
            print(f"Error sending batch: {e}")

        time.sleep(0.1)

    return total_sent, fraud_count

def main():
    print("Generating fraud detection data...")

    # Generate events
    events = []
    for i in range(EVENTS_TO_SEND):
        events.append(generate_transaction())
        if (i + 1) % 100 == 0:
            print(f"Generated {i + 1} events...")

    fraud_events = sum(1 for event in events if event["is_fraud"] == True)
    print(f"📊 Generated {len(events)} total events ({fraud_events} fraud, {fraud_events/len(events)*100:.1f}%)")

    # Send to stream
    print("Sending data to Pipeline stream...")
    sent, fraud_sent = send_batch_to_stream(events)

    print(f"\nComplete!")
    print(f"   Events sent: {sent:,}")
    print(f"   Fraud events: {fraud_sent:,} ({fraud_sent/sent*100:.1f}%)")
    print(f"   Data is now flowing through your pipeline!")

if __name__ == "__main__":
    main()

必要な Python 依存関係をインストールし、スクリプトを実行します。

pip install requests
python fraud_data_generator.py

5. R2 SQL でデータをクエリする

R2 SQL で不正検知データを分析できます。次はクエリの例です。

5.1. 最近のトランザクションを表示する

npx wrangler r2 sql query "$WAREHOUSE" "
SELECT
    transaction_id,
    user_id,
    amount,
    location,
    merchant_category,
    is_fraud,
    transaction_timestamp
FROM fraud_detection.transactions
WHERE __ingest_ts > '2025-09-24T01:00:00Z'
AND is_fraud = true
LIMIT 10"

5.2. 生のトランザクションを新しいテーブルに絞り込み、高額トランザクションを目立たせる

絞り込んだデータを、R2 Data Catalog の新しい Apache Iceberg テーブルへ書き込む sink を作成します。

npx wrangler pipelines sinks create fraud_filter_sink \
  --type "r2-data-catalog" \
  --bucket "fraud-pipeline" \
  --roll-interval 30 \
  --namespace "fraud_detection" \
  --table "fraud_transactions" \
  --catalog-token $WRANGLER_R2_SQL_AUTH_TOKEN

次に、元の raw_events_stream からデータを処理し、amount が 1,000 を超えるフラグ付きトランザクションだけを書き込む新しい SQL クエリを作成します。

npx wrangler pipelines create fraud_events_pipeline \
  --sql "INSERT INTO fraud_filter_sink SELECT * FROM raw_events_stream WHERE is_fraud=true and amount > 1000"

テーブルをクエリして結果を確認します。

npx wrangler r2 sql query "$WAREHOUSE" "
SELECT
    transaction_id,
    user_id,
    amount,
    location,
    merchant_category,
    is_fraud,
    transaction_timestamp
FROM fraud_detection.fraud_transactions
LIMIT 10"

不正ではないイベントが除外されていることも確認します。

npx wrangler r2 sql query "$WAREHOUSE" "
SELECT
    transaction_id,
    user_id,
    amount,
    location,
    merchant_category,
    is_fraud,
    transaction_timestamp
FROM fraud_detection.fraud_transactions
WHERE is_fraud = false
LIMIT 10"

次の出力になるはずです。

Query executed successfully with no results

まとめ

Cloudflare のデータプラットフォームを使い、エンドツーエンドのデータパイプラインを構築できました。このチュートリアルでは、次を学びました。

  1. R2 Data Catalog を使う: Apache Iceberg テーブルで、データを効率よく保存します
  2. Cloudflare Pipelines をセットアップする: データ取り込み用の stream、sink、pipeline を作成します
  3. サンプルデータを生成する: 基本的な不正パターンを含むトランザクションデータを作成します
  4. R2 SQL でテーブルをクエリする: R2 Data Catalog に保存した生データと加工済みデータのテーブルにアクセスします

役に立ちましたか?