Ищите лучшее решение для регистрации событий использования веб-приложения - PullRequest
0 голосов
/ 01 октября 2018

Я ищу лучшее решение для регистрации событий использования в базе данных, которые затем будут использоваться для создания отчетов и некоторых необычных диаграмм.

Способ, которым мы в настоящее время делаем это, заключается в следующем:

у нас есть фильтры действий 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...
}

Я точно знаю, что, если я попытаюсь исправить любую из существующих проблем, я могу в конечном итоге ввести больше ошибок.Так что я думал о том, чтобы переделать все это лучше.

Мне удалось придумать 2 решения.

  1. Записать соответствующие события внутри каждого метода действия непосредственно перед возвратом
  2. Используя тот же поток фильтра действий, создать новыйКлассы следующим образом и извлекать данные и регистрировать их.

(обратите внимание, что оно неполное)

// 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 вместе с данными реферера и данными модели и регистрировать ихв базе данных.

Так что я думаю, что мой вопрос будет, какой путь мне выбрать?Если бы я сделал это по-своему (2-й), я на правильном пути или есть лучший способ сделать это?

...