abp 中雖然已經(jīng)有日志模塊,但是沒(méi)有UI界面,而一個(gè)日志界面對(duì)開(kāi)發(fā)的應(yīng)用程序來(lái)說(shuō)很重要,因此,經(jīng)過(guò)一番摸索,終于做出了自己的日志模塊,列出關(guān)鍵代碼,給有需要的朋友參考。
1、首先,在Application.Contracts項(xiàng)目中新增加一個(gè)類AuditLogDto.cs 和GetAuditLogInput.cs:
代碼塊
public class AuditLogDto : EntityDto<Guid>
{
public virtual string ApplicationName { get; set; }
public virtual Guid? UserId { get; protected set; }
public virtual string UserName { get; protected set; }
public virtual Guid? TenantId { get; protected set; }
public virtual string TenantName { get; protected set; }
public virtual Guid? ImpersonatorUserId { get; protected set; }
public virtual Guid? ImpersonatorTenantId { get; protected set; }
public virtual DateTime ExecutionTime { get; protected set; }
public virtual int ExecutionDuration { get; protected set; }
public virtual string ClientIpAddress { get; protected set; }
public virtual string ClientName { get; protected set; }
public virtual string ClientId { get; set; }
public virtual string CorrelationId { get; set; }
public virtual string BrowserInfo { get; protected set; }
public virtual string HttpMethod { get; protected set; }
public virtual string Url { get; protected set; }
public virtual string Exceptions { get; protected set; }
public virtual string Comments { get; protected set; }
public virtual int? HttpStatusCode { get; set; }
public virtual ICollection<EntityChange> EntityChanges { get; protected set; }
public virtual ICollection<AuditLogAction> Actions { get; protected set; }
}
public class GetAuditLogInput : PagedAndSortedResultRequestDto
{
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public string UserName { get; set; }
public string ServiceName { get; set; }
public string MethodName { get; set; }
public string BrowserInfo { get; set; }
public string HttpMethod { get; set; }
public string Url { get; set; }
public string UseName { get; set; }
public string ApplicationName { get; set; }
public string CorrelationId { get; set; }
public int? MaxExecutinDuration { get; set; }
public int? MinExecutionDuration { get; set; }
public System.Net.HttpStatusCode? httpStutusCode { get; set; }
public bool IncludeDetails { get; set; }
public bool? HasException { get; set; }
}
2、增加IAuditLogAppService.cs類
public interface IAuditLogAppService : IApplicationService
{
Task<PagedResultDto<AuditLogDto>> GetListAsync(GetAuditLogInput input);
}
3、在Application項(xiàng)目在增加AuditLogAppService.cs類:
public class AuditLogAppService : XXAppService, IAuditLogAppService
{
private readonly IAuditLogRepository _auditLogRepository;
public AuditLogAppService(IAuditLogRepository auditLogRepository)
{
_auditLogRepository = auditLogRepository;
}
public async Task<PagedResultDto<AuditLogDto>> GetListAsync(GetAuditLogInput input)
{
input.Sorting = "ExecutionTime Desc";
input.IncludeDetails = true;
var count = await _auditLogRepository.GetCountAsync(
input.StartDate, input.EndDate, input.HttpMethod,
input.Url, input.UseName, input.ApplicationName, input.CorrelationId, input.MaxExecutinDuration,
input.MinExecutionDuration, input.HasException, input.httpStutusCode).ConfigureAwait(false);
var list = await _auditLogRepository.GetListAsync(input.Sorting,
input.MaxResultCount, input.SkipCount, input.StartDate, input.EndDate, input.HttpMethod,
input.Url, input.UseName, input.ApplicationName, input.CorrelationId, input.MaxExecutinDuration, input.MinExecutionDuration,
input.HasException, input.httpStutusCode, input.IncludeDetails
).ConfigureAwait(false);
return new PagedResultDto<AuditLogDto>(
count,
ObjectMapper.Map<List<AuditLog>, List<AuditLogDto>>(list)
);
}
4、XXApplicationAutoMapperProfile.cs 類中增加 AutoMap類映射關(guān)系:
public class AuditManagementApplicationAutoMapperProfile : Profile
{
public AuditManagementApplicationAutoMapperProfile()
{
CreateMap<AuditLog, AuditLogDto>();
}
}
5、web 項(xiàng)目中Pages目錄下增加AuditLogs目錄,在AuditLogs目錄下增加index.cshtml文件:
<abp-card>
<abp-card-header>
<abp-row>
<abp-column size-md="_6">
<h2>@L["AbpAuditLogs"]</h2>
</abp-column>
</abp-row>
</abp-card-header>
<abp-card-body>
<form id="AuditLogFilterForm">
<abp-row>
<abp-column size-md="_3">
<div class="form-group">
<label for="StartEndRange" class="control-label">@L["DateRange"]</label>
<input id="StartEndRange" type="text" class="form-control date-range-picker" />
</div>
</abp-column>
<abp-column size-md="_3">
<abp-input asp-for="@Model.Input.UserName" label="用戶" />
</abp-column>
<abp-column size-md="_3">
<abp-select asp-for="@Model.Input.HttpStutusCode" asp-items="@Model.HttpStutusCodes" label="Http狀態(tài)碼" />
</abp-column>
<abp-column size-md="_3">
<abp-select asp-for="@Model.Input.HttpMethod" asp-items="@Model.HttpMethods" label="http方法"/>
</abp-column>
</abp-row>
<abp-row>
<abp-column size-md="_3">
<abp-select asp-for="@Model.Input.HasException" asp-items="@Model.HasExceptions" label="有錯(cuò)誤" />
</abp-column>
<abp-column size-md="_3">
<button id="RefreshAuditLogsButton" class="btn btn-primary"><i class="fa fa-sync"></i> @L["Refresh"]</button>
</abp-column>
</abp-row>
</form>
<abp-table striped-rows="true" id="AbpAuditLogssTable">
<thead>
<tr>
<th width="40">@L["Http"]</th>
<th width="40">@L["Method"]</th>
<th>@L["UserName"]</th>
<th>@L["ExecutionDuration"]</th>
<th>@L["ClientIpAddress"]</th>
<th>@L["Url"]</th>
<th>@L["ExecutionTime"]</th>
</tr>
</thead>
</abp-table>
</abp-card-body>
</abp-card>
6、增加index.js代碼:
$(function () {
var l = abp.localization.getResource('AuditManagement');
var _auditLogService = xxxnamespace.auditLog;
var _$auditLogFilterForm = $('#AuditLogFilterForm');
var _$auditLogsTable = $('#AbpAuditLogssTable');
var _selectedDateRangeAuditLog = {
startDate: moment().startOf('day'),
endDate: moment().endOf('day')
};
var createDateRangePickerOptions = function (extraOptions) {
extraOptions = extraOptions ||
{
allowFutureDate: false
};
var options = {
locale: {
format: 'L',
applyLabel: l('Apply'),
cancelLabel: l('Cancel'),
customRangeLabel: l('CustomRange')
},
min: moment('2015-05-01'),
minDate: moment('2015-05-01'),
opens: 'left',
ranges: {}
};
if (!extraOptions.allowFutureDate) {
options.max = moment();
options.maxDate = moment();
}
options.ranges[l('Today')] = [moment().startOf('day'), moment().endOf('day')];
options.ranges[l('Yesterday')] = [moment().subtract(1, 'days').startOf('day'), moment().subtract(1, 'days').endOf('day')];
options.ranges[l('Last7Days')] = [moment().subtract(6, 'days').startOf('day'), moment().endOf('day')];
options.ranges[l('Last30Days')] = [moment().subtract(29, 'days').startOf('day'), moment().endOf('day')];
options.ranges[l('ThisMonth')] = [moment().startOf('month'), moment().endOf('month')];
options.ranges[l('LastMonth')] = [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')];
return options;
};
_$auditLogFilterForm.find('input.date-range-picker').daterangepicker(
$.extend(true, createDateRangePickerOptions(), _selectedDateRangeAuditLog),
function (start, end) {
_selectedDateRangeAuditLog.startDate = start.format('YYYY-MM-DDT00:00:00Z');
_selectedDateRangeAuditLog.endDate = end.format('YYYY-MM-DDT23:59:59.999Z');
getAuditLogs();
});
var dataTable = _$auditLogsTable.DataTable(abp.libs.datatables.normalizeConfiguration({
processing: true,
serverSide: true,
paging: true,
searching: false,
autoWidth: false,
scrollCollapse: true,
order: [[1, "asc"]],
ajax: abp.libs.datatables.createAjax(_auditLogService.getList,
function () { return createAuditLogRequestParams() }),
columnDefs: [
{
data: "httpStatusCode"
},
{
data: "httpMethod"
},
{ data: "userName" },
{ data: "executionDuration" },
{ data: "clientIpAddress" },
{ data: "url" },
{
data: "executionTime",
render: function (executionTime) {
return moment(executionTime).format('YYYY-MM-DD HH:mm:ss');
}
}
]
}));
function createAuditLogRequestParams() {
var prms = {};
_$auditLogFilterForm.serializeArray().map(function (x) {
prms[abp.utils.toCamelCase(x.name.substring(6))] = x.value;
});
return $.extend(prms, _selectedDateRangeAuditLog);
}
function getAuditLogs() {
dataTable.ajax.reload();
}
$('#RefreshAuditLogsButton').click(function (e) {
e.preventDefault();
getAuditLogs();
});
});
7、在xxMenuContributor.cs中添加菜單:
context.Menu.Items.Add(new ApplicationMenuItem("Stock.Audit", l["Menu:Audit"], "/Audits"));
基本的代碼就是這些,當(dāng)然,如果要真正做成一個(gè)實(shí)用的日志功能,最好是把它做成一個(gè)模塊,然后添加到你的新項(xiàng)目中。還要有查詢功能等等。
image.png
image.png
image.png
image.png
上面的圖片是我最終做出來(lái)的日志界面,還有待完善。