新增业务外部接口日志管理
This commit is contained in:
18
ruoyi-ui/src/api/monitor/apilog.js
Normal file
18
ruoyi-ui/src/api/monitor/apilog.js
Normal file
@@ -0,0 +1,18 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询业务外部接口日志列表
|
||||
export function listApiLog(query) {
|
||||
return request({
|
||||
url: '/monitor/apilog/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询业务外部接口日志详情
|
||||
export function getApiLog(logId) {
|
||||
return request({
|
||||
url: '/monitor/apilog/' + logId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
289
ruoyi-ui/src/views/monitor/apilog/index.vue
Normal file
289
ruoyi-ui/src/views/monitor/apilog/index.vue
Normal file
@@ -0,0 +1,289 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form
|
||||
ref="queryForm"
|
||||
:model="queryParams"
|
||||
size="small"
|
||||
:inline="true"
|
||||
v-show="showSearch"
|
||||
label-width="82px"
|
||||
>
|
||||
<el-form-item label="接口地址" prop="apiUrl">
|
||||
<el-input
|
||||
v-model="queryParams.apiUrl"
|
||||
placeholder="请输入接口地址"
|
||||
clearable
|
||||
style="width: 260px"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="HTTP方法" prop="httpMethod">
|
||||
<el-select v-model="queryParams.httpMethod" placeholder="全部" clearable style="width: 140px">
|
||||
<el-option label="GET" value="GET" />
|
||||
<el-option label="POST" value="POST" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="HTTP调用状态" prop="callStatus">
|
||||
<el-select v-model="queryParams.callStatus" placeholder="全部" clearable style="width: 140px">
|
||||
<el-option label="成功" value="0" />
|
||||
<el-option label="失败" value="1" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="调用时间">
|
||||
<el-date-picker
|
||||
v-model="dateRange"
|
||||
type="datetimerange"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
range-separator="-"
|
||||
start-placeholder="开始时间"
|
||||
end-placeholder="结束时间"
|
||||
:default-time="['00:00:00', '23:59:59']"
|
||||
style="width: 360px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList" />
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="日志编号" align="center" prop="logId" width="100" />
|
||||
<el-table-column label="调用账号" align="center" prop="callerUsername" width="130" show-overflow-tooltip />
|
||||
<el-table-column label="接口地址" prop="apiUrl" min-width="320" show-overflow-tooltip />
|
||||
<el-table-column label="方法" align="center" prop="httpMethod" width="90">
|
||||
<template slot-scope="scope">
|
||||
<el-tag size="mini" effect="plain">{{ scope.row.httpMethod }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="HTTP状态" align="center" prop="responseStatus" width="100">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.responseStatus == null ? '-' : scope.row.responseStatus }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="HTTP调用状态" align="center" prop="callStatus" width="120">
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.callStatus === '0'" type="success" size="mini">成功</el-tag>
|
||||
<el-tag v-else type="danger" size="mini">失败</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="耗时" align="right" prop="costTime" width="110">
|
||||
<template slot-scope="scope">{{ scope.row.costTime }} 毫秒</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="调用时间" align="center" prop="callTime" width="165">
|
||||
<template slot-scope="scope">{{ parseTime(scope.row.callTime) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="90">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-view"
|
||||
v-hasPermi="['monitor:apilog:query']"
|
||||
@click="handleView(scope.row)"
|
||||
>详细</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
:page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<el-dialog
|
||||
title="接口日志详细"
|
||||
:visible.sync="open"
|
||||
width="90%"
|
||||
custom-class="api-log-dialog"
|
||||
append-to-body
|
||||
>
|
||||
<div v-loading="detailLoading" class="api-log-detail">
|
||||
<el-descriptions :column="2" border size="small">
|
||||
<el-descriptions-item label="调用账号">{{ detail.callerUsername || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="用户ID">{{ detail.callerUserId == null ? '-' : detail.callerUserId }}</el-descriptions-item>
|
||||
<el-descriptions-item label="HTTP方法">{{ detail.httpMethod || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="Content-Type">{{ detail.contentType || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="HTTP状态">{{ detail.responseStatus == null ? '-' : detail.responseStatus }}</el-descriptions-item>
|
||||
<el-descriptions-item label="HTTP调用状态">{{ detail.callStatus === '0' ? '成功' : '失败' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="耗时">{{ detail.costTime == null ? '-' : detail.costTime + ' 毫秒' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="调用时间">{{ parseTime(detail.callTime) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="接口地址" :span="2">{{ detail.apiUrl || '-' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<section class="detail-section">
|
||||
<h4>请求头</h4>
|
||||
<pre class="log-content">{{ formatLogContent(detail.requestHeaders) }}</pre>
|
||||
</section>
|
||||
<section class="detail-section">
|
||||
<h4>请求参数</h4>
|
||||
<pre class="log-content">{{ formatLogContent(detail.requestParams) }}</pre>
|
||||
</section>
|
||||
<section class="detail-section">
|
||||
<h4>响应头</h4>
|
||||
<pre class="log-content">{{ formatLogContent(detail.responseHeaders) }}</pre>
|
||||
</section>
|
||||
<section class="detail-section">
|
||||
<h4>原始返回正文</h4>
|
||||
<pre class="log-content log-content-large">{{ formatLogContent(detail.responseBody) }}</pre>
|
||||
</section>
|
||||
<section v-if="detail.errorMsg" class="detail-section">
|
||||
<h4 class="error-title">异常信息</h4>
|
||||
<pre class="log-content error-content">{{ formatLogContent(detail.errorMsg) }}</pre>
|
||||
</section>
|
||||
</div>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="open = false">关 闭</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { js_beautify } from 'js-beautify'
|
||||
import { getApiLog, listApiLog } from '@/api/monitor/apilog'
|
||||
|
||||
export default {
|
||||
name: 'ApiLog',
|
||||
data() {
|
||||
return {
|
||||
loading: true,
|
||||
detailLoading: false,
|
||||
showSearch: true,
|
||||
total: 0,
|
||||
list: [],
|
||||
open: false,
|
||||
detail: {},
|
||||
dateRange: [],
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
apiUrl: undefined,
|
||||
httpMethod: undefined,
|
||||
callStatus: undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
getList() {
|
||||
this.loading = true
|
||||
const query = { ...this.queryParams }
|
||||
if (this.dateRange && this.dateRange.length === 2) {
|
||||
query.beginTime = this.dateRange[0]
|
||||
query.endTime = this.dateRange[1]
|
||||
}
|
||||
listApiLog(query).then(response => {
|
||||
this.list = response.rows
|
||||
this.total = response.total
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1
|
||||
this.getList()
|
||||
},
|
||||
resetQuery() {
|
||||
this.dateRange = []
|
||||
this.resetForm('queryForm')
|
||||
this.queryParams.pageNum = 1
|
||||
this.getList()
|
||||
},
|
||||
formatLogContent(value) {
|
||||
if (value === null || value === undefined || value === '') {
|
||||
return '-'
|
||||
}
|
||||
if (typeof value !== 'string') {
|
||||
return JSON.stringify(value, null, 2)
|
||||
}
|
||||
try {
|
||||
JSON.parse(value)
|
||||
return js_beautify(value, { indent_size: 2 })
|
||||
} catch (error) {
|
||||
return value
|
||||
}
|
||||
},
|
||||
handleView(row) {
|
||||
this.open = true
|
||||
this.detail = {}
|
||||
this.detailLoading = true
|
||||
getApiLog(row.logId).then(response => {
|
||||
this.detail = response.data || {}
|
||||
}).finally(() => {
|
||||
this.detailLoading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.api-log-detail {
|
||||
min-height: 180px;
|
||||
}
|
||||
|
||||
::v-deep .api-log-dialog {
|
||||
max-width: 920px;
|
||||
}
|
||||
|
||||
::v-deep .api-log-dialog .el-descriptions-item__content {
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.detail-section {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.detail-section h4 {
|
||||
margin: 0 0 8px;
|
||||
color: #303133;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
line-height: 20px;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
.log-content {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
max-height: 220px;
|
||||
margin: 0;
|
||||
overflow: auto;
|
||||
padding: 12px;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 6px;
|
||||
background: #f7f8fa;
|
||||
color: #303133;
|
||||
font-family: Monaco, Menlo, Consolas, monospace;
|
||||
font-size: 12px;
|
||||
line-height: 1.55;
|
||||
letter-spacing: 0;
|
||||
white-space: pre-wrap;
|
||||
overflow-wrap: anywhere;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.log-content-large {
|
||||
max-height: 320px;
|
||||
}
|
||||
|
||||
.error-title {
|
||||
color: #c03639 !important;
|
||||
}
|
||||
|
||||
.error-content {
|
||||
border-color: #f3c5c7;
|
||||
background: #fff6f6;
|
||||
color: #9f2d30;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user