Initial commit
This commit is contained in:
388
uniCloud-alipay/cloudfunctions/common/uni-stat/stat/stat.js
Normal file
388
uniCloud-alipay/cloudfunctions/common/uni-stat/stat/stat.js
Normal file
@@ -0,0 +1,388 @@
|
||||
/**
|
||||
* @class UniStatDataStat uni统计-数据统计调度处理模块
|
||||
* @function cron 数据统计定时任务处理函数
|
||||
* @function stat 数据统计调度处理函数
|
||||
* @function cleanLog 日志清理调度处理函数
|
||||
*/
|
||||
const {
|
||||
DateTime
|
||||
} = require('./lib')
|
||||
|
||||
const {
|
||||
sleep
|
||||
} = require('../shared')
|
||||
|
||||
const {
|
||||
BaseMod,
|
||||
SessionLog,
|
||||
PageLog,
|
||||
EventLog,
|
||||
ShareLog,
|
||||
ErrorLog,
|
||||
StatResult,
|
||||
ActiveDevices,
|
||||
ActiveUsers,
|
||||
PageResult,
|
||||
EventResult,
|
||||
ErrorResult,
|
||||
Loyalty,
|
||||
RunErrors,
|
||||
UserSessionLog,
|
||||
uniPay,
|
||||
Setting
|
||||
} = require('./mod')
|
||||
class UniStatDataStat {
|
||||
/**
|
||||
* 数据统计定时任务处理函数
|
||||
* @param {Object} context 服务器请求上下文参数
|
||||
*/
|
||||
async cron(context) {
|
||||
const baseMod = new BaseMod()
|
||||
const dateTime = new DateTime()
|
||||
console.log('Cron start time: ', dateTime.getDate('Y-m-d H:i:s'))
|
||||
|
||||
// const setting = new Setting();
|
||||
// let settingValue = await setting.getSetting()
|
||||
// if (settingValue.mode === "close") {
|
||||
// // 如果关闭了统计任务,则任务直接结束
|
||||
// return {
|
||||
// code: 0,
|
||||
// msg: 'Task is close',
|
||||
// }
|
||||
// } else if (settingValue.mode === "auto") {
|
||||
// // 如果开启了节能模式,则判断N天内是否有设备访问记录
|
||||
// let runKey = await setting.checkAutoRun(settingValue);
|
||||
// if (!runKey) {
|
||||
// return {
|
||||
// code: 0,
|
||||
// msg: 'Task is auto close',
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
//获取运行参数
|
||||
const timeInfo = dateTime.getTimeInfo(null, false)
|
||||
const cronConfig = baseMod.getConfig('cron')
|
||||
const cronMin = baseMod.getConfig('cronMin')
|
||||
const realtimeStat = baseMod.getConfig('realtimeStat')
|
||||
// 数据跑批
|
||||
let res = null
|
||||
if (cronConfig && cronConfig.length > 0) {
|
||||
for (var mi in cronConfig) {
|
||||
const currCronConfig = cronConfig[mi]
|
||||
const cronType = currCronConfig.type
|
||||
const cronTime = currCronConfig.time.split(' ')
|
||||
const cronDimension = currCronConfig.dimension
|
||||
|
||||
//未开启分钟级定时任务,则设置为小时级定时任务
|
||||
if (cronTime.length === 4 && !cronMin) {
|
||||
cronTime.splice(3, 1)
|
||||
}
|
||||
|
||||
if (baseMod.debug) {
|
||||
console.log('cronTime', cronTime)
|
||||
}
|
||||
//精度为分钟级的定时任务
|
||||
if (cronTime.length === 4) {
|
||||
if (cronTime[0] !== '*') {
|
||||
//周统计任务
|
||||
if (timeInfo.nWeek == cronTime[0] && timeInfo.nHour == cronTime[2] && timeInfo.nMinutes ==
|
||||
cronTime[3]) {
|
||||
let dimension = cronDimension || 'week';
|
||||
console.log(cronType + `--${dimension} run`)
|
||||
res = await this.stat({
|
||||
type: cronType,
|
||||
dimension: cronDimension,
|
||||
config: currCronConfig
|
||||
})
|
||||
}
|
||||
} else if (cronTime[1] !== '*') {
|
||||
//月统计任务(包含季度统计任务和年统计任务)
|
||||
if (timeInfo.nDay == cronTime[1] && timeInfo.nHour == cronTime[2] && timeInfo.nMinutes ==
|
||||
cronTime[3]) {
|
||||
let dimension = cronDimension || 'month';
|
||||
console.log(cronType + `--${dimension} run`)
|
||||
res = await this.stat({
|
||||
type: cronType,
|
||||
dimension: dimension,
|
||||
config: currCronConfig
|
||||
})
|
||||
}
|
||||
} else if (cronTime[2] !== '*') {
|
||||
//日统计任务
|
||||
if (timeInfo.nHour == cronTime[2] && timeInfo.nMinutes == cronTime[3]) {
|
||||
let dimension = cronDimension || 'day';
|
||||
console.log(cronType + `--${dimension} run`)
|
||||
res = await this.stat({
|
||||
type: cronType,
|
||||
dimension: dimension,
|
||||
config: currCronConfig
|
||||
})
|
||||
}
|
||||
} else if (cronTime[3] !== '*') {
|
||||
//实时统计任务
|
||||
if (timeInfo.nMinutes == cronTime[3] && realtimeStat) {
|
||||
let dimension = cronDimension || 'hour';
|
||||
console.log(cronType + `--${dimension} run`)
|
||||
res = await this.stat({
|
||||
type: cronType,
|
||||
dimension: dimension,
|
||||
config: currCronConfig
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
//精度为小时级的定时任务
|
||||
else if (cronTime.length === 3) {
|
||||
if (cronTime[0] !== '*') {
|
||||
//周统计任务
|
||||
if (timeInfo.nWeek == cronTime[0] && timeInfo.nHour == cronTime[2]) {
|
||||
let dimension = cronDimension || 'week';
|
||||
console.log(cronType + `--${dimension} run`)
|
||||
res = await this.stat({
|
||||
type: cronType,
|
||||
dimension: dimension,
|
||||
config: currCronConfig
|
||||
})
|
||||
}
|
||||
} else if (cronTime[1] !== '*') {
|
||||
//月统计任务(包含季度统计任务和年统计任务)
|
||||
if (timeInfo.nDay == cronTime[1] && timeInfo.nHour == cronTime[2]) {
|
||||
let dimension = cronDimension || 'month';
|
||||
console.log(cronType + `--${dimension} run`)
|
||||
res = await this.stat({
|
||||
type: cronType,
|
||||
dimension: dimension,
|
||||
config: currCronConfig
|
||||
})
|
||||
}
|
||||
} else if (cronTime[2] !== '*') {
|
||||
//日统计任务
|
||||
if (timeInfo.nHour == cronTime[2]) {
|
||||
let dimension = cronDimension || 'day';
|
||||
console.log(cronType + `--${dimension} run`)
|
||||
res = await this.stat({
|
||||
type: cronType,
|
||||
dimension: dimension,
|
||||
config: currCronConfig
|
||||
})
|
||||
}
|
||||
} else {
|
||||
//实时统计任务
|
||||
if (realtimeStat) {
|
||||
let dimension = cronDimension || 'hour';
|
||||
console.log(cronType + `--${dimension} run`)
|
||||
res = await this.stat({
|
||||
type: cronType,
|
||||
dimension: dimension,
|
||||
config: currCronConfig
|
||||
})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.error('Cron configuration error')
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log('Cron end time: ', dateTime.getDate('Y-m-d H:i:s'))
|
||||
return {
|
||||
code: 0,
|
||||
msg: 'Task have done',
|
||||
lastCronResult: res
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据统计调度处理函数
|
||||
* @param {Object} params 统计参数
|
||||
*/
|
||||
async stat(params) {
|
||||
const {
|
||||
type,
|
||||
dimension,
|
||||
date,
|
||||
reset,
|
||||
config
|
||||
} = params
|
||||
let res = {
|
||||
code: 0,
|
||||
msg: 'success'
|
||||
}
|
||||
|
||||
try {
|
||||
switch (type) {
|
||||
// 基础统计
|
||||
case 'stat': {
|
||||
const resultStat = new StatResult()
|
||||
res = await resultStat.stat(dimension, date, reset)
|
||||
break
|
||||
}
|
||||
// 活跃设备统计归集
|
||||
case 'active-device': {
|
||||
const activeDevices = new ActiveDevices()
|
||||
res = await activeDevices.stat(date, reset)
|
||||
break
|
||||
}
|
||||
// 活跃用户统计归集
|
||||
case 'active-user': {
|
||||
const activeUsers = new ActiveUsers()
|
||||
res = await activeUsers.stat(date, reset)
|
||||
break
|
||||
}
|
||||
// 设备留存统计
|
||||
case 'retention-device': {
|
||||
const retentionStat = new StatResult()
|
||||
res = await retentionStat.retentionStat(dimension, date)
|
||||
break
|
||||
}
|
||||
// 用户留存统计
|
||||
case 'retention-user': {
|
||||
const retentionStat = new StatResult()
|
||||
res = await retentionStat.retentionStat(dimension, date, 'user')
|
||||
break
|
||||
}
|
||||
// 页面统计
|
||||
case 'page': {
|
||||
const pageStat = new PageResult()
|
||||
res = await pageStat.stat(dimension, date, reset)
|
||||
break
|
||||
}
|
||||
// 事件统计
|
||||
case 'event': {
|
||||
const eventStat = new EventResult()
|
||||
res = await eventStat.stat(dimension, date, reset)
|
||||
break
|
||||
}
|
||||
// 错误统计
|
||||
case 'error': {
|
||||
const errorStat = new ErrorResult()
|
||||
res = await errorStat.stat(dimension, date, reset)
|
||||
break
|
||||
}
|
||||
// 设备忠诚度统计
|
||||
case 'loyalty': {
|
||||
const loyaltyStat = new Loyalty()
|
||||
res = await loyaltyStat.stat(dimension, date, reset)
|
||||
break
|
||||
}
|
||||
// 日志清理
|
||||
case 'clean': {
|
||||
res = await this.cleanLog()
|
||||
}
|
||||
// 支付统计
|
||||
case 'pay-result': {
|
||||
const paymentResult = new uniPay.PayResult()
|
||||
res = await paymentResult.stat(dimension, date, reset, config)
|
||||
break
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
const maxTryTimes = 2
|
||||
if (!this.tryTimes) {
|
||||
this.tryTimes = 1
|
||||
} else {
|
||||
this.tryTimes++
|
||||
}
|
||||
|
||||
//报错则重新尝试2次, 解决部分云服务器偶现连接超时问题
|
||||
if (this.tryTimes <= maxTryTimes) {
|
||||
//休眠1秒后重新调用
|
||||
await sleep(1000)
|
||||
params.reset = true
|
||||
res = await this.stat(params)
|
||||
} else {
|
||||
// 2次尝试失败后记录错误
|
||||
console.error('server error: ' + e)
|
||||
const runError = new RunErrors()
|
||||
runError.create({
|
||||
mod: 'stat',
|
||||
params: params,
|
||||
error: e,
|
||||
create_time: new DateTime().getTime()
|
||||
})
|
||||
|
||||
res = {
|
||||
code: 500,
|
||||
msg: 'server error' + e
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
/**
|
||||
* 日志清理调度处理函数
|
||||
*/
|
||||
async cleanLog() {
|
||||
const baseMod = new BaseMod()
|
||||
const cleanLog = baseMod.getConfig('cleanLog')
|
||||
if (!cleanLog || !cleanLog.open) {
|
||||
return {
|
||||
code: 100,
|
||||
msg: 'The log cleanup service has not been turned on'
|
||||
}
|
||||
}
|
||||
|
||||
const res = {
|
||||
code: 0,
|
||||
msg: 'success',
|
||||
data: {}
|
||||
}
|
||||
|
||||
// 会话日志
|
||||
if (cleanLog.reserveDays.sessionLog > 0) {
|
||||
const sessionLog = new SessionLog()
|
||||
res.data.sessionLog = await sessionLog.clean(cleanLog.reserveDays.sessionLog)
|
||||
}
|
||||
|
||||
// 用户会话日志
|
||||
if (cleanLog.reserveDays.userSessionLog > 0) {
|
||||
const userSessionLog = new UserSessionLog()
|
||||
res.data.userSessionLog = await userSessionLog.clean(cleanLog.reserveDays.userSessionLog)
|
||||
}
|
||||
|
||||
// 页面日志
|
||||
if (cleanLog.reserveDays.pageLog > 0) {
|
||||
const pageLog = new PageLog()
|
||||
res.data.pageLog = await pageLog.clean(cleanLog.reserveDays.pageLog)
|
||||
}
|
||||
|
||||
// 事件日志
|
||||
if (cleanLog.reserveDays.eventLog > 0) {
|
||||
const eventLog = new EventLog()
|
||||
res.data.eventLog = await eventLog.clean(cleanLog.reserveDays.eventLog)
|
||||
}
|
||||
|
||||
// 分享日志
|
||||
if (cleanLog.reserveDays.shareLog > 0) {
|
||||
const shareLog = new ShareLog()
|
||||
res.data.shareLog = await shareLog.clean(cleanLog.reserveDays.shareLog)
|
||||
}
|
||||
|
||||
// 错误日志
|
||||
if (cleanLog.reserveDays.errorLog > 0) {
|
||||
const errorLog = new ErrorLog()
|
||||
res.data.errorLog = await errorLog.clean(cleanLog.reserveDays.errorLog)
|
||||
}
|
||||
|
||||
// 活跃设备日志
|
||||
const activeDevicesLog = new ActiveDevices()
|
||||
res.data.activeDevicesLog = await activeDevicesLog.clean()
|
||||
|
||||
// 活跃用户日志
|
||||
const activeUsersLog = new ActiveUsers()
|
||||
res.data.activeUsersLog = await activeUsersLog.clean()
|
||||
|
||||
// 实时统计日志
|
||||
const resultHourLog = new StatResult()
|
||||
res.data.resultHourLog = await resultHourLog.cleanHourLog()
|
||||
|
||||
//原生应用崩溃日志
|
||||
const appCrashLogs = new AppCrashLogs()
|
||||
res.data.appCrashLogs = await appCrashLogs.clean()
|
||||
|
||||
return res
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = UniStatDataStat
|
||||
Reference in New Issue
Block a user