完善slow

This commit is contained in:
xiangheng
2024-11-07 19:03:35 +08:00
parent 784d9bdd4a
commit aeabacc6a5
18 changed files with 350 additions and 303 deletions

View File

@@ -13,6 +13,21 @@
padding: 0;
}
</style>
<script src="/XErr.umd.js"></script>
<script>
const xErr = new XErr.XErr(
{
Dns: `${location.origin}/api`,
Pid: 'e19e3be20de94f49b68fafb4c30668bc',
Uid: ''
},
new XErr.XErrWeb({
onloadTimeOut: 300
})
)
xErr.SetUid(2) //设置用户ID
</script>
<link rel="stylesheet" href="/src/styles/loading.css" />
</head>
<body>

3
admin/public/XErr.umd.js Normal file

File diff suppressed because one or more lines are too long

View File

@@ -11,19 +11,18 @@ import ElementPlus from 'element-plus'
import VForm3 from 'vform3-builds' //引入VForm3库
import { XErr, XErrWeb } from '../../x_err_sdk/web/index'
// { XErr, XErrWeb }
const xErr = new XErr(
{
Dns: `${location.origin}/api`,
Pid: 'e19e3be20de94f49b68fafb4c30668bc',
Uid: ''
},
new XErrWeb({
onloadTimeOut: 3000
})
)
xErr.SetUid(1) //设置用户ID
// import { Base, Web } from '../../x_err_sdk/web/index'
// const xErr = new Base(
// {
// Dns: `${location.origin}/api`,
// Pid: 'e19e3be20de94f49b68fafb4c30668bc',
// Uid: ''
// },
// new Web({
// onloadTimeOut: 300
// })
// )
// xErr.SetUid(1) //设置用户ID
const app = createApp(App)
app.use(install)

View File

@@ -97,10 +97,12 @@ const code = computed(() => {
new XErr(
{
Dns: '${location.origin}/api',
Pid: ${formData.ProjectKey},
Pid: '${formData.ProjectKey}',
Uid: ''
},
new XErrWeb()
new XErrWeb({
onloadTimeOut: 3000
})
)`
})
const formRules = {

View File

@@ -9,16 +9,22 @@
label-width="70px"
label-position="left"
>
<el-form-item label="项目key" prop="ProjectKey" class="w-[280px]">
<el-input v-model="queryParams.ProjectKey" />
</el-form-item>
<el-form-item label="sdk生成的客户端id" prop="ClientId" class="w-[280px]">
<el-input v-model="queryParams.ClientId" />
<el-form-item label="项目" prop="ProjectKey" class="w-[280px]">
<el-select v-model="queryParams.ProjectKey" clearable>
<el-option label="全部" value="" />
<el-option
v-for="(item, index) in listAllData.monitor_project_listAll"
:key="index"
:label="item.ProjectName"
:value="item.ProjectKey"
/>
</el-select>
</el-form-item>
<el-form-item label="用户id" prop="UserId" class="w-[280px]">
<el-input v-model="queryParams.UserId" />
</el-form-item>
<el-form-item label="创建时间" prop="CreateTime" class="w-[280px]">
<el-form-item label="创建时间" prop="CreateTime" class="w-[420px]">
<daterange-picker
v-model:startTime="queryParams.CreateTimeStart"
v-model:endTime="queryParams.CreateTimeEnd"
@@ -32,13 +38,13 @@
</el-card>
<el-card class="!border-none mt-4" shadow="never">
<div class="text-right">
<el-button v-perms="['admin:monitor_slow:add']" type="primary" @click="handleAdd()">
<!-- <el-button v-perms="['admin:monitor_slow:add']" type="primary" @click="handleAdd()">
<template #icon>
<icon name="el-icon-Plus" />
</template>
新增
</el-button>
<upload
</el-button> -->
<!-- <upload
v-perms="['admin:monitor_slow:ImportFile']"
class="ml-3 mr-3"
:url="monitor_slow_import_file"
@@ -53,8 +59,8 @@
</template>
导入
</el-button>
</upload>
<el-button
</upload> -->
<!-- <el-button
v-perms="['admin:monitor_slow:ExportFile']"
type="primary"
@click="exportFile"
@@ -63,7 +69,7 @@
<icon name="el-icon-Download" />
</template>
导出
</el-button>
</el-button> -->
<el-button
v-perms="['admin:monitor_slow:delBatch']"
type="danger"
@@ -81,22 +87,31 @@
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" />
<el-table-column label="项目key" prop="ProjectKey" min-width="130" />
<el-table-column label="sdk生成的客户端id" prop="ClientId" min-width="130" />
<el-table-column label="用户id" prop="UserId" min-width="130" />
<el-table-column label="URL地址" prop="Path" min-width="130" />
<el-table-column label="时间" prop="Time" min-width="130" />
<el-table-column label="创建时间" prop="CreateTime" min-width="130" />
<el-table-column label="操作" width="120" fixed="right">
<el-table-column label="项目" prop="ProjectKey" width="150">
<template #default="{ row }">
<el-button
<dict-value
:options="listAllData.monitor_project_listAll"
:value="row.ProjectKey"
labelKey="ProjectName"
valueKey="ProjectKey"
/>
</template>
</el-table-column>
<el-table-column label="用户id" prop="UserId" width="150" />
<el-table-column label="URL地址" prop="Path" />
<el-table-column label="时间(毫秒)" prop="Time" width="130" />
<el-table-column label="创建时间" prop="CreateTime" width="180" />
<el-table-column label="操作" width="80" fixed="right">
<template #default="{ row }">
<!-- <el-button
v-perms="['admin:monitor_slow:edit']"
type="primary"
link
@click="handleEdit(row)"
>
编辑
</el-button>
</el-button> -->
<el-button
v-perms="['admin:monitor_slow:del']"
type="danger"
@@ -116,16 +131,15 @@
</div>
</template>
<script lang="ts" setup>
import { ref, reactive, shallowRef, nextTick } from 'vue'
import { ref, reactive, shallowRef } from 'vue'
import {
monitor_slow_delete,
monitor_slow_delete_batch,
monitor_slow_list,
monitor_slow_import_file,
monitor_slow_export_file
monitor_slow_list
} from '@/api/monitor/slow'
import type { type_monitor_slow, type_monitor_slow_query } from '@/api/monitor/slow'
import { useListAllData } from '@/hooks/useDictOptions'
import { usePaging } from '@/hooks/usePaging'
import feedback from '@/utils/feedback'
import EditPopup from './edit.vue'
@@ -148,19 +162,12 @@ const { pager, getLists, resetPage, resetParams } = usePaging<type_monitor_slow>
fetchFun: monitor_slow_list,
params: queryParams
})
const { listAllData } = useListAllData<{
monitor_project_listAll: any[]
}>({
monitor_project_listAll: '/monitor_project/listAll'
})
const handleAdd = async () => {
showEdit.value = true
await nextTick()
editRef.value?.open('add')
}
const handleEdit = async (data: any) => {
showEdit.value = true
await nextTick()
editRef.value?.open('edit')
editRef.value?.getDetail(data)
}
const multipleSelection = ref<type_monitor_slow[]>([])
const handleSelectionChange = (val: type_monitor_slow[]) => {
console.log(val)
@@ -191,11 +198,5 @@ const deleteBatch = async () => {
} catch (error) {}
}
const exportFile = async () => {
try {
await feedback.confirm('确定要导出?')
await monitor_slow_export_file(queryParams)
} catch (error) {}
}
getLists()
</script>

View File

@@ -23,10 +23,12 @@ export default ({ mode }) => {
// 依赖预构建,避免开发刷新
include: ['@wangeditor/editor-for-vue', 'vuedraggable', 'vue-echarts', 'crypto-js']
},
base: '/',
build: {
sourcemap: true,
rollupOptions: {
external: ['XErr'],
output: {
manualChunks: {
vue: ['vue'],

View File

@@ -13,6 +13,7 @@ import (
"x_admin/core/response"
"x_admin/util"
"x_admin/util/excel2"
"x_admin/util/img_util"
"github.com/gin-gonic/gin"
"golang.org/x/sync/singleflight"
@@ -141,28 +142,24 @@ func (hd *MonitorClientHandler) Add(c *gin.Context) {
data, err := url.QueryUnescape(c.Query("data"))
if err != nil {
// response.CheckAndRespWithData(c, 0, err)
c.Writer.WriteString("0")
c.Data(200, "image/gif", img_util.EmptyGif())
return
}
var addReq MonitorClientAddReq
json.Unmarshal([]byte(data), &addReq)
// if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &addReq)) {
// return
// }
lastClient, err := MonitorClientService.DetailByClientId(*addReq.ClientId)
uaStr := c.GetHeader("user-agent")
ip := c.ClientIP()
// createFlag := true
if err == nil {
last := lastClient.UserId + lastClient.Width.String() + lastClient.Height.String() + lastClient.Ip + lastClient.Ua
newStr := *addReq.UserId + addReq.Width.String() + addReq.Height.String() + ip + uaStr
if last == newStr {
// 前后数据一样,不用创建新的数据
fmt.Println("前后数据一样,不用创建新的数据")
c.Writer.WriteString("0")
c.Data(200, "image/gif", img_util.EmptyGif())
// response.CheckAndRespWithData(c, 0, nil)
return
} else {
@@ -188,10 +185,9 @@ func (hd *MonitorClientHandler) Add(c *gin.Context) {
addReq.Province = &regionInfo.Province
}
createId, _ := MonitorClientService.Add(addReq)
// response.CheckAndRespWithData(c, createId, e)
// c.Value(createId)
c.Writer.WriteString(strconv.Itoa(createId))
MonitorClientService.Add(addReq)
c.Data(200, "image/gif", img_util.EmptyGif())
}
// @Summary 监控-客户端信息删除

View File

@@ -1,11 +1,7 @@
package monitor_error
import (
"bytes"
"encoding/json"
"image"
"image/color"
"image/gif"
"net/http"
"net/url"
"strconv"
@@ -15,6 +11,7 @@ import (
"x_admin/core/response"
"x_admin/util"
"x_admin/util/excel2"
"x_admin/util/img_util"
"github.com/gin-gonic/gin"
"golang.org/x/sync/singleflight"
@@ -111,7 +108,8 @@ func (hd *MonitorErrorHandler) Detail(c *gin.Context) {
func (hd *MonitorErrorHandler) Add(c *gin.Context) {
data, err := url.QueryUnescape(c.Query("data"))
if err != nil {
response.CheckAndRespWithData(c, 0, err)
// response.CheckAndRespWithData(c, 0, err)
c.Data(200, "image/gif", img_util.EmptyGif())
return
}
@@ -124,35 +122,8 @@ func (hd *MonitorErrorHandler) Add(c *gin.Context) {
for i := 0; i < len(addReq); i++ {
MonitorErrorService.Add(addReq[i])
}
img := image.NewRGBA(image.Rect(0, 0, 1, 1))
// 设置像素颜色为黑色
img.Set(0, 0, color.Black)
// 创建GIF动画
g := &gif.GIF{
Image: []*image.Paletted{imageToPaletted(img)},
Delay: []int{0}, // 延迟时间单位是10毫秒
}
var buffer bytes.Buffer
// 编码GIF到缓冲区
err = gif.EncodeAll(&buffer, g)
// response.CheckAndRespWithData(c, g, nil)
c.Data(200, "image/gif", buffer.Bytes())
}
// 将image.Image转换为*image.Paletted
func imageToPaletted(img image.Image) *image.Paletted {
b := img.Bounds()
pm := image.NewPaletted(b, color.Palette{color.Black})
for y := b.Min.Y; y < b.Max.Y; y++ {
for x := b.Min.X; x < b.Max.X; x++ {
pm.Set(x, y, img.At(x, y))
}
}
return pm
c.Data(200, "image/gif", img_util.EmptyGif())
}
// @Summary 监控-错误列删除

View File

@@ -1,38 +1,42 @@
package monitor_slow
import (
"encoding/json"
"net/http"
"net/url"
"strconv"
"strings"
"time"
"github.com/gin-gonic/gin"
"x_admin/core/request"
"x_admin/core/response"
"x_admin/util"
"x_admin/util/excel2"
"x_admin/util/img_util"
"github.com/gin-gonic/gin"
"golang.org/x/sync/singleflight"
)
type MonitorSlowHandler struct {
requestGroup singleflight.Group
}
// @Summary 监控-错误列列表
// @Tags monitor_slow-监控-错误列
// @Produce json
// @Param Token header string true "token"
// @Param PageNo query int true "页码"
// @Param PageSize query int true "每页数量"
// @Param ProjectKey query string false "项目key"
// @Param ClientId query string false "sdk生成的客户端id"
// @Param UserId query string false "用户id"
// @Param Path query string false "URL地址"
// @Param Time query number false "时间"
// @Param CreateTimeStart query string false "创建时间"
// @Param CreateTimeEnd query string false "创建时间"
//@Success 200 {object} response.Response{ data=response.PageResp{ lists=[]MonitorSlowResp}} "成功"
//@Router /api/admin/monitor_slow/list [get]
// @Summary 监控-错误列列表
// @Tags monitor_slow-监控-错误列
// @Produce json
// @Param Token header string true "token"
// @Param PageNo query int true "页码"
// @Param PageSize query int true "每页数量"
// @Param ProjectKey query string false "项目key"
// @Param ClientId query string false "sdk生成的客户端id"
// @Param UserId query string false "用户id"
// @Param Path query string false "URL地址"
// @Param Time query number false "时间"
// @Param CreateTimeStart query string false "创建时间"
// @Param CreateTimeEnd query string false "创建时间"
//
// @Success 200 {object} response.Response{ data=response.PageResp{ lists=[]MonitorSlowResp}} "成功"
// @Router /api/admin/monitor_slow/list [get]
func (hd *MonitorSlowHandler) List(c *gin.Context) {
var page request.PageReq
var listReq MonitorSlowListReq
@@ -46,18 +50,18 @@ func (hd *MonitorSlowHandler) List(c *gin.Context) {
response.CheckAndRespWithData(c, res, err)
}
// @Summary 监控-错误列列表-所有
// @Tags monitor_slow-监控-错误列
// @Produce json
// @Param ProjectKey query string false "项目key"
// @Param ClientId query string false "sdk生成的客户端id"
// @Param UserId query string false "用户id"
// @Param Path query string false "URL地址"
// @Param Time query number false "时间"
// @Param CreateTimeStart query string false "创建时间"
// @Param CreateTimeEnd query string false "创建时间"
// @Success 200 {object} response.Response{ data=[]MonitorSlowResp} "成功"
// @Router /api/admin/monitor_slow/listAll [get]
// @Summary 监控-错误列列表-所有
// @Tags monitor_slow-监控-错误列
// @Produce json
// @Param ProjectKey query string false "项目key"
// @Param ClientId query string false "sdk生成的客户端id"
// @Param UserId query string false "用户id"
// @Param Path query string false "URL地址"
// @Param Time query number false "时间"
// @Param CreateTimeStart query string false "创建时间"
// @Param CreateTimeEnd query string false "创建时间"
// @Success 200 {object} response.Response{ data=[]MonitorSlowResp} "成功"
// @Router /api/admin/monitor_slow/listAll [get]
func (hd *MonitorSlowHandler) ListAll(c *gin.Context) {
var listReq MonitorSlowListReq
if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &listReq)) {
@@ -67,13 +71,13 @@ func (hd *MonitorSlowHandler) ListAll(c *gin.Context) {
response.CheckAndRespWithData(c, res, err)
}
// @Summary 监控-错误列详情
// @Tags monitor_slow-监控-错误列
// @Produce json
// @Param Token header string true "token"
// @Param Id query number false "错误id"
// @Success 200 {object} response.Response{ data=MonitorSlowResp} "成功"
// @Router /api/admin/monitor_slow/detail [get]
// @Summary 监控-错误列详情
// @Tags monitor_slow-监控-错误列
// @Produce json
// @Param Token header string true "token"
// @Param Id query number false "错误id"
// @Success 200 {object} response.Response{ data=MonitorSlowResp} "成功"
// @Router /api/admin/monitor_slow/detail [get]
func (hd *MonitorSlowHandler) Detail(c *gin.Context) {
var detailReq MonitorSlowDetailReq
if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &detailReq)) {
@@ -87,52 +91,58 @@ func (hd *MonitorSlowHandler) Detail(c *gin.Context) {
response.CheckAndRespWithData(c, res, err)
}
// @Summary 监控-错误列新增
// @Tags monitor_slow-监控-错误列
// @Produce json
// @Param Token header string true "token"
// @Param ProjectKey body string false "项目key"
// @Param ClientId body string false "sdk生成的客户端id"
// @Param UserId body string false "用户id"
// @Param Path body string false "URL地址"
// @Param Time body number false "时间"
// @Success 200 {object} response.Response "成功"
// @Router /api/admin/monitor_slow/add [post]
// @Summary 监控-错误列新增
// @Tags monitor_slow-监控-错误列
// @Produce json
// @Param Token header string true "token"
// @Param ProjectKey body string false "项目key"
// @Param ClientId body string false "sdk生成的客户端id"
// @Param UserId body string false "用户id"
// @Param Path body string false "URL地址"
// @Param Time body number false "时间"
// @Success 200 {object} response.Response "成功"
// @Router /api/admin/monitor_slow/add [post]
func (hd *MonitorSlowHandler) Add(c *gin.Context) {
var addReq MonitorSlowAddReq
if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &addReq)) {
data, err := url.QueryUnescape(c.Query("data"))
if err != nil {
c.Data(200, "image/gif", img_util.EmptyGif())
return
}
createId, e := MonitorSlowService.Add(addReq)
response.CheckAndRespWithData(c,createId, e)
var addReq MonitorSlowAddReq
json.Unmarshal([]byte(data), &addReq)
MonitorSlowService.Add(addReq)
c.Data(200, "image/gif", img_util.EmptyGif())
}
// @Summary 监控-错误列编辑
// @Tags monitor_slow-监控-错误列
// @Produce json
// @Param Token header string true "token"
// @Param Id body number false "错误id"
// @Param ProjectKey body string false "项目key"
// @Param ClientId body string false "sdk生成的客户端id"
// @Param UserId body string false "用户id"
// @Param Path body string false "URL地址"
// @Param Time body number false "时间"
// @Success 200 {object} response.Response "成功"
// @Router /api/admin/monitor_slow/edit [post]
// @Summary 监控-错误列编辑
// @Tags monitor_slow-监控-错误列
// @Produce json
// @Param Token header string true "token"
// @Param Id body number false "错误id"
// @Param ProjectKey body string false "项目key"
// @Param ClientId body string false "sdk生成的客户端id"
// @Param UserId body string false "用户id"
// @Param Path body string false "URL地址"
// @Param Time body number false "时间"
// @Success 200 {object} response.Response "成功"
// @Router /api/admin/monitor_slow/edit [post]
func (hd *MonitorSlowHandler) Edit(c *gin.Context) {
var editReq MonitorSlowEditReq
if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &editReq)) {
return
}
response.CheckAndRespWithData(c,editReq.Id, MonitorSlowService.Edit(editReq))
response.CheckAndRespWithData(c, editReq.Id, MonitorSlowService.Edit(editReq))
}
// @Summary 监控-错误列删除
// @Tags monitor_slow-监控-错误列
// @Produce json
// @Param Token header string true "token"
// @Param Id body number false "错误id"
// @Success 200 {object} response.Response "成功"
// @Router /api/admin/monitor_slow/del [post]
// @Summary 监控-错误列删除
// @Tags monitor_slow-监控-错误列
// @Produce json
// @Param Token header string true "token"
// @Param Id body number false "错误id"
// @Success 200 {object} response.Response "成功"
// @Router /api/admin/monitor_slow/del [post]
func (hd *MonitorSlowHandler) Del(c *gin.Context) {
var delReq MonitorSlowDelReq
if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &delReq)) {
@@ -143,6 +153,7 @@ func (hd *MonitorSlowHandler) Del(c *gin.Context) {
// @Summary 监控-错误列删除-批量
// @Tags monitor_slow-监控-错误列
//
// @Produce json
// @Param Token header string true "token"
// @Param Ids body string false "逗号分割的id"
@@ -162,20 +173,18 @@ func (hd *MonitorSlowHandler) DelBatch(c *gin.Context) {
response.CheckAndResp(c, MonitorSlowService.DelBatch(Ids))
}
// @Summary 监控-错误列导出
// @Tags monitor_slow-监控-错误列
// @Produce json
// @Param Token header string true "token"
// @Param ProjectKey query string false "项目key"
// @Param ClientId query string false "sdk生成的客户端id"
// @Param UserId query string false "用户id"
// @Param Path query string false "URL地址"
// @Param Time query number false "时间"
// @Param CreateTimeStart query string false "创建时间"
// @Param CreateTimeEnd query string false "创建时间"
// @Router /api/admin/monitor_slow/ExportFile [get]
// @Summary 监控-错误列导出
// @Tags monitor_slow-监控-错误列
// @Produce json
// @Param Token header string true "token"
// @Param ProjectKey query string false "项目key"
// @Param ClientId query string false "sdk生成的客户端id"
// @Param UserId query string false "用户id"
// @Param Path query string false "URL地址"
// @Param Time query number false "时间"
// @Param CreateTimeStart query string false "创建时间"
// @Param CreateTimeEnd query string false "创建时间"
// @Router /api/admin/monitor_slow/ExportFile [get]
func (hd *MonitorSlowHandler) ExportFile(c *gin.Context) {
var listReq MonitorSlowListReq
if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &listReq)) {
@@ -186,18 +195,18 @@ func (hd *MonitorSlowHandler) ExportFile(c *gin.Context) {
response.FailWithMsg(c, response.SystemError, "查询信息失败")
return
}
f, err := excel2.Export(res,MonitorSlowService.GetExcelCol(), "Sheet1", "监控-错误列")
f, err := excel2.Export(res, MonitorSlowService.GetExcelCol(), "Sheet1", "监控-错误列")
if err != nil {
response.FailWithMsg(c, response.SystemError, "导出失败")
return
}
excel2.DownLoadExcel("监控-错误列" + time.Now().Format("20060102-150405"), c.Writer, f)
excel2.DownLoadExcel("监控-错误列"+time.Now().Format("20060102-150405"), c.Writer, f)
}
// @Summary 监控-错误列导入
// @Tags monitor_slow-监控-错误列
// @Produce json
// @Router /api/admin/monitor_slow/ImportFile [post]
// @Summary 监控-错误列导入
// @Tags monitor_slow-监控-错误列
// @Produce json
// @Router /api/admin/monitor_slow/ImportFile [post]
func (hd *MonitorSlowHandler) ImportFile(c *gin.Context) {
file, _, err := c.Request.FormFile("file")
if err != nil {
@@ -206,7 +215,7 @@ func (hd *MonitorSlowHandler) ImportFile(c *gin.Context) {
}
defer file.Close()
importList := []MonitorSlowResp{}
err = excel2.GetExcelData(file, &importList,MonitorSlowService.GetExcelCol())
err = excel2.GetExcelData(file, &importList, MonitorSlowService.GetExcelCol())
if err != nil {
c.String(http.StatusInternalServerError, err.Error())
return

View File

@@ -1,63 +1,61 @@
package monitor_slow
import (
"x_admin/core"
)
//MonitorSlowListReq 监控-错误列列表参数
// MonitorSlowListReq 监控-错误列列表参数
type MonitorSlowListReq struct {
ProjectKey *string // 项目key
ClientId *string // sdk生成的客户端id
UserId *string // 用户id
Path *string // URL地址
Time *float64 // 时间
CreateTimeStart *string // 开始创建时间
CreateTimeEnd *string // 结束创建时间
ProjectKey *string // 项目key
ClientId *string // sdk生成的客户端id
UserId *string // 用户id
Path *string // URL地址
Time *float64 // 时间
CreateTimeStart *string // 开始创建时间
CreateTimeEnd *string // 结束创建时间
}
//MonitorSlowAddReq 监控-错误列新增参数
// MonitorSlowAddReq 监控-错误列新增参数
type MonitorSlowAddReq struct {
ProjectKey *string // 项目key
ClientId *string // sdk生成的客户端id
UserId *string // 用户id
Path *string // URL地址
Time core.NullFloat // 时间
ProjectKey *string // 项目key
ClientId *string // sdk生成的客户端id
UserId *string // 用户id
Path *string // URL地址
Time core.NullFloat // 时间
}
//MonitorSlowEditReq 监控-错误列编辑参数
// MonitorSlowEditReq 监控-错误列编辑参数
type MonitorSlowEditReq struct {
Id int // 错误id
ProjectKey *string // 项目key
ClientId *string // sdk生成的客户端id
UserId *string // 用户id
Path *string // URL地址
Time core.NullFloat // 时间
Id int // 错误id
ProjectKey *string // 项目key
ClientId *string // sdk生成的客户端id
UserId *string // 用户id
Path *string // URL地址
Time core.NullFloat // 时间
}
//MonitorSlowDetailReq 监控-错误列详情参数
// MonitorSlowDetailReq 监控-错误列详情参数
type MonitorSlowDetailReq struct {
Id int // 错误id
Id int // 错误id
}
//MonitorSlowDelReq 监控-错误列删除参数
// MonitorSlowDelReq 监控-错误列删除参数
type MonitorSlowDelReq struct {
Id int // 错误id
Id int // 错误id
}
//MonitorSlowDelReq 监控-错误列批量删除参数
// MonitorSlowDelReq 监控-错误列批量删除参数
type MonitorSlowDelBatchReq struct {
Ids string
}
//MonitorSlowResp 监控-错误列返回信息
// MonitorSlowResp 监控-错误列返回信息
type MonitorSlowResp struct {
Id int // 错误id
ProjectKey string // 项目key
ClientId string // sdk生成的客户端id
UserId string // 用户id
Path string // URL地址
Time core.NullFloat // 时间
CreateTime core.NullTime // 创建时间
Id int // 错误id
ProjectKey string // 项目key
ClientId string // sdk生成的客户端id
UserId string // 用户id
Path string // URL地址
Time core.NullFloat // 时间
CreateTime core.NullTime // 创建时间
}

View File

@@ -45,7 +45,7 @@ INSERT INTO x_system_auth_menu (pid, menu_type, menu_name, perms,is_cache, is_sh
// MonitorSlowRoute(rg)
func MonitorSlowRoute(rg *gin.RouterGroup) {
handle := monitor_slow.MonitorSlowHandler{}
rg.POST("/monitor_slow/add", middleware.RecordLog("慢接口新增"), handle.Add)
rg.GET("/monitor_slow/add", middleware.RecordLog("慢接口新增"), handle.Add)
r := rg.Group("/", middleware.TokenAuth())
r.GET("/monitor_slow/list", handle.List)
r.GET("/monitor_slow/listAll", handle.ListAll)

View File

@@ -0,0 +1,38 @@
package img_util
import (
"bytes"
"image"
"image/color"
"image/gif"
)
func EmptyGif() []byte {
img := image.NewRGBA(image.Rect(0, 0, 1, 1))
// 设置像素颜色为黑色
img.Set(0, 0, color.Black)
// 创建GIF动画
g := &gif.GIF{
Image: []*image.Paletted{imageToPaletted(img)},
Delay: []int{0}, // 延迟时间单位是10毫秒
}
var buffer bytes.Buffer
// 编码GIF到缓冲区
gif.EncodeAll(&buffer, g)
return buffer.Bytes()
}
// 将image.Image转换为*image.Paletted
func imageToPaletted(img image.Image) *image.Paletted {
b := img.Bounds()
pm := image.NewPaletted(b, color.Palette{color.Black})
for y := b.Min.Y; y < b.Max.Y; y++ {
for x := b.Min.X; x < b.Max.X; x++ {
pm.Set(x, y, img.At(x, y))
}
}
return pm
}

View File

@@ -2,21 +2,25 @@
"name": "@adtkcn/x_err_sdk",
"version": "1.0.0",
"description": "错误监控sdk",
"main": "dist/web/index.js",
"main": "dist/web/XErr.umd.js",
"private": false,
"file": [
"dist"
],
"scripts": {
"build": "npm run build:web&&npm run build:ts",
"build:web": "esbuild web/index.ts --bundle --sourcemap --minify --outfile=dist/web/index.js --format=esm --target=es2015",
"build": "vite build&&npm run build:ts",
"build:ts": "tsc --emitDeclarationOnly",
"outdated": "pnpm outdated"
},
"keywords": ["x_err_sdk","X_admin"],
"keywords": [
"x_err_sdk",
"X_admin"
],
"author": "adtkcn",
"license": "ISC",
"dependencies": {},
"devDependencies": {
"typescript": "^5.6.3",
"uuid": "^11.0.2",
"esbuild": "^0.24.0"
"vite": "^5.4.10"
}
}

View File

@@ -5,13 +5,20 @@ export type LogWithEnv = {
ScreenWidth?: number;
};
export type LogWithError = {
Type: "error"|"event"|"resources"|'click'|'historyChange'|'hashChange'|'onloadTime';
Type: "error"|"event"|"resources"|'click';
EventType: string;
Path:string;
Message?: string;
Stack?: string;
};
export type ISlow = {
Type: "onloadTime"
Path:string;
Time: number;
};
// 扩展必须实现的接口
export interface IErrorEvent {
@@ -23,4 +30,4 @@ export interface IErrorEvent {
listen(callback: ListenCallbackFn): void;
unListen(): void;
}
export type ListenCallbackFn = (params: LogWithError) => void;
export type ListenCallbackFn = (params: LogWithError|ISlow) => void;

21
x_err_sdk/vite.config.js Normal file
View File

@@ -0,0 +1,21 @@
import { defineConfig, loadEnv } from 'vite'
export default defineConfig({
build: {
lib: {
entry: 'web/index.ts', // 库的入口文件
name: 'XErr', // 库的名称
fileName: (format) => `web/XErr.${format}.js`, // 输出文件名
},
rollupOptions: {
// 外部化处理不想打包进库的依赖
// external: ['vue'],
output: {
globals: {
// vue: 'Vue'
}
}
}
}
})

View File

@@ -1,5 +1,5 @@
import { v1 as uuid_v1 } from "uuid";
import type { LogWithError, IErrorEvent, LogWithEnv } from "../types";
import type { LogWithError, IErrorEvent,ISlow, LogWithEnv } from "../types";
type Uid = string | number;
@@ -9,7 +9,7 @@ type Props = {
Uid?: Uid; //用户标识
};
class XLog {
class Base {
private Dns: string = "";
private client_id: string = "";
private Pid: string = "";
@@ -38,17 +38,23 @@ class XLog {
return;
}
if (props.Uid) {
this.Uid = props.Uid;
this.Uid = String(props.Uid);
}
this.setClientID();
this.SetUid();
this.getLocalMessage();
// 监听错误
platform.listen((params: LogWithError) => {
console.log("listenCallback", params);
this.Push(params);
// 监听错误
platform.listen((params: LogWithError|ISlow) => {
console.log("listenCallback", params);
if(params.Type=='onloadTime'){
let slow=params as ISlow;
this.uploadSlow(slow);
}else{
this.Push(params);
}
});
this.timer = setInterval(() => {
@@ -59,8 +65,8 @@ class XLog {
// 设置用户id
public SetUid(uid?: Uid) {
if (uid) {
this.Uid = uid;
this.platform?.setCache("x_err_uid", uid);
this.Uid =String(uid) ;
this.platform?.setCache("x_err_uid", this.Uid);
} else {
const u_id = this.platform?.getCache("x_err_uid");
@@ -127,6 +133,23 @@ class XLog {
});
} catch (error) {}
}
public uploadSlow=(envInfo: ISlow) =>{
if (!this.Dns) return; //未设置Dns服务器不上传
try {
this.platform
?.upload(this.Dns + `/admin/monitor_slow/add`, {
ProjectKey: this.Pid,
ClientId: this.client_id,
UserId: this.Uid,
Path: envInfo.Path,
Time: envInfo.Time,
})
.catch((err: any) => {
// 上传失败
});
} catch (error) {}
}
// 上传文件
public upload() {
@@ -149,4 +172,4 @@ class XLog {
this.platform?.unListen();
}
}
export default XLog;
export default Base;

View File

@@ -1,6 +1,4 @@
import XErr from "./err-entry"
import XErrWeb from "./err-implement"
export {XErr,XErrWeb}
import Base from "./base";
import Web from "./web";
export { Base, Web };

View File

@@ -2,18 +2,18 @@ import type {
LogWithError,
LogWithEnv,
ListenCallbackFn,
IErrorEvent,
IErrorEvent,ISlow
} from "../types";
interface LoggerProps {
// timeout:number
onloadTimeOut?: number;
}
class Logger implements IErrorEvent {
class Web implements IErrorEvent {
props: LoggerProps;
constructor(props?: LoggerProps) {
this.props = {
onloadTimeOut: 3000,
onloadTimeOut: 5000,
...props,
};
}
@@ -67,7 +67,7 @@ class Logger implements IErrorEvent {
}
return env;
}
private callback(err: LogWithError): void {}
private callback(err: LogWithError|ISlow): void {}
private listenError = (err: any) => {
console.error([err]);
let target = err.target;
@@ -117,46 +117,8 @@ class Logger implements IErrorEvent {
});
}
};
// private listenClick = (e: Event) => {
// let target = e.target as HTMLElement;
// let tagName = target?.localName;
// let name = [tagName];
// if (target.id) {
// name.push("#" + target.id);
// }
// target.classList.forEach((item) => {
// name.push("." + item);
// });
// if (target.innerText) {
// name.push(":" + target.innerText.slice(0, 20));
// }
// this.callback({
// Type: "click",
// EventType: "click",
// Path: window.location.href,
// Message: name.join(""),
// Stack: "",
// });
// };
// private listenHistoryRouterChange = () => {
// this.callback({
// Type: "historyChange",
// EventType: "popstate",
// Path: window.location.href,
// Message: "",
// Stack: "",
// });
// };
// // 监听hash
// private listenHashRouterChange = () => {
// this.callback({
// Type: "hashChange",
// EventType: "hashChange",
// Path: window.location.href,
// Message: "",
// Stack: "",
// });
// };
private handleStack(stack: string): string {
let newStack: string[] = [];
if (stack) {
@@ -186,10 +148,8 @@ class Logger implements IErrorEvent {
// 页面加载时间5s以上
this.callback({
Type: "onloadTime",
EventType: "onloadTime",
Path: window.location.href,
Message: "时间:" + parseFloat(onloadTime.toFixed(2)) + "ms",
Stack: "",
Time:onloadTime
});
}
}
@@ -216,4 +176,4 @@ class Logger implements IErrorEvent {
}
}
export default Logger;
export default Web;