ApplicationInsights — пользовательские свойства не обновляются между запросами

#c# #azure #asp.net-core #azure-application-insights

#c# #azure #asp.net-core #azure-application-insights

Вопрос:

Я хочу сообщить о некоторых свойствах через Azure-ApplicationInsights для каждого маршрута, как показано на рисунке ниже: введите описание изображения здесь

Проблема в том, что даже если я выполняю второй вызов по тому же маршруту или по другому маршруту, эти значения не меняются. Только при третьем вызове значение изменяется, но даже тогда оно не является текущим. Пример:

  1. Я делаю https://localhost:5001/api/testobject /7 «Собственный пользовательский» = «valoare пользовательский 7«
  2. Я делаю https://localhost:5001/api/testobject /8 «Собственный пользовательский» = «valoare пользовательский 7«
  3. Я делаю https://localhost:5001/api/testobject /9 «Собственный пользовательский» = «valoare пользовательский 8«

Код, лежащий в основе, выглядит следующим образом:

 [Route("api/[controller]")]
[ApiController]
public class TestObjectController
{
    private TelemetryClient telemetryClient;

    public TestObjectController(TelemetryClient telemetryClient)
    {
        this.telemetryClient = telemetryClient;
    }

    // GET api/values/5
    [HttpGet("{id}")]
    public ActionResult<string> Get(int id)
    {
        telemetryClient.Context.Properties.Clear(); 
        telemetryClient.Context.GlobalProperties["TestObjectController"] = "nok";
        telemetryClient.Context.Properties["proprietate custom"] = $"valoare custom {id}";
        return "value";
    }
}
  

Есть идеи, как сохранить его точным?

Ответ №1:

telemetryClient.Context.Properties задает контекст только для экземпляра клиента телеметрии. Это означает, что несколько элементов телеметрии могут быть созданы с предыдущим контекстом, прежде чем новый вступит в силу (если элемент телеметрии создан до обновления контекста).

Похоже, что здесь дело в этом — элемент телеметрии запроса создается в момент вызова метода, и только позже внутри метода клиент обновляется для получения нового контекста.

Я бы предложил использовать TelemetryInitializer вместо обновления контекста на уровне элемента телеметрии, но не клиента телеметрии:

 using System;
using Microsoft.ApplicationInsights.Channel;
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.ApplicationInsights.Extensibility;

namespace MvcWebRole.Telemetry
{
  /*
   * Custom TelemetryInitializer that overrides the default SDK
   * behavior of treating response codes >= 400 as failed requests
   *
   */
  public class MyTelemetryInitializer : ITelemetryInitializer
  {
    public void Initialize(ITelemetry telemetry)
    {
        var requestTelemetry = telemetry as RequestTelemetry;
        // Is this a TrackRequest() ?
        if (requestTelemetry == null) return;
        int code;
        bool parsed = Int32.TryParse(requestTelemetry.ResponseCode, out code);
        if (!parsed) return;
        if (code >= 400 amp;amp; code < 500)
        {
            // If we set the Success property, the SDK won't change it:
            requestTelemetry.Success = true;
            // Allow us to filter these requests in the portal:
            requestTelemetry.Context.Properties["Overridden400s"] = "true";
        }
        // else leave the SDK to set the Success property      
    }
  }
}
  

Затем добавьте этот инициализатор в AI либо через ApplicationInsights.config, либо в коде:

 <ApplicationInsights>
  <TelemetryInitializers>
    <!-- Fully qualified type name, assembly name: -->
    <Add Type="MvcWebRole.Telemetry.MyTelemetryInitializer, MvcWebRole"/>
    ...
  </TelemetryInitializers>
</ApplicationInsights>

protected void Application_Start()
{
    // ...
    TelemetryConfiguration.Active.TelemetryInitializers
    .Add(new MyTelemetryInitializer());
}
  

Ответ №2:

@[Дмитрий Матвеев] спасибо, но ваше предложение частично работает, но мне было больше интересно добавить определенную информацию из содержимого запроса (например, имя клиента). Для этого я закончил с добавлением информации в HttpContext.Элементы, а затем получить к ним доступ через ‘MyTelemetryInitializer’, как описано в этой ссылке: https://github.com/Microsoft/ApplicationInsights-aspnetcore/wiki/Custom-Configuration#track-custom-traceeventmetric

Код, добавляющий информацию к маршруту:

     [HttpGet("{id}/details")]
    public ActionResult<string> GetDetails(int id)
    {
        HttpContext.Items.Add("custom property2", id);
        return "value";
    }
  

Часть метода инициализации MyTelemetryInitializer:

     foreach (var prop in httpContextAccessor.HttpContext.Items)
    {
        if (prop.Key is string)
            requestTelemetry.Context.GlobalProperties[prop.Key.ToString()] = prop.Value.ToString();
    }