Commit bd1d4993 by trace

v1.3 统计上下线时长

parent 56c233ad
let version = '1.0' let version = '1.3'
let release = `<div><br/> let release = `<div><br/>
<br/>1. <br/> <br/>1. <br/>
单独监控菲律宾<br/> 添加"上", "下", 单独搜索客户 id 加上上下标识, 如: "上2002"<br/>
<br/>2. <br/>
添加在线时长统计. 详见 "在线/下线 情况"<br/>
<div/> <div/>
<br/> <br/>
<br/> <br/>
...@@ -11,7 +13,7 @@ let release = `<div><br/> ...@@ -11,7 +13,7 @@ let release = `<div><br/>
// 依赖 // 依赖
var gplay = require('google-play-scraper') var gplay = require('google-play-scraper')
var nodemailer = require('nodemailer') var nodemailer = require('nodemailer')
// var moment = require('moment') var moment = require('moment')
let developer = ['yingchen.nong@starwin.com'] let developer = ['yingchen.nong@starwin.com']
let notifyEmail = developer let notifyEmail = developer
...@@ -237,10 +239,18 @@ function generateDailyOnlineReport() { ...@@ -237,10 +239,18 @@ function generateDailyOnlineReport() {
let daichaoOnlines = daichaoApps.filter(val => status[val] && status[val].status || false) let daichaoOnlines = daichaoApps.filter(val => status[val] && status[val].status || false)
let daichaoOfflines = daichaoApps.filter(val => !daichaoOnlines.includes(val)) let daichaoOfflines = daichaoApps.filter(val => !daichaoOnlines.includes(val))
let content = '' let content = ''
content += wrapSummary(`Gitlab 在线 app (${onlineApps.length}/${ourAppIds.length})`, onlineApps.map(val => link(val)), 'green') let calTime = (val) => {
content += wrapSummary(`Gitlab 下线 app (${offlineApps.length}/${ourAppIds.length})`, offlineApps.map(val => link(val)), 'red') return `<br/>在线: ${status[val].onlineDuration} | 下线: ${status[val].offlineDuration}`
content += wrapSummary(`贷超在线 App (${daichaoOnlines.length}/${daichaoApps.length})`, daichaoOnlines.map(val => link(val)), 'green') }
content += wrapSummary(`贷超下线 App (${daichaoOfflines.length}/${daichaoApps.length})`, daichaoOfflines.map(val => link(val)), 'red') content += wrapSummary(`Gitlab 在线 app (${onlineApps.length}/${ourAppIds.length})`, onlineApps.map(val => link(val) + calTime(val)), 'green')
content += '在线时长情况:'
content += rankOnlineTime(onlineApps)
content += wrapSummary(`Gitlab 下线 app (${offlineApps.length}/${ourAppIds.length})`, offlineApps.map(val => link(val) + calTime(val)), 'red')
content += '<br/><br/>贷超------------------------------'
content += wrapSummary(`贷超在线 App (${daichaoOnlines.length}/${daichaoApps.length})`, daichaoOnlines.map(val => link(val) + calTime(val)), 'green')
content += '在线时长情况:'
content += rankOnlineTime(daichaoOnlines)
content += wrapSummary(`贷超下线 App (${daichaoOfflines.length}/${daichaoApps.length})`, daichaoOfflines.map(val => link(val) + calTime(val)), 'red')
return content return content
} }
...@@ -459,35 +469,65 @@ async function monitorIfOnline(names) { ...@@ -459,35 +469,65 @@ async function monitorIfOnline(names) {
await gplay.app({ appId: name, requestOptions: { timeout: requestTimeout } }) await gplay.app({ appId: name, requestOptions: { timeout: requestTimeout } })
.then((val) => { .then((val) => {
log(`获取到(${status[name] && status[name].category || 'noType'}): ${name}`) log(`获取到(${status[name] && status[name].category || 'noType'}): ${name}`)
judgeNewOnline(name)
// judgePermissionChanged(name, val) // judgePermissionChanged(name, val)
// 第一次运行上下架时长功能时没有 updated 字段, 使用gp 最近更新时间
if (!(status[name] && status[name].updated)) {
status[name] = {
...(status[name] || {}),
updated: val.updated
}
}
// 标记 gp 更新时间, 普通更新不会计入, 下了再上的会重置更新时间
if (judgeNewOnline(name)) {
status[name] = {
...(status[name] || {}),
updated: val.updated,
onlineDuration: calDuration(moment.now(), (status[name] && status[name].updated || moment.now())),
}
} else {
// 非新上架, 一直在线, 统计在线时长
status[name] = {
...(status[name] || {}),
onlineDuration: calDuration(moment.now(), (status[name] && status[name].updated || moment.now()))
}
}
status[name] = { status[name] = {
...(status[name] || {}), ...(status[name] || {}),
// permissions: val, // permissions: val,
status: true, status: true,
date: Date().toString() date: Date().toString(),
} }
}) })
.catch((err) => { .catch((err) => {
if (err.toString().includes('404')) { if (err.toString().includes('404')) {
log(`获取不到: ${name}, error: ${err}`, true) log(`获取不到: ${name}, error: ${err}`, true)
failedApps.push(name) failedApps.push(name)
judgeNewOffline(name)
let a = status[name] || {} let a = status[name] || {}
// 记录被下架时间
if (judgeNewOffline(name)) {
status[name] = { ...a, offlineDuration: 0, offlineDate: moment.now() }
} else {
// 一直在下架状态, 统计下架持续时间
status[name] = {
...a,
offlineDuration: calDuration(moment.now(), (status[name] && status[name].offlineDate || moment.now()))
}
}
a = status[name] || {}
status[name] = { ...a, status: false, date: Date().toString() } status[name] = { ...a, status: false, date: Date().toString() }
} else if (err.toString().includes('ETIMEDOUT')) { } else if (err.toString().includes('ETIMEDOUT')) {
log(`连接超时: ${err.toString()}`, true) log(`连接超时: ${err.toString()}`, true)
throw err throw err
} else { } else {
errorLog.push(`Motitor Online Error: ${link(name, true)} - ${err.message}`) errorLog.push(`Motitor Online Error: ${link(name, "error ")} - ${err.message}`)
log(`获取在线错误: ${name}, ${err.message}`, true) log(`获取在线错误: ${name}, ${err.message}`, true)
} }
}) })
} }
} }
function link(name, countOurs) { function link(name, tag) {
let ourName = isOurs(name, countOurs) let ourName = isOurs(name, tag)
return `${ourName} ____ return `${ourName} ____
<a href="${base_gp_url}${name}"> <a href="${base_gp_url}${name}">
${getRegion(name)}[${monitorType[status[name] && status[name].category || ''] || ''}] - ${name} ${getRegion(name)}[${monitorType[status[name] && status[name].category || ''] || ''}] - ${name}
...@@ -553,7 +593,7 @@ function genMail() { ...@@ -553,7 +593,7 @@ function genMail() {
if (failedApps.length > 0 && isFirstRun) { if (failedApps.length > 0 && isFirstRun) {
emailContent += `<div>本次第一次监控</div>` emailContent += `<div>本次第一次监控</div>`
failedApps.forEach(name => { failedApps.forEach(name => {
emailContent += `<div>获取失败}: ${link(name, true)} </div>` emailContent += `<div>获取失败}: ${link(name, "failed")} </div>`
}) })
} }
if (isFirstRun) { if (isFirstRun) {
...@@ -587,7 +627,7 @@ function genMail() { ...@@ -587,7 +627,7 @@ function genMail() {
ourTop = [...ourTop, ...ourAppIds.filter(val => names.includes(val))] ourTop = [...ourTop, ...ourAppIds.filter(val => names.includes(val))]
daichaoTop = [...daichaoTop, ...daichaoApps.filter(val => names.includes(val))] daichaoTop = [...daichaoTop, ...daichaoApps.filter(val => names.includes(val))]
emailContent += wrapSummary(`本次在<${monitorRegion[key]}>top${requestTopAppNum}监控列表: ${names.length} 个`, emailContent += wrapSummary(`本次在<${monitorRegion[key]}>top${requestTopAppNum}监控列表: ${names.length} 个`,
names.map(n => `${link(n.id, true)}进top${requestTopAppNum}`)) names.map(n => `${link(n.id)}进top${requestTopAppNum}`))
} }
}) })
emailContent += `<br/>/>^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<br/>` emailContent += `<br/>/>^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<br/>`
...@@ -620,7 +660,7 @@ function genMail() { ...@@ -620,7 +660,7 @@ function genMail() {
newOffline.forEach(name => { newOffline.forEach(name => {
let his = (status[name] && status[name].permissionHis && status[name].permissionHis) || {} let his = (status[name] && status[name].permissionHis && status[name].permissionHis) || {}
his.lastPermissions = (status[name] && status[name].permissions && status[name].permissions) || [] his.lastPermissions = (status[name] && status[name].permissions && status[name].permissions) || []
emailContent += getPermissionChangeContent(name, his, `新下架ಥ_ಥ(及上次权限情况)`) emailContent += getPermissionChangeContent(name, his, `新下架ಥ_ಥ(及上次权限情况)[上次在线持续: ${status[name].onlineDuration || 0}]`, '下')
// emailContent += `<div>检测到新下架ಥ_ಥ: ${link(name)}</div>` // emailContent += `<div>检测到新下架ಥ_ಥ: ${link(name)}</div>`
}) })
emailContent += `<br/>/>^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<br/>` emailContent += `<br/>/>^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<br/>`
...@@ -632,11 +672,11 @@ function genMail() { ...@@ -632,11 +672,11 @@ function genMail() {
emailContent += `<div>-----------新上架: ${newOnline.length} 个---------------------</div>` emailContent += `<div>-----------新上架: ${newOnline.length} 个---------------------</div>`
newOnline.forEach(name => { newOnline.forEach(name => {
if (permissionChange[name]) { if (permissionChange[name]) {
emailContent += getPermissionChangeContent(name, permissionChange[name], `新上架😃: `) emailContent += getPermissionChangeContent(name, permissionChange[name], `新上架😃: `, '上')
emailContent += `<br/>/>^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<br/>` emailContent += `<br/>/>^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<br/>`
delete permissionChange[name] delete permissionChange[name]
} else { } else {
emailContent += wrapSummary(`<div>新上架^_^: ${link(name, true)}</div>`, emailContent += wrapSummary(`<div>新上架^_^ [上次下架持续时间: ${status[name].offlineDuration || 0}]: <br/>${link(name, "上")}</div>`,
((status[name] && status[name].permissions && status[name].permissions) || [])) ((status[name] && status[name].permissions && status[name].permissions) || []))
emailContent += `<br/>/>^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<br/>` emailContent += `<br/>/>^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<br/>`
} }
...@@ -662,11 +702,16 @@ function genMail() { ...@@ -662,11 +702,16 @@ function genMail() {
emailContent += `<div>下面是监控列表<br/>当前监控${countrys.length}个国家</div>` emailContent += `<div>下面是监控列表<br/>当前监控${countrys.length}个国家</div>`
Object.keys(monitorNames).forEach(val => { Object.keys(monitorNames).forEach(val => {
let num = monitorNames[val].length let num = monitorNames[val].length
emailContent += wrapSummary(`${monitorRegion[val] || val}(${num}个)`, monitorNames[val].map(id => link(id, false))) emailContent += wrapSummary(`${monitorRegion[val] || val}(${num}个)`, monitorNames[val].map(id => link(id)))
}) })
status.sendListDate = today.toString() status.sendListDate = today.toString()
} }
// 发送在线时长情况
// emailContent += '<br/><br/><br/>'
// emailContent += '在线时长情况:'
// emailContent += rankOnlineTime()
// 有变化也发送当前监控在线情况 // 有变化也发送当前监控在线情况
emailContent += '<br/><br/><br/>' emailContent += '<br/><br/><br/>'
emailContent += '在线/下线 情况:' emailContent += '在线/下线 情况:'
...@@ -680,7 +725,7 @@ function genMail() { ...@@ -680,7 +725,7 @@ function genMail() {
return `<div>${firstLine}</div><br/>${emailContent}<br/>version: ${version}` return `<div>${firstLine}</div><br/>${emailContent}<br/>version: ${version}`
} }
function isOurs(name, countOurs) { function isOurs(name, tag) {
let prefix = '' let prefix = ''
if (daichaoApps.includes(name)) { if (daichaoApps.includes(name)) {
prefix = `🏦(贷超.${daichaoAppInfoes[name].region}[${daichaoAppInfoes[name].daichaoId}]__<a href="${daichaoAppInfoes[name].mgt}${daichaoAppInfoes[name] && prefix = `🏦(贷超.${daichaoAppInfoes[name].region}[${daichaoAppInfoes[name].daichaoId}]__<a href="${daichaoAppInfoes[name].mgt}${daichaoAppInfoes[name] &&
...@@ -688,15 +733,15 @@ function isOurs(name, countOurs) { ...@@ -688,15 +733,15 @@ function isOurs(name, countOurs) {
} }
if (ourAppIds.includes(name)) { if (ourAppIds.includes(name)) {
if (prefix != '') { if (prefix != '') {
prefix = `📌(${ourApps[name]}|${prefix}` prefix = `📌(${tag || ""}${ourApps[name]}|${prefix}`
} else { } else {
prefix = `📌(${ourApps[name] || 'No Name in Gitlab'})` prefix = `📌(${tag || ""}${ourApps[name] || 'No Name in Gitlab'})`
} }
} }
return prefix return prefix
} }
function getPermissionChangeContent(id, obj, title) { function getPermissionChangeContent(id, obj, title, tag) {
changes = [] changes = []
if (obj.adds && obj.adds.length > 0) { changes.push(wrapSummary(`添加`, obj.adds, "green")) } if (obj.adds && obj.adds.length > 0) { changes.push(wrapSummary(`添加`, obj.adds, "green")) }
if (obj.deletes && obj.deletes.length > 0) { changes.push(wrapSummary(`删除`, obj.deletes, "red")) } if (obj.deletes && obj.deletes.length > 0) { changes.push(wrapSummary(`删除`, obj.deletes, "red")) }
...@@ -704,7 +749,7 @@ function getPermissionChangeContent(id, obj, title) { ...@@ -704,7 +749,7 @@ function getPermissionChangeContent(id, obj, title) {
if (obj.newPermission && obj.newPermission.length > 0) { changes.push(wrapSummary(`新权限`, obj.newPermission)) } if (obj.newPermission && obj.newPermission.length > 0) { changes.push(wrapSummary(`新权限`, obj.newPermission)) }
if (obj.lastPermissions && obj.lastPermissions.length > 0) { changes.push(wrapSummary(`旧权限`, obj.lastPermissions)) } if (obj.lastPermissions && obj.lastPermissions.length > 0) { changes.push(wrapSummary(`旧权限`, obj.lastPermissions)) }
log(`权限改变: ${id}: ${changes.length}`) log(`权限改变: ${id}: ${changes.length}`)
return wrapSummary(`- <div>${title || '权限改变'}:<br/>${link(id, true)}</div>`, changes) return wrapSummary(`- <div>${title || '权限改变'}:<br/>${link(id, tag)}</div>`, changes)
} }
function setPermissionHis(name, obj) { function setPermissionHis(name, obj) {
...@@ -866,17 +911,23 @@ function sleep(ms) { ...@@ -866,17 +911,23 @@ function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms)); return new Promise(resolve => setTimeout(resolve, ms));
} }
function judgeNewOnline(name) { function judgeNewOnline(name) {
log(`判断 ${name} 是否新上架`)
if (status[name] && status[name].status == false) { if (status[name] && status[name].status == false) {
log(`${name} 新上架 😃`) log(`${name} 新上架 😃`)
newOnline.push(name) newOnline.push(name)
return true
} }
return false
} }
function judgeNewOffline(name) { function judgeNewOffline(name) {
log(`判断 ${name} 是否新下架`)
if (status[name] && status[name].status == true) { if (status[name] && status[name].status == true) {
log(`${name} 被下架了 ಥ_ಥ`) log(`${name} 被下架了 ಥ_ಥ`)
newOffline.push(name) newOffline.push(name)
return true
} }
return false
} }
function judgePermissionChanged(name, newPermission) { function judgePermissionChanged(name, newPermission) {
...@@ -948,3 +999,67 @@ function isInTimeInRangeToday(start, end) { ...@@ -948,3 +999,67 @@ function isInTimeInRangeToday(start, end) {
return false return false
} }
function getMoment(timestamp) {
return moment(timestamp)
}
function calDuration(laterTime, updateTime, unit = 'day') {
let duration = getMoment(laterTime).diff(getMoment(updateTime), unit)
let ret = `${duration} 天`
if (unit == 'day' && duration == 0) {
duration = getMoment(laterTime).diff(getMoment(updateTime), 'hours')
ret = `${duration} 小时`
}
return ret
}
function rankOnlineTime(apps) {
let rankApps = apps || ourAppIds.filter(val => status[val] && status[val].status || false)
let onlineApps = rankApps
let day30Up = []
let day14_30 = []
let day5_14 = []
let day5Down = []
let day1 = []
for (id of onlineApps) {
let duration = status[id].onlineDuration || '0 小时'
durations = duration.split(' ')
duration = durations[0]
let unit = durations[1]
if (unit == '天') {
if (duration >= 30) {
day30Up = day30Up.concat({ id, duration })
} else if (duration >= 14 && duration < 30) {
day14_30 = day14_30.concat({ id, duration })
} else if (duration >= 5 && duration < 14) {
day5_14 = day5_14.concat({ id, duration })
} else {
day5Down = day5Down.concat({ id, duration })
}
} else {
day1 = day1.concat({ id, duration })
}
}
let sortFoo = (val1, val2) => {
return val2.duration - val1.duration
}
day30Up = day30Up.sort(sortFoo).map(val => val.id)
day14_30 = day14_30.sort(sortFoo).map(val => val.id)
day5_14 = day5_14.sort(sortFoo).map(val => val.id)
day5Down = day5Down.sort(sortFoo).map(val => val.id)
day1 = day1.sort(sortFoo).map(val => val.id)
let calTime = (val) => {
return `<br/>在线时长: ${status[val].onlineDuration} | 下线时长: ${status[val].offlineDuration}`
}
let content = ''
content += wrapSummary(`30天及以上app (${day30Up.length}/${ourAppIds.length})`, day30Up.map(val => link(val) + calTime(val)), 'green')
content += wrapSummary(`[14, 30)天app (${day14_30.length}/${ourAppIds.length})`, day14_30.map(val => link(val) + calTime(val)), 'green')
content += wrapSummary(`[5, 14)天app (${day5_14.length}/${ourAppIds.length})`, day5_14.map(val => link(val) + calTime(val)), 'green')
content += wrapSummary(`[1, 5)天app (${day5Down.length}/${ourAppIds.length})`, day5Down.map(val => link(val) + calTime(val)), 'green')
content += wrapSummary(`[0, 1)天app (${day1.length}/${ourAppIds.length})`, day1.map(val => link(val) + calTime(val)), 'green')
return content
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment