c# - 在 ILogger 自定义实现中检索身份

标签 c# logging asp.net-core asp.net-core-mvc

我正在实现一个自定义的 Microsoft.Extensions.Logging.ILogger (和 ILoggerProvider。我想检索当前的身份,但我真的不知道,因为我无法注入(inject)任何东西,而且我也不知道当前的 HttpContext。

我的方法可能是错误的......这种要求有典型的解决方案吗?

这里有几行代码:

factory.AddProvider(new MongoDBLoggerProvider(connectionString, database));

在提供者中:
public ILogger CreateLogger(string categoryName)
{
    var client = new MongoClient(_connectionString);
    var database = client.GetDatabase(_database);

    return new MongoDBLogger(database, categoryName);
}

在记录器中:
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
    var now = DateTime.Now;
    var entry = new LogEntry
    {
        Date = now,
        UserId = ?????
        Exception = exception,
        Level = logLevel,
        State = state.ToString(),
        Scope = _categoryName,
        EventId = eventId.Id,
        EventName = eventId.Name,
        FormattedState = formatter != null ? formatter(state, exception) : null
    };

    PushAndForget(entry, _database);
}

最佳答案

这是一个可以访问身份的工作自定义记录器的示例。它应该完成您正在寻找的内容,我刚刚在示例中重命名了一些类以提高可读性。在您设计客户记录器时,这篇 Microsoft 文章也可能是一个有用的资源https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-3.1#create-a-custom-logger
您可以根据需要设置配置值:

public class LoggingServiceConfig
{
    public LogLevel LogLevel { get; set; } = LogLevel.Information;
    public int EventId { get; set; } = 0;
    public ConsoleColor Color { get; set; } = ConsoleColor.Yellow;
}
Config 类有以下用途:
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
设置自定义记录器:
public class LoggingService : ILogger
{
    private readonly ILogStore _logStore;
    private readonly Microsoft.AspNetCore.Http.IHttpContextAccessor _httpContextAccessor;
    private readonly LoggingServiceConfig _config;

    public LoggingService(string categoryName, LoggingServiceConfig config,
        Microsoft.AspNetCore.Http.IHttpContextAccessor httpContextAccessor,
        ILogStore logStore)
    {
        _config = config;
        _logStore = logStore;
        _httpContextAccessor = httpContextAccessor;

    }

    public IDisposable BeginScope<TState>(TState state)
    {
        return null;
    }

    public bool IsEnabled(LogLevel logLevel)
    {
        return true; //currently log everything regardless of logLevel
    }

    public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
    {
        LogEntry log = new LogEntry(); //this is your log entry
        if (_httpContextAccessor.HttpContext != null)
        {
            var userManager = _httpContextAccessor.HttpContext.RequestServices.GetService<UserManager<AspNetUser>>(); //this is the user manager you can use to perform identity functions, you can likewise request the signInManager  service as well if needed

            var user = userManager.GetUserAsync(_httpContextAccessor.HttpContext.User);

            if (user != null && user.Result != null)
            {
                //do something with user.Result as this is your identity user record
                log.UserId = user.Result.UserId;
                log.Username = user.Result.UserName;
            }
        }
        
        if (exception != null)
        {
            log.ErrorMessage = exception.Message;
        }

        var signInManager = _httpContextAccessor.HttpContext.RequestServices.GetService<SignInManager<AspNetUser>>(); //I accessed the sign in manager in case you need it to conditionally affect how you write create your LogEntry

        //add other properties you want to the log here
        _logStore.Add(log); //this is where you can call your PushAndForget or any method to write to database assumed you injected it correctly or the like, you can reference the .net core respository pattern for further details on how i did my _logStore
    }
}
自定义记录器有以下用途:
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
设置日志记录提供程序:
public class LoggingServiceLoggerProvider : ILoggerProvider
{
    private readonly LoggingServiceConfig _config;
    private readonly ConcurrentDictionary<string, LoggingService> _loggers = new ConcurrentDictionary<string, LoggingService>();
    private readonly ILogStore _logStore;
    private readonly Microsoft.AspNetCore.Http.IHttpContextAccessor _httpContextAccessor;
    public LoggingServiceLoggerProvider(LoggingServiceConfig config,
        Microsoft.AspNetCore.Http.IHttpContextAccessor httpContextAccessor,
        ILogStore logStore)
    {
        _config = config;
        _httpContextAccessor = httpContextAccessor;
        _logStore = logStore; //this is a repository for storing logs
    }
    public ILogger CreateLogger(string categoryName)
    {
        return _loggers.GetOrAdd(categoryName, name => new LoggingService(name, _config,
            _httpContextAccessor,
            _logStore));
    }

    public void Dispose()
    {
        _loggers.Clear();
    }
}
自定义日志记录提供程序具有以下 using 语句:
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
在您的 Startup.cs 中确保配置方法具有 ILoggerFactory loggerFactory 参数并包括以下内容:
loggerFactory.AddProvider(new LoggingServiceLoggerProvider(
                                  new LoggingServiceConfig
                                  {
                                      LogLevel = LogLevel.Error,
                                      Color = ConsoleColor.Red
                                  },
                                  new Microsoft.AspNetCore.Http.HttpContextAccessor(),
                                  new LogStore()));

关于c# - 在 ILogger 自定义实现中检索身份,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39367044/

相关文章:

c# - 使接口(interface)实现与 == 具有可比性

c# - 如何在 ClaimsIdentity Asp.Net Core 中传递对象

c++ - 如何创建优化的图形多色记录器?

sql-server - 截断 SQL Server 日志文件的命令是什么?

asp.net - '找不到方法 : !!0 AutoMapper.IMapper.Map&lt;!0>(对象)'(ASP.NET 零)

asp.net-core - 内存缓存的 IDistributedCache 实现在哪里?

c# - 将 SQL 转换为 Linq 查询

c# - Windows 工作流和 Thread.CurrentPrincipal

c# - 检测我的表单何时获得焦点

java - 创建记录器 java 时未调用构造函数