Как использовать пользовательский OperationId без утечек памяти и игнорирования его в Application Insights?


Мой вопрос:

Как правильно / лучше ввести пользовательский идентификатор корреляции / операции в мой сценарий, который не приводит к утечкам памяти и правильно используется и отображается на портале Azure?

И вот конкретные детали моего сценария:

У меня есть рабочая роль Azure, которая постоянно удаляет сообщения из очереди Azure и выполняет обработку. Сообщение содержит идентификатор корреляции (Operation Id) и имя операции, которое я хочу использовать для всей телеметрии, собранной и переданной через Application Insights во время обработки этого сообщения.

В настоящее время это реализуется через пользовательский ITelemetryInitializer, который выглядит примерно так:

public class MiTelemetryInitialiser : ITelemetryInitializer
{
    private readonly ILoggingContext _context;

    public MiTelemetryInitialiser(ILoggingContext context)
    {
        _context = context;
    }

    public void Initialize(ITelemetry telemetry)
    {
        if (string.IsNullOrEmpty(telemetry.Context.Operation.Id) && _context != null)
        {
            telemetry.Context.Operation.Id = _context.OperationId;

            if (!String.IsNullOrWhiteSpace(_context.OperationName))
                telemetry.Context.Operation.Name = _context.OperationName;
        }
    }
}

Тогда мой цикл обработки рабочих ролей выглядит примерно так (si:

while(!cancellationToken.IsCancellationRequested) {
    // 1. Get message from the queue
    // 2. Extract operation name and Correlation Id from the message
    TelemetryConfiguration config = TelemetryConfiguration.CreateDefault();

    var loggingContext = //new logging context with operation name and correlation id
    config.TelemetryInitializers.Add(new MiTelemetryInitialiser(loggingContext));
    TelemetryClient telemetryClient = new TelemetryClient(config);        

    // do work

    client.Flush();
}

Я использую это TelemetryChannel:

<TelemetryChannel Type="Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel.ServerTelemetryChannel, Microsoft.AI.ServerTelemetryChannel"/>

Есть два вопроса:

  1. утечка памяти (значительная) - я предполагаю, что из-за способа реализации ServerTelemetryChannel (к сожалению в отличие от большинства .NET SDK - этот канал не является открытым исходным кодом) и из-за плотного цикла?
  2. несмотря на то, что client.TrackRequest() толкает мой пользовательский идентификатор корреляции (проверенный с помощью Fiddler) - Application Insights перезаписывает его на портале Azure и отображает свой собственный идентификатор операции, а не мой. Другая телеметрия во время запроса имеет правильный OperationId, который я установил.

Вот фотография утечки памяти после выполнения цикла в течение ~10 минут (растет до 1 ГБ+ через некоторое время):

Введите описание изображения здесь

2 5

2 ответа:

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

TelemetryConfiguration config = TelemetryConfiguration.CreateDefault();

var loggingContext = //new logging context with operation name and correlation id
config.TelemetryInitializers.Add(new MiTelemetryInitialiser(loggingContext));

while(!cancellationToken.IsCancellationRequested) {
    // 1. Get message from the queue
    // 2. Extract operation name and Correlation Id from the message
    TelemetryClient telemetryClient = new TelemetryClient(config);        

    // do work

    client.Flush();
}

Или просто используйте это:

while(!cancellationToken.IsCancellationRequested) {
    // 1. Get message from the queue
    // 2. Extract operation name and Correlation Id from the message
    TelemetryClient telemetryClient = new TelemetryClient();        

    // do work

    client.Flush();
}

И добавьте инициализатор телеметрии в ApplicationInsigths.config:

<Add Type="Namespace.MiTelemetryInitialiser , AssemblyName" />

Смотрите также мой пост в блоге о том, как добавить инициализатор телеметрии в глобальный синглтон конфигурация:

Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.Active.TelemetryInitializers.Add(new MiTelemetryInitialiser());

Для проблемы идентификатора операции-в последних версиях, в частности для телеметрии запроса, чтобы избежать путаницы между RequestTelemetry.ID и TelemetryContext.Operation.ID (с точки зрения пользовательского интерфейса), мы инициализируем TelemetryContext.Operation.ID и назначаем то же самое RequestTelemetry.ID, как только создается телеметрия запроса. Смотритепример на github . Лучший способ решить эту проблему назначения пользовательского идентификатора операции-принудительно назначить свой идентификатор операции, удалив проверку string.IsNullOrEmpty.