Exchange Server 2013の管理パックに含まれるレポートが動作しない(SQL Server Reporting Servicesのデバッグ)

Operations Manager用のExchange Server 2013管理パックに含まれるレポートが動作せず、レポートを開始しようとすると「レポートを初期化できません。」というエラーが出てしまう事象が発生しました。色々と調査をして原因にたどり着きとりあえず回避はできたのですが、トラブルシューティング中にかなり紆余曲折してしまったので、「わかっている今ならこうやってすんなり対処できるはず」というものを同じような問題に遭遇する人や将来の自分のためにまとめておきます。

発生した事象

SCOM上のレポートにてExchange Server 2013関連のレポートを実行しようとすると、以下のエラーが出てしまいます。

image

日付: 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からも確認します。

image

同様にエラーになります。「ReportRules」が選択式にも関わらず、何も値が入っていないのが直接の原因であることがわかりました。

ほぼすべてのレポートで同様の状態になっており、問題の原因はリンクされているレポートで発生していることもわかりました。

 

image

様々なレポートのリンク先となっているレポートにて問題を確認します。

 

image

ReportRulesが選択式にも関わらず値が入っていないためにエラーになっているのは同じ状況です。

 

image

レポートのプロパティより、ReportRulesはクエリベースのパラメータであることがわかります。Webからは確認できないので、レポートビルダーにてレポートを開き確認していきます。

 

レポートビルダーでのレポート定義の確認

実際にレポートビルダーでレポートを開いて確認していくと、以下のようにデータソースへの接続ができずに失敗してしまいます。

image

なので、前準備として、一時的にData Warehouse Mainの接続設定を変更します。

もともとは以下のように「資格情報は必要ありません」となっています。

image

これを以下のように「レポートサーバーに保存され、セキュリティで保護された資格情報」に変更します。

image

 

※この接続設定変更部分はあまりよくわからずに実行している点があります。実際にこれでレポートビルダー上で資格情報を要求され、うまく確認可能になるのですが、もう少し深い理解が必要だと感じています。

 

準備ができたので、レポートを開いていきます。

レポートのURLは、「Reporting Services構成マネージャー」から確認できますので、そこを開きます。

image

 

問題となっているパラメータの設定を確認します。

image

image

image

「Exchange2013_Report_GetRelatedRules」というデータセットから値を取得していることがわかりました。次は「Exchange2013_Report_GetRelatedRules」データセットを確認します。

image

まず、クエリを確認してみます。

 

image

「Exchange2013_Report_GetRelatedRules」というストアドプロシージャを呼び出していることがわかります。また、@rulesと@langという2つのパラメータを渡していることもわかります。

image

image

ストアドプロシージャに渡しているパラメータを確認してみると、@rulesには[@ReportRelatedRules]という別のパラメータを渡し、@langには何も値が指定されていない事がわかります。

 

@ReportRelatedRulesというパラメータの定義を確認します。

image

image

image

image

規定値として「<Rules/>」が指定されている事がわかりました。

 

ここまででわかったこと

ここまででわかったのは

  • 「ReportRules」というパラメータが選択式にも関わらず、何も値が入っていない
  • 「ReportRules」というパラメータは「Exchange2013_Report_GetRelatedRules」というストアドプロシージャを呼び出した結果を選択肢として保持する
  • 「Exchange2013_Report_GetRelatedRules」というストアドプロシージャは@rulesと@langという2つのパラメータを取る。
  • レポートでは@rulesに「<Rules/>」を渡し、@langには何も渡していない

ということです。

ですので、Exchange2013_Report_GetRelatedRulesというストアドプロシージャに的を絞って確認していきます。

 

ストアドプロシージャの実行結果確認

レポートビルダーから問題のストアドプロシージャを実行してみます。ここまででわかっている通り@rulesに「<Rules/>」を渡し@langには何も渡しません。

image

image

image

結果は何も返ってきていません。やはりこれが原因で間違いないようです。

 

次は、SQL Server Management Studioでストアドプロシージャを実行してみます。同様に@rulesに「<Rules/>」を渡し@langには何も渡しません。

image

image

正常に処理され、結果が返ってきました。

これが意図する状態のはずであり、これらが「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文を確認してみます。

image

image

image

image

適切なイベントを選択します。

キャプチャを開始してから、レポートビルダーにて問題を再現させ、キャプチャをストップします。

その上で「Exchange2013_Report_GetRelatedRules」で検索します。

image

ヒットしました。以下の呼ばれ方になっています。

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」と実行してみます。

image

結果はかえってきません。問題は再現しました。

 

ストアドプロシージャの確認

ストアドプロシージャの中身を確認してみます。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を指定しても値は返ってきません。

image

image

そもそもが、レポートの定義では@langには何も値が入っていませんでした。その結果@lang=NULLとなってわたってしまい、結果何もデータが取得されない状況になってしまっています。

これが原因です。

そもそもの製品の問題なのか、環境の問題なのかは微妙なところですね…。おそらく管理パック側の問題だろうというのが私の現時点での見解です。

 

 

修正

管理パックの修正バージョンを待っていると相当時間がかかってしまいますので、暫定的に対処したいと思います。修正方法は色々ありますが

  • レポーティングサービス側からは@langはそもそも値を入れていない
  • ストアドプロシージャ側では@langに値がなければ’ENU’をセットする

という動きになっていますので、事実上レポーティングサービス側からの@langを渡すことをやめさせてしまえば渡すパラメータが1つだけになり問題は回避できると思われます。

image

image

レポートの定義にて、パラメーターから@langを削除してレポートを上書きします。

これでうまく動作するようになりました。

image

image

image

 

この回避方法だときちんと日本語版の管理パックを後から導入した時に、日本語化されない…という問題はありますが、どこをどのように参照すると言語情報を取ってこられるのかをまだ理解していないですし、パフォーマンスカウンタの値であれば英語でもほぼ支障ないのでこの回避策でさしあたりよしとしておきます。


投稿日

カテゴリー:

投稿者:

コメント

コメントを残す