Токен корреляции для субъектов и служб Service Fabric

Мы начали экспериментировать с Service Fabric как платформой микросервисов, и после успешного внедрения наших первых примеров «привет, мир» о шаблоне субъекта, службах без сохранения состояния/с отслеживанием состояния, веб-API (и т. д.) мы переходим к поиску решений для других основных аспектов, таких как аутентификация. /autz и ведение журнала приложений.

У меня есть сомнения по поводу регистрации; во всех SOA, которые мы разработали до сих пор, мы всегда добавляли «маркер корреляции» ко всем задействованным службам (часто на архитектурном уровне, автоматически добавляемым в качестве заголовка в WCF, скрытым для разработчиков), поэтому теперь мы пытаемся сделать то же самое с Service Fabric.

В поисках наилучшего решения, позволяющего пропустить «Токен корреляции» через все вызовы актора/службы, поскольку мы не обнаружили ничего готового «из коробки», нам интересно, не ищем ли мы что-то теоретически неправильное.

Любое предложение там?


person MonDeveloper    schedule 04.07.2016    source источник


Ответы (1)


Я добился большого успеха, используя serilog и seq и использовать средство обогащения для добавления свойств в сообщения журнала.

В своих службах я вызываю ServiceLogger.CreateLogger(this), чтобы обогатить журнал всеми сведениями о службе. Если вам нужен токен корреляции, вы сможете добавить его относительно легко, но я еще не сделал этого.

Кажется, я скопировал соответствующий код ниже!

public class ServiceFabricEnricher<T> : ILogEventEnricher where T : ServiceContext
{
    protected T Context { get; }
    private LogEventProperty _nodeName;

    public ServiceFabricEnricher(T context)
    {
        Context = context;
    }

    public virtual void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
    {
        if (_nodeName == null) _nodeName = propertyFactory.CreateProperty("NodeName", Context.NodeContext.NodeName);
        logEvent.AddPropertyIfAbsent(_nodeName);
    }
}


public class ServiceEnricher<T> : ServiceFabricEnricher<T> where T : ServiceContext
{
    private LogEventProperty _serviceName;
    private LogEventProperty _partitionId;
    private LogEventProperty _applicationName;

    public ServiceEnricher(T context) : base(context)
    {
    }

    public override void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
    {
        base.Enrich(logEvent, propertyFactory);

        if (_serviceName == null) _serviceName = propertyFactory.CreateProperty("ServiceName", Context.ServiceName);
        if (_partitionId == null) _partitionId = propertyFactory.CreateProperty("PartitionId", Context.PartitionId);
        if (_applicationName == null) _applicationName = propertyFactory.CreateProperty("ApplicationName", Context.CodePackageActivationContext.ApplicationName);

        logEvent.AddPropertyIfAbsent(_serviceName);
        logEvent.AddPropertyIfAbsent(_partitionId);
        logEvent.AddPropertyIfAbsent(_applicationName);
    }
}

public static class ServiceFabricLogger
{
    private static ILogger CreaterDefaultLogger()
    {
        var configurationProvider = new FabricConfigurationProvider("SeqConfig");

        var loggerConfiguration = new LoggerConfiguration();
        if (configurationProvider.HasConfiguration)
        {
            var seqServer = configurationProvider.GetValue("SeqServer");
            loggerConfiguration =
                loggerConfiguration
                .WriteTo.Seq(seqServer, period: TimeSpan.FromMilliseconds(500))
                ;

            var level = configurationProvider.GetValue("MinimumLevel");
            LogEventLevel minimumLevel;
            if (!string.IsNullOrWhiteSpace(level) && Enum.TryParse<LogEventLevel>(level, true, out minimumLevel))
            {
                loggerConfiguration = loggerConfiguration.MinimumLevel.Is(minimumLevel);
            }
        }
        else
        {
            loggerConfiguration =
                loggerConfiguration
                .MinimumLevel.Error()
                ;
        }

        Log.Logger = loggerConfiguration.CreateLogger();
        return Log.Logger;
    }

    public static ILogger Logger { get; } = CreaterDefaultLogger();
}

public static class ServiceLogger
{
    public static ILogger CreateLogger(this StatefulServiceBase service) =>
        ServiceFabricLogger.Logger.ForContext(new[] { new StatefulServiceEnricher(service.Context) });

    public static ILogger CreateLogger(this StatelessService service) =>
        ServiceFabricLogger.Logger.ForContext(new[] { new StatelessServiceEnricher(service.Context) });
}
person Nick Randell    schedule 05.07.2016
comment
@nick-radell Моя проблема не в моделировании инфраструктуры журналов, для этой цели мой выбор отличается от вашего (я полагаюсь на common.loggin + log4net), но это совершенно не имеет значения. Моя проблема заключается в том, как сделать так, чтобы токен перетекал от клиентов к серверам в рамках субъектов/служб ServiceFabric. Еще лучше, если я решу установить связь с помощью WCF, это довольно просто, достаточно добавить заголовок через поведение, но проблема заключается в том же, используя удаленное взаимодействие (которое используется по умолчанию, и я хотел бы придерживаться его) - person MonDeveloper; 23.02.2017