Skip to content

Commit

Permalink
add error handling to stats, botstats, allstats commands
Browse files Browse the repository at this point in the history
  • Loading branch information
fegloff committed Jul 6, 2024
1 parent 48b53cf commit b6d703d
Show file tree
Hide file tree
Showing 5 changed files with 237 additions and 136 deletions.
262 changes: 152 additions & 110 deletions src/database/stats.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@ import { AppDataSource } from './datasource'
import { StatBotCommand } from './entities/StatBotCommand'
import moment from 'moment-timezone'
import { BotLog } from './entities/Log'
import pino from 'pino'

const logger = pino({
name: 'StatsService',
transport: {
target: 'pino-pretty',
options: { colorize: true }
}
})

const statBotCommandRepository = AppDataSource.getRepository(StatBotCommand)
const logRepository = AppDataSource.getRepository(BotLog)
Expand Down Expand Up @@ -37,143 +46,176 @@ export class StatsService {
}

async getTotalONE (): Promise<number> {
const rows = await logRepository.query('select sum("amountOne") from logs')
return rows.length ? +rows[0].sum : 0
try {
const rows = await logRepository.query('select sum("amountOne") from logs')
return rows.length ? +rows[0].sum : 0
} catch (e) {
logger.error(e)
return 0
}
}

async getTotalFreeCredits (): Promise<number> {
const rows = await logRepository.query('select sum("amountCredits") from logs')
return rows.length ? +rows[0].sum : 0
try {
const rows = await logRepository.query('select sum("amountCredits") from logs')
return rows.length ? +rows[0].sum : 0
} catch (e) {
logger.error(e)
return 0
}
}

async getUniqueUsersCount (): Promise<number> {
const rows = await logRepository.query('select count(distinct("tgUserId")) from logs')
return rows.length ? +rows[0].count : 0
try {
const rows = await logRepository.query('select count(distinct("tgUserId")) from logs')
return rows.length ? +rows[0].count : 0
} catch (e) {
logger.error(e)
return 0
}
}

public async getActiveUsers (daysPeriod = 0): Promise<number> {
const currentTime = moment()
const dateStart = moment()
.tz('America/Los_Angeles')
.set({ hour: 0, minute: 0, second: 0 })
.subtract(daysPeriod, 'days')
.unix()

const dateEnd = currentTime.unix()

const rows = await logRepository
.createQueryBuilder('logs')
.select('count(distinct(logs."tgUserId"))')
.where(`logs.createdAt BETWEEN TO_TIMESTAMP(${dateStart}) and TO_TIMESTAMP(${dateEnd})`)
.execute()

return rows.length ? +rows[0].count : 0
try {
const currentTime = moment()
const dateStart = moment()
.tz('America/Los_Angeles')
.set({ hour: 0, minute: 0, second: 0 })
.subtract(daysPeriod, 'days')
.unix()
const dateEnd = currentTime.unix()
const rows = await logRepository
.createQueryBuilder('logs')
.select('count(distinct(logs."tgUserId"))')
.where(`logs.createdAt BETWEEN TO_TIMESTAMP(${dateStart}) and TO_TIMESTAMP(${dateEnd})`)
.execute()
return rows.length ? +rows[0].count : 0
} catch (e) {
logger.error(e)
return 0
}
}

public async getNewUsers (daysPeriod = 0): Promise<number> {
const currentTime = moment()
const dateStart = moment()
.tz('America/Los_Angeles')
.set({ hour: 0, minute: 0, second: 0 })
.subtract(daysPeriod, 'days')
.unix()

const dateEnd = currentTime.unix()

const query = logRepository
.createQueryBuilder('logs')
.select('distinct("FirstInsertTime")')
.from(subQuery =>
subQuery
.select('"tgUserId", MIN("createdAt") AS "FirstInsertTime"')
.from(BotLog, 'logs')
.groupBy('"tgUserId"'), 'first_inserts')
if (daysPeriod > 0) {
query.where(`"FirstInsertTime" BETWEEN TO_TIMESTAMP(${dateStart}) and TO_TIMESTAMP(${dateEnd})`)
try {
const currentTime = moment()
const dateStart = moment()
.tz('America/Los_Angeles')
.set({ hour: 0, minute: 0, second: 0 })
.subtract(daysPeriod, 'days')
.unix()
const dateEnd = currentTime.unix()
const query = logRepository
.createQueryBuilder('logs')
.select('distinct("FirstInsertTime")')
.from(subQuery =>
subQuery
.select('"tgUserId", MIN("createdAt") AS "FirstInsertTime"')
.from(BotLog, 'logs')
.groupBy('"tgUserId"'), 'first_inserts')
if (daysPeriod > 0) {
query.where(`"FirstInsertTime" BETWEEN TO_TIMESTAMP(${dateStart}) and TO_TIMESTAMP(${dateEnd})`)
}
const result = await query.execute()
// console.log(dateStart, dateEnd, result.length)
return result.length
} catch (e) {
logger.error(e)
return 0
}
const result = await query.execute()
// console.log(dateStart, dateEnd, result.length)
return result.length
}

// Doesn't check last 7 days.
public async getOnetimeUsers (): Promise<number> {
const bufferDays = 7
const bufferDate = moment()
.tz('America/Los_Angeles')
.set({ hour: 0, minute: 0, second: 0 })
.subtract(bufferDays, 'days')
.unix()

const query = await logRepository
.createQueryBuilder('logs')
.select('count("tgUserId") AS row_count, "tgUserId", MAX("createdAt") AS max_created')
.where(`"createdAt" < TO_TIMESTAMP(${bufferDate})`)
.groupBy('"tgUserId"')
.getRawMany()
const result = query.filter(row => row.row_count === '1')
return result.length
try {
const bufferDays = 7
const bufferDate = moment()
.tz('America/Los_Angeles')
.set({ hour: 0, minute: 0, second: 0 })
.subtract(bufferDays, 'days')
.unix()
const query = await logRepository
.createQueryBuilder('logs')
.select('count("tgUserId") AS row_count, "tgUserId", MAX("createdAt") AS max_created')
.where(`"createdAt" < TO_TIMESTAMP(${bufferDate})`)
.groupBy('"tgUserId"')
.getRawMany()
const result = query.filter(row => row.row_count === '1')
return result.length
} catch (e) {
logger.error(e)
return 0
}
}

public async getTotalMessages (daysPeriod = 0, onlySupportedCommands = false): Promise<number> {
const currentTime = moment()
const dateStart = moment()
.tz('America/Los_Angeles')
.set({ hour: 0, minute: 0, second: 0 })
.subtract(daysPeriod, 'days')
.unix()

const dateEnd = currentTime.unix()

const query = logRepository
.createQueryBuilder('logs')
.select('count(*)')
if (daysPeriod > 0) {
query.where(`logs.createdAt BETWEEN TO_TIMESTAMP(${dateStart}) and TO_TIMESTAMP(${dateEnd})`)
}
if (onlySupportedCommands) {
query.andWhere('logs.isSupportedCommand=true')
try {
const currentTime = moment()
const dateStart = moment()
.tz('America/Los_Angeles')
.set({ hour: 0, minute: 0, second: 0 })
.subtract(daysPeriod, 'days')
.unix()

const dateEnd = currentTime.unix()

const query = logRepository
.createQueryBuilder('logs')
.select('count(*)')
if (daysPeriod > 0) {
query.where(`logs.createdAt BETWEEN TO_TIMESTAMP(${dateStart}) and TO_TIMESTAMP(${dateEnd})`)
}
if (onlySupportedCommands) {
query.andWhere('logs.isSupportedCommand=true')
}
const rows = await query.execute()
return rows.length ? +rows[0].count : 0
} catch (e) {
logger.error(e)
return 0
}

const rows = await query.execute()

return rows.length ? +rows[0].count : 0
}

public async getUserEngagementByCommand (daysPeriod = 7): Promise<EngagementByCommand[]> {
const currentTime = moment()
const dateStart = moment()
.tz('America/Los_Angeles')
.set({ hour: 0, minute: 0, second: 0 })
.subtract(daysPeriod, 'days')
.unix()

const dateEnd = currentTime.unix()

const rows = await logRepository.createQueryBuilder('logs')
.select('logs.command, count(logs.command) as "commandCount", SUM(logs.amountOne) as "oneAmount"')
.where(`logs.createdAt BETWEEN TO_TIMESTAMP(${dateStart}) and TO_TIMESTAMP(${dateEnd})`)
.groupBy('logs.command')
.orderBy('"commandCount"', 'DESC').execute()

return rows
try {
const currentTime = moment()
const dateStart = moment()
.tz('America/Los_Angeles')
.set({ hour: 0, minute: 0, second: 0 })
.subtract(daysPeriod, 'days')
.unix()
const dateEnd = currentTime.unix()
const rows = await logRepository.createQueryBuilder('logs')
.select('logs.command, count(logs.command) as "commandCount", SUM(logs.amountOne) as "oneAmount"')
.where(`logs.createdAt BETWEEN TO_TIMESTAMP(${dateStart}) and TO_TIMESTAMP(${dateEnd})`)
.groupBy('logs.command')
.orderBy('"commandCount"', 'DESC').execute()
return rows
} catch (e) {
logger.error(e)
return []
}
}

public async getRevenueFromLog (daysPeriod = 7): Promise<string> {
const currentTime = moment()
const dateStart = moment()
.tz('America/Los_Angeles')
.set({ hour: 0, minute: 0, second: 0 })
.subtract(daysPeriod, 'days')
.unix()

const dateEnd = currentTime.unix()
const result = await logRepository.createQueryBuilder('logs')
.select('SUM(CAST(logs.amountCredits AS NUMERIC)) AS revenue')
.where('logs.isSupportedCommand=true')
.andWhere(`logs.createdAt BETWEEN TO_TIMESTAMP(${dateStart}) and TO_TIMESTAMP(${dateEnd})`)
.execute()
return result[0].revenue
try {
const currentTime = moment()
const dateStart = moment()
.tz('America/Los_Angeles')
.set({ hour: 0, minute: 0, second: 0 })
.subtract(daysPeriod, 'days')
.unix()
const dateEnd = currentTime.unix()
const result = await logRepository.createQueryBuilder('logs')
.select('SUM(CAST(logs.amountCredits AS NUMERIC)) AS revenue')
.where('logs.isSupportedCommand=true')
.andWhere(`logs.createdAt BETWEEN TO_TIMESTAMP(${dateStart}) and TO_TIMESTAMP(${dateEnd})`)
.execute()
return result[0].revenue
} catch (e) {
logger.error(e)
return ''
}
}

public async addCommandStat ({ tgUserId, rawMessage, command }: { tgUserId: number, rawMessage: string, command: string }): Promise<StatBotCommand> {
Expand Down
45 changes: 31 additions & 14 deletions src/modules/schedule/bridgeAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@ import axios from 'axios'
import moment from 'moment'
import { abbreviateNumber, getPercentDiff } from './utils'
import { BigNumber } from 'bignumber.js'
import pino from 'pino'

const logger = pino({
name: 'BridgeAPI',
transport: {
target: 'pino-pretty',
options: { colorize: true }
}
})

const bridgeUrl = 'https://hmy-lz-api-token.fly.dev'
const stakeApiUrl = 'https://api.stake.hmny.io'
Expand Down Expand Up @@ -144,8 +153,13 @@ export const getBridgeStats = async (): Promise<{ change: string, value: string
}

export const getTVL = async (): Promise<number> => {
const tokens = await getTokensList()
return tokens.reduce((acc, item) => acc + +item.totalLockedUSD, 0)
try {
const tokens = await getTokensList()
return tokens.reduce((acc, item) => acc + +item.totalLockedUSD, 0)
} catch (e) {
logger.error(e)
return 0
}
}

export const getTotalStakes = async (): Promise<number> => {
Expand All @@ -154,17 +168,20 @@ export const getTotalStakes = async (): Promise<number> => {
}

export const getAvgStakes = async (): Promise<number> => {
const { history } = await getStakingStats()
const sortedHistory = Object.values(history).sort((a, b) => b.current_epoch - a.current_epoch)

const epochCount = 30
const values = []
for (let i = 0; i < sortedHistory.length || i < epochCount; i++) {
values.push(sortedHistory[i]['total-staking'])
try {
const { history } = await getStakingStats()
const sortedHistory = Object.values(history).sort((a, b) => b.current_epoch - a.current_epoch)
const epochCount = 30
const values = []
for (let i = 0; i < sortedHistory.length || i < epochCount; i++) {
values.push(sortedHistory[i]['total-staking'])
}
// calc avg total / values.length
return values.reduce((acc, item) => {
return acc.plus(item)
}, BigNumber(0)).div(values.length).div(10 ** 18).toNumber()
} catch (e) {
logger.error(e)
return 0
}

// calc avg total / values.length
return values.reduce((acc, item) => {
return acc.plus(item)
}, BigNumber(0)).div(values.length).div(10 ** 18).toNumber()
}
22 changes: 18 additions & 4 deletions src/modules/schedule/exchangeApi.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
import axios from 'axios'
import pino from 'pino'

const logger = pino({
name: 'ExchangeAPI',
transport: {
target: 'pino-pretty',
options: { colorize: true }
}
})

interface CoinGeckoResponse {
harmony: {
Expand All @@ -7,8 +16,13 @@ interface CoinGeckoResponse {
}

export const getOneRate = async (): Promise<number> => {
const { data } = await axios.get<CoinGeckoResponse>(
'https://api.coingecko.com/api/v3/simple/price?ids=harmony&vs_currencies=usd'
)
return +data.harmony.usd
try {
const { data } = await axios.get<CoinGeckoResponse>(
'https://api.coingecko.com/api/v3/simple/price?ids=harmony&vs_currencies=usd'
)
return +data.harmony.usd
} catch (e) {
logger.error(e)
return 0
}
}
Loading

0 comments on commit b6d703d

Please sign in to comment.