TelemetryProcessor - несколько экземпляров перезаписывают пользовательские свойства - PullRequest
0 голосов
/ 09 апреля 2019

У меня есть очень простой API, запускаемый через http-POST, который создает TelemetryClient. Мне нужно было предоставить пользовательское свойство в этой телеметрии для каждого отдельного запроса, поэтому я реализовал TelemtryProcessor .

Однако, когда последующие запросы POST обрабатываются и создается новый TelemetryClient, который, кажется, мешает первому запросу. В итоге я вижу около дюжины или около того записей в App Insights, содержащих первый customPropertyId и близких к 500 для второго, когда на самом деле число должно делиться равномерно. Кажется, что создание второго Клиента телеметрии как-то мешает первому.

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

ApiController, который обрабатывает запрос POST:

public class TestApiController : ApiController
{
    public HttpResponseMessage Post([FromBody]RequestInput request)
    {
        try
        {
            Task.Run(() => ProcessRequest(request));
            return Request.CreateResponse(HttpStatusCode.OK);
        }
        catch (Exception)
        {
            return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, Constants.GenericErrorMessage);
        }
    }

    private async void ProcessRequest(RequestInput request)
    {
        string customPropertyId = request.customPropertyId;

        //trace handler creates the TelemetryClient for custom property
        CustomTelemetryProcessor handler = new CustomTelemetryProcessor(customPropertyId);

        //etc.....
    }
}

CustomTelemetryProcessor, который создает TelemetryClient:

public class CustomTelemetryProcessor
{
    private readonly string _customPropertyId;
    private readonly TelemetryClient _telemetryClient;

    public CustomTelemetryProcessor(string customPropertyId)
    {
        _customPropertyId = customPropertyId;

        var builder = TelemetryConfiguration.Active.TelemetryProcessorChainBuilder;
        builder.Use((next) => new TelemetryProcessor(next, _customPropertyId));

        builder.Build();

        _telemetryClient = new TelemetryClient();
    }
}

TelemetryProcessor:

public class TelemetryProcessor : ITelemetryProcessor
{
    private string CustomPropertyId { get; }
    private ITelemetryProcessor Next { get; set; }

    // Link processors to each other in a chain.
    public TelemetryProcessor(ITelemetryProcessor next, string customPropertyId)
    {
        CustomPropertyId = customPropertyId;
        Next = next;
    }
    public void Process(ITelemetry item)
    {
        if (!item.Context.Properties.ContainsKey("CustomPropertyId"))
        {
            item.Context.Properties.Add("CustomPropertyId", CustomPropertyId);
        }
        else
        {
            item.Context.Properties["CustomPropertyId"] = CustomPropertyId;
        }

        Next.Process(item);
    }
}

1 Ответ

1 голос
/ 09 апреля 2019

Лучше избегать создания клиента телеметрии для каждого запроса, вместо повторного использования одного экземпляра статического клиента телеметрии. Телеметрические процессоры и / или инициализаторы телеметрии также обычно должны регистрироваться только один раз для телеметрического конвейера, а не для каждого запроса. TelemetryConfiguration.Active является статическим, и при добавлении нового процессора с каждым запросом очередь процессора только увеличивается.

Соответствующей настройкой будет добавление Инициализатора телеметрии (Телеметрические процессоры обычно используются для фильтрации и Инициализаторы для обогащения данных) один раз в телеметрический конвейер, например, хотя добавление записи в файл ApplicationInsights.config (если есть) или через код в TelemetryConfiguration.Active где-то в global.asax, например, Application_Start

TelemetryConfiguration.Active.TelemetryInitializers.Add(new MyTelemetryInitializer());

Инициализаторы выполняются в том же контексте / потоке, где был вызван Track..(..) / была создана телеметрия, поэтому они будут иметь доступ к локальному хранилищу потока или локальным объектам для чтения параметров / значений.

...