日志上下文浏览 - 自定义 Drawer 和 Scroll 实现

mac2024-04-19  3

1. 前言

    运维系统接入日志查询,开发日志上下文功能方便查看日志。     参照阿里云日志服务控制台上下文浏览。

图1-1.日志上下文浏览图

2. 效果

    查看日志列表时,选中某条日志查看其上下文,查询指定日志前后紧邻时间的记录。效果是抽屉加滚动列表;element-ui 组件支持InfiniteScroll(无限滚动组件)和Drawer(抽屉组件)实现。此处使用原生HTML 标签及CSS 样式自定义实现Drawer 效果。

图2-1.日志查询列表图     选中某行日志记录,展开日志可选择查询上下文,上下文查询支持查询紧邻的更早时间记录,更新可查看当前日志时间点之后紧邻的记录。

图2-2.日志查询上下文图

图2-3.日志查询上下文更早日志图

图2-4.日志查询上下文更新日志图

3. 实现

    日志查询模块文件结构如图

图3-1.日志查询文件结构图

    NSTableAnalysisLog.js 和NSTableAnalysisLog.vue 是图2-1.日志查询日志列表图中的日志表单列表效果页。日志上下文效果在index.vue 文件实现。     此处贴出index.vue 和index.js 文件代码。

3.1 index.vue

<template> <div class="page-operate-analysis-log"> <ns-table-analysis-log/> <!-- <el-drawer title="我是标题" :visible.sync="drawer" direction="rtl"> <span>我来啦!</span> </el-drawer> --> <div class="ns-drawer"> <div :class="drawer?'mask':''"/> <div :class="drawer?'open':'close'"> <ns-button @click="closeDrawer()" class="ns-drawer-close" icon="el-icon-close" circle></ns-button> <div class="ns-drawer-header"> 日志上下文浏览 </div> <br/> <ns-button class="ns-button" type="info" @click="handleTopMore">更早</ns-button> <div class="ns-loading"> <span v-if="topLoading">加载中...</span> </div> <div class="ns-data-log" v-for="(dataLog, index) in dataLogList" :key="index"> <pre> <font v-if="dataLog.orderNumber > 0" color=red>【{{dataLog.orderNumber}}】</font><font v-if="dataLog.orderNumber < 0" color=blue>【{{dataLog.orderNumber}}】</font><font v-if="dataLog.orderNumber === 0" color=black>【{{dataLog.orderNumber}}】</font><b>【{{dataLog.time}}】{{dataLog.level}}:{{dataLog.location}}</b> <b>日志信息</b>:{{dataLog.message}} <b>日志详情</b>:{{dataLog.log}} </pre> </div> <div class="ns-loading"> <span v-if="buttomLoading">加载中...</span> <span v-if="!topLoading && !buttomLoading && dataLogList.length === 0">暂无数据</span> </div> <ns-button class="ns-button" type="info" @click="handleButtomMore">更新</ns-button> </div> </div> </div> </template> <script> import NsTableAnalysisLog from './NsTableAnalysisLog' import index from './src' index.components = { NsTableAnalysisLog } export default index </script> <style> pre { display: block; font-family: -moz-fixed; margin: 1em 0; white-space: pre-wrap; word-wrap: break-word; } .ns-button { width: 100%; } .ns-data-log { background: #FAFAFA; margin: 5px; } .ns-loading { text-align: center; font-weight: 700; margin: 10px;; } .ns-drawer { .mask { position: fixed; z-index: 10; left: 0; top: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, .1); } .close { position: absolute; z-index: 10; left: -800px; top: 0; width: 800px; height: 100%; background: #fff; transition: left linear 1s; } .open { z-index: 10; right: 0; top: 0; width: 70%; height: 100%; padding-left: 1%; padding-right: 1%; float: right; overflow-y: auto; position: fixed; background: #fff; transition: left linear 1s; .ns-drawer-header { margin-top: 10%; font-size: 14px; font-weight: 700; float: right; } .ns-drawer-close { margin-top: 5%; position: fixed; } } } </style>

3.2 index.js

import NsTableAnalysisLog from '../NsTableAnalysisLog' // import InfiniteScroll from 'vue-infinite-scroll' // import drawer from 'drawer' export default { name: 'OperateAnalysisLog', components: { NsTableAnalysisLog }, data () { return { // 记录日志库 platformSLSType: '', startTime: '', endTime: '', dataLogList: [], // 加载中 topLoading: false, topNoMore: false, buttomLoading: false, buttomNoMore: false, // 抽屉 drawer: false } }, methods: { showDrawer (row, platformSLSType, date) { this.buttomLoading = true this.platformSLSType = platformSLSType this.startTime = date[0] this.endTime = date[1] this.drawer = true let type = 0 this.handleCursorLogContext(row, type) }, closeDrawer () { this.buttomLoading = false this.topLoading = false this.drawer = false this.dataLogList = [] }, handleButtomMore () { this.buttomLoading = true // 查询之后的日志 let type = 0 let size = this.dataLogList.length - 1 let row = this.dataLogList[size] this.handleCursorLogContext(row, type) }, handleTopMore () { this.topLoading = true // 查询更早的日志 let type = 1 let row = this.dataLogList[0] this.handleCursorLogContext(row, type) }, // 上下文查询,type = 0 更新,type = 1 更早 handleCursorLogContext (row, type) { if (row === undefined || row === null) { this.$notify.warning('当前日志上下文暂无数据!') this.buttomLoading = false this.topLoading = false return } if (this.dataLogList.length > 300) { this.$notify.warning('当前日志上下文已超出300条记录!') this.buttomLoading = false this.topLoading = false return } let params = { startTime: this.startTime, endTime: this.endTime, fromTime: row.time, logStore: this.platformSLSType, type: type } this.$http.fetch(this.$api.operate.analysisLog.findCursorLogList, params) .then((resp) => { let resultLength = resp.result.length let dataLogListLength = this.dataLogList.length if (type === 0) { let resultData = [] for (var index = 0; index < resultLength; index++) { let resultIndex = resp.result[index] let indexOfFlag = false for (let dataLog of this.dataLogList) { if (dataLog.level === resultIndex.level && dataLog.location === resultIndex.location && dataLog.log === resultIndex.log && dataLog.message === resultIndex.message && dataLog.time === resultIndex.time) { indexOfFlag = true } } if (indexOfFlag) { continue } if (index === 0 && this.dataLogList.length === 0) { resultIndex.orderNumber = 0 } else if (index === 0 && this.dataLogList.length > 0) { resultIndex.orderNumber = this.dataLogList[this.dataLogList.length - 1].orderNumber + 1 } else if (index > 0) { resultIndex.orderNumber = resp.result[index - 1].orderNumber + 1 } resultData.push(resultIndex) } this.dataLogList = this.dataLogList.concat(resultData) } else if (type === 1) { for (var i = resultLength - 1; i > 0; i--) { if (this.dataLogList.indexOf(resp.result[i]) !== -1) { continue } // 清空临时数据 let tempData = [] if (i === resultLength - 1 && this.dataLogList.length === 0) { resp.result[i].orderNumber = 0 } else if (i === resultLength - 1 && this.dataLogList.length > 0) { resp.result[i].orderNumber = this.dataLogList[0].orderNumber - 1 tempData.push(resp.result[i]) this.dataLogList = tempData.concat(this.dataLogList) } else if (i > 0) { resp.result[i].orderNumber = resp.result[i + 1].orderNumber - 1 tempData.push(resp.result[i]) this.dataLogList = tempData.concat(this.dataLogList) } } } if (dataLogListLength === this.dataLogList.length) { this.$notify.warning('暂无更多数据!') } }).catch((resp) => { this.$notify.warning(resp.msg) }).finally(() => { this.buttomLoading = false this.topLoading = false }) } } }

3.3 附件:日志记录实体类SLSMessageVo.java

import io.swagger.annotations.ApiModelProperty; import lombok.Getter; import lombok.Setter; import lombok.ToString; @Setter @Getter @ToString public class SLSMessageVo { @ApiModelProperty(value = "日志级别") private String level; @ApiModelProperty(value = "location") private String location; @ApiModelProperty(value = "日志信息") private String message; @ApiModelProperty(value = "日志时间") private String time; @ApiModelProperty(value = "日志详情") private String log; @ApiModelProperty(value = "序号") private Integer orderNumber; }

The End

最新回复(0)