gpt4 book ai didi

c# - 异步记录对站点的每个请求的请求记录器

转载 作者:太空宇宙 更新时间:2023-11-03 23:29:02 26 4
gpt4 key购买 nike

我正在尝试将每个请求记录到我的网站 (Asp.net mvc)。为此,我创建了一个全局过滤器属性,用于从当前请求中收集日志信息。异步执行此操作的主要思想是不要阻止我的主应用程序。并静静地记录数据。当我的操作记录器无法记录请求时,当我设置一个错误记录器来记录错误时,一切都很好。

下面的代码是我的过滤器

public class RequestLoggingAttribute : ActionFilterAttribute
{
private readonly IActionLogService _actionLogService;
public RequestLoggingAttribute(IActionLogService actionLogService)
{
_actionLogService = actionLogService;
}

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//Run an async method here to log any data you need.
Task.Run(() => GatherActionLog(filterContext)).ConfigureAwait(false);

base.OnActionExecuting(filterContext);
}

private async Task GatherActionLog(ActionExecutingContext filterContext)
{
try
{
var httpContext = filterContext.RequestContext.HttpContext;
var request = httpContext.Request;
if (!request.Url.AbsoluteUri.Contains("elmah"))
{
var roles = ((ClaimsIdentity) httpContext.User.Identity).Claims
.Where(c => c.Type == ClaimTypes.Role)
.Select(c => c.Value).ToArray();

var parameters = filterContext.ActionParameters.Select(x => new {x.Key, x.Value});
var jsonParameters = Json.Encode(parameters);

var actionLog = new ActionLog()
{
Action = filterContext.ActionDescriptor.ActionName,
Controller = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName,
DateTimeUTC = DateTime.UtcNow,
IpAddress = request.UserHostAddress,
UserName = httpContext.User.Identity.Name,
Request = request.Url.AbsoluteUri,
ComputerName = request.UserHostName,
UserRole = String.Join(",", roles),
UserAgent = request.UserAgent,
ClientLoggedInUser = request.LogonUserIdentity.Name,
HttpMethod = httpContext.Request.HttpMethod,
Parameters = jsonParameters,
BrowserName = request.Browser.Id,
BrowserVersion = request.Browser.Version
};

await _actionLogService.InsertAsync(actionLog);
}
}
catch (Exception ex)
{
Elmah.ErrorLog.GetDefault(filterContext.HttpContext.ApplicationInstance.Context).Log(new Elmah.Error(ex));

}
}
}

在我的 Elmah 的错误列表中,这种方法有两个错误。如下:

首先:

A second operation started on this context before a previous asynchronous operation completed. Use 'await' to ensure that any asynchronous operations have completed before calling another method on this context. Any instance members are not guaranteed to be thread safe.

第二个:

Saving or accepting changes failed because more than one entity of type 'Domain.LogEntities.ActionLog' have the same primary key value. Ensure that explicitly set primary key values are unique. Ensure that database-generated primary keys are configured correctly in the database and in the Entity Framework model. Use the Entity Designer for Database First/Model First configuration. Use the 'HasDatabaseGeneratedOption" fluent API or 'DatabaseGeneratedAttribute' for Code First configuration.

ActionLog 的域类如下:

public class ActionLog
{
public Guid ActionLogId { get; set; }
public string UserRole { get; set; }
public string UserName { get; set; }
public string ClientLoggedInUser { get; set; }
public string UserFullName { get; set; }
public DateTime DateTimeUTC { get; set; }
public string Action { get; set; }
public string Controller { get; set; }
public string Request { get; set; }
public string ComputerName { get; set; }
public string IpAddress { get; set; }
public string HttpMethod { get; set; }
public string Parameters { get; set; }
public string UserAgent { get; set; }
public string BrowserName { get; set; }
public string BrowserVersion { get; set; }
}

如果重要的话,我使用了两个数据库,一个用于我的主应用程序,另一个用于日志记录(错误和请求日志记录)。所以我的 DAL 层中有两个 Entity Framework DbContext。一个 DbContext 用于应用程序,第二个用于记录器。但是我使用了一个接受 DbContext 的 BaseRepository。我对 BaseRepository 的调用如下:

public class GenericRepository<T> : BaseRepository<T, ApplicationDbContext> where T : class
{
public GenericRepository(ApplicationDbContext db)
:base(db)
{
}

}

public class LoggerRepository<T> : BaseRepository<T, LoggerDbContext> where T : class
{
public LoggerRepository(LoggerDbContext db)
:base(db)
{

}
}

1) 有没有更好的方法!? (我不想改变我的整个代码,只是适合这种方法的更好的方式)

2) 如何避免上述错误?

谢谢

最佳答案

希望我有足够的“声望”将其添加到评论中。无论如何,ActionFilters 应该在 HTTP 管道将请求移动到 Controller 之前完成它们的工作。请看this post .

您可以将您的日志记录详细信息发送到 MQ(例如,在单独的进程中运行的 MSMQ)并让 MQ 与数据库对话,这样您的主应用程序就不会被阻塞。

关于c# - 异步记录对站点的每个请求的请求记录器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32901515/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com