我正在尝试在ASP.NET核心应用程序(.NET框架)中实现SeriLog
以下是我目前执行的步骤 -
1)在Project.json
中添加了以下引用"Serilog": "2.2.0",
"Serilog.Extensions.Logging": "1.2.0",
"Serilog.Sinks.RollingFile": "2.0.0",
"Serilog.Sinks.File": "3.0.0"
2)将以下行添加到Startup类的构造函数中 -
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.RollingFile(Path.Combine(env.ContentRootPath, "log-{Date}.txt"))
.CreateLogger();
3)在启动类的配置方法中添加以下行 -
loggerFactory.AddSerilog();
4)将记录器注入HomeController,如下所示 -
ILogger logger;
public HomeController(ILogger logger)
{
this.logger = logger;
}
5)在“关于”操作中,尝试记录此类异常 -
public IActionResult About()
{
ViewData["Message"] = "Your application description page.";
try
{
throw new Exception("Serilog Testing");
}
catch (System.Exception ex)
{
this.logger.Error(ex.Message);
}
return View();
}
在运行我的应用程序时,我收到以下错误 -
System.InvalidOperationException:无法解析类型的服务 ' Serilog.ILogger'在尝试激活时 ' AspNetCore_SeriLog_trial1.Controllers.HomeController&#39 ;.在 Microsoft.Extensions.Internal.ActivatorUtilities.GetService(的IServiceProvider sp,Type type,Type requiredBy,Boolean isDefaultParameterRequired)
在lambda_method(Closure,IServiceProvider,Object [])at Microsoft.AspNetCore.Mvc.Internal.TypeActivatorCache.CreateInstance [TInstance](的IServiceProvider serviceProvider,类型implementationType)at Microsoft.AspNetCore.Mvc.Controllers.DefaultControllerActivator.Create(ControllerContext controllerContext)at Microsoft.AspNetCore.Mvc.Controllers.DefaultControllerFactory.CreateController(ControllerContext 上下文) Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__26.MoveNext()
有人可以帮我吗? Serilog缺少任何配置?
答案 0 :(得分:23)
尝试在控制器中执行以下操作。
ILogger<HomeController> logger = null;
public HomeController(ILogger<HomeController> _logger)
{
logger = _logger;
}
答案 1 :(得分:4)
您的控制器中有以下两行?
import importlib
import inspect
from enum import EnumMeta
_readonly_attrs = {'__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__',
'__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__func__', '__ge__', '__get__',
'__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__',
'__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__',
'__reduce__', '__reduce_ex__', '__repr__', '__self__', '__setattr__', '__sizeof__', '__str__',
'__subclasshook__', '__weakref__', '__members__', '__mro__', '__itemsize__', '__isabstractmethod__',
'__basicsize__', '__base__'}
def reset_module(module, inner_modules_also=True):
"""
This function is a stronger form of importlib's `reload` function. What it does, is that aside from reloading a
module, it goes to the old instance of the module, and sets all the (not read-only) attributes, functions and classes
to be the reloaded-module's
:param module: The module to reload (module reference, not the name)
:param inner_modules_also: Whether to treat ths module as a package as well, and reload all the modules within it.
"""
new_module = importlib.reload(module)
reset_items = set()
# For the case when the module is actually a package
if inner_modules_also:
submods = {submod for _, submod in inspect.getmembers(module)
if (type(submod).__name__ == 'module') and (submod.__package__.startswith(module.__name__))}
for submod in submods:
reset_module(submod, True)
_reset_item_recursively(module, new_module, module.__name__, reset_items)
def _reset_item_recursively(item, new_item, module_name, reset_items=None):
if reset_items is None:
reset_items = set()
attr_names = set(dir(item)) - _readonly_attrs
for sitem_name in attr_names:
sitem = getattr(item, sitem_name)
new_sitem = getattr(new_item, sitem_name)
try:
# Set the item
setattr(item, sitem_name, new_sitem)
try:
# Will work for classes and functions defined in that module.
mod_name = sitem.__module__
except AttributeError:
mod_name = None
# If this item was defined within this module, deep-reset
if (mod_name is None) or (mod_name != module_name) or (id(sitem) in reset_items) \
or isinstance(sitem, EnumMeta): # Deal with enums
continue
reset_items.add(id(sitem))
_reset_item_recursively(sitem, new_sitem, module_name, reset_items)
except Exception as ex:
raise Exception(sitem_name) from ex
如果是前一个(using Serilog;
using Microsoft.Extensions.Logging;
),则可能是您的问题。
注册服务时,您实际上是在说:“当构造函数要求Microsoft.Extensions.Logging.ILogger时,将它们传递给Serilog实例,因为我正在使用Serilog进行日志记录”,但是随后在您的构造函数中您不是要使用Microsoft.Extensions.Logging.ILogger ,而是要使用 Serilog.ILogger ,而且您的应用程序越来越混乱,因为您尚未定义为using Serilog;
注入服务,您已经为Serilog.ILoger
定义了一个服务
请记住,您正在实现Microsoft的ILogger接口:您的构造函数不需要知道您正在使用Serilog ...实际上,您不希望这样做!整个要点是,您可以随时将Serilog换成其他记录器,而无需更改代码。
在构造函数中将Microsoft.Extensions.Logging.ILogger
更改为using Serilog;
,您将请求正确的服务类型
答案 2 :(得分:0)
我收到此问题“尝试激活'Controller_Name'时无法解析'interface_name'类型的服务...。
通过在startup.cs中添加以下行,我已经解决了相同的问题: services.AddScoped();
答案 3 :(得分:0)
您错过了将接口注入控制器构造函数的过程:
ILogger<HomeController> logger = null;
public HomeController(ILogger<HomeController> _logger)
{
logger = _logger;
}
在Program.cs中,您还必须添加UseSerilog:
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseSerilog();
答案 4 :(得分:0)
如果您需要使用ILogger
(来自Serilog
)而不是ILogger<HomeController>
(来自Microsoft.Extensions.Logging
),则可以在Startup类中注册ILogger
:
services.AddSingleton(Log.Logger);
答案 5 :(得分:0)
我知道这是一个老问题,但我刚遇到这个问题并找到了不同的解决方案。
我为 Microsoft.Extensions.Logging
切换了 Serilog
,但我没有将它从构造函数参数列表中删除。
public HomeController(IIdentityServerInteractionService interaction, IWebHostEnvironment environment, ILogger logger)
一旦我删除了那个参数,错误就消失了。
public HomeController(IIdentityServerInteractionService interaction, IWebHostEnvironment environment)
看起来 OP 试图通过构造函数注入记录器,但应该为该控制器创建一个特定的记录器。你也可以让它static
所以there's only 1 creation of the logger for every time this project runs, instead of 1 for every instance of the class.
public class HomeController : Controller
{
private static readonly ILogger Logger = Log.ForContext<HomeController>();
...
public HomeController(IIdentityServerInteractionService interaction, IWebHostEnvironment environment)
{
...
}
...
}
显然,正在发生的事情是编译器默认给构造函数一个 Microsoft.Extensions.Logging
记录器,而不是尝试匹配构造函数实际期望的 Serilog
记录器,所以这就是错误出现的地方来自。