Operations Manager用のExchange Server 2013管理パックに含まれるレポートが動作せず、レポートを開始しようとすると「レポートを初期化できません。」というエラーが出てしまう事象が発生しました。色々と調査をして原因にたどり着きとりあえず回避はできたのですが、トラブルシューティング中にかなり紆余曲折してしまったので、「わかっている今ならこうやってすんなり対処できるはず」というものを同じような問題に遭遇する人や将来の自分のためにまとめておきます。
発生した事象
SCOM上のレポートにてExchange Server 2013関連のレポートを実行しようとすると、以下のエラーが出てしまいます。
日付: 2015/02/09 17:12:33
アプリケーション: Operations Manager
アプリケーションのバージョン: 7.1.10226.0
重要度: エラー
メッセージ: レポートを初期化できません。
System.ArgumentNullException: 値を Null にすることはできません。
パラメーター名: GroupList
場所 Microsoft.EnterpriseManagement.Mom.Internal.UI.Reporting.Parameters.Controls.Monitoring.ReportMonitoringObjectXmlEditorBase.LoadValues(ReportParameterInfoCollection reportParameters)
場所 Microsoft.EnterpriseManagement.Mom.Internal.UI.Reporting.Parameters.ReportParameterBlock.LoadValues()
場所 Microsoft.EnterpriseManagement.Mom.Internal.UI.Console.ReportForm.SetReportJob(Object sender, ConsoleJobEventArgs args)
レポーティングサービスのWebサイトからの確認
SCOM上でのレポート実行では情報に乏しいので、実態であるレポーティングサービスのWebからも確認します。
同様にエラーになります。「ReportRules」が選択式にも関わらず、何も値が入っていないのが直接の原因であることがわかりました。
ほぼすべてのレポートで同様の状態になっており、問題の原因はリンクされているレポートで発生していることもわかりました。
様々なレポートのリンク先となっているレポートにて問題を確認します。
ReportRulesが選択式にも関わらず値が入っていないためにエラーになっているのは同じ状況です。
レポートのプロパティより、ReportRulesはクエリベースのパラメータであることがわかります。Webからは確認できないので、レポートビルダーにてレポートを開き確認していきます。
レポートビルダーでのレポート定義の確認
実際にレポートビルダーでレポートを開いて確認していくと、以下のようにデータソースへの接続ができずに失敗してしまいます。
なので、前準備として、一時的にData Warehouse Mainの接続設定を変更します。
もともとは以下のように「資格情報は必要ありません」となっています。
これを以下のように「レポートサーバーに保存され、セキュリティで保護された資格情報」に変更します。
※この接続設定変更部分はあまりよくわからずに実行している点があります。実際にこれでレポートビルダー上で資格情報を要求され、うまく確認可能になるのですが、もう少し深い理解が必要だと感じています。
準備ができたので、レポートを開いていきます。
レポートのURLは、「Reporting Services構成マネージャー」から確認できますので、そこを開きます。
問題となっているパラメータの設定を確認します。
「Exchange2013_Report_GetRelatedRules」というデータセットから値を取得していることがわかりました。次は「Exchange2013_Report_GetRelatedRules」データセットを確認します。
まず、クエリを確認してみます。
「Exchange2013_Report_GetRelatedRules」というストアドプロシージャを呼び出していることがわかります。また、@rulesと@langという2つのパラメータを渡していることもわかります。
ストアドプロシージャに渡しているパラメータを確認してみると、@rulesには[@ReportRelatedRules]という別のパラメータを渡し、@langには何も値が指定されていない事がわかります。
@ReportRelatedRulesというパラメータの定義を確認します。
規定値として「<Rules/>」が指定されている事がわかりました。
ここまででわかったこと
ここまででわかったのは
- 「ReportRules」というパラメータが選択式にも関わらず、何も値が入っていない
- 「ReportRules」というパラメータは「Exchange2013_Report_GetRelatedRules」というストアドプロシージャを呼び出した結果を選択肢として保持する
- 「Exchange2013_Report_GetRelatedRules」というストアドプロシージャは@rulesと@langという2つのパラメータを取る。
- レポートでは@rulesに「<Rules/>」を渡し、@langには何も渡していない
ということです。
ですので、Exchange2013_Report_GetRelatedRulesというストアドプロシージャに的を絞って確認していきます。
ストアドプロシージャの実行結果確認
レポートビルダーから問題のストアドプロシージャを実行してみます。ここまででわかっている通り@rulesに「<Rules/>」を渡し@langには何も渡しません。
結果は何も返ってきていません。やはりこれが原因で間違いないようです。
次は、SQL Server Management Studioでストアドプロシージャを実行してみます。同様に@rulesに「<Rules/>」を渡し@langには何も渡しません。
正常に処理され、結果が返ってきました。
これが意図する状態のはずであり、これらが「ReportRules」に選択肢として入るはずです。SQL Server Management Studioからの実行では問題が再現していない状態です。
ここまででわかったこと
ここまでで以下のことがわかりました。
- 「ReportRules」というパラメータが選択式にも関わらず、何も値が入っていない
- 「ReportRules」というパラメータは「Exchange2013_Report_GetRelatedRules」というストアドプロシージャを呼び出した結果を選択肢として保持する
- 「Exchange2013_Report_GetRelatedRules」というストアドプロシージャは@rulesと@langという2つのパラメータを取る。
- レポートでは@rulesに「<Rules/>」を渡し、@langには何も渡していない
- レポートビルダー(レポーティングサービス)から問題のストアドプロシージャを呼び出すと値が返ってこない(問題発生)
- SQL Management Studioから問題のストアドプロシージャを呼び出すと値が返ってくる(問題は発生しない)
実行対象は間違いなく同じストアドプロシージャですから呼び出し方に違いがあるはずです。呼び出し方の違いを確認していきます。
引数の確認(SQL Server Profiler)
SQL Server Management Studioからの実行は見てわかるように以下のSQL文となっています。
EXEC @return_value = [dbo].[Exchange2013_Report_GetRelatedRules]
@rules = N’<Rules/>’
異なる結果になるということは、レポーティングサービスからの呼び出しでは異なるSQL文になっているはずです。それを追いたいです。
やり方は色々ありますが、SQL Server Profilerを使ってSQL文を確認してみます。
適切なイベントを選択します。
キャプチャを開始してから、レポートビルダーにて問題を再現させ、キャプチャをストップします。
その上で「Exchange2013_Report_GetRelatedRules」で検索します。
ヒットしました。以下の呼ばれ方になっています。
exec Exchange2013_Report_GetRelatedRules @rules=NULL,@lang=NULL
※上記、本来は「@rules=’<Rules/>’,@lang=NULL」となるようにきちんと引数を今までの想定と同じように指定して実行すべきなのですが、引数のわたり方にのみ注目していて、引数をきちんと入力せずにレポートビルダーを動作させてしまっています。取り直すのも面倒なのでこのままとしてありますが、あまりよくないですね。
引数は「@rules=NULL,@lang=NULL」という形で渡されています。特に、@langに対して明示的にNULLが指定されている点が重要です。
実際に「exec Exchange2013_Report_GetRelatedRules @rules=’<Rules/>’,@lang=NULL」と実行してみます。
結果はかえってきません。問題は再現しました。
ストアドプロシージャの確認
ストアドプロシージャの中身を確認してみます。SQL Server Management Studioにて「変更」で中身を確認してしまうのが簡単だと思います。
USE [OperationsManagerDW]
GO
/****** Object: StoredProcedure [dbo].[Exchange2013_Report_GetRelatedRules] Script Date: 2015/02/10 5:34:46 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[Exchange2013_Report_GetRelatedRules]
@rules XML,
@lang NVARCHAR(3) = ‘ENU’
AS
BEGIN
BEGIN TRY
DECLARE @r TABLE (RuleSystemName NVARCHAR(1024))
INSERT INTO @r
(
RuleSystemName
)
SELECT
r.n.value(‘.’,’nvarchar(1024)’)
FROM
@rules.nodes(‘/Rules/Rule’) AS r(n)
IF NOT EXISTS (SELECT * FROM @r)
BEGIN
INSERT INTO @r
(
RuleSystemName
)
SELECT
vr.RuleSystemName
FROM
vRule vr
INNER JOIN vManagementPack vmp ON vmp.ManagementPackRowId = vr.ManagementPackRowId
INNER JOIN vPerformanceRule vpr ON vpr.RuleRowId = vr.RuleRowId
WHERE
vmp.ManagementPackSystemName=’Microsoft.Exchange.15′
END
SELECT
vr.RuleGuid,
vr.RuleSystemName,
DisplayName = ISNULL(vds.Name,vr.RuleDefaultName)
FROM
@r r
INNER JOIN vRule vr ON vr.RuleSystemName = r.RuleSystemName
INNER JOIN vDisplayString vds ON vds.ElementGuid=vr.RuleGuid AND vds.LanguageCode=@lang
ORDER BY DisplayName
END TRY
BEGIN CATCH
DECLARE @errMsg VARCHAR(1024)
SET @errMsg = ERROR_MESSAGE()
RAISERROR(@errMsg, 16, 1)
END CATCH
END
@langは以下の場所で使われています。
SELECT
vr.RuleGuid,
vr.RuleSystemName,
DisplayName = ISNULL(vds.Name,vr.RuleDefaultName)
FROM
@r r
INNER JOIN vRule vr ON vr.RuleSystemName = r.RuleSystemName
INNER JOIN vDisplayString vds ON vds.ElementGuid=vr.RuleGuid AND vds.LanguageCode=@lang
vDisplayStringビューで各言語ごとの表示名を取得してきているわけですね。
でも、残念ながらExchange Server 2013の管理パックにはまだ日本語版は出ていない状況ですので、JPNを指定しても値は返ってきません。
そもそもが、レポートの定義では@langには何も値が入っていませんでした。その結果@lang=NULLとなってわたってしまい、結果何もデータが取得されない状況になってしまっています。
これが原因です。
そもそもの製品の問題なのか、環境の問題なのかは微妙なところですね…。おそらく管理パック側の問題だろうというのが私の現時点での見解です。
修正
管理パックの修正バージョンを待っていると相当時間がかかってしまいますので、暫定的に対処したいと思います。修正方法は色々ありますが
- レポーティングサービス側からは@langはそもそも値を入れていない
- ストアドプロシージャ側では@langに値がなければ’ENU’をセットする
という動きになっていますので、事実上レポーティングサービス側からの@langを渡すことをやめさせてしまえば渡すパラメータが1つだけになり問題は回避できると思われます。
レポートの定義にて、パラメーターから@langを削除してレポートを上書きします。
これでうまく動作するようになりました。
この回避方法だときちんと日本語版の管理パックを後から導入した時に、日本語化されない…という問題はありますが、どこをどのように参照すると言語情報を取ってこられるのかをまだ理解していないですし、パフォーマンスカウンタの値であれば英語でもほぼ支障ないのでこの回避策でさしあたりよしとしておきます。
コメントを残す