监视 Azure IoT 中心

当你的关键应用程序和业务流程依赖于 Azure 资源时,你需要监视这些资源的可用性、性能和操作。 本文介绍了 Azure IoT 中心生成的监视数据,以及如何使用 Azure Monitor 的功能在此数据的基础上进行分析和发出警报。

Monitor 概述

每个 IoT 中心的 Azure 门户中的“概述”页面都包括提供某些使用指标的图表,例如使用的消息数以及连接到 IoT 中心的设备数。

Default metric charts on IoT hub Overview page.

正确的消息计数值可能会延迟 1 分钟显示。 由于 IoT 中心服务基础结构的原因,在刷新时,该值有时会在较高值与较低值之间弹跳。 此计数器只有上一分钟应计的值会不正确。

“概述”窗格中提供的信息很有用,但只代表提供给 IoT 中心的少量监视数据。 某些监视数据会在你创建 IoT 中心后立即自动收集,并可供用于分析。 你可以使用某些配置启用其他数据收集类型。

说明是 Azure Monitor?

Azure IoT 中心使用全栈监视服务 Azure Monitor 来监视数据。 Azure Monitor 可以监视 Azure 资源和其他云或本地资源。

一开始可以阅读使用 Azure Monitor 监视 Azure 资源一文,其中介绍了以下概念:

  • 说明是 Azure Monitor?
  • 监视 Azure 中收集的数据
  • 配置数据收集
  • 指标和日志
  • Azure 中标准的分析和见解工具
  • 监视数据时触发的警报

有关 Azure IoT 中心创建的指标和日志的详细信息,请参阅监视 Azure IoT 中心监视数据参考

重要

IoT 中心服务使用 Azure Monitor 资源日志发出的事件不保证可靠或有序。 某些事件可能会丢失或未按顺序传送。 资源日志并非设计为实时的,因此可能需要几分钟的时间才能将事件记录到所选的目标。

本文的余下内容是在使用 Azure Monitor 监视 Azure 资源一文的基础上编写的,介绍为 Azure IoT 中心收集的特定数据。 其中提供了有关配置数据收集以及如何使用 Azure 工具分析这些数据的示例。

收集和路由

平台指标、活动日志和资源日志都有独特的收集、存储和路由规范。

  • 平台指标和活动日志会自动收集和存储,但你可以使用诊断设置将其路由到其他位置。

  • 在创建诊断设置并将其路由到一个或多个位置之前,不会收集和存储资源日志。

  • 指标和日志可路由到多个位置,包括:

    • Azure Monitor 日志存储(使用关联的 Log Analytics 工作区)。 可以在其中使用 Log Analytics 对它们进行分析。
    • 用于存档和脱机分析的 Azure 存储
    • 一个事件中心终结点,外部应用程序(例如第三方安全信息和事件管理 (SIEM) 工具)可在其中读取上述数据。

在 Azure 门户的 IoT 中心的“监视”下选择“诊断设置”,然后选择“添加诊断设置”,以便创建作用域为 IoT 中心发出的日志和平台指标的诊断设置。

Screenshot showing how to add a diagnostic setting in your IoT hub in the Azure portal.

以下屏幕截图显示了用于将资源日志类型“连接操作”和所有平台指标路由到 Log Analytics 工作区的诊断设置。

Screenshot of the Diagnostic Settings form for monitoring an IoT hub.

有关使用 Azure 门户、CLI 或 PowerShell 创建诊断设置的更多信息,请参阅创建诊断设置以收集 Azure 中的平台日志和指标。 创建诊断设置时,请指定要收集的日志类别。 Azure IoT 中心监视数据参考中的“资源日志”下列出了 Azure IoT 中心的类别。 仅针对某些类别的错误发出事件。

将 IoT 中心平台指标路由到其他位置时:

  • 无法通过诊断设置导出以下平台指标:“连接的设备数”和“设备总数”。

  • 多维指标(例如,某些路由指标)当前导出为跨维度值聚合的平展单维指标。 有关更多详细信息,请参阅将平台指标导出到其他位置

分析指标

你可以使用指标资源管理器通过其他 Azure 服务中的指标分析 Azure IoT 中心的指标。 有关此工具的详细信息,请参阅 Azure 指标资源管理器入门指南

若要打开指标资源管理器,请转到 Azure 门户并打开你的 IoT 中心,然后选择“监视”下的“指标”。 默认情况下,此资源管理器中的内容范围限定为 IoT 中心发出的平台指标。

Screenshot showing the metrics explorer page for an IoT hub.

有关为 Azure IoT 中心收集的平台指标的列表,请参阅 Azure IoT 中心监视数据参考中的“指标”。 有关为所有 Azure 服务收集的平台指标的列表,请参阅 Azure Monitor 支持的指标

对于以计数单位收集的 IoT 中心平台指标,某些聚合可能不可用或无法使用。 若要了解详细信息,请参阅 Azure IoT 中心监视数据参考中的“支持的聚合”

某些 IoT 中心指标(例如路由指标)是多维的。 对于这些指标,你可以基于某个维度对图表应用筛选器拆分

分析日志

Azure Monitor 日志中的数据以表形式存储,每个表具有自己独有的属性集。 这些表中的数据与某个 Log Analytics 工作区相关联,并且可以在 Log Analytics 中进行查询。 若要详细了解 Azure Monitor 日志,请参阅 Azure Monitor 文档中的 Azure Monitor 日志概述

若要将数据路由到 Azure Monitor 日志,你必须创建一个诊断设置,以便将资源日志或平台指标发送到 Log Analytics 工作区。 若要了解详细信息,请参阅收集和路由

若要执行 Log Analytics,请转到 Azure 门户并打开你的 IoT 中心,然后选择“监视”下的“日志”。 默认情况下,这些 Log Analytics 查询的范围限定为在 Azure Monitor 日志中为 IoT 中心收集的日志和指标。

Logs page for an IoT hub.

有关 Azure Monitor 日志使用的可供 Log Analytics 查询的表的列表,请参阅 Azure IoT 中心监视数据参考中的“Azure Monitor 日志表”

Azure Monitor 中的所有资源日志都具有后跟服务特定字段的相同字段。 Azure Monitor 资源日志架构概述了常见架构。 可以在 Azure IoT 中心监视数据参考中的“资源日志”中找到为 Azure IoT 中心收集的资源日志的架构和类别。 仅针对某些类别的错误发出事件。

活动日志是 Azure 中的一种平台日志,可用于深入了解订阅级别事件。 你可以单独查看它或将它路由到 Azure Monitor 日志,然后便可以在其中使用 Log Analytics 执行复杂得多的查询。

将 IoT 中心平台指标路由到 Azure Monitor 日志时:

  • 以下平台指标不可通过诊断设置导出:“已连接设备数”和“设备总数”。

  • 多维指标(例如,某些路由指标)当前导出为跨维度值聚合的平展单维指标。 有关更多详细信息,请参阅将平台指标导出到其他位置

有关 IoT 中心的常见查询,请参阅示例 Kusto 查询。 有关使用 Log Analytics 查询的详细信息,请参阅 Azure Monitor 中的日志查询概述

IoT 中心日志中的 SDK 版本

IoT 中心资源日志中的一些操作在其 properties 对象中返回 sdkVersion 属性。 对于这些操作,当设备或后端应用使用 Azure IoT SDK 之一时,此属性包含有关所使用的 SDK、SDK 版本和运行 SDK 的平台的信息。

以下示例显示了使用以下工具为 deviceConnect 操作发出的 sdkVersion 属性:

  • Node.js 设备 SDK:"azure-iot-device/1.17.1 (node v10.16.0; Windows_NT 10.0.18363; x64)"
  • .NET (C#) SDK:".NET/1.21.2 (.NET Framework 4.8.4200.0; Microsoft Windows 10.0.17763 WindowsProduct:0x00000004; X86)"

下表显示了用于不同 Azure IoT SDK 的 SDK 名称:

SdkVersion 属性中的 SDK 名称 语言
.NET .NET (C#)
microsoft.azure.devices .NET (C#) 服务 SDK
microsoft.azure.devices.client .NET (C#) 设备 SDK
iothubclient C 或 Python v1(已弃用)设备 SDK
iothubserviceclient C 或 Python v1(已弃用)服务 SDK
azure-iot-device-iothub-py Python 设备 SDK
azure-iot-device Node.js 设备 SDK
azure-iothub Node.js 服务 SDK
com.microsoft.azure.iothub-java-client Java 设备 SDK
com.microsoft.azure.iothub.service.sdk Java 服务 SDK
com.microsoft.azure.sdk.iot.iot-device-client Java 设备 SDK
com.microsoft.azure.sdk.iot.iot-service-client Java 服务 SDK
C Embedded C
C + (OSSimplified = Azure RTOS) Azure RTOS

对 IoT 中心资源日志执行查询时,可以提取 SDK 版本属性。 例如,下面的查询从连接操作返回的属性中提取 SDK 版本属性(和设备 ID)。 这两个属性将与操作时间以及设备所连接到的 IoT 中心的资源 ID 一起写入到结果中。

// SDK version of devices
// List of devices and their SDK versions that connect to IoT Hub
AzureDiagnostics
| where ResourceProvider == "MICROSOFT.DEVICES" and ResourceType == "IOTHUBS"
| where Category == "Connections"
| extend parsed_json = parse_json(properties_s) 
| extend SDKVersion = tostring(parsed_json.sdkVersion) , DeviceId = tostring(parsed_json.deviceId)
| distinct DeviceId, SDKVersion, TimeGenerated, _ResourceId

示例 Kusto 查询

使用以下 Kusto 查询来帮助监视 IoT 中心。

重要

从“IoT 中心”菜单中选择“日志”会打开“Log Analytics”,并仅显示你的 IoT 中心资源的数据。 对于包含其他 IoT 中心或 Azure 服务的数据的查询,请从“Azure Monitor”菜单中选择“日志”。 有关详细信息,请参阅 Azure Monitor Log Analytics 中的日志查询范围和时间范围

  • 连接性错误:确定设备连接错误。

    AzureDiagnostics
    | where ResourceProvider == "MICROSOFT.DEVICES" and ResourceType == "IOTHUBS"
    | where Category == "Connections" and Level == "Error"
    
  • 限制错误:确定因发出的请求最多而导致限制错误的设备。

    AzureDiagnostics
    | where ResourceProvider == "MICROSOFT.DEVICES" and ResourceType == "IOTHUBS"
    | where ResultType == "429001"
    | extend DeviceId = tostring(parse_json(properties_s).deviceId)
    | summarize count() by DeviceId, Category, _ResourceId
    | order by count_ desc
    
  • 死终结点:按报告问题的次数来确定死的或不正常的终结点并知晓原因。

    AzureDiagnostics
    | where ResourceProvider == "MICROSOFT.DEVICES" and ResourceType == "IOTHUBS"
    | where Category == "Routes" and OperationName in ("endpointDead", "endpointUnhealthy")
    | extend parsed_json = parse_json(properties_s)
    | extend Endpoint = tostring(parsed_json.endpointName), Reason = tostring(parsed_json.details) 
    | summarize count() by Endpoint, OperationName, Reason, _ResourceId
    | order by count_ desc
    
  • 错误摘要:所有操作的按类型的错误计数。

    AzureDiagnostics
    | where ResourceProvider == "MICROSOFT.DEVICES" and ResourceType == "IOTHUBS"
    | where Level == "Error"
    | summarize count() by ResultType, ResultDescription, Category, _ResourceId
    
  • 最近连接的设备:IoT 中心在指定时间段内看到其已连接的设备的列表。

    AzureDiagnostics
    | where ResourceProvider == "MICROSOFT.DEVICES" and ResourceType == "IOTHUBS"
    | where Category == "Connections" and OperationName == "deviceConnect"
    | extend DeviceId = tostring(parse_json(properties_s).deviceId)
    | summarize max(TimeGenerated) by DeviceId, _ResourceId
    
  • 特定设备的连接事件:为特定设备 (test-device) 记录的所有连接事件。

    AzureDiagnostics
    | where ResourceProvider == "MICROSOFT.DEVICES" and ResourceType == "IOTHUBS"
    | where Category == "Connections"
    | extend DeviceId = tostring(parse_json(properties_s).deviceId)
    | where DeviceId == "test-device"
    
  • 设备的 SDK 版本:用于设备连接或设备到云孪生操作的设备及其 SDK 版本的列表。

    AzureDiagnostics
    | where ResourceProvider == "MICROSOFT.DEVICES" and ResourceType == "IOTHUBS"
    | where Category == "Connections" or Category == "D2CTwinOperations"
    | extend parsed_json = parse_json(properties_s)
    | extend SDKVersion = tostring(parsed_json.sdkVersion) , DeviceId = tostring(parsed_json.deviceId)
    | distinct DeviceId, SDKVersion, TimeGenerated, _ResourceId
    

从 Azure 事件中心读取日志

通过诊断设置来设置事件日志记录后,可以创建应用程序以读出日志,从而可以根据日志中的信息采取措施。 以下示例代码从事件中心检索日志。

class Program
{ 
    static string connectionString = "{your AMS eventhub endpoint connection string}";
    static string monitoringEndpointName = "{your AMS event hub endpoint name}";
    static EventHubClient eventHubClient;
    //This is the Diagnostic Settings schema
    class AzureMonitorDiagnosticLog
    {
        string time { get; set; }
        string resourceId { get; set; }
        string operationName { get; set; }
        string category { get; set; }
        string level { get; set; }
        string resultType { get; set; }
        string resultDescription { get; set; }
        string durationMs { get; set; }
        string callerIpAddress { get; set; }
        string correlationId { get; set; }
        string identity { get; set; }
        string location { get; set; }
        Dictionary<string, string> properties { get; set; }
    };

    static void Main(string[] args)
    {
        Console.WriteLine("Monitoring. Press Enter key to exit.\n");
        eventHubClient = EventHubClient.CreateFromConnectionString(connectionString, monitoringEndpointName);
        var d2cPartitions = eventHubClient.GetRuntimeInformationAsync().PartitionIds;
        CancellationTokenSource cts = new CancellationTokenSource();
        var tasks = new List<Task>();
        foreach (string partition in d2cPartitions)
        {
            tasks.Add(ReceiveMessagesFromDeviceAsync(partition, cts.Token));
        }
        Console.ReadLine();
        Console.WriteLine("Exiting...");
        cts.Cancel();
        Task.WaitAll(tasks.ToArray());
    }

    private static async Task ReceiveMessagesFromDeviceAsync(string partition, CancellationToken ct)
    {
        var eventHubReceiver = eventHubClient.GetDefaultConsumerGroup().CreateReceiver(partition, DateTime.UtcNow);
        while (true)
        {
            if (ct.IsCancellationRequested)
            {
                await eventHubReceiver.CloseAsync();
                break;
            }
            EventData eventData = await eventHubReceiver.ReceiveAsync(new TimeSpan(0,0,10));
            if (eventData != null)
            {
                string data = Encoding.UTF8.GetString(eventData.GetBytes());
                Console.WriteLine("Message received. Partition: {0} Data: '{1}'", partition, data);
                var deserializer = new JavaScriptSerializer();
                //deserialize json data to azure monitor object
                AzureMonitorDiagnosticLog message = new JavaScriptSerializer().Deserialize<AzureMonitorDiagnosticLog>(result);
            }
        }
    }
}

警报

在监视数据中发现重要情况时,Azure Monitor 警报会主动通知你。 有了警报,你就可以在客户注意到你的系统中的问题之前确定和解决它们。 可以在指标日志活动日志上设置警报。 不同类型的警报各有优缺点。

当你根据平台指标(按计数单位收集)创建警报规则时,某些聚合可能未提供或不可用。 有关详细信息,请参阅 Azure IoT 中心监视数据参考中的支持的聚合

使用事件网格监视每个设备的连接断开问题

Azure Monitor 提供了一个“连接的设备数”指标,你可以使用它来监视连接到你的 IoT 中心的设备数。 当连接的设备数降到阈值以下时,此指标会触发警报。 Azure Monitor 还会发出连接类别中的事件,你可以使用这些事件来监视设备连接、断开连接和连接错误。 尽管在某些情况下,仅使用这些事件就足以达到目的,但 Azure 事件网格还提供了一个低延迟、每设备监视解决方案,可用于跟踪关键设备和基础结构的设备连接。

借助事件网格,可以订阅 IoT 中心 DeviceConnected 和 DeviceDisconnected 事件,以触发警报和监视设备连接状态 。 与 Azure Monitor 相比,事件网格提供的事件延迟要低得多,因此你可以按设备进行监视,而不是监视所有已连接的设备。 这些因素使事件网格成为监视关键设备和基础结构的连接的首选方法。 强烈建议在生产环境中使用事件网格监视设备连接。

有关通过事件网格和 Azure Monitor 监视设备连接的更多信息,请参阅监视、诊断和排查与 Azure IoT 中心的设备连接问题

后续步骤