Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
E
ezijing-node-server
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
EzijingWeb
ezijing-node-server
Commits
399048a6
提交
399048a6
authored
12月 03, 2025
作者:
王鹏飞
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
chore: update
上级
78f4550b
显示空白字符变更
内嵌
并排
正在显示
4 个修改的文件
包含
30 行增加
和
33 行删除
+30
-33
package-lock.json
package-lock.json
+7
-0
package.json
package.json
+1
-0
logs.model.js
src/modules/logs/logs.model.js
+12
-3
logs.service.js
src/modules/logs/logs.service.js
+10
-30
没有找到文件。
package-lock.json
浏览文件 @
399048a6
...
...
@@ -12,6 +12,7 @@
"axios"
:
"^1.13.0"
,
"cors"
:
"^2.8.5"
,
"cross-env"
:
"^7.0.3"
,
"dayjs"
:
"^1.11.19"
,
"dotenv"
:
"^16.4.5"
,
"express"
:
"^4.21.1"
,
"mongoose"
:
"^8.8.0"
,
...
...
@@ -669,6 +670,12 @@
"node"
:
"*"
}
},
"node_modules/dayjs"
:
{
"version"
:
"1.11.19"
,
"resolved"
:
"https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz"
,
"integrity"
:
"sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw=="
,
"license"
:
"MIT"
},
"node_modules/debug"
:
{
"version"
:
"2.6.9"
,
"resolved"
:
"https://registry.npmjs.org/debug/-/debug-2.6.9.tgz"
,
...
...
package.json
浏览文件 @
399048a6
...
...
@@ -26,6 +26,7 @@
"
axios
"
:
"^1.13.0"
,
"
cors
"
:
"^2.8.5"
,
"
cross-env
"
:
"^7.0.3"
,
"
dayjs
"
:
"^1.11.19"
,
"
dotenv
"
:
"^16.4.5"
,
"
express
"
:
"^4.21.1"
,
"
mongoose
"
:
"^8.8.0"
,
...
...
src/modules/logs/logs.model.js
浏览文件 @
399048a6
import
mongoose
from
'mongoose'
import
dayjs
from
'dayjs'
// 最大存储大小(字符数)
const
MAX_BODY_SIZE
=
2000
...
...
@@ -92,9 +93,16 @@ const logSchema = new mongoose.Schema(
userAgent
:
String
,
ip
:
String
,
url
:
String
,
createdAt
:
String
,
updatedAt
:
String
,
},
{
timestamps
:
true
,
timestamps
:
{
// 返回服务器本地时间格式的字符串:YYYY-MM-DD HH:mm:ss
currentTime
:
()
=>
{
return
dayjs
().
format
(
'YYYY-MM-DD HH:mm:ss'
)
},
},
versionKey
:
false
,
}
)
...
...
@@ -123,8 +131,9 @@ logSchema.pre('insertMany', function (next, docs) {
next
()
})
// TTL index: auto delete logs after 360 days
logSchema
.
index
({
createdAt
:
1
},
{
expireAfterSeconds
:
360
*
24
*
60
*
60
})
// 注意:TTL 索引需要 Date 类型,但 createdAt 现在是字符串类型
// 如果需要自动删除功能,需要添加一个 Date 类型的字段用于 TTL,或者使用定时任务删除
// logSchema.index({ createdAt: 1 }, { expireAfterSeconds: 360 * 24 * 60 * 60 })
// Compound index for common queries
logSchema
.
index
({
type
:
1
,
appName
:
1
,
createdAt
:
-
1
})
...
...
src/modules/logs/logs.service.js
浏览文件 @
399048a6
import
Log
from
'./logs.model.js'
import
dayjs
from
'dayjs'
export
const
create
=
async
(
logData
)
=>
{
const
log
=
new
Log
(
logData
)
...
...
@@ -21,8 +22,9 @@ export const query = async (filters = {}, options = {}) => {
if
(
filters
.
userId
)
query
.
userId
=
filters
.
userId
if
(
filters
.
startTime
||
filters
.
endTime
)
{
query
.
createdAt
=
{}
if
(
filters
.
startTime
)
query
.
createdAt
.
$gte
=
new
Date
(
filters
.
startTime
)
if
(
filters
.
endTime
)
query
.
createdAt
.
$lte
=
new
Date
(
filters
.
endTime
)
// createdAt 是字符串格式 YYYY-MM-DD HH:mm:ss,直接使用字符串比较
if
(
filters
.
startTime
)
query
.
createdAt
.
$gte
=
filters
.
startTime
if
(
filters
.
endTime
)
query
.
createdAt
.
$lte
=
filters
.
endTime
}
if
(
filters
.
keyword
)
{
query
.
message
=
{
$regex
:
filters
.
keyword
,
$options
:
'i'
}
...
...
@@ -44,18 +46,15 @@ export const query = async (filters = {}, options = {}) => {
}
}
// 获取今日开始时间
// 获取今日开始时间
(服务器本地时间,字符串格式 YYYY-MM-DD HH:mm:ss)
const
getTodayStart
=
()
=>
{
const
today
=
new
Date
()
today
.
setHours
(
0
,
0
,
0
,
0
)
return
today
return
dayjs
().
startOf
(
'day'
).
format
(
'YYYY-MM-DD HH:mm:ss'
)
}
// 获取昨日时间范围
// 获取昨日时间范围
(服务器本地时间,字符串格式)
const
getYesterdayRange
=
()
=>
{
const
today
=
getTodayStart
()
const
yesterday
=
new
Date
(
today
)
yesterday
.
setDate
(
yesterday
.
getDate
()
-
1
)
const
today
=
dayjs
().
startOf
(
'day'
).
format
(
'YYYY-MM-DD HH:mm:ss'
)
const
yesterday
=
dayjs
().
subtract
(
1
,
'day'
).
startOf
(
'day'
).
format
(
'YYYY-MM-DD HH:mm:ss'
)
return
{
start
:
yesterday
,
end
:
today
}
}
...
...
@@ -67,7 +66,7 @@ export const getStats = async (filters = {}) => {
if
(
filters
.
appName
)
baseMatch
.
appName
=
filters
.
appName
// 并行查询所有统计数据
const
[
todayTotal
,
yesterdayTotal
,
todayErrors
,
yesterdayErrors
,
todayApps
,
yesterdayApps
,
hourlyTrend
,
recentLogs
]
=
const
[
todayTotal
,
yesterdayTotal
,
todayErrors
,
yesterdayErrors
,
todayApps
,
yesterdayApps
,
recentLogs
]
=
await
Promise
.
all
([
// 今日日志总数
Log
.
countDocuments
({
...
baseMatch
,
createdAt
:
{
$gte
:
todayStart
}
}),
...
...
@@ -85,17 +84,6 @@ export const getStats = async (filters = {}) => {
Log
.
distinct
(
'appName'
,
{
...
baseMatch
,
createdAt
:
{
$gte
:
todayStart
}
}),
// 昨日活跃应用数
Log
.
distinct
(
'appName'
,
{
...
baseMatch
,
createdAt
:
{
$gte
:
yesterdayStart
,
$lt
:
yesterdayEnd
}
}),
// 按小时分组的趋势(今日)
Log
.
aggregate
([
{
$match
:
{
...
baseMatch
,
createdAt
:
{
$gte
:
todayStart
}
}
},
{
$group
:
{
_id
:
{
$hour
:
'$createdAt'
},
count
:
{
$sum
:
1
},
},
},
{
$sort
:
{
_id
:
1
}
},
]),
// 最近日志
Log
.
find
(
baseMatch
).
sort
({
createdAt
:
-
1
}).
limit
(
10
).
lean
(),
])
...
...
@@ -106,12 +94,6 @@ export const getStats = async (filters = {}) => {
return
Number
((((
today
-
yesterday
)
/
yesterday
)
*
100
).
toFixed
(
1
))
}
// 填充24小时趋势数据
const
trend
=
Array
.
from
({
length
:
24
},
(
_
,
hour
)
=>
{
const
found
=
hourlyTrend
.
find
((
h
)
=>
h
.
_id
===
hour
)
return
{
hour
,
count
:
found
?.
count
||
0
}
})
return
{
// 今日日志
todayTotal
:
{
...
...
@@ -128,8 +110,6 @@ export const getStats = async (filters = {}) => {
count
:
todayApps
.
length
,
change
:
todayApps
.
length
-
yesterdayApps
.
length
,
},
// 按小时趋势
trend
,
// 最近日志
recentLogs
,
}
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论