データ基盤モジュールの作成

Cortex Framework は、SAP(cortex.sap)などのエンタープライズ ERP システム用のすぐに使用できるデータ基盤モジュールを提供しますが、カスタム Namespace 内で新しいカスタム データ基盤モジュールを作成することもできます。これにより、カスタム ビルド動作を定義し、新しいソースシステムへのサポートを拡張できます。これには、生データを BigQuery に複製する PostgreSQL や MySQL などのデータベース管理システムが含まれます。

このガイドでは、データ(customersticketsticketlogitem テーブル)が PostgreSQL データベースから ticketing_data_raw という名前の未加工の BigQuery データセットに複製された顧客サービス チケット発行システムの新しいデータ基盤モジュールを作成するエンドツーエンドの例について説明します。

カスタムのデータ基盤モジュールを作成する場合は、専用のカスタム Namespace を使用して、拡張機能とカスタマイズを Cortex Framework アーティファクトから分離し、ライフサイクル管理を改善することをおすすめします。

シナリオ例の概要

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

  1. データ基盤アセットを分離するために、専用のカスタム Namespace ticketing を作成します。
  2. パス ticketing.ticketing.foundations.ticketing_system の新しいデータ基盤モジュールを定義します。
  3. customersticketsticketlogitem テーブルのテーブル設定(table_settings.default.yaml)を構成します。
  4. 各テーブルの列レベルとフィールド レベルのメタデータ アノテーションを作成します。
  5. config/config.yaml で、未加工のデータソース(ticketing_data_raw)、ターゲットの準拠データセット(data_foundation_ticketing)、新しい基盤モジュールを登録します。

モジュールのフォルダとファイルの構造

新しいデータ基盤モジュールのすべての物理ファイルは、src/data_modules/ のカスタム名前空間内に存在します。次の表とディレクトリ ツリーに、各ファイルを配置する場所の概要を示します。

config/
└── config.yaml                                           # Global configuration & module registration
src/data_modules/ticketing/ticketing/foundations/ticketing_system/
├── manifest.yaml                                         # Declares module category, type, and builder
├── table_settings.default.yaml                           # Table materialization, bigQueryLabels, dataformTags, and layouts
├── builder.py                                            # (Optional) Custom Dataform generator class for this module
└── annotations/                                          # Field and column-level schema descriptions
    ├── customers.yaml
    ├── tickets.yaml
    └── ticketlogitem.yaml

重要: 開始する前に、処理する予定のソーステーブルが生レイヤ データセットに存在することを確認してください。

ファイルまたはディレクトリのパス 目的と説明
config/config.yaml ticketing 名前空間、PostgreSQL の未加工データソース、ターゲット BigQuery データセット、基盤モジュール インスタンスを登録します。
src/data_modules/ticketing/ticketing/foundations/ticketing_system/manifest.yaml モジュールのメタデータ、表示名、カテゴリ(foundation など)、モジュール タイプ(generic など)、コンパイル時に使用されるジェネレータ ビルダー クラスを宣言します。
src/data_modules/ticketing/ticketing/foundations/ticketing_system/table_settings.default.yaml ticketing_data_raw からどのソーステーブルを準拠させるかを構成します。また、BigQuery 最適化データフォームタグ、bigQueryLabels、パーティションの詳細、クラスタの詳細も構成します。
src/data_modules/ticketing/ticketing/foundations/ticketing_system/annotations/*.yaml テーブルとフィールドの定義を記述するリッチな YAML メタデータが含まれています。これらはコンパイルされた Dataform 定義に自動的に統合されるため、説明は BigQuery テーブルのメタデータに保持されます。
src/data_modules/ticketing/ticketing/foundations/ticketing_system/builder.py 省略可。コンパイル時にソース データベースでカスタム データ クリーニングや方言固有の SQL 変換が必要な場合は、ここでモジュール レベルのビルダー クラスを定義できます。

ステップ 1: config.yaml で名前空間、データソース、ターゲットを登録する

物理ファイルを作成する前に、デプロイ構成ファイル(config/config.yaml)を開き、カスタム Namespace、未加工の PostgreSQL ソース データセット、準拠テーブルが作成される移行先データセットを宣言します。

data:
  namespaces:
    - name: cortex
      path: ../src/data_modules/cortex
    - name: ticketing                              # <-- Name of custom namespace
      path: ../src/data_modules/ticketing          # <-- Points to subdirectory under 'src/data_modules/'

  datasets:
    - id: ticketing_data_raw                       # <-- Unique source ID
      projectId: "source_project_id"
      datasetId: ticketing_data_raw                # <-- Raw dataset containing PostgreSQL replication tables
    - id: data_foundation_ticketing                # <-- Unique target ID
      projectId: "target_project_id"
      datasetId: data_foundation_ticketing         # <-- Target dataset for conformed foundation tables

ステップ 2: config.yaml にデータ基盤モジュールを登録する

config/config.yamldata.modules.foundations セクションで、新しいデータ基盤モジュール インスタンスを登録し、データソース(ticketing_data_raw)をデータ ターゲット(data_foundation_ticketing)にリンクします。

data:
  modules:
    foundations:
      - moduleId: ticketing_foundation
        modulePath: ticketing.ticketing.foundations.ticketing_system   # Format: {namespace}.{systemtype}.{module_type:foundations}.{subsystemtype}
        dataSourceId: ticketing_data_raw
        dataTargetId: data_foundation_ticketing
        # Custom table settings file relative to 'config/' directory
        # Recommended path: '{namespace_dir}/{system_type}/foundations/{system_sub_type}/table_settings.yaml'
        # If omitted, defaults to "../src/data_modules/ticketing/ticketing/foundations/ticketing_system/table_settings.default.yaml"
        tableSettings: "ticketing/ticketing/foundations/ticketing_system/table_settings.yaml"

ステップ 3: モジュール マニフェスト ファイルを作成する

モジュールのメタデータを宣言するマニフェスト ファイル src/data_modules/ticketing/ticketing/foundations/ticketing_system/manifest.yaml を作成します。

displayName: Ticketing System Data Foundation
description: Conformed foundation tables for PostgreSQL raw ticketing database.
category: foundation
type: generic
builder: ticketing_foundation

ステップ 4: テーブル設定ファイル(table_settings.default.yaml)を作成する

デフォルトのテーブル構成ファイル src/data_modules/ticketing/ticketing/foundations/ticketing_system/table_settings.default.yaml を作成します。このファイルは、BigQuery 内で複製された PostgreSQL テーブル(customersticketsticketlogitem)が具体化、パーティショニング、クラスタリングされる方法を定義します。

common:
  - source:
      tableName: customers
    target:
      bigQueryLabels:
        - key: data_class
          value: master
      dataformTags: [ticketing, foundation, masterdata]
      clusterDetails:
        columns: [customer_id]

  - source:
      tableName: tickets
    target:
      bigQueryLabels:
        - key: data_class
          value: transactional
      dataformTags: [ticketing, foundation, transactional]
      partitionDetails:
        column: created_at
        partitionType: time
        timeGrain: day
      clusterDetails:
        columns: [ticket_id, customer_id]

  - source:
      tableName: ticketlogitem
    target:
      bigQueryLabels:
        - key: data_class
          value: transactional
      dataformTags: [ticketing, foundation, transactional]
      partitionDetails:
        column: log_timestamp
        partitionType: time
        timeGrain: day
      clusterDetails:
        columns: [ticket_id, log_id]

ステップ 5: フィールドレベルのメタデータ アノテーションを作成する

BigQuery の準拠テーブルに明確なドキュメントが含まれるようにするには、src/data_modules/ticketing/ticketing/foundations/ticketing_system/annotations/ 内の各テーブルのアノテーション YAML ファイルを作成します。ファイル名はソーステーブル名と完全に一致している必要があります。

annotations/customers.yaml

description: "Customer master data conformed from PostgreSQL raw ticketing database."
fields:
  - name: "customer_id"
    description: "Unique customer identifier, PK"
  - name: "email"
    description: "Primary email address associated with the customer"
  - name: "full_name"
    description: "Customer full name or account contact name"
  - name: "created_at"
    description: "Timestamp when the customer record was originally created in PostgreSQL"

annotations/tickets.yaml

description: "Customer service tickets conformed from PostgreSQL raw ticketing database."
fields:
  - name: "ticket_id"
    description: "Unique ticket identifier, PK"
  - name: "customer_id"
    description: "Foreign key referencing customers.customer_id"
  - name: "subject"
    description: "Summary or subject line of the customer inquiry"
  - name: "status"
    description: "Current ticket lifecycle status (e.g., OPEN, IN_PROGRESS, RESOLVED, CLOSED)"
  - name: "priority"
    description: "Priority severity level (e.g., LOW, MEDIUM, HIGH, URGENT)"
  - name: "created_at"
    description: "Timestamp when the ticket was created"
  - name: "updated_at"
    description: "Timestamp when the ticket was last modified"

annotations/ticketlogitem.yaml

description: "Audit log history and activity events for customer service tickets."
fields:
  - name: "log_id"
    description: "Unique log event identifier, PK"
  - name: "ticket_id"
    description: "Foreign key referencing tickets.ticket_id"
  - name: "action"
    description: "Action or event performed on the ticket"
  - name: "description"
    description: "Notes and description on performed events on the ticket"
  - name: "performed_by"
    description: "User, agent, or automated system that performed the action"
  - name: "log_timestamp"
    description: "Exact timestamp when the activity log event occurred"

ステップ 6: (省略可)カスタム基盤ビルダーを定義する

PostgreSQL データ基盤でコンパイル時にロジック(すべてのテーブルにわたるデータ型の自動キャスト、タイムスタンプ変換、データ クリーニング ルールなど)が必要な場合は、このモジュールにスコープ設定されたカスタム ビルダーを定義できます。

src/data_modules/ticketing/ticketing/foundations/ticketing_system/builder.py を作成します。

import logging
import pathlib
import yaml
from common.builders.base import FoundationBuilder, Source
from common.registry import builder_registry
from common.schemas import config_schema, manifest_schema

logger = logging.getLogger(__name__)

@builder_registry.register("ticketing_foundation")
class TicketingFoundationBuilder(FoundationBuilder[config_schema.BaseModuleConfig]):
    """Custom Dataform generator for PostgreSQL ticketing data foundation."""

    def build(
        self,
        *,
        module_id: str,
        module_config: config_schema.BaseModuleConfig,
        global_config: config_schema.GlobalConfig,
        manifest: manifest_schema.ManifestConfig,
        base_dir: pathlib.Path,
        annotations_dir: pathlib.Path,
        output_dir: pathlib.Path,
        module_dir_name: str,
        sources_registry: set[Source],
        table_settings_file: pathlib.Path | None = None,
        required_tables: set[str] | None = None,
    ) -> None:
        logger.info("Building ticketing data foundation for module: %s", module_id)
        
        # 1. Load table settings
        if not table_settings_file or not table_settings_file.exists():
            logger.warning("No valid table settings found for %s", module_id)
            return

        with open(table_settings_file, encoding="utf-8") as f:
            settings = yaml.safe_load(f) or {}

        tables = settings.get("common", [])
        source_config = global_config.get_data_source(module_config.data_source_id)
        target_dataset = global_config.get_data_target(module_config.data_target_id)

        # 2. Generate Dataform .sqlx files for each table
        for table_item in tables:
            source_table = table_item["source"]["tableName"]
            if required_tables and source_table not in required_tables and not table_item.get("deployAlways"):
                continue

            # Register source table for centralized source generation
            sources_registry.add(Source(source_config.project_id, source_config.dataset_id, source_table))

            # Retrieve labels if configured
            bigquery_config = {}
            if "bigQueryLabels" in table_item["target"]:
                labels_dict = {label["key"]: label["value"] for label in table_item["target"]["bigQueryLabels"]}
                bigquery_config["labels"] = labels_dict

            dataform_tags = table_item["target"].get("dataformTags", ["ticketing", "foundation"])

            sqlx_content = f"""config {{
  type: "table",
  schema: "{target_dataset.dataset_id}",
  name: "{source_table}",
  tags: {dataform_tags}"""
            
            if bigquery_config:
                sqlx_content += f",\n  bigquery: {bigquery_config}"
                
            sqlx_content += f"""
}}

SELECT *
FROM `${{source_config.project_id}}.${{source_config.dataset_id}}.{source_table}`
"""
            out_file = output_dir / f"{source_table}.sqlx"
            out_file.write_text(sqlx_content, encoding="utf-8")
            logger.info("Generated %s", out_file)

新しい基盤モジュールの検証

新しく作成したデータ基盤モジュールを検証してデプロイするには:

  1. Cortex Framework のビルドとデプロイ スクリプトを実行します。bash uv run cortex-build-and-deploy --config "config/config.yaml"
  2. Dataform のコンパイルがエラーなしで成功し、customersticketsticketlogitem.sqlx スクリプトが生成されたことを確認します。
  3. デプロイ後の手順に沿って、Dataform パイプライン アクションを実行し、BigQuery の data_foundation_ticketing データセット内の準拠レコードを確認します。

カスタム データ基盤モジュールが正常にコンパイルされてデプロイされたことを確認するには、データ プロダクトの拡張性ページの検証セクションをご覧ください。