befly 3.61.0 → 3.63.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apis/auth/login.js +65 -13
- package/apis/tongJi/_tongJi.js +92 -41
- package/apis/tongJi/dailyReport.js +73 -51
- package/apis/tongJi/dailyStats.js +98 -125
- package/apis/tongJi/dailyStatsDistribution.js +86 -0
- package/apis/tongJi/errorList.js +5 -9
- package/apis/tongJi/errorReport.js +81 -44
- package/apis/tongJi/errorStats.js +19 -125
- package/checks/config.js +1 -4
- package/configs/beflyConfig.json +1 -4
- package/index.js +5 -0
- package/lib/logger.js +125 -296
- package/package.json +1 -1
- package/plugins/cron.js +96 -0
- package/plugins/logger.js +2 -5
- package/sql/befly.sql +53 -25
- package/tables/dailyReport.json +124 -0
- package/tables/errorReport.json +31 -48
- package/tables/loginLog.json +29 -32
- package/utils/is.js +3 -36
- package/utils/loggerUtils.js +0 -3
- package/utils/userAgent.js +229 -104
- package/apis/tongJi/_daily.js +0 -159
|
@@ -1,74 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { getErrorStatsDayBucketCountKey, getErrorStatsDayBucketsKey, getErrorStatsDayTypeCountKey, getErrorStatsDayTypesKey, getErrorStatsPeriodCountKey, getTongJiDateRangeList, getTongJiMonthStartDate, getTongJiNumber, getTongJiRecentDateList, getTongJiWeekStartDate } from "./_tongJi.js";
|
|
1
|
+
import { getTongJiDateRangeList, getTongJiDateYmdNumber, getTongJiMonthStartDate, getTongJiRecentDateList } from "./_tongJi.js";
|
|
4
2
|
|
|
5
3
|
const ERROR_STATS_DAY_LIMIT = 30;
|
|
6
4
|
|
|
7
|
-
function
|
|
8
|
-
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
async function getErrorStatsRedisSummary(befly, periodType, periodValue) {
|
|
12
|
-
return {
|
|
13
|
-
count: getTongJiNumber(await befly.redis.getString(getErrorStatsPeriodCountKey(periodType, periodValue)))
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
async function getErrorStatsRedisTrend(befly, bucketDate) {
|
|
18
|
-
const bucketSet = await befly.redis.smembers(getErrorStatsDayBucketsKey(bucketDate));
|
|
19
|
-
const trend = await Promise.all(
|
|
20
|
-
bucketSet.map(async (bucketTime) => {
|
|
21
|
-
const itemBucketTime = getTongJiNumber(bucketTime);
|
|
22
|
-
|
|
23
|
-
return {
|
|
24
|
-
bucketTime: itemBucketTime,
|
|
25
|
-
bucketDate: bucketDate,
|
|
26
|
-
count: getTongJiNumber(await befly.redis.getString(getErrorStatsDayBucketCountKey(bucketDate, itemBucketTime)))
|
|
27
|
-
};
|
|
28
|
-
})
|
|
29
|
-
);
|
|
5
|
+
function toCount(value) {
|
|
6
|
+
const num = Number(value);
|
|
30
7
|
|
|
31
|
-
|
|
32
|
-
return trend;
|
|
8
|
+
return Number.isFinite(num) ? num : 0;
|
|
33
9
|
}
|
|
34
10
|
|
|
35
|
-
|
|
36
|
-
return Promise.all(
|
|
37
|
-
recentDateList.map(async (item) => {
|
|
38
|
-
return {
|
|
39
|
-
bucketDate: item,
|
|
40
|
-
count: getTongJiNumber(await befly.redis.getString(getErrorStatsPeriodCountKey("day", item)))
|
|
41
|
-
};
|
|
42
|
-
})
|
|
43
|
-
);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
async function getErrorStatsRedisTopTypes(befly, bucketDate) {
|
|
47
|
-
const typeSet = await befly.redis.smembers(getErrorStatsDayTypesKey(bucketDate));
|
|
48
|
-
const topTypes = await Promise.all(
|
|
49
|
-
typeSet.map(async (errorType) => {
|
|
50
|
-
const name = String(errorType || "unknown");
|
|
51
|
-
|
|
52
|
-
return {
|
|
53
|
-
errorType: name,
|
|
54
|
-
count: getTongJiNumber(await befly.redis.getString(getErrorStatsDayTypeCountKey(bucketDate, name)))
|
|
55
|
-
};
|
|
56
|
-
})
|
|
57
|
-
);
|
|
58
|
-
|
|
59
|
-
return topTypes
|
|
60
|
-
.filter((item) => item.count > 0)
|
|
61
|
-
.toSorted((a, b) => {
|
|
62
|
-
if (b.count !== a.count) {
|
|
63
|
-
return b.count - a.count;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return String(a.errorType).localeCompare(String(b.errorType), "zh-CN");
|
|
67
|
-
})
|
|
68
|
-
.slice(0, 5);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function buildErrorStatsResponse(bucketDate, weekStartDate, monthStartDate, recentDateList, todaySummary, yesterdaySummary, dayBeforeYesterdaySummary, weekSummary, monthSummary, recent30Count, trend, days, topTypes) {
|
|
11
|
+
function buildErrorStatsResponse(bucketDate, monthStartDate, recentDateList, todaySummary, yesterdaySummary, dayBeforeYesterdaySummary, monthSummary, recent30Count, trend, days, topTypes) {
|
|
72
12
|
return {
|
|
73
13
|
today: {
|
|
74
14
|
bucketDate: bucketDate,
|
|
@@ -82,11 +22,6 @@ function buildErrorStatsResponse(bucketDate, weekStartDate, monthStartDate, rece
|
|
|
82
22
|
bucketDate: recentDateList[recentDateList.length - 3] || recentDateList[recentDateList.length - 2] || bucketDate,
|
|
83
23
|
count: dayBeforeYesterdaySummary.count
|
|
84
24
|
},
|
|
85
|
-
week: {
|
|
86
|
-
startDate: weekStartDate,
|
|
87
|
-
endDate: bucketDate,
|
|
88
|
-
count: weekSummary.count
|
|
89
|
-
},
|
|
90
25
|
month: {
|
|
91
26
|
startDate: monthStartDate,
|
|
92
27
|
endDate: bucketDate,
|
|
@@ -103,37 +38,12 @@ function buildErrorStatsResponse(bucketDate, weekStartDate, monthStartDate, rece
|
|
|
103
38
|
};
|
|
104
39
|
}
|
|
105
40
|
|
|
106
|
-
function isRedisResultEmpty(todaySummary, yesterdaySummary, dayBeforeYesterdaySummary, weekSummary, monthSummary, recent30Count, trend, topTypes) {
|
|
107
|
-
return todaySummary.count <= 0 && yesterdaySummary.count <= 0 && dayBeforeYesterdaySummary.count <= 0 && weekSummary.count <= 0 && monthSummary.count <= 0 && recent30Count <= 0 && trend.length === 0 && topTypes.length === 0;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
async function getErrorStatsFromRedis(befly, bucketDate, weekStartDate, monthStartDate, recentDateList) {
|
|
111
|
-
const [todaySummary, yesterdaySummary, dayBeforeYesterdaySummary, weekSummary, monthSummary, trend, days, topTypes] = await Promise.all([
|
|
112
|
-
getErrorStatsRedisSummary(befly, "day", bucketDate),
|
|
113
|
-
getErrorStatsRedisSummary(befly, "day", recentDateList[recentDateList.length - 2] || bucketDate),
|
|
114
|
-
getErrorStatsRedisSummary(befly, "day", recentDateList[recentDateList.length - 3] || recentDateList[recentDateList.length - 2] || bucketDate),
|
|
115
|
-
getErrorStatsRedisSummary(befly, "week", weekStartDate),
|
|
116
|
-
getErrorStatsRedisSummary(befly, "month", monthStartDate),
|
|
117
|
-
getErrorStatsRedisTrend(befly, bucketDate),
|
|
118
|
-
getErrorStatsRedisDays(befly, recentDateList),
|
|
119
|
-
getErrorStatsRedisTopTypes(befly, bucketDate)
|
|
120
|
-
]);
|
|
121
|
-
|
|
122
|
-
const recent30Count = sumCounts(days);
|
|
123
|
-
|
|
124
|
-
if (isRedisResultEmpty(todaySummary, yesterdaySummary, dayBeforeYesterdaySummary, weekSummary, monthSummary, recent30Count, trend, topTypes)) {
|
|
125
|
-
return null;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
return buildErrorStatsResponse(bucketDate, weekStartDate, monthStartDate, recentDateList, todaySummary, yesterdaySummary, dayBeforeYesterdaySummary, weekSummary, monthSummary, recent30Count, trend, days, topTypes);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
41
|
async function getErrorStatsDayCountMap(befly, startDate, endDate) {
|
|
132
|
-
const result = await befly.mysql.execute("SELECT bucket_date as bucketDate,
|
|
42
|
+
const result = await befly.mysql.execute("SELECT bucket_date as bucketDate, COUNT(*) as count FROM befly_error_report WHERE state = 1 AND bucket_date BETWEEN ? AND ? GROUP BY bucket_date", [startDate, endDate]);
|
|
133
43
|
const map = new Map();
|
|
134
44
|
|
|
135
45
|
for (const item of result.data || []) {
|
|
136
|
-
map.set(Number(item.bucketDate),
|
|
46
|
+
map.set(Number(item.bucketDate), toCount(item.count));
|
|
137
47
|
}
|
|
138
48
|
|
|
139
49
|
return map;
|
|
@@ -143,37 +53,35 @@ function sumDateCounts(map, dateList) {
|
|
|
143
53
|
return dateList.reduce((sum, date) => sum + (map.get(date) || 0), 0);
|
|
144
54
|
}
|
|
145
55
|
|
|
146
|
-
async function getErrorStatsFromMysql(befly, bucketDate,
|
|
56
|
+
async function getErrorStatsFromMysql(befly, bucketDate, monthStartDate, recentDateList) {
|
|
147
57
|
const yesterdayDate = recentDateList[recentDateList.length - 2] || bucketDate;
|
|
148
58
|
const dayBeforeYesterdayDate = recentDateList[recentDateList.length - 3] || yesterdayDate;
|
|
149
|
-
const weekDateList = getTongJiDateRangeList(weekStartDate, bucketDate);
|
|
150
59
|
const monthDateList = getTongJiDateRangeList(monthStartDate, bucketDate);
|
|
151
60
|
|
|
152
61
|
const [dayCountMap, trendRes, topTypesRes] = await Promise.all([
|
|
153
62
|
getErrorStatsDayCountMap(befly, recentDateList[0], bucketDate),
|
|
154
|
-
befly.mysql.execute("SELECT bucket_time as bucketTime, bucket_date as bucketDate,
|
|
155
|
-
befly.mysql.execute("SELECT error_type as errorType,
|
|
63
|
+
befly.mysql.execute("SELECT bucket_time as bucketTime, bucket_date as bucketDate, COUNT(*) as count FROM befly_error_report WHERE state = 1 AND bucket_date = ? GROUP BY bucket_time, bucket_date ORDER BY bucket_time ASC", [bucketDate]),
|
|
64
|
+
befly.mysql.execute("SELECT error_type as errorType, COUNT(*) as count FROM befly_error_report WHERE state = 1 AND bucket_date = ? GROUP BY error_type ORDER BY count DESC LIMIT 5", [bucketDate])
|
|
156
65
|
]);
|
|
157
66
|
|
|
158
67
|
const todaySummary = { count: dayCountMap.get(bucketDate) || 0 };
|
|
159
68
|
const yesterdaySummary = { count: dayCountMap.get(yesterdayDate) || 0 };
|
|
160
69
|
const dayBeforeYesterdaySummary = { count: dayCountMap.get(dayBeforeYesterdayDate) || 0 };
|
|
161
|
-
const weekSummary = { count: sumDateCounts(dayCountMap, weekDateList) };
|
|
162
70
|
const monthSummary = { count: sumDateCounts(dayCountMap, monthDateList) };
|
|
163
71
|
const recent30Count = sumDateCounts(dayCountMap, recentDateList);
|
|
164
72
|
|
|
165
73
|
const trend = (trendRes.data || []).map((item) => {
|
|
166
74
|
return {
|
|
167
|
-
bucketTime:
|
|
168
|
-
bucketDate:
|
|
169
|
-
count:
|
|
75
|
+
bucketTime: toCount(item.bucketTime),
|
|
76
|
+
bucketDate: toCount(item.bucketDate),
|
|
77
|
+
count: toCount(item.count)
|
|
170
78
|
};
|
|
171
79
|
});
|
|
172
80
|
|
|
173
81
|
const topTypes = (topTypesRes.data || []).map((item) => {
|
|
174
82
|
return {
|
|
175
83
|
errorType: String(item.errorType || "unknown"),
|
|
176
|
-
count:
|
|
84
|
+
count: toCount(item.count)
|
|
177
85
|
};
|
|
178
86
|
});
|
|
179
87
|
|
|
@@ -184,7 +92,7 @@ async function getErrorStatsFromMysql(befly, bucketDate, weekStartDate, monthSta
|
|
|
184
92
|
};
|
|
185
93
|
});
|
|
186
94
|
|
|
187
|
-
return buildErrorStatsResponse(bucketDate,
|
|
95
|
+
return buildErrorStatsResponse(bucketDate, monthStartDate, recentDateList, todaySummary, yesterdaySummary, dayBeforeYesterdaySummary, monthSummary, recent30Count, trend, days, topTypes);
|
|
188
96
|
}
|
|
189
97
|
|
|
190
98
|
function buildEmptyDays(recentDateList) {
|
|
@@ -196,7 +104,7 @@ function buildEmptyDays(recentDateList) {
|
|
|
196
104
|
});
|
|
197
105
|
}
|
|
198
106
|
|
|
199
|
-
function buildEmptyErrorStats(bucketDate,
|
|
107
|
+
function buildEmptyErrorStats(bucketDate, monthStartDate, recentDateList) {
|
|
200
108
|
return {
|
|
201
109
|
today: {
|
|
202
110
|
bucketDate: bucketDate,
|
|
@@ -210,11 +118,6 @@ function buildEmptyErrorStats(bucketDate, weekStartDate, monthStartDate, recentD
|
|
|
210
118
|
bucketDate: recentDateList[recentDateList.length - 3] || recentDateList[recentDateList.length - 2] || bucketDate,
|
|
211
119
|
count: 0
|
|
212
120
|
},
|
|
213
|
-
week: {
|
|
214
|
-
startDate: weekStartDate,
|
|
215
|
-
endDate: bucketDate,
|
|
216
|
-
count: 0
|
|
217
|
-
},
|
|
218
121
|
month: {
|
|
219
122
|
startDate: monthStartDate,
|
|
220
123
|
endDate: bucketDate,
|
|
@@ -242,23 +145,14 @@ export default {
|
|
|
242
145
|
const tableExistsResult = await befly.mysql.tableExists("beflyErrorReport");
|
|
243
146
|
const tableReady = tableExistsResult.data === true;
|
|
244
147
|
const now = Date.now();
|
|
245
|
-
const bucketDate =
|
|
246
|
-
const weekStartDate = getTongJiWeekStartDate(now);
|
|
148
|
+
const bucketDate = getTongJiDateYmdNumber(now);
|
|
247
149
|
const monthStartDate = getTongJiMonthStartDate(now);
|
|
248
150
|
const recentDateList = getTongJiRecentDateList(now, ERROR_STATS_DAY_LIMIT);
|
|
249
151
|
|
|
250
152
|
if (!tableReady) {
|
|
251
|
-
return befly.tool.Yes("获取成功", buildEmptyErrorStats(bucketDate,
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
if (befly.redis) {
|
|
255
|
-
const redisResult = await getErrorStatsFromRedis(befly, bucketDate, weekStartDate, monthStartDate, recentDateList);
|
|
256
|
-
|
|
257
|
-
if (redisResult) {
|
|
258
|
-
return befly.tool.Yes("获取成功", redisResult);
|
|
259
|
-
}
|
|
153
|
+
return befly.tool.Yes("获取成功", buildEmptyErrorStats(bucketDate, monthStartDate, recentDateList));
|
|
260
154
|
}
|
|
261
155
|
|
|
262
|
-
return befly.tool.Yes("获取成功", await getErrorStatsFromMysql(befly, bucketDate,
|
|
156
|
+
return befly.tool.Yes("获取成功", await getErrorStatsFromMysql(befly, bucketDate, monthStartDate, recentDateList));
|
|
263
157
|
}
|
|
264
158
|
};
|
package/checks/config.js
CHANGED
|
@@ -63,10 +63,7 @@ const configSchema = z
|
|
|
63
63
|
logger: z
|
|
64
64
|
.object({
|
|
65
65
|
debug: boolIntSchema,
|
|
66
|
-
excludeFields: z.array(noTrimString)
|
|
67
|
-
dir: noTrimString,
|
|
68
|
-
console: boolIntSchema,
|
|
69
|
-
maxSize: z.int().min(1)
|
|
66
|
+
excludeFields: z.array(noTrimString)
|
|
70
67
|
})
|
|
71
68
|
.strict(),
|
|
72
69
|
|
package/configs/beflyConfig.json
CHANGED
|
@@ -19,10 +19,7 @@
|
|
|
19
19
|
"excludeApisLog": ["/api/core/tongJi/*Report"],
|
|
20
20
|
"logger": {
|
|
21
21
|
"debug": 1,
|
|
22
|
-
"excludeFields": ["password", "token", "secret"]
|
|
23
|
-
"dir": "./logs",
|
|
24
|
-
"console": 1,
|
|
25
|
-
"maxSize": 20
|
|
22
|
+
"excludeFields": ["password", "token", "secret"]
|
|
26
23
|
},
|
|
27
24
|
|
|
28
25
|
"mysql": {
|
package/index.js
CHANGED
|
@@ -120,6 +120,11 @@ export async function createBefly(env = {}, config = {}, menus = []) {
|
|
|
120
120
|
const mergedMenus = deepMerge(prefixMenuPaths(beflyMenus, "core"), menus);
|
|
121
121
|
mergedConfig.projectLists = mergeProjectListsByCode(mergedConfig.projectLists);
|
|
122
122
|
|
|
123
|
+
Logger.configure({
|
|
124
|
+
runtimeEnv: mergedConfig.runMode,
|
|
125
|
+
...mergedConfig.logger
|
|
126
|
+
});
|
|
127
|
+
|
|
123
128
|
const configHasError = await checkConfig(mergedConfig);
|
|
124
129
|
const { apis, tables, plugins, hooks } = await scanSources();
|
|
125
130
|
|