使用 Azure 云服务托管网站或继续执行数据过程时,建议集成日志系统以收集更详细的信息和日志记录。 Application Insights 旨在实现此目的。 本文档提供了一些常见方案,我们可以从将 Application Insights 与云服务集成中获益。
若要详细了解如何将 Application Insights 与云服务配合使用,请参阅 功能概述。
诊断设置和 Application Insights
在云服务上启用 Application Insights 时,必须同时启用诊断设置。 诊断设置收集的某些指标数据和日志将发送到 Application Insights。 有关详细信息,请参阅为 Azure 云服务设置诊断。
启用诊断设置后, 性能计数器 设置在 Web 角色和辅助角色上的工作方式不同。
对于 Web 角色
以下九个指标具有数据,即使诊断设置中禁用了性能计数器,也会自动收集这些数据。 这九个指标中的数据保存在 Application Insights 的 performanceCounter 表中。 启用性能计数器时,其他指标(例如 \Process(w3wp)\% Processor Time
)将保存在 customMetrics 表上。
\Process(??APP_WIN32_PROC??)\% Processor Time
\Memory\Available Bytes
.NET CLR Exceptions(??APP_CLR_PROC??)# # of Exceps Thrown / sec
\Process(??APP_WIN32_PROC??)\Private Bytes
\Process(??APP_WIN32_PROC??)\IO Data Bytes/sec
\Processor(_Total)% Processor time
\ASP.NET Applications(??APP_W3SVC_PROC??)\Requests/sec
\ASP.NET Applications(??APP_W3SVC_PROC??)\Request Execution Time
\SP.NET Applications(??APP_W3SVC_PROC??)\Requests In Application Queue
对于辅助角色
如果在诊断设置中禁用了性能计数器,则不会自动收集并保存在 Application Insights 中的性能指标数据。
对于 Web 角色和辅助角色
HeartBeatState 指标数据始终自动保存在 Application Insights 中。 此指标用于确定实例在服务器级别是否仍然正常。 它将每隔 15 分钟触发一次,并保存到 customMetrics 表中。 需要在诊断设置的性能计数器中手动启用其他性能指标数据。
重要
仅当收集实际数据时,Application Insights 才会生成记录。 如果 Web 角色从未收到请求,则辅助角色不会从磁盘或磁盘读取或写入数据。 如果数据 IO 量相当低,则 Application Insights 可能会不记录任何信息。
下表显示了诊断设置中的选项与 Application Insights 日志中的表名称之间的映射:
Application Insights 中的表 | 诊断设置中的日志 |
---|---|
traces | 应用程序日志 |
traces | ETW 日志 |
traces | 基础结构日志 |
traces/custom events | Windows 事件日志 |
自定义指标 | 性能计数器 |
将 Application Insights 与云服务配合使用的高级方法
可通过几种常见的高级方法将 Application Insights 与云服务配合使用。 例如,用户可以在云服务项目中使用 Azure 应用程序 Insights SDK 来生成或修改保存到 Application Insights 中的数据。
添加自定义日志
若要将自定义日志添加到应用程序,请执行以下步骤:
右键单击角色项目,然后选择“ 管理 NuGet 包”。
确保已安装 Microsoft.ApplicationInsights。
将 Application Insights 配置添加到 .cscfg 和 .csdef 文件中。
注意
- 对基于检测密钥的全球引入的技术支持将于 2025 年 3 月 31 日结束。 建议使用 连接字符串,而不是在该日期之前连接到 Application Insights。 有关详细信息,请参阅转换到 2025 年 3 月 31 日前使用连接字符串进行数据引入。
- 当 Application Insights 与云服务项目链接时,
APPINSIGHTS_INSTRUMENTATIONKEY
会自动添加。 有关详细信息,请参阅使用 Application Insights 排查云服务应用问题 - 功能概述。
下面是 .csdef 文件的示例:
<ConfigurationSettings> <Setting name="APPLICATIONINSIGHTS_CONNECTION_STRING" /> <Setting name="APPINSIGHTS_INSTRUMENTATIONKEY" /> </ConfigurationSettings>
下面是 .cscfg 文件的示例:
<ConfigurationSettings> <Setting name="APPINSIGHTS_INSTRUMENTATIONKEY" value="{Instrumentation_key}" /> <Setting name="APPLICATIONINSIGHTS_CONNECTION_STRING" value="{Connection_String}" /> </ConfigurationSettings>
可以在 Application Insights 的概述页上找到连接字符串。 有关详细信息,请参阅从 Application Insights 检测密钥迁移到 连接字符串。
在角色的启动函数中添加以下代码。 Web 角色的启动函数位于
Application_Start()
Global.asax 中。 对于辅助角色,它OnStart()
位于WorkerRoleName.cs中。TelemetryConfiguration.Active.ConnectionString = RoleEnvironment.GetConfigurationSettingValue("APPLICATIONINSIGHTS_CONNECTION_STRING");
创建遥测客户端并记录日志上下文:
using Microsoft.ApplicationInsights; TelemetryClient ai = new TelemetryClient(); ai.TrackTrace("The custom log context");
除了跟踪日志,还可以使用以下方法来记录处理的异常:
ai.TrackException(exception);
将正在运行的辅助角色应用程序记录为请求
根据设计,Web 角色的请求会自动在云服务中使用唯一 ID 进行标记,以标识相关性。 在辅助角色中,没有此类系统。 但是,可以将辅助角色应用程序进度的结果模拟为请求,并将此请求记录到 Application Insights 中。 因此,可以简化在辅助角色中检查应用程序的工作状态的方法。 下面是辅助角色应用程序示例。
此辅助角色每隔 30 秒将跟踪日志添加到 Application Insights 中。 但是,不会始终成功添加日志,因为已选择一个更改布尔变量,以使 Run 函数在每个两个循环中返回一个已处理的异常。 记录到 Application Insights 中的跟踪日志将包含时间戳(完全随机 GUID),作为关联 ID 来标识请求记录和其他记录之间的关系。 每个循环都被视为请求,因此它将生成包含开始时间戳、持续时间、成功状态、响应代码(成功 200 和异常为 500)和相关 ID 的请求记录。
生成请求记录时,只需要持续时间和成功状态。 其他信息保存在请求记录中,因为:
启动时间戳和响应代码可以使它成为实际请求,不同的响应代码(例如,400 和 500 个失败请求)可帮助用户确定不同的失败原因。
如果应用程序使用多个线程,则同一时刻可能会有不同线程的跟踪日志、异常和请求记录,这将导致用户无法按时间戳跟踪它们。 通过所有步骤使用的相关 ID 非常重要。 根据文档,请求的 ID 应全局唯一。 为了确保示例完美运行,应添加一个函数来验证 Application Insights 中的任何请求记录是否已使用新生成的随机 GUID(以下示例代码中未实现)。
using Microsoft.WindowsAzure.ServiceRuntime;
using System;
using System.Diagnostics;
using Microsoft.ApplicationInsights; //Import the Application Insight SDK
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.ApplicationInsights.DataContracts;
namespace Worker Role1
{
public class Worker Role : RoleEntryPoint
{
private TelemetryClient ai = new TelemetryClient(); //Define a private TelemetryClient
private bool select = true;
private int a = 0;
private int b;
private volatile bool onStopCalled = false;
private volatile bool returnedFromRunMethod = false;
private Stopwatch requestTimer;
private bool requestResult;
public override void Run()
{
ai.TrackTrace("Worker Role1 is running AI");
var request = new RequestTelemetry(); // Generate a RequestTelemetry. Once it's created, all the changes should be saved into this RequestTelemetry and SDK will save this RequestTelemetry into Application Insight.
while (true)
{
request.Name = "A test request"; //the following three lines configure the Name, Id and StartTime property of the request.
request.Id = Guid.NewGuid().ToString();
request.StartTime = DateTimeOffset.UtcNow;
ai.TrackTrace("New cycle. AI " + DateTimeOffset.UtcNow.ToString() + " " + request.Id);
requestTimer = Stopwatch.StartNew();
try
{
if (onStopCalled == true)
{
ai.TrackTrace("Onstopcalled Worker Role AI");
returnedFromRunMethod = true;
return;
}
if (select == true)
{
select = false;
b = 100 / a;
}
else
{
select = true;
b = 100 / 10;
}
ai.TrackTrace("normal Worker Role AI " + DateTimeOffset.UtcNow.ToString() + " " + request.Id);
requestResult = true;
}
catch (Exception ex) // Pay attention to the way that saves the custom Trace log and Exception. The unique specific ID will be helpful for us to track the request workflow in Application Insight if your application is multi thread.
{
ai.TrackTrace("Exception Worker Role AI " + DateTimeOffset.UtcNow.ToString() + " " + request.Id);
ai.TrackException(ex, new Dictionary<string, string>() { { "id", request.Id } });
requestResult = false;
}
request.Success = requestResult; //The following codes set Success, Duration and ResponseCode property of the request, then save it into Application Insight.
request.Duration = requestTimer.Elapsed;
request.ResponseCode = requestResult ? "200" : "500";
ai.TrackRequest(request);
System.Threading.Thread.Sleep(30*1000);
}
}
public override bool OnStart()
{
TelemetryConfiguration.Active.InstrumentationKey = RoleEnvironment.GetConfigurationSettingValue("APPINSIGHTS_INSTRUMENTATIONKEY");
bool result = base.OnStart();
return result;
}
public override void OnStop()
{
onStopCalled = true;
while (returnedFromRunMethod == false)
{
System.Threading.Thread.Sleep(1000);
}
}
}
}
注意
还可以使用自定义遥测执行相同的操作。 有关详细信息,请参阅 工作角色代码示例。
检查 Web 角色失败的请求和相关异常
对于 Web 角色中的失败请求,未处理的异常和已处理的异常(在 try 函数中) ai.TrackException
会自动收集到异常表中。
若要在 Application Insights 实例中查找异常记录,可以使用以下方法之一:
在Azure 门户中查看“失败”页
- 转到Azure 门户,选择 Application Insights 实例,然后选择“失败”。
- 通过调整时间范围并选择相应的操作,在 “操作 ”选项卡中找到失败的请求。
- 选择操作名称。 具有特定异常类型或响应代码的失败请求将自动列出。
查询Azure 门户中的日志
第二种方法使用 Application Insights 的 Logs 选项。 此方法更为复杂,但它允许使用更多自定义筛选器来查找特定类型的异常。 它还提供了在“失败”页上不会显示的更多详细信息。
根据设计,Web 角色的请求会自动在云服务中使用唯一 ID 进行标记,以标识相关性。 若要查找请求的 ID,请执行以下步骤:
在请求表中找到失败的请求并记录其 ID:
requests | where resultCode == "500"
在异常表中查找具有相同 ID 的异常:
exceptions | where operation_ParentId == "8d1adf11abf73c42"
在排查间歇性故障问题时,基于失败请求跟踪异常非常有用,因为它包含该请求的完整 CallStack。
检查辅助角色失败的请求和相关异常
由于辅助角色的未经处理的异常可能导致整个应用程序出现停机,因此建议处理辅助角色中的所有异常。 这意味着它应包含函数 try
。 对于 Web 角色中处理的异常, ai.TrackException
需要在 Application Insights 中记录异常。
检查辅助角色中的异常的步骤类似于 Web 角色中的异常。 唯一的区别是,没有内置系统自动记录异常,因此需要一些额外的代码来存档目标。
下面是一些可能的情况:
辅助角色不包括用于记录自定义请求的系统。 唯一可用于跟踪异常记录与应用程序中实际操作之间的关系的数据是时间戳。
在这种情况下,仍可以检查“失败”页,但需要切换到“异常”页并手动检查时间戳。 还可以在“日志”页上检查数据的准确性。 下面是用于检查特定时间范围之间的异常的示例查询。
exceptions | where timestamp between (datetime(2022-05-11 00:00) .. datetime(2022-05-13 00:00))
辅助角色包括一个系统,用于记录具有自定义 ID 的自定义请求,但不包括在异常记录中。 这与以前的情况相同。
辅助角色包括一个系统来记录具有自定义 ID 的自定义请求,并且它包含在异常记录中,例如示例中的第 62 行。 将辅助角色应用程序的功能记录为请求的方式将与 Web 角色的情况相同。 可以检查 “失败 ”页或 “日志 ”页来查找相关的请求和异常。 “日志”页中使用的查询将为:
requests | where success == False
exceptions | where * contains "<request ID>"
常见方案和指南
本部分介绍几个常见方案和有关使用 Application Insights 来满足要求的相关准则。
监视 Web 角色的内存和请求状态
若要监视云服务中 Web 角色的内存和请求状态,只需在要从中收集指标数据的角色上启用 Application Insights。 然后,它将自动收集 Web 角色的内存使用情况和请求状态的数据。
若要查看收集的数据,建议使用 Application Insights 的“ 指标”页。 有关详细信息,请参阅 Application Insights 中的系统性能计数器。
与 Web 角色一样,还可以监视辅助角色的内存和请求状态,但存在一些限制:
对于辅助角色,默认情况下不会自动收集内存指标数据。 若要监视内存状态,需要启用
\Memory\Available MBytes
诊断设置的性能计数器。 收集的数据将位于custommetrics
“日志”页的表中。若要查看收集的内存数据的指标图表,请转到 Application Insights 中的“指标”页,在指标命名空间中选择“基于日志的指标”指标,然后在“指标中的性能”下选择“可用内存”。 图表将显示所选时间范围的可用内存。 图表中的虚线表示数据不够准确,无法生成数据,或者在该时间范围内缺少数据。 从日志中,收集内存数据的间隔约为三分钟。 在上图中,由于时间范围设置为“过去一小时”,因此每两个点之间的时间差将小于三分钟,因此收集的数据不够准确。 因此,它是一条虚线。
排查性能问题,例如响应时间缓慢
例如,当云服务 Web 角色收到请求时,它需要从远程服务器(如SQL 数据库)获取某些数据,然后在网页上生成数据并将其返回到用户。 假设这一进展比预期慢得多,但仍成功。 用户希望澄清大部分时间是在与SQL 数据库通信期间还是在云服务内部的进度期间花费的时间是合理的。 为此,用户需要添加一些额外的自定义日志来记录每个步骤的时间戳,例如进度的开始、与SQL 数据库的通信开始、与SQL 数据库的通信结束以及生成网页的结束等。
对于辅助角色和 Web 角色,建议在进程中的每个起始步骤中保存跟踪日志。 例如,在上面的示例代码中,可以在以下时间点添加跟踪日志:
- WebRole 接收请求。
- WebRole 开始与 SQL Server 建立通信。
- WebRole 接收 SQL Server 返回的数据,并开始生成网页。
- WebRole 将生成网页并将其返回到用户。
如果主进程是辅助角色中的应用程序,请将辅助角色应用程序的函数记录为将自定义关联 ID 添加到自定义请求记录和异常记录的请求中。
实现逻辑后,可以在 Application Insights 的“性能”页上检查请求,并关注请求持续时间,如下所示:
- 选择要检查的操作。
- 将持续时间分布图缩放为最长持续时间部分。
- 选择 “钻取示例”。
- 选择请求作为示例,并获取此请求的内置或自定义 ID。
如果系统过于复杂,则不同步骤花费的时间将显示在端到端事务图表中。 如果系统很复杂,或者我们使用的是导致无法在图表中显示数据的自定义 ID,请使用以下查询获取包含相同关联 ID 的所有相关跟踪日志:
traces
| where * contains "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
这样,就可以计算每个跟踪日志之间的差异,以获取每个步骤花费的时间。
排查性能问题,例如高 CPU/辅助角色内存
有时,需要确定工作角色占用非常高 CPU/内存的问题。 从云服务外部观察到的唯一情况是辅助角色消耗过多的 CPU/内存,但你不知道此实例中到底发生了什么。
若要排查此类问题,有两个步骤:
添加自定义日志以跟踪辅助角色应用程序将执行的每个步骤。 这非常重要,因为此步骤使你能够确定应用程序是否仍然运行良好,并将每个步骤中花费的时间与正常情况进行比较。 这有助于确定应用程序是否受到高 CPU/内存问题的影响。 有关如何添加自定义日志系统的信息,请参阅 添加自定义日志。
捕获转储文件。 以下是一些提示:
可以使用远程桌面连接到 CPU/内存过高的实例,并验证哪个进程消耗了大部分 CPU/内存。 如果进程为 WaWorkerHost,则表示应用程序消耗过多的 CPU/内存。
如果实例出现高 CPU/内存问题,并且应用程序遇到低性能但未崩溃,则可以尝试使用远程桌面连接到实例并捕获转储文件。 当 WaWorkerHost 进程使用的 CPU 超过 85% 至少 3 秒时,可以使用 procdumps 捕获转储文件。 将捕获五个转储文件并将其保存到 c:\procdumps
目录中。
procdump.exe -accepteula -c 85 -s 3 -n 5 WaWorkerHost.exe c:\procdumps
在云服务的“诊断设置”页中,还可以设置故障转储文件自动生成。 有关详细信息,请参阅为 Azure 云服务和虚拟机设置诊断。