Симптом
У записи об ошибке консьюмера (BaseConsumer.LogError) в Elastic есть trace.id, но по нему не
находится ничего со стороны публикации: трейс начинается с самого консьюмера, до инициатора по нему
не дойти.
Механизм
ActivityTracingSendFilter.SetActivityHeader:
if (Activity.Current?.Id != null)
context.Headers.Set(Consts.ActivityIdName, Activity.Current.Id);
Заголовок MT-Activity-Id ставится только при наличии ambient Activity. У публикации внутри
ASP.NET-запроса она есть, у фоновой — нет: джоба Quartz или BackgroundService, тик диспетчера
outbox, консольный хост, тест. Заголовка тогда нет, и ActivityTracingConsumeFilter создаёт
new Activity(...) без SetParentId — то есть новый TraceId. Связь публикация → приём теряется
молча: ни варнинга, ни признака в записи.
Почему это мешает
Запись LogError — основное, по чему разбирают падение консьюмера. При разорванном трейсе от неё
остаются только брокерные идентификаторы (MessageId, ConversationId, RetryAttempt), а связать
падение с тем, что и откуда сообщение отправило, нельзя.
Предложение
Не полагаться на ambient Activity: в ActivityTracingSendFilter при Activity.Current == null
стартовать свою Activity на отправку, положить её Id в заголовок и остановить после next.Send.
Тогда у каждой отправки есть трейс, а у консьюмера — родитель.
Отдельным вопросом — нужен ли собственный заголовок MT-Activity-Id: стоит проверить, покрывает ли
это встроенная инструментация MassTransit 8 (она пишет traceparent в заголовки сообщения). Если
покрывает, обёртку правильнее не чинить, а снять — свой заголовок сторонние коллекторы не понимают.
Как проверить
Опубликовать сообщение из BackgroundService без входящего HTTP-запроса и сравнить trace.id у
записи отправителя и у записи консьюмера: сейчас они разные, после правки должны совпадать.
Связанное
Симптом
У записи об ошибке консьюмера (
BaseConsumer.LogError) в Elastic естьtrace.id, но по нему ненаходится ничего со стороны публикации: трейс начинается с самого консьюмера, до инициатора по нему
не дойти.
Механизм
ActivityTracingSendFilter.SetActivityHeader:Заголовок
MT-Activity-Idставится только при наличии ambientActivity. У публикации внутриASP.NET-запроса она есть, у фоновой — нет: джоба Quartz или
BackgroundService, тик диспетчераoutbox, консольный хост, тест. Заголовка тогда нет, и
ActivityTracingConsumeFilterсоздаётnew Activity(...)безSetParentId— то есть новый TraceId. Связь публикация → приём теряетсямолча: ни варнинга, ни признака в записи.
Почему это мешает
Запись
LogError— основное, по чему разбирают падение консьюмера. При разорванном трейсе от неёостаются только брокерные идентификаторы (
MessageId,ConversationId,RetryAttempt), а связатьпадение с тем, что и откуда сообщение отправило, нельзя.
Предложение
Не полагаться на ambient Activity: в
ActivityTracingSendFilterприActivity.Current == nullстартовать свою Activity на отправку, положить её
Idв заголовок и остановить послеnext.Send.Тогда у каждой отправки есть трейс, а у консьюмера — родитель.
Отдельным вопросом — нужен ли собственный заголовок
MT-Activity-Id: стоит проверить, покрывает лиэто встроенная инструментация MassTransit 8 (она пишет
traceparentв заголовки сообщения). Еслипокрывает, обёртку правильнее не чинить, а снять — свой заголовок сторонние коллекторы не понимают.
Как проверить
Опубликовать сообщение из
BackgroundServiceбез входящего HTTP-запроса и сравнитьtrace.idузаписи отправителя и у записи консьюмера: сейчас они разные, после правки должны совпадать.
Связанное
MessageId,ConversationId,RetryAttempt, чточастично компенсирует разорванный трейс.