# 機能設計書 130-Get-DbaMaintenanceSolutionLog

## 概要

本ドキュメントは、Ola HallengrenのMaintenanceSolutionでデータベースログが無効時に生成されるIndexOptimizeテキストログファイルを解析するGet-DbaMaintenanceSolutionLog機能の設計仕様を記載する。

### 本機能の処理概要

Get-DbaMaintenanceSolutionLogは、LogToTable='N'で実行されたIndexOptimize処理のテキストログファイルをパースし、インデックス操作の詳細（開始時刻、期間、フラグメンテーション、エラー等）を構造化データとして取得する機能である。

**業務上の目的・背景**：Ola Hallengren's MaintenanceSolutionは、SQL Serverの定番メンテナンスソリューションである。LogToTable='N'設定時はデータベースに実行履歴が残らず、テキストファイルに記録される。DBAは、これらのログを解析してインデックスメンテナンスの結果を確認する必要がある。本機能により、ログファイルの手動解析作業を自動化できる。

**機能の利用シーン**：
- IndexOptimize実行履歴の取得（テーブルログ無効時）
- インデックス再構築/再編成の結果分析
- フラグメンテーション状況の確認
- エラー発生の検出と調査

**主要な処理内容**：
1. SQL Serverインスタンスに接続してエラーログパスを取得
2. IndexOptimize_*.txtファイルを検索
3. Sinceパラメータでファイルをフィルタリング
4. テキストファイルを行単位で読み取り、ブロック単位でパース
5. ALTER INDEXやUPDATE STATISTICSコマンドを正規表現で抽出
6. 構造化データとしてPSCustomObjectを出力

**関連システム・外部連携**：Ola Hallengren's MaintenanceSolution、ファイルシステム

**権限による制御**：SQL Serverエラーログディレクトリへのファイルシステムアクセス権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | コンソール/ターミナル | 主画面 | コマンド実行と結果表示 |

## 機能種別

データ取得(SELECT) / ログ解析

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| SqlInstance | DbaInstanceParameter[] | Yes | 対象SQL Serverインスタンス | Mandatory, ValueFromPipeline |
| SqlCredential | PSCredential | No | 代替認証情報 | Windows/SQL認証対応 |
| LogType | string[] | No | ログタイプ（デフォルト: IndexOptimize） | ValidateSet: IndexOptimize, DatabaseBackup, DatabaseIntegrityCheck |
| Since | datetime | No | 指定日時以降のログのみ取得 | - |
| Path | string | No | カスタムログディレクトリパス | デフォルトはSQL Serverエラーログパス |
| EnableException | switch | No | 例外を直接スローするか | - |

### 入力データソース

- SQL Serverインスタンス（エラーログパス取得用）
- IndexOptimize_*.txtファイル

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ComputerName | string | SQL Serverホストのコンピュータ名 |
| InstanceName | string | SQL Serverインスタンス名 |
| SqlInstance | string | 完全修飾インスタンス名 |
| Database | string | 対象データベース名 |
| StartTime | dbadatetime | 操作開始日時 |
| Duration | timespan | 操作所要時間 |
| Index | string | インデックス名（ALTER INDEX操作時、UPDATE STATISTICS時はnull） |
| Statistics | string | 統計名（UPDATE STATISTICS操作時、ALTER INDEX時はnull） |
| Schema | string | スキーマ名 |
| Table | string | テーブル名 |
| Action | string | 実行アクション（REBUILD, REORGANIZE等） |
| Options | string | インデックス操作オプション |
| Timeout | string | ロックタイムアウト値（ミリ秒） |
| Partition | string | パーティション番号（パーティションインデックスの場合） |
| ObjectType | string | オブジェクトタイプ |
| IndexType | string | インデックスタイプ（Heap, ClusteredIndex, NonClusteredIndex） |
| ImageText | string | Image Text情報 |
| NewLOB | string | New LOB情報 |
| FileStream | string | FileStream情報 |
| ColumnStore | string | ColumnStore情報 |
| AllowPageLocks | string | Page Lock設定 |
| PageCount | string | ページ数 |
| Fragmentation | string | フラグメンテーション率（%） |
| Error | string | エラー情報（複数行は\nで結合） |

### 出力先

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

## 処理フロー

### 処理シーケンス

```
1. beginブロックでprocess-blockヘルパー関数を定義
   └─ ログブロックのパース処理

2. 各SqlInstanceをループ処理
   └─ Connect-DbaInstance接続

3. ログディレクトリを決定
   └─ Path指定時はそれを使用、未指定時はerrorlogpath

4. IndexOptimize_*.txtファイルを検索
   └─ Since指定時は日時フィルタリング

5. 各ファイルを行単位で読み取り
   └─ StreamReaderで効率的に読み取り

6. 空行でブロックを区切り、process-blockで解析
   └─ ALTER INDEX/UPDATE STATISTICSコマンドを正規表現抽出

7. Commentフィールドから追加情報を抽出
   └─ ObjectType, IndexType, PageCount, Fragmentation等

8. PSCustomObjectとして出力
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{SqlInstanceループ}
    B -->|各インスタンス| C[Connect-DbaInstance]
    C --> D{LogType確認}
    D -->|IndexOptimize以外| E[Warning出力、次へ]
    D -->|IndexOptimize| F{ホストプラットフォーム確認}
    F -->|非Windows & リモート| G[Warning出力、次へ]
    F -->|Windows or ローカル| H[ログディレクトリ決定]
    H --> I[IndexOptimize_*.txt検索]
    I --> J{Sinceフィルタ}
    J --> K{ファイルループ}
    K -->|各ファイル| L[StreamReaderで読み取り]
    L --> M{行ループ}
    M -->|空行| N[process-block実行]
    N --> O{Database情報あり?}
    O -->|No| P[ブロックリセット]
    O -->|Yes| Q[正規表現でコマンド解析]
    Q --> R[PSCustomObject出力]
    R --> P
    P --> M
    M -->|EOF| K
    K -->|終了| B
    E --> B
    G --> B
    B -->|全インスタンス完了| S[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | ログタイプ制限 | 現在はIndexOptimizeのみサポート | LogType指定時 |
| BR-002 | Sinceフィルタ | ファイル名またはCreationTimeで日時フィルタリング | Since指定時 |
| BR-003 | 空行区切り | ログファイルは空行でブロックを区切る | パース処理 |
| BR-004 | sqlcmd前提 | sqlcmdで実行されたログのみ対応（レガシー） | 全ての処理 |

### 計算ロジック

- **ALTER INDEX正規表現**: `'(SET LOCK_TIMEOUT (?<timeout>\d+); )?ALTER INDEX \[(?<index>[^\]]+)\] ON \[(?<database>[^\]]+)\]\.\[(?<schema>[^]]+)\]\.\[(?<table>[^\]]+)\] (?<action>[^\ ]+)( PARTITION = (?<partition>\d+))? WITH \((?<options>[^\)]+)'`
- **UPDATE STATISTICS正規表現**: `'(SET LOCK_TIMEOUT (?<timeout>\d+); )?UPDATE STATISTICS \[(?<database>[^\]]+)\]\.\[(?<schema>[^]]+)\]\.\[(?<table>[^\]]+)\] \[(?<stat>[^\]]+)\]'`

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| エラーログパス取得 | - | プロパティ参照 | SMO Server.errorlogpath |

### ファイルシステムアクセス詳細

#### IndexOptimize_*.txt

| 操作 | パス | 条件 | 備考 |
|-----|-----|------|------|
| 検索 | {errorlogpath} or {Path} | IndexOptimize_*.txtパターン | EnumerateFiles使用 |
| 読み取り | - | Sinceより新しいファイル | StreamReader使用 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ConnectionError | 接続エラー | SQL Serverインスタンスへの接続失敗 | Stop-Function -Continueで次へ |
| - | サポート外LogType | IndexOptimize以外のLogType | Warning出力して次へ |
| - | 非Windowsリモート | リモートの非Windowsホスト | Warning出力して次へ |
| - | ディレクトリアクセス不可 | ログディレクトリが存在しないまたはアクセス不可 | Warning出力して次へ |

### リトライ仕様

リトライ処理なし。エラー発生時は警告出力後に次のインスタンスを処理。

## トランザクション仕様

読み取り専用操作のため、トランザクション管理は不要。

## パフォーマンス要件

- 大量のログファイルがある場合は処理時間が長くなる可能性
- StreamReaderで効率的なファイル読み取りを実装

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

- SQL Serverエラーログディレクトリへのファイルシステムアクセス権限が必要
- SqlCredentialによる認証情報の安全な受け渡し
- Join-AdminUncでUNCパスに変換してリモートアクセス

## 備考

- sqlcmdで実行されたログのみ対応（レガシーな実行方法）
- 現在はIndexOptimizeのみサポート（DatabaseBackup、DatabaseIntegrityCheckは未実装）
- 最新のインストールではLogToTable='Y'を推奨
- 参考: https://ola.hallengren.com

---

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

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

### 推奨読解順序

#### Step 1: ヘルパー関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Get-DbaMaintenanceSolutionLog.ps1 | `public/Get-DbaMaintenanceSolutionLog.ps1` | beginブロックのprocess-block関数 |

**主要処理フロー**:
1. **136-148行目**: process-block関数定義（ログブロックのパース）
2. **149-167行目**: ログ行を": "で分割してキー・バリューを抽出
3. **168-187行目**: Commandフィールドを正規表現でパース
4. **189-197行目**: Commentフィールドから追加情報抽出
5. **198-200行目**: Errorフィールドを改行で結合

**読解のコツ**:
- `$fresh`ハッシュテーブルで各ブロックの初期値を定義
- `-match`演算子で正規表現マッチング、`$Matches`で名前付きグループを取得
- ALTER INDEX / UPDATE STATISTICSで分岐処理

#### Step 2: メイン処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Get-DbaMaintenanceSolutionLog.ps1 | `public/Get-DbaMaintenanceSolutionLog.ps1` | processブロックのファイル処理 |

**主要処理フロー**:
- **210-214行目**: Connect-DbaInstanceで接続
- **215-218行目**: LogTypeがIndexOptimize以外は警告
- **219-222行目**: 非Windowsリモートホストは警告
- **223-227行目**: ログディレクトリ決定
- **238行目**: EnumerateFilesでファイル検索
- **263-301行目**: StreamReaderでファイル読み取り、空行でブロック区切り

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

```
Get-DbaMaintenanceSolutionLog
    │
    ├─ Connect-DbaInstance
    │      └─ errorlogpath取得
    │
    ├─ Join-AdminUnc (UNCパス変換)
    │
    ├─ [System.IO.Directory]::EnumerateFiles
    │      └─ IndexOptimize_*.txt検索
    │
    ├─ System.IO.StreamReader
    │      └─ ファイル行単位読み取り
    │
    └─ process-block (ヘルパー関数)
           ├─ ログ行パース
           ├─ 正規表現マッチング
           └─ PSCustomObject変換
```

### データフロー図

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

SqlInstance    ───▶  Connect-DbaInstance       ───▶  errorlogpath取得
                           │
Path/Since     ───▶  ファイル検索・フィルタ   ───▶  ファイルリスト
                           │
                     StreamReader              ───▶  行データ
                           │
                     空行でブロック区切り      ───▶
                           │
                     process-block             ───▶  パース結果
                           │
                     正規表現マッチング        ───▶  コマンド詳細
                           │
                     PSCustomObject            ───▶  パイプライン出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Get-DbaMaintenanceSolutionLog.ps1 | `public/Get-DbaMaintenanceSolutionLog.ps1` | ソース | メイン関数定義 |
| Get-DbaMaintenanceSolutionLog.Tests.ps1 | `tests/Get-DbaMaintenanceSolutionLog.Tests.ps1` | テスト | 単体・統合テスト |
| Install-DbaMaintenanceSolution.ps1 | `public/Install-DbaMaintenanceSolution.ps1` | ソース | MaintenanceSolutionインストール |
