# 通知設計書 17-Copy-DbaAgentAlert

## 概要

本ドキュメントは、SQL Serverエージェントアラートを別のインスタンスにコピーするdbatools PowerShellコマンド「Copy-DbaAgentAlert」の設計仕様を記載します。

### 本通知の処理概要

Copy-DbaAgentAlertは、ソースSQL ServerインスタンスのSQL Serverエージェントアラートを、1つ以上の宛先インスタンスにコピーするコマンドです。アラートの設定、通知設定、ジョブ関連付けを含めて移行できます。

**業務上の目的・背景**：サーバー移行、災害復旧準備、複数SQL Server環境の監視標準化において、アラート設定を手動で再作成することは労力がかかりエラーが起きやすくなります。本コマンドは、アラート、オペレーター、ジョブ間の複雑な依存関係を自動的に処理し、移行作業を効率化します。

**通知の送信タイミング**：本コマンドは「アラート設定をコピーする」コマンドであり、コピーされたアラートが宛先インスタンスでトリガーされた際に通知が発生します。コピー処理自体の結果はPSCustomObjectとして即座に出力されます。

**通知の受信者**：本コマンドの実行結果はコマンド実行者に返されます。コピーの成功/失敗/スキップ状況がオブジェクトとして出力されます。

**通知内容の概要**：コピー処理の結果として、SourceServer、DestinationServer、Name（アラート名）、Type（オブジェクト種別）、Status（Successful/Failed/Skipped）、Notes、DateTimeが返されます。

**期待されるアクション**：管理者は出力結果を確認し、全てのアラートが正常にコピーされたことを検証します。Skippedステータスの場合は、Notesに記載された理由（オペレーター未存在、既存アラートとの競合など）を確認し、必要に応じて前提条件を整えて再実行します。

## 通知種別

PowerShellコンソール出力 / パイプライン出力（PSCustomObject）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（コマンド実行と同時に結果出力） |
| 優先度 | 中（ConfirmImpact = 'Medium'） |
| リトライ | 無（失敗時はエラーメッセージ出力） |

### 送信先決定ロジック

- Sourceパラメータ：コピー元SQL Serverインスタンスを指定
- Destinationパラメータ：コピー先SQL Serverインスタンスを指定（複数指定可能）
- Alertパラメータ：コピー対象のアラート名を指定
- ExcludeAlertパラメータ：コピーから除外するアラート名を指定
- IncludeDefaultsパラメータ：アラートデフォルト設定もコピー
- Forceパラメータ：既存アラートを削除して再作成

## 通知テンプレート

### コンソール出力の場合

| 項目 | 内容 |
|-----|------|
| 出力形式 | PSCustomObject（MigrationObject TypeName） |
| 確認プロンプト | ShouldProcess による確認 |

### 本文テンプレート

```
コピー成功時:
SourceServer      : {SourceServerName}
DestinationServer : {DestinationServerName}
Name              : {AlertName}
Type              : Agent Alert
Status            : Successful
Notes             :
DateTime          : {DateTime}

スキップ時（オペレーター不足）:
SourceServer      : {SourceServerName}
DestinationServer : {DestinationServerName}
Name              : {AlertName}
Type              : Agent Alert
Status            : Skipped
Notes             : Operator(s) [operatorName] do not exist on destination
DateTime          : {DateTime}

失敗時:
SourceServer      : {SourceServerName}
DestinationServer : {DestinationServerName}
Name              : {AlertName}
Type              : Agent Alert
Status            : Failed
Notes             : {ErrorDetails}
DateTime          : {DateTime}
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| なし | - | - | 本コマンドは添付ファイルを出力しない |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| SourceServer | コピー元サーバー名 | $sourceServer.Name | Yes |
| DestinationServer | コピー先サーバー名 | $destServer.Name | Yes |
| Name | アラート名 | $serverAlert.name | Yes |
| Type | オブジェクト種別 | "Agent Alert" / "Agent Alert Job Association" / "Agent Alert Notification" / "Alert Defaults" | Yes |
| Status | 処理結果 | "Successful" / "Failed" / "Skipped" | Yes |
| Notes | 追加情報 | エラーメッセージ/スキップ理由 | No |
| DateTime | 処理日時 | Get-Date（DbaDateTime型） | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| コマンド実行 | Copy-DbaAgentAlert実行 | Source/Destination接続可能 | アラート設定をコピー |
| IncludeDefaults | -IncludeDefaults指定 | デフォルト設定存在 | アラートデフォルト設定もコピー |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| オペレーター不存在 | 通知先オペレーターが宛先に存在しない場合はスキップ |
| 既存アラート | 同名アラートが存在し-Forceなしの場合はスキップ |
| 重複定義 | 同一Severity/MessageId/Database/Keywordのアラートが存在する場合はスキップ |
| ジョブ不存在 | 応答ジョブが宛先に存在しない場合はスキップ |
| -WhatIf指定時 | 実際のコピーは行わず、処理内容のみ表示 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[コマンド実行開始] --> B[Source接続]
    B --> C{接続成功?}
    C -->|No| D[Stop-Function: 接続エラー]
    D --> E[終了]
    C -->|Yes| F[foreach destination in Destination]
    F --> G[Destination接続]
    G --> H{接続成功?}
    H -->|No| I[Stop-Function: 接続エラー]
    I --> F
    H -->|Yes| J{IncludeDefaults?}
    J -->|Yes| K[AlertDefaultsコピー]
    J -->|No| L[foreach alert in Alerts]
    K --> L
    L --> M{オペレーター存在?}
    M -->|No| N[Skipped: オペレーター不存在]
    N --> L
    M -->|Yes| O{既存アラート?}
    O -->|Yes| P{Force指定?}
    P -->|No| Q[Skipped: 既存]
    Q --> L
    P -->|Yes| R[既存アラート削除]
    O -->|No| S{競合チェック}
    R --> S
    S -->|競合| T[Skipped: 重複定義]
    T --> L
    S -->|OK| U{ジョブ存在?}
    U -->|No| V[Skipped: ジョブ不存在]
    V --> L
    U -->|Yes/NA| W[アラートコピー]
    W --> X{ジョブ関連付け?}
    X -->|Yes| Y[ジョブ関連付けコピー]
    X -->|No| Z[通知設定コピー]
    Y --> Z
    Z --> AA{次のアラート?}
    AA -->|Yes| L
    AA -->|No| AB{次のDestination?}
    AB -->|Yes| F
    AB -->|No| AC[終了]
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| msdb.dbo.sysalerts | ソースアラート情報 | SMO経由 |
| msdb.dbo.sysoperators | オペレーター存在確認 | 宛先で参照 |
| msdb.dbo.sysjobs | ジョブ存在確認 | 宛先で参照 |

### テーブル別参照項目詳細

#### msdb.dbo.sysalerts（ソース）

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| name | アラート名 | コピー対象特定 |
| severity | 重大度 | 競合チェック |
| message_id | メッセージID | 競合チェック |
| database_name | データベース名 | 競合チェック |
| event_description_keyword | キーワード | 競合チェック |
| job_id | ジョブID | ジョブ関連付け確認 |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| msdb.dbo.sysalerts | INSERT/DELETE | アラートのコピー/Force時の削除 |
| msdb.dbo.sysnotifications | INSERT | 通知設定のコピー |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| Source接続失敗 | Sourceに接続不可 | Stop-Function（処理終了） |
| Destination接続失敗 | Destinationに接続不可 | Stop-Function -Continue |
| オペレーター不存在 | 通知先がDestinationに未存在 | Skipped（Copy-DbaAgentOperator推奨） |
| ジョブ不存在 | 応答ジョブがDestinationに未存在 | Skipped |
| アラート競合 | 同一条件のアラートが存在 | Skipped |
| Script失敗 | SMO Script()失敗 | Failed |
| Query失敗 | T-SQL実行失敗 | Failed |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | なし |
| 1日あたり上限 | なし |

### 配信時間帯

制限なし（任意のタイミングで実行可能）

## セキュリティ考慮事項

- sysadmin権限がソースと全ての宛先インスタンスに必要
- SourceSqlCredential/DestinationSqlCredentialパラメータで個別の認証情報を指定可能
- Forceパラメータ使用時は既存アラートが削除されるため注意が必要
- ジョブID置換により、宛先でのジョブ関連付けが正しく設定される

## 備考

- SMO Script()メソッドでアラートのT-SQLを生成し、宛先で実行
- ジョブIDは00000000-0000-0000-0000-000000000000に置換後、正しいジョブIDで更新
- 通知設定（Email/Pager/NetSend）はEnumNotifications()で取得し、AddNotification()で追加
- AlertDefaultsはAlertSystem.Script()で取得
- MigrationObject TypeNameにより、Select-DefaultViewで適切な表示フォーマットが適用される

---

## コードリーディングガイド

本通知を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、出力されるMigrationObjectの構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Copy-DbaAgentAlert.ps1 | `public/Copy-DbaAgentAlert.ps1` | 69-84行目: .OUTPUTSセクションで出力プロパティを確認 |
| 1-2 | Copy-DbaAgentAlert.ps1 | `public/Copy-DbaAgentAlert.ps1` | 137-144行目: copyAgentAlertStatus オブジェクト定義 |

**読解のコツ**: Status列の値（Successful/Failed/Skipped）とNotes列の内容が重要な処理結果情報となる。

#### Step 2: エントリーポイントを理解する

処理の起点となるパラメータ定義と初期化を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Copy-DbaAgentAlert.ps1 | `public/Copy-DbaAgentAlert.ps1` | 101-114行目: パラメータ定義 |
| 2-2 | Copy-DbaAgentAlert.ps1 | `public/Copy-DbaAgentAlert.ps1` | 115-123行目: beginブロック（Source接続） |

**主要処理フロー**:
1. **103行目**: Source（必須）- コピー元インスタンス
2. **107行目**: Destination（必須）- コピー先インスタンス（複数可）
3. **117-121行目**: Source接続とアラートコレクション取得

#### Step 3: 依存関係チェックを理解する

オペレーター、既存アラート、ジョブの依存関係チェック処理を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Copy-DbaAgentAlert.ps1 | `public/Copy-DbaAgentAlert.ps1` | 180-195行目: オペレーター存在チェック |
| 3-2 | Copy-DbaAgentAlert.ps1 | `public/Copy-DbaAgentAlert.ps1` | 197-222行目: 既存アラートチェックとForce処理 |
| 3-3 | Copy-DbaAgentAlert.ps1 | `public/Copy-DbaAgentAlert.ps1` | 224-247行目: 競合チェックとジョブ存在チェック |

**主要処理フロー**:
- **181-194行目**: HasNotification時、宛先にオペレーターが存在するか確認
- **197-206行目**: 既存アラート存在時、Forceなしならスキップ
- **208-221行目**: Force時、sp_delete_alertで既存アラート削除
- **224-238行目**: Severity/MessageId/Database/Keywordの組み合わせで競合チェック
- **240-247行目**: 応答ジョブの存在チェック

#### Step 4: アラートコピー処理を理解する

SMO Script()を使用したアラートコピー処理を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Copy-DbaAgentAlert.ps1 | `public/Copy-DbaAgentAlert.ps1` | 249-265行目: アラートスクリプト生成と実行 |

**主要処理フロー**:
- **252行目**: `$serverAlert.Script()` でT-SQL生成
- **253行目**: ジョブIDを空GUIDに置換（後で正しいIDに更新）
- **256行目**: `$destServer.Query($sql)` でアラート作成

#### Step 5: ジョブ関連付けと通知設定コピーを理解する

ジョブ関連付けの更新と通知設定のコピー処理を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | Copy-DbaAgentAlert.ps1 | `public/Copy-DbaAgentAlert.ps1` | 275-306行目: ジョブ関連付け処理 |
| 5-2 | Copy-DbaAgentAlert.ps1 | `public/Copy-DbaAgentAlert.ps1` | 308-347行目: 通知設定コピー処理 |

**主要処理フロー**:
- **275行目**: JobId が空GUIDでない場合にジョブ関連付け処理
- **289-292行目**: 正しいジョブIDに置換し、sp_update_alertで更新
- **320-338行目**: EnumNotifications()で通知設定を取得し、AddNotification()で追加

### プログラム呼び出し階層図

```
Copy-DbaAgentAlert (エントリーポイント)
    |
    +-- [beginブロック]
    |       ├── Connect-DbaInstance (Source)
    |       └── $sourceServer.JobServer.Alerts取得
    |
    └── [processブロック]
            |
            └── foreach ($destinstance in $Destination)
                    |
                    ├── Connect-DbaInstance (Destination)
                    |
                    ├── IncludeDefaults処理
                    |       └── AlertSystem.Script() → Query()
                    |
                    └── foreach ($serverAlert)
                            |
                            ├── 依存関係チェック
                            |       ├── オペレーター存在確認
                            |       ├── 既存アラート確認/Force削除
                            |       ├── 競合チェック
                            |       └── ジョブ存在確認
                            |
                            ├── Alert.Script() → Query()
                            |
                            ├── ジョブ関連付け更新
                            |       └── sp_update_alert
                            |
                            └── 通知設定コピー
                                    ├── EnumNotifications()
                                    └── AddNotification()
```

### データフロー図

```
[入力]                         [処理]                           [出力]

Source ─────────────┐
SourceSqlCredential─┼──▶ Connect-DbaInstance ──▶ $sourceServer
                    │                               │
                    │                               ▼
                    │                    $sourceServer.JobServer.Alerts
                    │
Destination ────────┼──▶ Connect-DbaInstance ──▶ $destServer
DestinationSqlCred ─┤                               │
Alert ──────────────┤                               ▼
ExcludeAlert ───────┤                    foreach ($serverAlert)
IncludeDefaults ────┤                               │
Force ──────────────┘                    ┌──────────┼──────────┐
                                         ▼          ▼          ▼
                                   依存関係    Script()     通知設定
                                   チェック    + Query()    コピー
                                         │          │          │
                                         ▼          ▼          ▼
                                              PSCustomObject
                                         (MigrationObject TypeName)
                                    SourceServer, DestinationServer,
                                    Name, Type, Status, Notes, DateTime
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Copy-DbaAgentAlert.ps1 | `public/Copy-DbaAgentAlert.ps1` | ソース | メインコマンド実装 |
| Connect-DbaInstance.ps1 | `public/Connect-DbaInstance.ps1` | ソース | SQL Server接続 |
| Stop-Function.ps1 | `private/functions/Stop-Function.ps1` | ソース | エラー処理ユーティリティ |
| Test-FunctionInterrupt.ps1 | `private/functions/Test-FunctionInterrupt.ps1` | ソース | 処理中断チェック |
| Write-Message.ps1 | `private/functions/Write-Message.ps1` | ソース | ログ出力ユーティリティ |
| Select-DefaultView.ps1 | `private/functions/Select-DefaultView.ps1` | ソース | デフォルト表示制御 |
