使用 Application Insights .NET SDK 跟踪自定义操作Track custom operations with Application Insights .NET SDK

Azure Application Insights SDK 自动跟踪传入的 HTTP 请求和对依赖服务的调用,比如 HTTP 请求和 SQL 查询。Azure Application Insights SDKs automatically track incoming HTTP requests and calls to dependent services, such as HTTP requests and SQL queries. 通过跟踪和关联请求及依赖项,可了解由微服务组成的应用程序对这些微服务的整体响应能力和可靠性。Tracking and correlation of requests and dependencies give you visibility into the whole application's responsiveness and reliability across all microservices that combine this application.

有一类应用程序模式一般不受支持。There is a class of application patterns that can't be supported generically. 正确监视此类模式需要手动代码检测。Proper monitoring of such patterns requires manual code instrumentation. 本文介绍几种可能需要手动检测的模式,比如自定义队列处理和运行长时间运行的后台任务。This article covers a few patterns that might require manual instrumentation, such as custom queue processing and running long-running background tasks.

本文档将指导用户如何使用 Application Insights SDK 跟踪自定义操作。This document provides guidance on how to track custom operations with the Application Insights SDK. 本文档面向:This documentation is relevant for:

  • 适用于 .NET 的 Application Insights(也称为 Base SDK)版本 2.4+。Application Insights for .NET (also known as Base SDK) version 2.4+.
  • 适用于 Web 应用程序的 Application Insights(运行 ASP.NET)版本 2.4+。Application Insights for web applications (running ASP.NET) version 2.4+.
  • 适用于 ASP.NET Core 的 Application Insights 版本 2.1+。Application Insights for ASP.NET Core version 2.1+.

概述Overview

操作是由应用程序运行的一项逻辑工作。An operation is a logical piece of work run by an application. 它具有名称、开始时间、持续时间、结果和执行上下文(如用户名、属性和结果)。It has a name, start time, duration, result, and a context of execution like user name, properties, and result. 如果操作 A 由操作 B 启动,则操作 B 设置为 A 的父级。一个操作只能有一个父操作,但可以有许多子操作。If operation A was initiated by operation B, then operation B is set as a parent for A. An operation can have only one parent, but it can have many child operations. 有关操作和遥测关联的详细信息,请参阅 Azure Application Insights 遥测关联For more information on operations and telemetry correlation, see Azure Application Insights telemetry correlation.

在 Application Insights.NET SDK 中,操作由抽象类 OperationTelemetry 及其后代 RequestTelemetryDependencyTelemetry 描述。In the Application Insights .NET SDK, the operation is described by the abstract class OperationTelemetry and its descendants RequestTelemetry and DependencyTelemetry.

传入操作跟踪Incoming operations tracking

Application Insights Web SDK 自动收集 ASP.NET 应用程序(在 IIS 管道中运行)和所有 ASP.NET Core 应用程序的 HTTP 请求。The Application Insights web SDK automatically collects HTTP requests for ASP.NET applications that run in an IIS pipeline and all ASP.NET Core applications. 有其他平台和框架的社区支持解决方案。There are community-supported solutions for other platforms and frameworks. 但是,如果应用程序不受任何标准或社区支持解决方案的支持,则可手动进行检测。However, if the application isn't supported by any of the standard or community-supported solutions, you can instrument it manually.

需要自定义跟踪的另一个示例是,从队列接收项目的辅助角色。Another example that requires custom tracking is the worker that receives items from the queue. 对于某些队列,向队列添加消息的调用将作为依赖项进行跟踪。For some queues, the call to add a message to this queue is tracked as a dependency. 但是,不会自动收集描述消息处理的高级操作。However, the high-level operation that describes message processing is not automatically collected.

我们来了解可以跟踪此类操作的方式。Let's see how such operations could be tracked.

大致而言,此任务旨在创建 RequestTelemetry 并设置已知的属性。On a high level, the task is to create RequestTelemetry and set known properties. 在操作完成后,可跟踪遥测数据。After the operation is finished, you track the telemetry. 以下示例演示了此任务。The following example demonstrates this task.

Owin 自托管应用中的 HTTP 请求HTTP request in Owin self-hosted app

在此示例中,跟踪上下文根据 HTTP 关联协议进行传播。In this example, trace context is propagated according to the HTTP Protocol for Correlation. 用户应该会收到此处所述的标头。You should expect to receive headers that are described there.

public class ApplicationInsightsMiddleware : OwinMiddleware
{
    // you may create a new TelemetryConfiguration instance, reuse one you already have
    // or fetch the instance created by Application Insights SDK.
    private readonly TelemetryConfiguration telemetryConfiguration = TelemetryConfiguration.CreateDefault();
    private readonly TelemetryClient telemetryClient = new TelemetryClient(telemetryConfiguration);
    
    public ApplicationInsightsMiddleware(OwinMiddleware next) : base(next) {}

    public override async Task Invoke(IOwinContext context)
    {
        // Let's create and start RequestTelemetry.
        var requestTelemetry = new RequestTelemetry
        {
            Name = $"{context.Request.Method} {context.Request.Uri.GetLeftPart(UriPartial.Path)}"
        };

        // If there is a Request-Id received from the upstream service, set the telemetry context accordingly.
        if (context.Request.Headers.ContainsKey("Request-Id"))
        {
            var requestId = context.Request.Headers.Get("Request-Id");
            // Get the operation ID from the Request-Id (if you follow the HTTP Protocol for Correlation).
            requestTelemetry.Context.Operation.Id = GetOperationId(requestId);
            requestTelemetry.Context.Operation.ParentId = requestId;
        }

        // StartOperation is a helper method that allows correlation of 
        // current operations with nested operations/telemetry
        // and initializes start time and duration on telemetry items.
        var operation = telemetryClient.StartOperation(requestTelemetry);

        // Process the request.
        try
        {
            await Next.Invoke(context);
        }
        catch (Exception e)
        {
            requestTelemetry.Success = false;
            telemetryClient.TrackException(e);
            throw;
        }
        finally
        {
            // Update status code and success as appropriate.
            if (context.Response != null)
            {
                requestTelemetry.ResponseCode = context.Response.StatusCode.ToString();
                requestTelemetry.Success = context.Response.StatusCode >= 200 && context.Response.StatusCode <= 299;
            }
            else
            {
                requestTelemetry.Success = false;
            }

            // Now it's time to stop the operation (and track telemetry).
            telemetryClient.StopOperation(operation);
        }
    }
    
    public static string GetOperationId(string id)
    {
        // Returns the root ID from the '|' to the first '.' if any.
        int rootEnd = id.IndexOf('.');
        if (rootEnd < 0)
            rootEnd = id.Length;

        int rootStart = id[0] == '|' ? 1 : 0;
        return id.Substring(rootStart, rootEnd - rootStart);
    }
}

HTTP 关联协议还声明 Correlation-Context 标头。The HTTP Protocol for Correlation also declares the Correlation-Context header. 但为了简单起见,此处省略了该标头。However, it's omitted here for simplicity.

队列检测Queue instrumentation

虽然可以根据 W3C 跟踪上下文HTTP 关联协议使用 HTTP 请求传递关联详细信息,但每个队列协议必须定义如何随队列消息传递相同的详细信息。While there are W3C Trace Context and HTTP Protocol for Correlation to pass correlation details with HTTP request, every queue protocol has to define how the same details are passed along the queue message. 某些队列协议(如 AMQP)允许传递附加元数据,而另一些队列协议(如 Azure 存储队列)需要将上下文编码为消息有效负载。Some queue protocols (such as AMQP) allow passing additional metadata and some others (such Azure Storage Queue) require the context to be encoded into the message payload.

备注

  • 使用 HTTP 的队列尚不支持跨组件跟踪,如果生产者和使用者将遥测发送到不同的 Application Insights 资源,则“事务诊断体验”和“应用程序映射”将显示事务和端到端映射。Cross-component tracing is not supported for queues yet With HTTP, if your producer and consumer send telemetry to different Application Insights resources, Transaction Diagnostics Experience and Application Map show transactions and map end-to-end. 对于队列,尚不支持此项。In case of queues this is not supported yet.

服务总线队列Service Bus Queue

Application Insights 使用新的适用于 .NET 的 Azure 服务总线客户端 3.0.0 及更高版本跟踪服务总线消息传送调用。Application Insights tracks Service Bus Messaging calls with the new Azure ServiceBus Client for .NET version 3.0.0 and higher. 如果使用消息处理程序模式来处理消息,则无需执行其他操作,系统会自动跟踪由服务所完成的所有服务总线调用,并将其与其他遥测项关联。If you use message handler pattern to process messages, you are done: all Service Bus calls done by your service are automatically tracked and correlated with other telemetry items. 如果手动处理消息,请参阅使用 Azure Application Insights 跟踪的 Service Bus 客户端Refer to the Service Bus client tracing with Azure Application Insights if you manually process messages.

如果使用 WindowsAzure.ServiceBus 包,请进一步阅读 - 以下示例演示当服务总线队列使用 AMQP 协议且 Application Insights 不自动跟踪队列操作时,如何跟踪(和关联)对服务总线的调用。If you use WindowsAzure.ServiceBus package, read further - following examples demonstrate how to track (and correlate) calls to the Service Bus as Service Bus queue uses AMQP protocol and Application Insights doesn't automatically track queue operations. 在消息属性中传递关联标识符。Correlation identifiers are passed in the message properties.

排队Enqueue

public async Task Enqueue(string payload)
{
    // StartOperation is a helper method that initializes the telemetry item
    // and allows correlation of this operation with its parent and children.
    var operation = telemetryClient.StartOperation<DependencyTelemetry>("enqueue " + queueName);
    
    operation.Telemetry.Type = "Azure Service Bus";
    operation.Telemetry.Data = "Enqueue " + queueName;

    var message = new BrokeredMessage(payload);
    // Service Bus queue allows the property bag to pass along with the message.
    // We will use them to pass our correlation identifiers (and other context)
    // to the consumer.
    message.Properties.Add("ParentId", operation.Telemetry.Id);
    message.Properties.Add("RootId", operation.Telemetry.Context.Operation.Id);

    try
    {
        await queue.SendAsync(message);
        
        // Set operation.Telemetry Success and ResponseCode here.
        operation.Telemetry.Success = true;
    }
    catch (Exception e)
    {
        telemetryClient.TrackException(e);
        // Set operation.Telemetry Success and ResponseCode here.
        operation.Telemetry.Success = false;
        throw;
    }
    finally
    {
        telemetryClient.StopOperation(operation);
    }
}

过程Process

public async Task Process(BrokeredMessage message)
{
    // After the message is taken from the queue, create RequestTelemetry to track its processing.
    // It might also make sense to get the name from the message.
    RequestTelemetry requestTelemetry = new RequestTelemetry { Name = "process " + queueName };

    var rootId = message.Properties["RootId"].ToString();
    var parentId = message.Properties["ParentId"].ToString();
    // Get the operation ID from the Request-Id (if you follow the HTTP Protocol for Correlation).
    requestTelemetry.Context.Operation.Id = rootId;
    requestTelemetry.Context.Operation.ParentId = parentId;

    var operation = telemetryClient.StartOperation(requestTelemetry);

    try
    {
        await ProcessMessage();
    }
    catch (Exception e)
    {
        telemetryClient.TrackException(e);
        throw;
    }
    finally
    {
        // Update status code and success as appropriate.
        telemetryClient.StopOperation(operation);
    }
}

Azure 存储队列Azure Storage queue

以下示例显示如何跟踪 Azure 存储队列操作,并将生成者、使用者和 Azure 存储之间的遥测相关联。The following example shows how to track the Azure Storage queue operations and correlate telemetry between the producer, the consumer, and Azure Storage.

存储队列具有一个 HTTP API。The Storage queue has an HTTP API. 用于 HTTP 请求的 Application Insights Dependency Collector 会跟踪对该队列的所有调用。All calls to the queue are tracked by the Application Insights Dependency Collector for HTTP requests. 它在 ASP.NET 和 ASP.NET Core 应用程序上默认配置。使用其他类型的应用程序时,可参阅控制台应用程序文档It is configured by default on ASP.NET and ASP.NET Core applications, with other kinds of applicaiton, you can refer to console applications documentation

用户可能还想将 Application Insights 操作 ID 与存储请求 ID 相关联。You also might want to correlate the Application Insights operation ID with the Storage request ID. 有关如何设置与获取存储请求客户端和服务器请求 ID 的信息,请参阅对 Azure 存储进行监视、诊断和故障排除For information on how to set and get a Storage request client and a server request ID, see Monitor, diagnose, and troubleshoot Azure Storage.

排队Enqueue

由于存储队列支持 HTTP API,因此 Application Insights 会自动跟踪队列的所有操作。Because Storage queues support the HTTP API, all operations with the queue are automatically tracked by Application Insights. 在多数情况下,此检测已足够。In many cases, this instrumentation should be enough. 但是,为了将使用者跟踪与生成者跟踪相关联,必须传递某些关联上下文,方法类似于 HTTP 关联协议中所执行的操作。However, to correlate traces on the consumer side with producer traces, you must pass some correlation context similarly to how we do it in the HTTP Protocol for Correlation.

此示例演示如何跟踪 Enqueue 操作。This example shows how to track the Enqueue operation. 方法:You can:

  • 关联重试(如果有) :它们都有一个共同的父级,即 Enqueue 操作。Correlate retries (if any): They all have one common parent that's the Enqueue operation. 否则,它们都作为传入请求的子级进行跟踪。Otherwise, they're tracked as children of the incoming request. 如果有多个对队列的逻辑请求,可能很难发现导致重试的调用。If there are multiple logical requests to the queue, it might be difficult to find which call resulted in retries.
  • 关联存储日志(如果需要) :它们与 Application Insights 遥测相关联。Correlate Storage logs (if and when needed): They're correlated with Application Insights telemetry.

Enqueue 操作是某个父操作(例如,传入 HTTP 请求)的子级。The Enqueue operation is the child of a parent operation (for example, an incoming HTTP request). HTTP 依赖项调用是 Enqueue 操作的子级以及传入请求的孙级:The HTTP dependency call is the child of the Enqueue operation and the grandchild of the incoming request:

public async Task Enqueue(CloudQueue queue, string message)
{
    var operation = telemetryClient.StartOperation<DependencyTelemetry>("enqueue " + queue.Name);
    operation.Telemetry.Type = "Azure queue";
    operation.Telemetry.Data = "Enqueue " + queue.Name;

    // MessagePayload represents your custom message and also serializes correlation identifiers into payload.
    // For example, if you choose to pass payload serialized to JSON, it might look like
    // {'RootId' : 'some-id', 'ParentId' : '|some-id.1.2.3.', 'message' : 'your message to process'}
    var jsonPayload = JsonConvert.SerializeObject(new MessagePayload
    {
        RootId = operation.Telemetry.Context.Operation.Id,
        ParentId = operation.Telemetry.Id,
        Payload = message
    });
    
    CloudQueueMessage queueMessage = new CloudQueueMessage(jsonPayload);

    // Add operation.Telemetry.Id to the OperationContext to correlate Storage logs and Application Insights telemetry.
    OperationContext context = new OperationContext { ClientRequestID = operation.Telemetry.Id};

    try
    {
        await queue.AddMessageAsync(queueMessage, null, null, new QueueRequestOptions(), context);
    }
    catch (StorageException e)
    {
        operation.Telemetry.Properties.Add("AzureServiceRequestID", e.RequestInformation.ServiceRequestID);
        operation.Telemetry.Success = false;
        operation.Telemetry.ResultCode = e.RequestInformation.HttpStatusCode.ToString();
        telemetryClient.TrackException(e);
    }
    finally
    {
        // Update status code and success as appropriate.
        telemetryClient.StopOperation(operation);
    }
}  

若要减少应用程序报告的遥测数或者由于其他原因不想跟踪 Enqueue 操作,可直接使用 Activity API:To reduce the amount of telemetry your application reports or if you don't want to track the Enqueue operation for other reasons, use the Activity API directly:

  • 创建(并启动)新的 Activity,而不是启动 Application Insights 操作。Create (and start) a new Activity instead of starting the Application Insights operation. 需在其上分配除操作名称以外的任何属性。You do not need to assign any properties on it except the operation name.
  • yourActivity.Id 串行化到消息有效负载,而不是 operation.Telemetry.IdSerialize yourActivity.Id into the message payload instead of operation.Telemetry.Id. 还可以使用 Activity.Current.IdYou can also use Activity.Current.Id.

取消排队Dequeue

Enqueue 类似,Application Insights 自动跟踪对存储队列的实际 HTTP 请求。Similarly to Enqueue, an actual HTTP request to the Storage queue is automatically tracked by Application Insights. 但是,Enqueue 操作可能发生在父上下文中,例如传入请求上下文。However, the Enqueue operation presumably happens in the parent context, such as an incoming request context. Application Insights SDK 自动将此类操作(及其 HTTP 部分)与父请求和同一范围内报告的其他遥测相关联。Application Insights SDKs automatically correlate such an operation (and its HTTP part) with the parent request and other telemetry reported in the same scope.

Dequeue 操作比较棘手。The Dequeue operation is tricky. Application Insights SDK 自动跟踪 HTTP 请求。The Application Insights SDK automatically tracks HTTP requests. 但是,在分析消息之前,它并不知道关联上下文。However, it doesn't know the correlation context until the message is parsed. 不可能将获取消息的 HTTP 请求与遥测的其余部分相关联,特别是当收到多个消息时。It's not possible to correlate the HTTP request to get the message with the rest of the telemetry especially when more than one message is received.

public async Task<MessagePayload> Dequeue(CloudQueue queue)
{
    var operation = telemetryClient.StartOperation<DependencyTelemetry>("dequeue " + queue.Name);
    operation.Telemetry.Type = "Azure queue";
    operation.Telemetry.Data = "Dequeue " + queue.Name;
    
    try
    {
        var message = await queue.GetMessageAsync();
    }
    catch (StorageException e)
    {
        operation.telemetry.Properties.Add("AzureServiceRequestID", e.RequestInformation.ServiceRequestID);
        operation.telemetry.Success = false;
        operation.telemetry.ResultCode = e.RequestInformation.HttpStatusCode.ToString();
        telemetryClient.TrackException(e);
    }
    finally
    {
        // Update status code and success as appropriate.
        telemetryClient.StopOperation(operation);
    }

    return null;
}

过程Process

在以下示例中,通过类似于跟踪传入 HTTP 请求的方式跟踪传入消息:In the following example, an incoming message is tracked in a manner similarly to incoming HTTP request:

public async Task Process(MessagePayload message)
{
    // After the message is dequeued from the queue, create RequestTelemetry to track its processing.
    RequestTelemetry requestTelemetry = new RequestTelemetry { Name = "process " + queueName };
    
    // It might also make sense to get the name from the message.
    requestTelemetry.Context.Operation.Id = message.RootId;
    requestTelemetry.Context.Operation.ParentId = message.ParentId;

    var operation = telemetryClient.StartOperation(requestTelemetry);

    try
    {
        await ProcessMessage();
    }
    catch (Exception e)
    {
        telemetryClient.TrackException(e);
        throw;
    }
    finally
    {
        // Update status code and success as appropriate.
        telemetryClient.StopOperation(operation);
    }
}

同样,可以检测其他队列操作。Similarly, other queue operations can be instrumented. 应该以类似于取消排队操作的方式检测速览操作。A peek operation should be instrumented in a similar way as a dequeue operation. 不必检测队列管理操作。Instrumenting queue management operations isn't necessary. Application Insights 会跟踪 HTTP 之类的操作,在大多数情况下,这就足够了。Application Insights tracks operations such as HTTP, and in most cases, it's enough.

检测消息删除时,请务必设置操作(关联)标识符。When you instrument message deletion, make sure you set the operation (correlation) identifiers. 或者,可以使用 Activity API。Alternatively, you can use the Activity API. 这样就无需在遥测项目上设置操作标识符,因为 Application Insights SDK 会为用户完成:Then you don't need to set operation identifiers on the telemetry items because Application Insights SDK does it for you:

  • 从队列中获取项目后,创建新的 ActivityCreate a new Activity after you've got an item from the queue.
  • 使用 Activity.SetParentId(message.ParentId) 关联使用者日志和生产者日志。Use Activity.SetParentId(message.ParentId) to correlate consumer and producer logs.
  • 启动 ActivityStart the Activity.
  • 使用 Start/StopOperation 帮助程序跟踪取消排队、处理和删除操作。Track dequeue, process, and delete operations by using Start/StopOperation helpers. 从同一个异步控制流(执行上下文)执行。Do it from the same asynchronous control flow (execution context). 这样,它们就能正确关联。In this way, they're correlated properly.
  • 停止 ActivityStop the Activity.
  • 使用 Start/StopOperation 或手动调用 Track 遥测。Use Start/StopOperation, or call Track telemetry manually.

依赖项类型Dependency Types

Application Insights 使用依赖项类型来自定义 UI 体验。Application Insights uses dependency type to cusomize UI experiences. 对于队列,它识别出以下可改善事务诊断体验DependencyTelemetry 类型:For queues it recognizes following types of DependencyTelemetry that improve Transaction diagnostics experience:

  • Azure queue 适用于 Azure 存储队列Azure queue for Azure Storage Queues
  • Azure Event Hubs 适用于 Azure 事件中心Azure Event Hubs for Azure Event Hubs
  • Azure Service Bus 适用于 Azure 服务总线Azure Service Bus for Azure Service Bus

批处理Batch processing

有些队列允许对一个请求的多条消息取消排队。With some queues, you can dequeue multiple messages with one request. 这类消息的处理可能彼此独立,而且属于不同的逻辑操作。Processing such messages is presumably independent and belongs to the different logical operations. 无法将 Dequeue 操作与正在处理的特定消息相关联。It's not possible to correlate the Dequeue operation to a particular message being processed.

每条消息都应在自己的异步控制流中处理。Each message should be processed in its own asynchronous control flow. 有关详细信息,请参阅传出依赖项跟踪部分。For more information, see the Outgoing dependencies tracking section.

长时间运行后台任务Long-running background tasks

某些应用程序可能因用户请求而启动长时间运行的操作。Some applications start long-running operations that might be caused by user requests. 从跟踪/检测的角度来看,它与请求或依赖项检测没有区别:From the tracing/instrumentation perspective, it's not different from request or dependency instrumentation:

async Task BackgroundTask()
{
    var operation = telemetryClient.StartOperation<DependencyTelemetry>(taskName);
    operation.Telemetry.Type = "Background";
    try
    {
        int progress = 0;
        while (progress < 100)
        {
            // Process the task.
            telemetryClient.TrackTrace($"done {progress++}%");
        }
        // Update status code and success as appropriate.
    }
    catch (Exception e)
    {
        telemetryClient.TrackException(e);
        // Update status code and success as appropriate.
        throw;
    }
    finally
    {
        telemetryClient.StopOperation(operation);
    }
}

在此示例中,telemetryClient.StartOperation 创建 DependencyTelemetry 并填充相关上下文。In this example, telemetryClient.StartOperation creates DependencyTelemetry and fills the correlation context. 假设有一个父操作,它是由计划操作的传入请求创建的。Let's say you have a parent operation that was created by incoming requests that scheduled the operation. 只要在与传入请求相同的异步控制流中启动 BackgroundTask,它就会与该父操作相关联。As long as BackgroundTask starts in the same asynchronous control flow as an incoming request, it's correlated with that parent operation. BackgroundTask 和所有嵌套的遥测项自动与引发此项的请求相关联,即使请求结束也一样。BackgroundTask and all nested telemetry items are automatically correlated with the request that caused it, even after the request ends.

从不含与之关联的任何操作 (Activity) 的后台线程启动任务时,BackgroundTask 没有任何父级。When the task starts from the background thread that doesn't have any operation (Activity) associated with it, BackgroundTask doesn't have any parent. 但是,它可以具有嵌套操作。However, it can have nested operations. 从任务报告的所有遥测项与 BackgroundTask 中创建的 DependencyTelemetry 相关联。All telemetry items reported from the task are correlated to the DependencyTelemetry created in BackgroundTask.

传出依赖项跟踪Outgoing dependencies tracking

用户可以跟踪自己的依赖项类型或不受 Application Insights 支持的操作。You can track your own dependency kind or an operation that's not supported by Application Insights.

服务总线队列或 Azure 存储队列中的 Enqueue 方法可作为此类自定义跟踪的示例。The Enqueue method in the Service Bus queue or the Storage queue can serve as examples for such custom tracking.

自定义依赖项跟踪的常规方法是:The general approach for custom dependency tracking is to:

  • 调用 TelemetryClient.StartOperation(扩展)方法,该方法填充关联所需的 DependencyTelemetry 属性和某些其他属性(开始时间戳、持续时间)。Call the TelemetryClient.StartOperation (extension) method that fills the DependencyTelemetry properties that are needed for correlation and some other properties (start time stamp, duration).
  • DependencyTelemetry 上设置其他自定义属性,比如名称和所需的任何其他上下文。Set other custom properties on the DependencyTelemetry, such as the name and any other context you need.
  • 进行依赖项调用,并等它完成。Make a dependency call and wait for it.
  • 完成后,使用 StopOperation 停止操作。Stop the operation with StopOperation when it's finished.
  • 处理异常。Handle exceptions.
public async Task RunMyTaskAsync()
{
    using (var operation = telemetryClient.StartOperation<DependencyTelemetry>("task 1"))
    {
        try 
        {
            var myTask = await StartMyTaskAsync();
            // Update status code and success as appropriate.
        }
        catch(...) 
        {
            // Update status code and success as appropriate.
        }
    }
}

释放操作会导致操作停止,因此你可以执行此操作而不用调用 StopOperationDisposing operation causes operation to be stopped, so you may do it instead of calling StopOperation.

警告:在某些情况下,未处理的异常可能会阻止调用 finally,因此无法跟踪操作。Warning: in some cases unhanded exception may prevent finally to be called so operations may not be tracked.

并行处理和跟踪操作Parallel operations processing and tracking

StopOperation 仅停止已启动的操作。StopOperation only stops the operation that was started. 如果当前运行的操作与要停止的操作不匹配,StopOperation 不执行任何操作。If the current running operation doesn't match the one you want to stop, StopOperation does nothing. 如果在同一执行上下文中并行启动多个操作,则可能发生这种情况:This situation might happen if you start multiple operations in parallel in the same execution context:

var firstOperation = telemetryClient.StartOperation<DependencyTelemetry>("task 1");
var firstTask = RunMyTaskAsync();

var secondOperation = telemetryClient.StartOperation<DependencyTelemetry>("task 2");
var secondTask = RunMyTaskAsync();

await firstTask;

// FAILURE!!! This will do nothing and will not report telemetry for the first operation
// as currently secondOperation is active.
telemetryClient.StopOperation(firstOperation); 

await secondTask;

请确保始终在同一异步方法中调用 StartOperation 和处理操作,以隔离并行运行的操作。Make sure you always call StartOperation and process operation in the same async method to isolate operations running in parallel. 如果操作是同步的(或非异步的),请包装过程并使用 Task.Run 跟踪:If operation is synchronous (or not async), wrap process and track with Task.Run:

public void RunMyTask(string name)
{
    using (var operation = telemetryClient.StartOperation<DependencyTelemetry>(name))
    {
        Process();
        // Update status code and success as appropriate.
    }
}

public async Task RunAllTasks()
{
    var task1 = Task.Run(() => RunMyTask("task 1"));
    var task2 = Task.Run(() => RunMyTask("task 2"));
    
    await Task.WhenAll(task1, task2);
}

ApplicationInsights 操作与 System.Diagnostics.ActivityApplicationInsights operations vs System.Diagnostics.Activity

System.Diagnostics.Activity 表示分布式跟踪上下文,可供框架和库用于在进程内外创建和传播上下文,并关联遥测项。System.Diagnostics.Activity represents the distributed tracing context and is used by frameworks and libraries to create and propagate context inside and outside of the process and correlate telemetry items. 活动与 System.Diagnostics.DiagnosticSource 配合使用,后者是框架/库之间的通知机制,用于通知有趣的事件(传入或传出请求、异常等)。Activity works together with System.Diagnostics.DiagnosticSource - the notification mechanism between the framework/library to notify about interesting events (incoming or outgoing requests, exceptions, etc).

活动是 Application Insights 中的“一类公民”,自动依赖项和请求集合特别依赖它们和 DiagnosticSource 事件。Activities are first-class citizens in Application Insights and automatic dependency and request collection relies heavily on them along with DiagnosticSource events. 如果在应用程序中创建活动,则不会创建 Application Insights 遥测。If you create Activity in your application - it would not result in Application Insights telemetry being created. Application Insights 需要接收 DiagnosticSource 事件并了解事件名称和有效负载,然后才能将活动转换为遥测。Application Insights needs to receive DiagnosticSource events and know the events names and payloads to translate Activity into telemetry.

每项 Application Insights 操作(请求或依赖)都涉及 Activity - 调用 StartOperation 时,它会在下面创建活动。Each Application Insights operation (request or dependency) involves Activity - when StartOperation is called, it creates Activity underneath. StartOperation 是建议的方法,用于手动跟踪请求或依赖项遥测,并确保一切都已关联。StartOperation is the recommended way to track request or dependency telemetries manually and ensure everything is correlated.

后续步骤Next steps