Вот метод, который создает действие, заполняет его случайными данными, а затем удаляет действие с помощью конструкции using. (Не ищите в этом особого смысла. Я только учусь этим пользоваться.)
Внизу вы можете видеть, что я измеряю, сколько времени требуется на завершение использования блока. Между sw.Start и sw.Stop НЕТ моего кода, просто выход из блока using.
Я вижу, что когда целевая конечная точка недоступна, для завершения удаления действия требуется около 4000 мс. Я не хочу, чтобы экспорт телеметрии снижал производительность моего приложения. Как я могу изолировать свое приложение от влияния экспорта телеметрии в неблагоприятном сценарии, когда целевая конечная точка не отвечает должным образом?
private static void OnePass(int Counter)
{
Stopwatch sw = new Stopwatch();
using (var actv = m_activitySource.StartActivity("OnePass"))
{
actv.AddEvent(new ActivityEvent("Start OnePass()"));
actv.SetTag("counter", Counter);
actv.SetTag("markstart", DateTime.Now.ToString());
actv.AddEvent(new ActivityEvent("Finisehd OnePass()"));
actv.SetTag("markfinish", DateTime.Now.ToString());
actv.SetStatus(Status.Ok);
sw.Start();
}
sw.Stop();
Console.WriteLine("");
Console.WriteLine("Elapsed Milliseconds: " + sw.ElapsedMilliseconds);
Console.WriteLine("--------------------------------------------------------");
Console.WriteLine("");
}
Обновлено: Вот подробности целевого сборщика телеметрии: Мы протестировали этот код на двух конечных точках, используя http/Protobuf. Первая конечная точка — это тривиальный веб-сервис, который я написал сам, чтобы просто перехватывать тело сообщения и записывать его в файл журнала. Это просто подтверждает, что клиент правильно экспортирует телеметрию. Вторая цель — сборщик открытой телеметрии Azure. В обоих случаях наблюдается одинаковое поведение. Если целевая конечная точка недоступна, мое приложение блокируется на несколько секунд при каждом экспорте трассировки (действия). Насколько я понимаю, архитектура OTel спроектирована таким образом, чтобы экспорт телеметрии был неблокирующей операцией. Это может либо добиться быстрого успеха, либо добиться успеха медленно, либо полностью потерпеть неудачу, но это ни в коем случае не замедлит выполнение приложения, экспортирующего телеметрию. Разве это не так? Создает ли внедрение телеметрии новое узкое место/точку сбоя в обработке моего приложения?
Обновлено: Вот код, который настраивает поставщика трассировки:
internal static TracerProvider GetTracerProvider(string service, string version, bool consoleExporter, bool OtlpExporter)
{
TracerProviderBuilder tpb = Sdk.CreateTracerProviderBuilder()
.AddSource(service)
.SetResourceBuilder(
ResourceBuilder.CreateDefault()
.AddService(serviceName: service, serviceVersion: version));
if (consoleExporter)
{
tpb.AddConsoleExporter();
}
if (OtlpExporter)
{
tpb.AddOtlpExporter
(exp =>
{
exp.Endpoint = new Uri((AppConfig.GetAppSetting("OTEL_EXPORTER_OTLP_ENDPOINT_BASE").TrimEnd('/')
+ "/"
+ AppConfig.GetAppSetting("OTEL_EXPORTER_OTLP_ENDPOINT_TRACES").TrimStart('/')).TrimEnd('/'));
exp.Protocol = (OtlpExportProtocol) Convert.ToInt16(AppConfig.GetAppSetting("OTEL_EXPORTER_OTLP_PROTOCOL", "1"));
exp.ExportProcessorType = (ExportProcessorType) Convert.ToInt16(AppConfig.GetAppSetting("OTEL_EXPORTER_OTLP_EXPORT_TYPE", "0"));
exp.BatchExportProcessorOptions = new BatchExportProcessorOptions<Activity>()
{
MaxQueueSize = Convert.ToInt16(AppConfig.GetAppSetting("OTEL_EXPORTER_OTLP_MAX_QUEUE", "2048")),
ScheduledDelayMilliseconds = Convert.ToInt16(AppConfig.GetAppSetting("OTEL_EXPORTER_OTLP_SCHED_DELAY", "5000")),
ExporterTimeoutMilliseconds = Convert.ToInt16(AppConfig.GetAppSetting("OTEL_EXPORTER_OTLP_TIMEOUT", "1000")),
MaxExportBatchSize = Convert.ToInt16(AppConfig.GetAppSetting("OTEL_EXPORTER_OTLP_MAX_BATCH", "512")),
};
});
}
return tpb.Build();
}
Вот соответствующие параметры конфигурации:
<!-- OTEL Configuration -->
<add key = "ExportTelemetry" value = "0"/>
<add key = "OTEL_EXPORTER_OTLP_ENDPOINT_BASE" value = "http://localhost:58234/Telemetry" />
<add key = "OTEL_EXPORTER_OTLP_ENDPOINT_METRICS" value = "v1/metrics" />
<add key = "OTEL_EXPORTER_OTLP_ENDPOINT_TRACES" value = "v1/traces" />
<add key = "OTEL_EXPORTER_OTLP_ENDPOINT_LOGS" value = "v1/logs" />
<add key = "OTEL_EXPORTER_OTLP_HEADERS" value = "" />
<add key = "OTEL_EXPORTER_OTLP_TIMEOUT" value = "300" />
<add key = "OTEL_EXPORTER_OTLP_MAX_QUEUE" value = "2048" />
<add key = "OTEL_EXPORTER_OTLP_SCHED_DELAY" value = "5000" />
<add key = "OTEL_EXPORTER_OTLP_MAX_BATCH" value = "512" />
<!-- Grpc = 0, Http/Protobuf = 1 -->
<add key = "OTEL_EXPORTER_OTLP_PROTOCOL" value = "1" />
<!-- Simple = 0, Batch = 1 -->
<add key = "OTEL_EXPORTER_OTLP_EXPORT_TYPE" value = "0" />
Имейте в виду, что OpenTelemetry использует размещенную службу для асинхронной обработки и отправки данных телеметрии, которые она получает из приложения, поэтому то, что вы видите здесь, не должно происходить, насколько мне известно. Но опять же, это будет зависеть от того, как именно вы интегрируетесь с OTEL и о каком типе приложения мы здесь говорим (веб-API, сервис, инструмент cmdline и т. д.).
@julealgon Я отредактировал вопрос, включив в него подробную информацию о целевой конечной точке. Если потребуется более подробная информация, буду рад предоставить.
@julealgon Я также добавил код, который настраивает поставщика трассировки. Дайте мне знать, если есть какие-либо дополнительные подробности, имеющие отношение к вопросу.
Хорошо, у вас много всего... Мое первое первоначальное предложение — сократить ваш случай, чтобы попытаться определить, какая часть вызывает поведение, которое вы видите. Например, хорошим началом было бы удаление вашего пользовательского экспортера, а также консольного экспортера. Я также вижу, что вы используете значение 0 (Simple) для OTEL_EXPORTER_OTLP_EXPORT_TYPE , тогда как фактическое значение по умолчанию равно 1 (Пакет) . Изменить это и посмотреть, изменит ли это ваше поведение, — это еще одно испытание.
Не могли бы вы также поделиться версиями каждого из пакетов OTEL, которые вы используете? Рассматривали ли вы возможность использовать абстракции OpenTelemetry.Extensions.Hosting вместо того, чтобы вручную обрабатывать TraceProvider с помощью необработанного SDK? OpenTelemetry.Extensions.Hosting должен привести к более простой (и менее подверженной ошибкам) настройке, поэтому я настоятельно рекомендую это.
@julealgon Вау! Переход от простого к пакетному процессу изменил мир к лучшему. Прототип теперь работает без снижения производительности, даже если целевая конечная точка не работает. Я проведу еще несколько испытаний на своем прототипе, а затем еще несколько испытаний на производстве. Я подтвержу позже. Это может быть решением!
Рад видеть, что это имело существенное значение! Дайте мне знать, чтобы я мог добавить его в качестве ответа, как только вы подтвердите, что он работает должным образом.
@julealgon Я могу подтвердить, что переключение на OTEL_EXPORTER_OTLP_EXPORT_TYPE = 1 (Batch) — это именно то, что нам нужно, чтобы изолировать уровень приложения от коллектора. Сегодня мы отключили коллектор на два часа и не заметили никаких негативных последствий для приложения. Если вы опубликуете это в качестве ответа, я приму это к вашей чести. Спасибо!





Проблема, которую вы видите, связана с тем, как работает тип экспорта Simple (значение 0): он немедленно и синхронно попытается опубликовать телеметрию, как только она будет отправлена прослушивателем при удалении Activity. Я заметил, что вы использовали режим Simple в своих настройках, но также заметил , что это не режим по умолчанию: на самом деле по умолчанию используется пакетный режим , который имеет значение 1.
Пакетный режим будет управлять очередью, которая время от времени очищается в фоновом режиме (настраивается), поэтому она становится асинхронным процессом, отделенным от выполнения вашего кода.
В качестве общего предложения для OTEL я всегда рекомендую начинать с конфигурации по умолчанию и настраивать только те параметры, которые имеют смысл для вашего конкретного случая использования. Это связано с тем, что существует множество различных настроек, которые могут существенно повлиять на поведение генерации и приема данных. Это может даже повлиять на принимающую платформу наблюдения (у нас самих были проблемы с Datadog при первоначальной интеграции, которая потребовала изменения настроек).
Кстати, для перечисления необычно использовать по умолчанию ненулевой элемент. Интересно, почему они выбрали это?
Вам нужно будет предоставить немного больше контекста, чтобы кто-нибудь мог помочь вам в этом. Как именно вы интегрируете свое приложение с внешним сервером телеметрии? Вы используете OpenTelemetry? Как выглядит код установки? Куда вы экспортируете данные телеметрии?