如何使用SCOM SDK将性能数据插入DW数据库?

How to insert performance data to DW database using SCOM SDK?

我们创建了一个Inbound Connector and custom Management Pack

我们使用 .NET SDK 将数据发送到我们的 SCOM 服务器 examples

我们可以在SCOM 控制台上看到性能数据和事件。

但是当我们创建性能报告时(Reporting > Microsoft Generic Report Library > Performance)我们看不到我们的性能计数器。

我们似乎无法将性能数据插入 DW 数据库。

请问我是否可以提供任何其他信息来解决问题。

更新

我们的管理包源代码:

<?xml version="1.0" encoding="utf-8"?><ManagementPack ContentReadable="true" SchemaVersion="2.0" OriginalSchemaVersion="1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <Manifest>
    <Identity>
      <ID>CloudMonix.ResourceMonitoring</ID>
      <Version>1.0.0.0</Version>
    </Identity>
    <Name>CloudMonix Resource Monitoring Pack</Name>
    <References>
      <Reference Alias="System">
        <ID>System.Library</ID>
        <Version>7.5.8501.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
      <Reference Alias="Health">
        <ID>System.Health.Library</ID>
        <Version>7.0.8438.6</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
      <Reference Alias="SystemCenter">
        <ID>Microsoft.SystemCenter.Library</ID>
        <Version>7.0.8438.6</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
    </References>
  </Manifest>
  <TypeDefinitions>
    <EntityTypes>
      <ClassTypes>
        <ClassType ID="CloudMonix.ResourceMonitoring.Resource" Accessibility="Public" Abstract="false" Base="System!System.Entity" Hosted="false" Singleton="false" Extension="false">
          <Property ID="ResourceId" Type="string" AutoIncrement="false" Key="true" CaseSensitive="false" MaxLength="256" MinLength="1" Required="false" Scale="0" />
          <Property ID="ResourceType" Type="string" AutoIncrement="false" Key="false" CaseSensitive="false" MaxLength="256" MinLength="1" Required="false" Scale="0" />
          <Property ID="ResourceGroups" Type="string" AutoIncrement="false" Key="false" CaseSensitive="false" MaxLength="1024" MinLength="1" Required="false" Scale="0" />
        </ClassType>
      </ClassTypes>
    </EntityTypes>
    <ModuleTypes>
      <WriteActionModuleType ID="CloudMonix.ResourceMonitoring.SetStateAction" Accessibility="Internal" Batching="false">
        <Configuration>
          <IncludeSchemaTypes>
            <SchemaType>Health!System.Health.AlertSchema</SchemaType>
          </IncludeSchemaTypes>
          <xsd:element name="ManagementGroupId" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
          <xsd:element name="MonitorId" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
          <xsd:element name="ManagedEntityId" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
          <xsd:element name="HealthState" type="System.Health.AlertHealthState" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
        </Configuration>
        <ModuleImplementation Isolation="Any">
          <Native>
            <ClassID>44cbc334-8b5f-4cb6-bee0-6bdcbc80e8d5</ClassID>
          </Native>
        </ModuleImplementation>
        <InputType>System!System.BaseData</InputType>
      </WriteActionModuleType>
      <WriteActionModuleType ID="CloudMonix.ResourceMonitoring.TargetSetStateAction" Accessibility="Internal" Batching="false">
        <Configuration>
          <IncludeSchemaTypes>
            <SchemaType>Health!System.Health.AlertSchema</SchemaType>
          </IncludeSchemaTypes>
          <xsd:element name="MonitorId" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
          <xsd:element name="HealthState" type="System.Health.AlertHealthState" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
        </Configuration>
        <ModuleImplementation Isolation="Any">
          <Composite>
            <MemberModules>
              <WriteAction ID="WA" TypeID="CloudMonix.ResourceMonitoring.SetStateAction">
                <ManagementGroupId>$Target/ManagementGroup/Id$</ManagementGroupId>
                <MonitorId>$Config/MonitorId$</MonitorId>
                <ManagedEntityId>$Data/ManagedEntityId$</ManagedEntityId>
                <HealthState>$Config/HealthState$</HealthState>
              </WriteAction>
            </MemberModules>
            <Composition>
              <Node ID="WA" />
            </Composition>
          </Composite>
        </ModuleImplementation>
        <InputType>System!System.BaseData</InputType>
      </WriteActionModuleType>
      <WriteActionModuleType ID="CloudMonix.ResourceMonitoring.TargetSetSuccessAction" Accessibility="Public" Batching="false">
        <Configuration>
          <xsd:element name="MonitorId" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
        </Configuration>
        <ModuleImplementation Isolation="Any">
          <Composite>
            <MemberModules>
              <WriteAction ID="WA" TypeID="CloudMonix.ResourceMonitoring.TargetSetStateAction">
                <MonitorId>$Config/MonitorId$</MonitorId>
                <HealthState>Success</HealthState>
              </WriteAction>
            </MemberModules>
            <Composition>
              <Node ID="WA" />
            </Composition>
          </Composite>
        </ModuleImplementation>
        <InputType>System!System.BaseData</InputType>
      </WriteActionModuleType>
      <WriteActionModuleType ID="CloudMonix.ResourceMonitoring.TargetSetWarningAction" Accessibility="Public" Batching="false">
        <Configuration>
          <xsd:element name="MonitorId" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
        </Configuration>
        <ModuleImplementation Isolation="Any">
          <Composite>
            <MemberModules>
              <WriteAction ID="WA" TypeID="CloudMonix.ResourceMonitoring.TargetSetStateAction">
                <MonitorId>$Config/MonitorId$</MonitorId>
                <HealthState>Warning</HealthState>
              </WriteAction>
            </MemberModules>
            <Composition>
              <Node ID="WA" />
            </Composition>
          </Composite>
        </ModuleImplementation>
        <InputType>System!System.BaseData</InputType>
      </WriteActionModuleType>
      <WriteActionModuleType ID="CloudMonix.ResourceMonitoring.TargetSetErrorAction" Accessibility="Public" Batching="false">
        <Configuration>
          <xsd:element name="MonitorId" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
        </Configuration>
        <ModuleImplementation Isolation="Any">
          <Composite>
            <MemberModules>
              <WriteAction ID="WA" TypeID="CloudMonix.ResourceMonitoring.TargetSetStateAction">
                <MonitorId>$Config/MonitorId$</MonitorId>
                <HealthState>Error</HealthState>
              </WriteAction>
            </MemberModules>
            <Composition>
              <Node ID="WA" />
            </Composition>
          </Composite>
        </ModuleImplementation>
        <InputType>System!System.BaseData</InputType>
      </WriteActionModuleType>
    </ModuleTypes>
  </TypeDefinitions>
  <Monitoring>
    <Rules>
      <Rule ID="CloudMonix.ResourceMonitoring.Monitor.Success" Enabled="true" Target="CloudMonix.ResourceMonitoring.Resource" ConfirmDelivery="false" Remotable="true" Priority="Normal" DiscardLevel="100">
        <Category>StateCollection</Category>
        <DataSources>
          <DataSource ID="DataSource" TypeID="SystemCenter!Microsoft.SystemCenter.SdkEventProvider" />
        </DataSources>
        <ConditionDetection ID="ConditionDetection" TypeID="System!System.ExpressionFilter">
          <Expression>
            <SimpleExpression>
              <ValueExpression>
                <XPathQuery>EventNumber</XPathQuery>
              </ValueExpression>
              <Operator>Equal</Operator>
              <ValueExpression>
                <Value>1</Value>
              </ValueExpression>
            </SimpleExpression>
          </Expression>
        </ConditionDetection>
        <WriteActions>
          <WriteAction ID="WriteAction" TypeID="CloudMonix.ResourceMonitoring.TargetSetSuccessAction">
            <MonitorId>$MPElement[Name="CloudMonix.ResourceMonitoring.Monitor"]$</MonitorId>
          </WriteAction>
        </WriteActions>
      </Rule>
      <Rule ID="CloudMonix.ResourceMonitoring.Monitor.Warning" Enabled="true" Target="CloudMonix.ResourceMonitoring.Resource" ConfirmDelivery="false" Remotable="true" Priority="Normal" DiscardLevel="100">
        <Category>StateCollection</Category>
        <DataSources>
          <DataSource ID="DataSource" TypeID="SystemCenter!Microsoft.SystemCenter.SdkEventProvider" />
        </DataSources>
        <ConditionDetection ID="ConditionDetection" TypeID="System!System.ExpressionFilter">
          <Expression>
            <SimpleExpression>
              <ValueExpression>
                <XPathQuery>EventNumber</XPathQuery>
              </ValueExpression>
              <Operator>Equal</Operator>
              <ValueExpression>
                <Value>2</Value>
              </ValueExpression>
            </SimpleExpression>
          </Expression>
        </ConditionDetection>
        <WriteActions>
          <WriteAction ID="WriteAction" TypeID="CloudMonix.ResourceMonitoring.TargetSetWarningAction">
            <MonitorId>$MPElement[Name="CloudMonix.ResourceMonitoring.Monitor"]$</MonitorId>
          </WriteAction>
        </WriteActions>
      </Rule>
      <Rule ID="CloudMonix.ResourceMonitoring.Monitor.Error" Enabled="true" Target="CloudMonix.ResourceMonitoring.Resource" ConfirmDelivery="false" Remotable="true" Priority="Normal" DiscardLevel="100">
        <Category>StateCollection</Category>
        <DataSources>
          <DataSource ID="DataSource" TypeID="SystemCenter!Microsoft.SystemCenter.SdkEventProvider" />
        </DataSources>
        <ConditionDetection ID="ConditionDetection" TypeID="System!System.ExpressionFilter">
          <Expression>
            <SimpleExpression>
              <ValueExpression>
                <XPathQuery>EventNumber</XPathQuery>
              </ValueExpression>
              <Operator>Equal</Operator>
              <ValueExpression>
                <Value>3</Value>
              </ValueExpression>
            </SimpleExpression>
          </Expression>
        </ConditionDetection>
        <WriteActions>
          <WriteAction ID="WriteAction" TypeID="CloudMonix.ResourceMonitoring.TargetSetErrorAction">
            <MonitorId>$MPElement[Name="CloudMonix.ResourceMonitoring.Monitor"]$</MonitorId>
          </WriteAction>
        </WriteActions>
      </Rule>
    </Rules>
    <Monitors>
      <AggregateMonitor ID="CloudMonix.ResourceMonitoring.Monitor" Accessibility="Public" Enabled="true" Target="CloudMonix.ResourceMonitoring.Resource" ParentMonitorID="Health!System.Health.EntityState" Remotable="true" Priority="Normal">
        <Category>StateCollection</Category>
        <Algorithm>WorstOf</Algorithm>
      </AggregateMonitor>
    </Monitors>
  </Monitoring>
  <Presentation>
    <Views>
      <View ID="CloudMonix.ResourceMonitoring.MainView" Accessibility="Public" Enabled="true" Target="CloudMonix.ResourceMonitoring.Resource" TypeID="SystemCenter!Microsoft.SystemCenter.StateViewType" Visible="true">
        <Category>Operations</Category>
        <Criteria>
          <InMaintenanceMode>false</InMaintenanceMode>
        </Criteria>
        <Presentation>
          <ColumnInfo Index="0" SortIndex="-1" Width="100" Grouped="false" Sorted="true" IsSortable="true" Visible="true" SortOrder="Ascending">
            <Name>State</Name>
            <Id>CloudMonix.ResourceMonitoring.Resource</Id>
          </ColumnInfo>
          <ColumnInfo Index="1" SortIndex="-1" Width="100" Grouped="false" Sorted="false" IsSortable="true" Visible="true" SortOrder="Ascending">
            <Name>Resource Type</Name>
            <Id>ResourceType</Id>
          </ColumnInfo>
          <ColumnInfo Index="2" SortIndex="-1" Width="100" Grouped="false" Sorted="false" IsSortable="true" Visible="true" SortOrder="Ascending">
            <Name>Resource Name</Name>
            <Id>DisplayName</Id>
          </ColumnInfo>
          <ColumnInfo Index="3" SortIndex="-1" Width="100" Grouped="false" Sorted="false" IsSortable="true" Visible="true" SortOrder="Ascending">
            <Name>Resource Groups</Name>
            <Id>ResourceGroups</Id>
          </ColumnInfo>
        </Presentation>
        <Target />
      </View>
    </Views>
    <Folders>
      <Folder ID="CloudMonix.ResourceMonitoring.MainFolder" Accessibility="Public" ParentFolder="SystemCenter!Microsoft.SystemCenter.Monitoring.ViewFolder.Root" />
    </Folders>
    <FolderItems>
      <FolderItem ElementID="CloudMonix.ResourceMonitoring.MainView" ID="CloudMonix.ResourceMonitoring.MainView" Folder="CloudMonix.ResourceMonitoring.MainFolder" />
    </FolderItems>
  </Presentation>
  <LanguagePacks>
    <LanguagePack ID="ENU" IsDefault="false">
      <DisplayStrings>
        <DisplayString ElementID="CloudMonix.ResourceMonitoring">
          <Name>CloudMonix Resource Monitoring</Name>
        </DisplayString>
        <DisplayString ElementID="CloudMonix.ResourceMonitoring.MainFolder">
          <Name>CloudMonix Folder</Name>
        </DisplayString>
        <DisplayString ElementID="CloudMonix.ResourceMonitoring.MainView">
          <Name>CloudMonix Resource View</Name>
        </DisplayString>
        <DisplayString ElementID="CloudMonix.ResourceMonitoring.Monitor">
          <Name>CloudMonix Health State Monitor</Name>
        </DisplayString>
        <DisplayString ElementID="CloudMonix.ResourceMonitoring.Resource">
          <Name>CloudMonix Resource</Name>
        </DisplayString>
        <DisplayString ElementID="CloudMonix.ResourceMonitoring.Resource" SubElementID="ResourceId">
          <Name>Resource Id</Name>
        </DisplayString>
        <DisplayString ElementID="CloudMonix.ResourceMonitoring.Resource" SubElementID="ResourceType">
          <Name>Resource Type</Name>
        </DisplayString>
        <DisplayString ElementID="CloudMonix.ResourceMonitoring.Resource" SubElementID="ResourceGroups">
          <Name>Resource Groups</Name>
        </DisplayString>
      </DisplayStrings>
    </LanguagePack>
  </LanguagePacks>
</ManagementPack>

更新 2

我们的源代码非常简单:

var customMonitoringPerformanceDatas = performanceDatas
    .Select(n => new CustomMonitoringPerformanceData("CloudMonix", n.MetricName, n.Value)
    {
        TimeSampled = n.TimeStamp
    })
    .OrderBy(n => n.TimeSampled)
    .ToList();

monitoringObject.InsertCustomMonitoringPerformanceData(customMonitoringPerformanceDatas);

更新 3

我已经实施了下一条规则:

<Rule ID="CloudMonix.ResourceMonitoring.PerformanceData" Enabled="true" Target="CloudMonix.ResourceMonitoring.Resource" ConfirmDelivery="false" Remotable="true" Priority="Normal" DiscardLevel="100">
  <Category>PerformanceCollection</Category>
  <DataSources>
    <DataSource ID="DataSource" TypeID="SystemCenter!Microsoft.SystemCenter.SdkPerformanceDataProvider" />
    </DataSource>         
  </DataSources>
  <WriteActions>
    <WriteAction ID="WriteToDB" TypeID="SystemCenter!Microsoft.SystemCenter.CollectPerformanceData" />
    <WriteAction ID="WriteToDW" TypeID="SystemCenterDataWarehouse!Microsoft.SystemCenter.DataWarehouse.PublishPerformanceDataCustomChannel">
      <ChannelId>69173604-6F23-4F98-3383-F3500BA26228</ChannelId>
    </WriteAction>
  </WriteActions>
</Rule>

我在规则中为 ChannelId 使用了我的自定义连接器 ID。 但不幸的是我没有看到性能计数器。

更新 4

我调查了SCOM DB,看到了我的麻烦。 我们的数据已收集到 DW 数据库。

但是我们所有的数据都是使用ONE RULE ID收集的。

由于 SCOM 对所有数据使用ONLY ONE RULE ID,我们可以看到ONLY ONE PERFORMANCE COUNTER NAME.

我们需要如何使用SDK正确收集性能数据?

我们已经解决了问题!

我查看了 SCOM DW 数据库,发现我们需要为每个指标实施单独的规则

我们可以在 Michel Kamp blog.

上找到类似的问题和描述

我们使用 SCOM SDK 创建动态规则并将这些规则添加到我们的管理包中。

详细的代码示例在这里:

const string conditionName = "System.ExpressionFilter";
const string dataSourceName = "Microsoft.SystemCenter.SdkPerformanceDataProvider";
const string writeActionName = "Microsoft.SystemCenter.DataWarehouse.PublishPerformanceData";

var managementClass = GetManagementPackClass(managementGroup, ManagementPackClass);

var criteria = new ManagementPackModuleTypeCriteria($"Name = '{conditionName}' OR Name = '{dataSourceName}' OR Name = '{writeActionName}'");
var moduleTypes = managementGroup.Monitoring.GetModuleTypes(criteria).ToList();

var conditionType = moduleTypes.Single(n => n.Name == conditionName);
var dataSourceType = moduleTypes.Single(n => n.Name == dataSourceName);
var writeActionType = moduleTypes.Single(n => n.Name == writeActionName);

foreach (var ruleName in missingRuleNames)
{
    var counterName = ruleName.Replace(MonitoringRulePrefix, string.Empty);

    var rule = new ManagementPackRule(managementPack, ruleName)
    {
        Target = managementClass,
        Category = ManagementPackCategoryType.PerformanceCollection,
        Enabled = ManagementPackMonitoringLevel.@true,
        ConfirmDelivery = false
    };

    rule.ConditionDetection = new ManagementPackConditionDetectionModule(rule, "ConditionDetection")
    {
        TypeID = (ManagementPackConditionDetectionModuleType) conditionType,
        Configuration = $@"
            <Expression>
                <SimpleExpression>
                    <ValueExpression>
                        <XPathQuery>CounterName</XPathQuery>
                    </ValueExpression>
                    <Operator>Equal</Operator>
                    <ValueExpression>
                        <Value>{counterName}</Value>
                    </ValueExpression>
                </SimpleExpression>
            </Expression>"
    };

    var dataSource = new ManagementPackDataSourceModule(rule, "DataSource")
    {
        TypeID = (ManagementPackDataSourceModuleType) dataSourceType
    };
    rule.DataSourceCollection.Add(dataSource);

    var action = new ManagementPackWriteActionModule(rule, "WriteToDataWarehouse")
    {
        TypeID = (ManagementPackWriteActionModuleType) writeActionType
    };
    rule.WriteActionCollection.Add(action);
}

managementPack.Verify();
managementPack.AcceptChanges();