寻找更好的解决方案来记录Web应用程序使用情况事件

时间:2018-10-01 07:08:40

标签: c# asp.net-mvc-4 event-handling asp.net-web-api2

我正在寻找一种更好的解决方案来在数据库中记录使用情况事件,然后将其用于生成报告和一些花式图表。

我们当前执行此操作的方式如下:

我们有MVC / API操作筛选器,该筛选器侦听每个请求并调用服务,该服务将提取所有元数据并将其存储在数据库中。您可能会在下面的代码中看到,当前的实现存在错误,并且无法维护和扩展。 (为简便起见,我删除了不重要的代码)

public class LogActivityAttribute : ActionFilterAttribute{
    // more code here...
    public override void OnActionExecuted(ActionExecutedContext filterContext){
        _eventLogService.LogMvcEventLog(filterContext);
    }
}

public class EventLogService : IEventLogService
{
    // more code here...
    public EventLogSummaryModel LogMvcEventLog(ActionExecutedContext filterContext){
    try
    {
        if (filterContext.Controller is ViewerController)
        {
            switch (filterContext.ActionDescriptor.ActionName)
            {
                case ReviewApproveDocumentActionName:
                    return LogEventLogForWorkflow(filterContext);
                case ExternalDocumentActionName:
                case DocumentActionName:
                    return HandlePossibleEventsForDocument(filterContext);
            }
        }
        else if (filterContext.Controller is AppController
            && filterContext.ActionDescriptor.ActionName.Equals(AppExternalDocumentActionName))
            return HandlePossibleEventsForDocument(filterContext);
        else if (filterContext.Controller is Areas.Viewer.Controllers.HomeController
            && filterContext.ActionDescriptor.ActionName.Equals(HomeActionName))
            return LogEventLogForWelcomePage(filterContext);
        else if (filterContext.Controller is Areas.Viewer.Controllers.HomeController
            && filterContext.ActionDescriptor.ActionName.Equals(LegacySearchActionName))
            return LogEventLogForLegacySearch(filterContext);
        else if (filterContext.Controller is ApiSearchController
            && filterContext.ActionDescriptor.ActionName.Equals(LegacyApiSearchActionName))
            return LogEventLogForLegacyApiSearch(filterContext);
        else if (filterContext.Controller is Areas.Viewer.Controllers.FeedbackController)
        {
            if (filterContext.ActionDescriptor.ActionName.Equals(FeedbackCreateActionViewer))
                LogEventsForAddFeedback(filterContext);
        }
    }
    catch (Exception e)
    {
        ViewerLogger.Instance.Log.Error($"LogMvcEventLog:{e.Message}");
    }
    return new EventLogSummaryModel();
   }
   // more code here...
}

我知道,如果尝试解决任何现有问题,最终可能会引入更多错误。所以我正在考虑以一种更好的方式重做整个事情。

我能够想到两种解决方案。

  1. 在即将返回之前,在每个操作方法内记录相关事件
  2. 使用相同的Action过滤器流程,如下创建新类并提取数据并记录它们。

(请注意,它不完整)

// event context metadata from mvc/api actions
public class EventContext
{
    public ModeTypes ModeType { get; set; }
    public string Instance { get; set; }
    public string HttpVerb { get; set; }
    public int HttpResponseCode { get; set; }
    public int UserId { get; set; }
    public ICollection<int> UserRoles { get; set; }
    public DateTime Timestamp => DateTime.UtcNow;
}    


internal class ApiEventContextDataExtractor 
                              : IApiEventContextDataExtractor
{
    private readonly IHttpContextService _httpContextService;

    public ApiEventContextDataExtractor(IHttpContextService httpContextService)
    {
        _httpContextService = httpContextService;
    }

    public EventContext GetContext(HttpActionExecutedContext filterContext)
    {
        var userRole = _httpContextService.GetCurrentUserRoles();
        var host = _httpContextService.GetHost();
        var area = filterContext.ActionContext.RequestContext.RouteData.Values[Constants.EventLogService.AreaName]?.ToString() ?? "";

        var mode = area.Equals(AnalyticConstants.EventLogService.AuthorArea, StringComparison.InvariantCultureIgnoreCase)
            ? ModeTypes.Editor
            : ModeTypes.Display;

        return new EventContext
        {
            HttpVerb = filterContext.Request.Method.Method,
            HttpResponseCode = (int)filterContext.Response.StatusCode,
            Instance = host,
            UserId = userRole.Id,
            ModeType = mode
        };
    }
}

internal class MvcEventContextDataExtractor : IMvcEventContextDataExtractor{
   // implementation
}

internal class MvcEventReferrerDataExtractor
{
   // implementation
}

internal class MvcEventModelDataExtractor
{
   // implementation
}

然后,我将获得一个公共服务,该服务将获取EventContext以及引荐来源数据和模型数据,并将它们记录在数据库中。

所以我想我的问题是,我应该走哪条路? 如果我按照自己的方式去做(第二个),那么我是在正确的轨道上吗?

0 个答案:

没有答案