.NET Core - подключить входящий запрос с помощью Request-Id к исходящим HTTP-запросам. - PullRequest
0 голосов
/ 13 сентября 2018

Мы ищем способ подключить Request-Id (или Correlation-Id) к нескольким запросам API, как показано на рисунке ниже:

enter image description here

Идея состоит в том, чтобы иметь один идентификатор для отслеживания определенного запроса через несколько API в наших Журналах. Мы используем стандарт ILogger, который поставляется из коробки с .NET Core 2.1.

То, что мы пробовали до сих пор

  • Мы попытались использовать Request-Id в заголовке запроса, который успешно регистрируется, но мы не можем получить значение, чтобы добавить его в последующий HTTP-запрос к другим API.

  • Мы заметили, что есть также CorrelationId, который регистрируется. Однако мы не можем понять, как его обновить.

  • Кроме того, мы заметили, что на HttpContextAccessor доступно TraceIdentity, которое потенциально может решить нашу задачу. Но мы не знаем, как использовать это для решения нашей проблемы.

Мы не можем использовать Application Insights и хотим полагаться на нашу собственную инфраструктуру ведения журналов. Мы ничего не можем найти в документации.

Существует ли какое-либо готовое решение, которое мы можем использовать, не придумывая собственное решение?

Ответы [ 4 ]

0 голосов
/ 01 июля 2019

Наша компания довольно активно использует микросервисы.У нас есть все функции с открытым исходным кодом ( NuGet , GitHub , Wiki ), которые распространяют идентификатор корреляции через различные транспорты:

  1. входящийHTTP (ASP.NET Core, IIS)
  2. исходящий HTTP (HttpClient, RestSharp)
  3. AWS SNS / SQS
  4. RabbitMQ (MassTransit)
  5. WCF,ASMX

Независимая структура ведения журнала (для внутренних целей мы используем SeriLog и log4net ).

0 голосов
/ 14 сентября 2018

Не уверен, если это напрямую связано, но мы сталкиваемся с такой же проблемой для корреляции запросов через API и сервисы в проектах Service Fabric. В итоге мы установили и получили correlationId из CallContext (внутри System.Runtime.Remoting.Messaging). По совпадению только что написал об этом здесь . Пожалуйста, посмотрите, поможет ли это.

0 голосов
/ 14 сентября 2018

Я задал тот же вопрос @davidfowl в Твиттере. Он ответил:

Нет, для этого нет ничего необычного. Это конец, конец работает с пониманием приложения, но оно не очень детализировано. Ты можешь рассмотрите возможность использования одного и того же промежуточного программного обеспечения в разных командах. если Есть рабочий элемент для решения этой проблемы в 3.0 https://github.com/aspnet/Hosting/issues/1350

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

Обновление

В итоге мы создали специальное промежуточное программное обеспечение, как предлагал @DavidMcEleney. Однако поверх этого мы добавили CorrelationId к свойству AsyncLocal. Это помогло нам получить доступ к CorrelationId в любом месте кода, если / когда это потребуется. Вот код get / set CorrelationId:

using System;
using System.Threading;

public static class CorrelationContext
{
    private static readonly AsyncLocal<string> CorrelationId = new AsyncLocal<string>();

    public static void SetCorrelationId(string correlationId)
    {
        if (string.IsNullOrWhiteSpace(correlationId))
        {
            throw new ArgumentException(nameof(correlationId), "Correlation id cannot be null or empty");
        }

        if (!string.IsNullOrWhiteSpace(CorrelationId.Value))
        {
            throw new InvalidOperationException("Correlation id is already set");
        }

        CorrelationId.Value = correlationId;
    }

    public static string GetCorrelationId()
    {
        return CorrelationId.Value;
    }
}

Для использования в CorrelationMiddleware.cs

public class CorrelationMiddleware
{
    private readonly RequestDelegate _next;

    public CorrelationMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        context.Request.Headers.TryGetValue("Correlation-Id-Header", out var correlationIds);

        var correlationId = correlationIds.FirstOrDefault() ?? Guid.NewGuid().ToString();

        CorrelationContext.SetCorrelationId(correlationId);

        using (LogContext.PushProperty("Correlation-Id", correlationId))
        {
            await _next.Invoke(context);
        }
    }
}

Если позже нам понадобится получить доступ к CorrelationId в любом месте кода, тогда мы просто позвоним: CorrelationContext.GetCorrelationId();

0 голосов
/ 13 сентября 2018

Я использую Serilog для входа в ядро ​​dotnet и запускаю свойства LogContext с использованием промежуточного программного обеспечения -

CorrelationMiddleware.cs

    public class CorrelationMiddleware
    {
    readonly RequestDelegate _next;

    public CorrelationMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        context.Request.Headers.TryGetValue(Headers.Correlation, out StringValues correlationId);

        using (LogContext.PushProperty("Correlation-Id", correlationId.FirstOrDefault()))
        {
            await _next.Invoke(context);
        }
    }
}

Зарегистрируйте это в своем Startup.cs Configure метод:

app.UseMiddleware<CorrelationLogger>();

Затем, когда вы отправляете исходящий http-вызов, вы можете добавить заголовок в HttpRequestMessage, добавив

request.Headers.Add(Headers.Correlation, GetHeader("Correlation-Id"));

При поиске в журналах мы можем выполнять поиск по идентификатору корреляции.и увидеть полный конец между всеми API ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...