#c# #azure #asp.net-core #azure-application-insights
#c# #azure #asp.net-core #azure-application-insights
Вопрос:
Я хочу сообщить о некоторых свойствах через Azure-ApplicationInsights для каждого маршрута, как показано на рисунке ниже:
Проблема в том, что даже если я выполняю второй вызов по тому же маршруту или по другому маршруту, эти значения не меняются. Только при третьем вызове значение изменяется, но даже тогда оно не является текущим. Пример:
- Я делаю https://localhost:5001/api/testobject /7 «Собственный пользовательский» = «valoare пользовательский 7«
- Я делаю https://localhost:5001/api/testobject /8 «Собственный пользовательский» = «valoare пользовательский 7«
- Я делаю 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();
}