error rates
This commit is contained in:
parent
4aeb565596
commit
16d4198364
13 changed files with 323 additions and 9 deletions
|
|
@ -885,6 +885,25 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => {
|
|||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||
})
|
||||
if (!opts.allowNotImplementedMethods && !methods.GetErrorStats) throw new Error('method: GetErrorStats is not implemented')
|
||||
app.post('/api/reports/errors', async (req, res) => {
|
||||
const info: Types.RequestInfo = { rpcName: 'GetErrorStats', batch: false, nostr: false, batchSize: 0}
|
||||
const stats: Types.RequestStats = { startMs:req.startTimeMs || 0, start:req.startTime || 0n, parse: process.hrtime.bigint(), guard: 0n, validate: 0n, handle: 0n }
|
||||
let authCtx: Types.AuthContext = {}
|
||||
try {
|
||||
if (!methods.GetErrorStats) throw new Error('method: GetErrorStats is not implemented')
|
||||
const authContext = await opts.MetricsAuthGuard(req.headers['authorization'])
|
||||
authCtx = authContext
|
||||
stats.guard = process.hrtime.bigint()
|
||||
stats.validate = stats.guard
|
||||
const query = req.query
|
||||
const params = req.params
|
||||
const response = await methods.GetErrorStats({rpcName:'GetErrorStats', ctx:authContext })
|
||||
stats.handle = process.hrtime.bigint()
|
||||
res.json({status: 'OK', ...response})
|
||||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||
})
|
||||
if (!opts.allowNotImplementedMethods && !methods.GetInviteLinkState) throw new Error('method: GetInviteLinkState is not implemented')
|
||||
app.post('/api/admin/app/invite/get', async (req, res) => {
|
||||
const info: Types.RequestInfo = { rpcName: 'GetInviteLinkState', batch: false, nostr: false, batchSize: 0}
|
||||
|
|
|
|||
|
|
@ -332,6 +332,20 @@ export default (params: ClientParams) => ({
|
|||
}
|
||||
return { status: 'ERROR', reason: 'invalid response' }
|
||||
},
|
||||
GetErrorStats: async (): Promise<ResultError | ({ status: 'OK' }& Types.ErrorStats)> => {
|
||||
const auth = await params.retrieveMetricsAuth()
|
||||
if (auth === null) throw new Error('retrieveMetricsAuth() returned null')
|
||||
let finalRoute = '/api/reports/errors'
|
||||
const { data } = await axios.post(params.baseUrl + finalRoute, {}, { headers: { 'authorization': auth } })
|
||||
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
||||
if (data.status === 'OK') {
|
||||
const result = data
|
||||
if(!params.checkResult) return { status: 'OK', ...result }
|
||||
const error = Types.ErrorStatsValidate(result)
|
||||
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||
}
|
||||
return { status: 'ERROR', reason: 'invalid response' }
|
||||
},
|
||||
GetHttpCreds: async (cb: (v:ResultError | ({ status: 'OK' }& Types.HttpCreds)) => void): Promise<void> => { throw new Error('http streams are not supported')},
|
||||
GetInviteLinkState: async (request: Types.GetInviteTokenStateRequest): Promise<ResultError | ({ status: 'OK' }& Types.GetInviteTokenStateResponse)> => {
|
||||
const auth = await params.retrieveAdminAuth()
|
||||
|
|
|
|||
|
|
@ -247,6 +247,20 @@ export default (params: NostrClientParams, send: (to:string, message: NostrRequ
|
|||
}
|
||||
return { status: 'ERROR', reason: 'invalid response' }
|
||||
},
|
||||
GetErrorStats: async (): Promise<ResultError | ({ status: 'OK' }& Types.ErrorStats)> => {
|
||||
const auth = await params.retrieveNostrMetricsAuth()
|
||||
if (auth === null) throw new Error('retrieveNostrMetricsAuth() returned null')
|
||||
const nostrRequest: NostrRequest = {}
|
||||
const data = await send(params.pubDestination, {rpcName:'GetErrorStats',authIdentifier:auth, ...nostrRequest })
|
||||
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
||||
if (data.status === 'OK') {
|
||||
const result = data
|
||||
if(!params.checkResult) return { status: 'OK', ...result }
|
||||
const error = Types.ErrorStatsValidate(result)
|
||||
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||
}
|
||||
return { status: 'ERROR', reason: 'invalid response' }
|
||||
},
|
||||
GetHttpCreds: async (cb: (res:ResultError | ({ status: 'OK' }& Types.HttpCreds)) => void): Promise<void> => {
|
||||
const auth = await params.retrieveNostrUserAuth()
|
||||
if (auth === null) throw new Error('retrieveNostrUserAuth() returned null')
|
||||
|
|
|
|||
|
|
@ -634,6 +634,19 @@ export default (methods: Types.ServerMethods, opts: NostrOptions) => {
|
|||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||
}catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||
break
|
||||
case 'GetErrorStats':
|
||||
try {
|
||||
if (!methods.GetErrorStats) throw new Error('method: GetErrorStats is not implemented')
|
||||
const authContext = await opts.NostrMetricsAuthGuard(req.appId, req.authIdentifier)
|
||||
stats.guard = process.hrtime.bigint()
|
||||
authCtx = authContext
|
||||
stats.validate = stats.guard
|
||||
const response = await methods.GetErrorStats({rpcName:'GetErrorStats', ctx:authContext })
|
||||
stats.handle = process.hrtime.bigint()
|
||||
res({status: 'OK', ...response})
|
||||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||
}catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||
break
|
||||
case 'GetHttpCreds':
|
||||
try {
|
||||
if (!methods.GetHttpCreds) throw new Error('method: GetHttpCreds is not implemented')
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ export type GuestWithPubMethodOutputs = LinkNPubThroughToken_Output | UseInviteL
|
|||
export type MetricsContext = {
|
||||
operator_id: string
|
||||
}
|
||||
export type MetricsMethodInputs = GetAppsMetrics_Input | GetLndMetrics_Input | GetUsageMetrics_Input
|
||||
export type MetricsMethodOutputs = GetAppsMetrics_Output | GetLndMetrics_Output | GetUsageMetrics_Output
|
||||
export type MetricsMethodInputs = GetAppsMetrics_Input | GetErrorStats_Input | GetLndMetrics_Input | GetUsageMetrics_Input
|
||||
export type MetricsMethodOutputs = GetAppsMetrics_Output | GetErrorStats_Output | GetLndMetrics_Output | GetUsageMetrics_Output
|
||||
export type UserContext = {
|
||||
app_id: string
|
||||
app_user_id: string
|
||||
|
|
@ -110,6 +110,9 @@ export type GetAppsMetrics_Output = ResultError | ({ status: 'OK' } & AppsMetric
|
|||
export type GetDebitAuthorizations_Input = {rpcName:'GetDebitAuthorizations'}
|
||||
export type GetDebitAuthorizations_Output = ResultError | ({ status: 'OK' } & DebitAuthorizations)
|
||||
|
||||
export type GetErrorStats_Input = {rpcName:'GetErrorStats'}
|
||||
export type GetErrorStats_Output = ResultError | ({ status: 'OK' } & ErrorStats)
|
||||
|
||||
export type GetHttpCreds_Input = {rpcName:'GetHttpCreds', cb:(res: HttpCreds, err:Error|null)=> void}
|
||||
export type GetHttpCreds_Output = ResultError | { status: 'OK' }
|
||||
|
||||
|
|
@ -300,6 +303,7 @@ export type ServerMethods = {
|
|||
GetAppUserLNURLInfo?: (req: GetAppUserLNURLInfo_Input & {ctx: AppContext }) => Promise<LnurlPayInfoResponse>
|
||||
GetAppsMetrics?: (req: GetAppsMetrics_Input & {ctx: MetricsContext }) => Promise<AppsMetrics>
|
||||
GetDebitAuthorizations?: (req: GetDebitAuthorizations_Input & {ctx: UserContext }) => Promise<DebitAuthorizations>
|
||||
GetErrorStats?: (req: GetErrorStats_Input & {ctx: MetricsContext }) => Promise<ErrorStats>
|
||||
GetHttpCreds?: (req: GetHttpCreds_Input & {ctx: UserContext }) => Promise<void>
|
||||
GetInviteLinkState?: (req: GetInviteLinkState_Input & {ctx: AdminContext }) => Promise<GetInviteTokenStateResponse>
|
||||
GetLNURLChannelLink?: (req: GetLNURLChannelLink_Input & {ctx: UserContext }) => Promise<LnurlLinkResponse>
|
||||
|
|
@ -1371,6 +1375,77 @@ export const EnrollAdminTokenRequestValidate = (o?: EnrollAdminTokenRequest, opt
|
|||
return null
|
||||
}
|
||||
|
||||
export type ErrorStat = {
|
||||
errors: number
|
||||
from_unix: number
|
||||
total: number
|
||||
}
|
||||
export const ErrorStatOptionalFields: [] = []
|
||||
export type ErrorStatOptions = OptionsBaseMessage & {
|
||||
checkOptionalsAreSet?: []
|
||||
errors_CustomCheck?: (v: number) => boolean
|
||||
from_unix_CustomCheck?: (v: number) => boolean
|
||||
total_CustomCheck?: (v: number) => boolean
|
||||
}
|
||||
export const ErrorStatValidate = (o?: ErrorStat, opts: ErrorStatOptions = {}, path: string = 'ErrorStat::root.'): Error | null => {
|
||||
if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message')
|
||||
if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
|
||||
|
||||
if (typeof o.errors !== 'number') return new Error(`${path}.errors: is not a number`)
|
||||
if (opts.errors_CustomCheck && !opts.errors_CustomCheck(o.errors)) return new Error(`${path}.errors: custom check failed`)
|
||||
|
||||
if (typeof o.from_unix !== 'number') return new Error(`${path}.from_unix: is not a number`)
|
||||
if (opts.from_unix_CustomCheck && !opts.from_unix_CustomCheck(o.from_unix)) return new Error(`${path}.from_unix: custom check failed`)
|
||||
|
||||
if (typeof o.total !== 'number') return new Error(`${path}.total: is not a number`)
|
||||
if (opts.total_CustomCheck && !opts.total_CustomCheck(o.total)) return new Error(`${path}.total: custom check failed`)
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
export type ErrorStats = {
|
||||
past10m: ErrorStat
|
||||
past1h: ErrorStat
|
||||
past1m: ErrorStat
|
||||
past24h: ErrorStat
|
||||
past6h: ErrorStat
|
||||
}
|
||||
export const ErrorStatsOptionalFields: [] = []
|
||||
export type ErrorStatsOptions = OptionsBaseMessage & {
|
||||
checkOptionalsAreSet?: []
|
||||
past10m_Options?: ErrorStatOptions
|
||||
past1h_Options?: ErrorStatOptions
|
||||
past1m_Options?: ErrorStatOptions
|
||||
past24h_Options?: ErrorStatOptions
|
||||
past6h_Options?: ErrorStatOptions
|
||||
}
|
||||
export const ErrorStatsValidate = (o?: ErrorStats, opts: ErrorStatsOptions = {}, path: string = 'ErrorStats::root.'): Error | null => {
|
||||
if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message')
|
||||
if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
|
||||
|
||||
const past10mErr = ErrorStatValidate(o.past10m, opts.past10m_Options, `${path}.past10m`)
|
||||
if (past10mErr !== null) return past10mErr
|
||||
|
||||
|
||||
const past1hErr = ErrorStatValidate(o.past1h, opts.past1h_Options, `${path}.past1h`)
|
||||
if (past1hErr !== null) return past1hErr
|
||||
|
||||
|
||||
const past1mErr = ErrorStatValidate(o.past1m, opts.past1m_Options, `${path}.past1m`)
|
||||
if (past1mErr !== null) return past1mErr
|
||||
|
||||
|
||||
const past24hErr = ErrorStatValidate(o.past24h, opts.past24h_Options, `${path}.past24h`)
|
||||
if (past24hErr !== null) return past24hErr
|
||||
|
||||
|
||||
const past6hErr = ErrorStatValidate(o.past6h, opts.past6h_Options, `${path}.past6h`)
|
||||
if (past6hErr !== null) return past6hErr
|
||||
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
export type FrequencyRule = {
|
||||
amount: number
|
||||
interval: IntervalType
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue