paged single metrics
This commit is contained in:
parent
db3c27c7f2
commit
eadc956c4c
12 changed files with 213 additions and 91 deletions
|
|
@ -158,9 +158,14 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- This methods has an __empty__ __request__ body
|
- This methods has an __empty__ __request__ body
|
||||||
- output: [LndSeed](#LndSeed)
|
- output: [LndSeed](#LndSeed)
|
||||||
|
|
||||||
|
- GetSingleUsageMetrics
|
||||||
|
- auth type: __Metrics__
|
||||||
|
- input: [SingleUsageMetricReq](#SingleUsageMetricReq)
|
||||||
|
- output: [UsageMetricTlv](#UsageMetricTlv)
|
||||||
|
|
||||||
- GetUsageMetrics
|
- GetUsageMetrics
|
||||||
- auth type: __Metrics__
|
- auth type: __Metrics__
|
||||||
- input: [UsageMetricReq](#UsageMetricReq)
|
- input: [LatestUsageMetricReq](#LatestUsageMetricReq)
|
||||||
- output: [UsageMetrics](#UsageMetrics)
|
- output: [UsageMetrics](#UsageMetrics)
|
||||||
|
|
||||||
- GetUserInfo
|
- GetUserInfo
|
||||||
|
|
@ -581,11 +586,18 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- This methods has an __empty__ __request__ body
|
- This methods has an __empty__ __request__ body
|
||||||
- output: [LndSeed](#LndSeed)
|
- output: [LndSeed](#LndSeed)
|
||||||
|
|
||||||
|
- GetSingleUsageMetrics
|
||||||
|
- auth type: __Metrics__
|
||||||
|
- http method: __post__
|
||||||
|
- http route: __/api/reports/usage/single__
|
||||||
|
- input: [SingleUsageMetricReq](#SingleUsageMetricReq)
|
||||||
|
- output: [UsageMetricTlv](#UsageMetricTlv)
|
||||||
|
|
||||||
- GetUsageMetrics
|
- GetUsageMetrics
|
||||||
- auth type: __Metrics__
|
- auth type: __Metrics__
|
||||||
- http method: __post__
|
- http method: __post__
|
||||||
- http route: __/api/reports/usage__
|
- http route: __/api/reports/usage__
|
||||||
- input: [UsageMetricReq](#UsageMetricReq)
|
- input: [LatestUsageMetricReq](#LatestUsageMetricReq)
|
||||||
- output: [UsageMetrics](#UsageMetrics)
|
- output: [UsageMetrics](#UsageMetrics)
|
||||||
|
|
||||||
- GetUserInfo
|
- GetUserInfo
|
||||||
|
|
@ -1070,6 +1082,9 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- __token__: _string_
|
- __token__: _string_
|
||||||
- __url__: _string_
|
- __url__: _string_
|
||||||
|
|
||||||
|
### LatestUsageMetricReq
|
||||||
|
- __limit__: _number_ *this field is optional
|
||||||
|
|
||||||
### LinkNPubThroughTokenRequest
|
### LinkNPubThroughTokenRequest
|
||||||
- __token__: _string_
|
- __token__: _string_
|
||||||
|
|
||||||
|
|
@ -1141,9 +1156,6 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- __tag__: _string_
|
- __tag__: _string_
|
||||||
|
|
||||||
### MetricsFile
|
### MetricsFile
|
||||||
- __app_id__: _string_
|
|
||||||
- __metrics_name__: _string_
|
|
||||||
- __page__: _number_
|
|
||||||
|
|
||||||
### MigrationUpdate
|
### MigrationUpdate
|
||||||
- __closure__: _[ClosureMigration](#ClosureMigration)_ *this field is optional
|
- __closure__: _[ClosureMigration](#ClosureMigration)_ *this field is optional
|
||||||
|
|
@ -1302,6 +1314,11 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- __amount__: _number_
|
- __amount__: _number_
|
||||||
- __invoice__: _string_
|
- __invoice__: _string_
|
||||||
|
|
||||||
|
### SingleUsageMetricReq
|
||||||
|
- __app_id__: _string_
|
||||||
|
- __metrics_name__: _string_
|
||||||
|
- __page__: _number_
|
||||||
|
|
||||||
### UpdateChannelPolicyRequest
|
### UpdateChannelPolicyRequest
|
||||||
- __policy__: _[ChannelPolicy](#ChannelPolicy)_
|
- __policy__: _[ChannelPolicy](#ChannelPolicy)_
|
||||||
- __update__: _[UpdateChannelPolicyRequest_update](#UpdateChannelPolicyRequest_update)_
|
- __update__: _[UpdateChannelPolicyRequest_update](#UpdateChannelPolicyRequest_update)_
|
||||||
|
|
@ -1319,10 +1336,6 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- __success__: _boolean_
|
- __success__: _boolean_
|
||||||
- __validate_in_nano__: _number_
|
- __validate_in_nano__: _number_
|
||||||
|
|
||||||
### UsageMetricReq
|
|
||||||
- __limit__: _number_ *this field is optional
|
|
||||||
- __metrics_file__: _[MetricsFile](#MetricsFile)_ *this field is optional
|
|
||||||
|
|
||||||
### UsageMetricTlv
|
### UsageMetricTlv
|
||||||
- __available_chunks__: ARRAY of: _number_
|
- __available_chunks__: ARRAY of: _number_
|
||||||
- __base_64_tlvs__: ARRAY of: _string_
|
- __base_64_tlvs__: ARRAY of: _string_
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,8 @@ type Client struct {
|
||||||
GetNPubLinkingState func(req GetNPubLinking) (*NPubLinking, error)
|
GetNPubLinkingState func(req GetNPubLinking) (*NPubLinking, error)
|
||||||
GetPaymentState func(req GetPaymentStateRequest) (*PaymentState, error)
|
GetPaymentState func(req GetPaymentStateRequest) (*PaymentState, error)
|
||||||
GetSeed func() (*LndSeed, error)
|
GetSeed func() (*LndSeed, error)
|
||||||
GetUsageMetrics func(req UsageMetricReq) (*UsageMetrics, error)
|
GetSingleUsageMetrics func(req SingleUsageMetricReq) (*UsageMetricTlv, error)
|
||||||
|
GetUsageMetrics func(req LatestUsageMetricReq) (*UsageMetrics, error)
|
||||||
GetUserInfo func() (*UserInfo, error)
|
GetUserInfo func() (*UserInfo, error)
|
||||||
GetUserOffer func(req OfferId) (*OfferConfig, error)
|
GetUserOffer func(req OfferId) (*OfferConfig, error)
|
||||||
GetUserOfferInvoices func(req GetUserOfferInvoicesReq) (*OfferInvoices, error)
|
GetUserOfferInvoices func(req GetUserOfferInvoicesReq) (*OfferInvoices, error)
|
||||||
|
|
@ -1057,7 +1058,36 @@ func NewClient(params ClientParams) *Client {
|
||||||
}
|
}
|
||||||
return &res, nil
|
return &res, nil
|
||||||
},
|
},
|
||||||
GetUsageMetrics: func(req UsageMetricReq) (*UsageMetrics, error) {
|
GetSingleUsageMetrics: func(req SingleUsageMetricReq) (*UsageMetricTlv, error) {
|
||||||
|
auth, err := params.RetrieveMetricsAuth()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
finalRoute := "/api/reports/usage/single"
|
||||||
|
body, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resBody, err := doPostRequest(params.BaseURL+finalRoute, body, auth)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result := ResultError{}
|
||||||
|
err = json.Unmarshal(resBody, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if result.Status == "ERROR" {
|
||||||
|
return nil, fmt.Errorf(result.Reason)
|
||||||
|
}
|
||||||
|
res := UsageMetricTlv{}
|
||||||
|
err = json.Unmarshal(resBody, &res)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &res, nil
|
||||||
|
},
|
||||||
|
GetUsageMetrics: func(req LatestUsageMetricReq) (*UsageMetrics, error) {
|
||||||
auth, err := params.RetrieveMetricsAuth()
|
auth, err := params.RetrieveMetricsAuth()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
||||||
|
|
@ -322,6 +322,9 @@ type HttpCreds struct {
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
Url string `json:"url"`
|
Url string `json:"url"`
|
||||||
}
|
}
|
||||||
|
type LatestUsageMetricReq struct {
|
||||||
|
Limit int64 `json:"limit"`
|
||||||
|
}
|
||||||
type LinkNPubThroughTokenRequest struct {
|
type LinkNPubThroughTokenRequest struct {
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
}
|
}
|
||||||
|
|
@ -393,9 +396,6 @@ type LnurlWithdrawInfoResponse struct {
|
||||||
Tag string `json:"tag"`
|
Tag string `json:"tag"`
|
||||||
}
|
}
|
||||||
type MetricsFile struct {
|
type MetricsFile struct {
|
||||||
App_id string `json:"app_id"`
|
|
||||||
Metrics_name string `json:"metrics_name"`
|
|
||||||
Page int64 `json:"page"`
|
|
||||||
}
|
}
|
||||||
type MigrationUpdate struct {
|
type MigrationUpdate struct {
|
||||||
Closure *ClosureMigration `json:"closure"`
|
Closure *ClosureMigration `json:"closure"`
|
||||||
|
|
@ -554,6 +554,11 @@ type SetMockInvoiceAsPaidRequest struct {
|
||||||
Amount int64 `json:"amount"`
|
Amount int64 `json:"amount"`
|
||||||
Invoice string `json:"invoice"`
|
Invoice string `json:"invoice"`
|
||||||
}
|
}
|
||||||
|
type SingleUsageMetricReq struct {
|
||||||
|
App_id string `json:"app_id"`
|
||||||
|
Metrics_name string `json:"metrics_name"`
|
||||||
|
Page int64 `json:"page"`
|
||||||
|
}
|
||||||
type UpdateChannelPolicyRequest struct {
|
type UpdateChannelPolicyRequest struct {
|
||||||
Policy *ChannelPolicy `json:"policy"`
|
Policy *ChannelPolicy `json:"policy"`
|
||||||
Update *UpdateChannelPolicyRequest_update `json:"update"`
|
Update *UpdateChannelPolicyRequest_update `json:"update"`
|
||||||
|
|
@ -571,10 +576,6 @@ type UsageMetric struct {
|
||||||
Success bool `json:"success"`
|
Success bool `json:"success"`
|
||||||
Validate_in_nano int64 `json:"validate_in_nano"`
|
Validate_in_nano int64 `json:"validate_in_nano"`
|
||||||
}
|
}
|
||||||
type UsageMetricReq struct {
|
|
||||||
Limit int64 `json:"limit"`
|
|
||||||
Metrics_file *MetricsFile `json:"metrics_file"`
|
|
||||||
}
|
|
||||||
type UsageMetricTlv struct {
|
type UsageMetricTlv struct {
|
||||||
Available_chunks []int64 `json:"available_chunks"`
|
Available_chunks []int64 `json:"available_chunks"`
|
||||||
Base_64_tlvs []string `json:"base_64_tlvs"`
|
Base_64_tlvs []string `json:"base_64_tlvs"`
|
||||||
|
|
|
||||||
|
|
@ -1106,6 +1106,28 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => {
|
||||||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
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 }
|
} 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.GetSingleUsageMetrics) throw new Error('method: GetSingleUsageMetrics is not implemented')
|
||||||
|
app.post('/api/reports/usage/single', async (req, res) => {
|
||||||
|
const info: Types.RequestInfo = { rpcName: 'GetSingleUsageMetrics', 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.GetSingleUsageMetrics) throw new Error('method: GetSingleUsageMetrics is not implemented')
|
||||||
|
const authContext = await opts.MetricsAuthGuard(req.headers['authorization'])
|
||||||
|
authCtx = authContext
|
||||||
|
stats.guard = process.hrtime.bigint()
|
||||||
|
const request = req.body
|
||||||
|
const error = Types.SingleUsageMetricReqValidate(request)
|
||||||
|
stats.validate = process.hrtime.bigint()
|
||||||
|
if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authContext }, opts.metricsCallback)
|
||||||
|
const query = req.query
|
||||||
|
const params = req.params
|
||||||
|
const response = await methods.GetSingleUsageMetrics({rpcName:'GetSingleUsageMetrics', ctx:authContext , req: request})
|
||||||
|
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.GetUsageMetrics) throw new Error('method: GetUsageMetrics is not implemented')
|
if (!opts.allowNotImplementedMethods && !methods.GetUsageMetrics) throw new Error('method: GetUsageMetrics is not implemented')
|
||||||
app.post('/api/reports/usage', async (req, res) => {
|
app.post('/api/reports/usage', async (req, res) => {
|
||||||
const info: Types.RequestInfo = { rpcName: 'GetUsageMetrics', batch: false, nostr: false, batchSize: 0}
|
const info: Types.RequestInfo = { rpcName: 'GetUsageMetrics', batch: false, nostr: false, batchSize: 0}
|
||||||
|
|
@ -1117,7 +1139,7 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => {
|
||||||
authCtx = authContext
|
authCtx = authContext
|
||||||
stats.guard = process.hrtime.bigint()
|
stats.guard = process.hrtime.bigint()
|
||||||
const request = req.body
|
const request = req.body
|
||||||
const error = Types.UsageMetricReqValidate(request)
|
const error = Types.LatestUsageMetricReqValidate(request)
|
||||||
stats.validate = process.hrtime.bigint()
|
stats.validate = process.hrtime.bigint()
|
||||||
if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authContext }, opts.metricsCallback)
|
if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authContext }, opts.metricsCallback)
|
||||||
const query = req.query
|
const query = req.query
|
||||||
|
|
|
||||||
|
|
@ -494,7 +494,21 @@ export default (params: ClientParams) => ({
|
||||||
}
|
}
|
||||||
return { status: 'ERROR', reason: 'invalid response' }
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
},
|
},
|
||||||
GetUsageMetrics: async (request: Types.UsageMetricReq): Promise<ResultError | ({ status: 'OK' }& Types.UsageMetrics)> => {
|
GetSingleUsageMetrics: async (request: Types.SingleUsageMetricReq): Promise<ResultError | ({ status: 'OK' }& Types.UsageMetricTlv)> => {
|
||||||
|
const auth = await params.retrieveMetricsAuth()
|
||||||
|
if (auth === null) throw new Error('retrieveMetricsAuth() returned null')
|
||||||
|
let finalRoute = '/api/reports/usage/single'
|
||||||
|
const { data } = await axios.post(params.baseUrl + finalRoute, request, { 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.UsageMetricTlvValidate(result)
|
||||||
|
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||||
|
}
|
||||||
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
},
|
||||||
|
GetUsageMetrics: async (request: Types.LatestUsageMetricReq): Promise<ResultError | ({ status: 'OK' }& Types.UsageMetrics)> => {
|
||||||
const auth = await params.retrieveMetricsAuth()
|
const auth = await params.retrieveMetricsAuth()
|
||||||
if (auth === null) throw new Error('retrieveMetricsAuth() returned null')
|
if (auth === null) throw new Error('retrieveMetricsAuth() returned null')
|
||||||
let finalRoute = '/api/reports/usage'
|
let finalRoute = '/api/reports/usage'
|
||||||
|
|
|
||||||
|
|
@ -422,7 +422,22 @@ export default (params: NostrClientParams, send: (to:string, message: NostrRequ
|
||||||
}
|
}
|
||||||
return { status: 'ERROR', reason: 'invalid response' }
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
},
|
},
|
||||||
GetUsageMetrics: async (request: Types.UsageMetricReq): Promise<ResultError | ({ status: 'OK' }& Types.UsageMetrics)> => {
|
GetSingleUsageMetrics: async (request: Types.SingleUsageMetricReq): Promise<ResultError | ({ status: 'OK' }& Types.UsageMetricTlv)> => {
|
||||||
|
const auth = await params.retrieveNostrMetricsAuth()
|
||||||
|
if (auth === null) throw new Error('retrieveNostrMetricsAuth() returned null')
|
||||||
|
const nostrRequest: NostrRequest = {}
|
||||||
|
nostrRequest.body = request
|
||||||
|
const data = await send(params.pubDestination, {rpcName:'GetSingleUsageMetrics',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.UsageMetricTlvValidate(result)
|
||||||
|
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||||
|
}
|
||||||
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
},
|
||||||
|
GetUsageMetrics: async (request: Types.LatestUsageMetricReq): Promise<ResultError | ({ status: 'OK' }& Types.UsageMetrics)> => {
|
||||||
const auth = await params.retrieveNostrMetricsAuth()
|
const auth = await params.retrieveNostrMetricsAuth()
|
||||||
if (auth === null) throw new Error('retrieveNostrMetricsAuth() returned null')
|
if (auth === null) throw new Error('retrieveNostrMetricsAuth() returned null')
|
||||||
const nostrRequest: NostrRequest = {}
|
const nostrRequest: NostrRequest = {}
|
||||||
|
|
|
||||||
|
|
@ -799,6 +799,22 @@ export default (methods: Types.ServerMethods, opts: NostrOptions) => {
|
||||||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
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 }
|
}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
|
break
|
||||||
|
case 'GetSingleUsageMetrics':
|
||||||
|
try {
|
||||||
|
if (!methods.GetSingleUsageMetrics) throw new Error('method: GetSingleUsageMetrics is not implemented')
|
||||||
|
const authContext = await opts.NostrMetricsAuthGuard(req.appId, req.authIdentifier)
|
||||||
|
stats.guard = process.hrtime.bigint()
|
||||||
|
authCtx = authContext
|
||||||
|
const request = req.body
|
||||||
|
const error = Types.SingleUsageMetricReqValidate(request)
|
||||||
|
stats.validate = process.hrtime.bigint()
|
||||||
|
if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback)
|
||||||
|
const response = await methods.GetSingleUsageMetrics({rpcName:'GetSingleUsageMetrics', ctx:authContext , req: request})
|
||||||
|
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 'GetUsageMetrics':
|
case 'GetUsageMetrics':
|
||||||
try {
|
try {
|
||||||
if (!methods.GetUsageMetrics) throw new Error('method: GetUsageMetrics is not implemented')
|
if (!methods.GetUsageMetrics) throw new Error('method: GetUsageMetrics is not implemented')
|
||||||
|
|
@ -806,7 +822,7 @@ export default (methods: Types.ServerMethods, opts: NostrOptions) => {
|
||||||
stats.guard = process.hrtime.bigint()
|
stats.guard = process.hrtime.bigint()
|
||||||
authCtx = authContext
|
authCtx = authContext
|
||||||
const request = req.body
|
const request = req.body
|
||||||
const error = Types.UsageMetricReqValidate(request)
|
const error = Types.LatestUsageMetricReqValidate(request)
|
||||||
stats.validate = process.hrtime.bigint()
|
stats.validate = process.hrtime.bigint()
|
||||||
if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback)
|
if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback)
|
||||||
const response = await methods.GetUsageMetrics({rpcName:'GetUsageMetrics', ctx:authContext , req: request})
|
const response = await methods.GetUsageMetrics({rpcName:'GetUsageMetrics', ctx:authContext , req: request})
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,8 @@ export type GuestWithPubMethodOutputs = LinkNPubThroughToken_Output | UseInviteL
|
||||||
export type MetricsContext = {
|
export type MetricsContext = {
|
||||||
operator_id: string
|
operator_id: string
|
||||||
}
|
}
|
||||||
export type MetricsMethodInputs = GetAppsMetrics_Input | GetErrorStats_Input | GetLndMetrics_Input | GetUsageMetrics_Input
|
export type MetricsMethodInputs = GetAppsMetrics_Input | GetErrorStats_Input | GetLndMetrics_Input | GetSingleUsageMetrics_Input | GetUsageMetrics_Input
|
||||||
export type MetricsMethodOutputs = GetAppsMetrics_Output | GetErrorStats_Output | GetLndMetrics_Output | GetUsageMetrics_Output
|
export type MetricsMethodOutputs = GetAppsMetrics_Output | GetErrorStats_Output | GetLndMetrics_Output | GetSingleUsageMetrics_Output | GetUsageMetrics_Output
|
||||||
export type UserContext = {
|
export type UserContext = {
|
||||||
app_id: string
|
app_id: string
|
||||||
app_user_id: string
|
app_user_id: string
|
||||||
|
|
@ -161,7 +161,10 @@ export type GetPaymentState_Output = ResultError | ({ status: 'OK' } & PaymentSt
|
||||||
export type GetSeed_Input = {rpcName:'GetSeed'}
|
export type GetSeed_Input = {rpcName:'GetSeed'}
|
||||||
export type GetSeed_Output = ResultError | ({ status: 'OK' } & LndSeed)
|
export type GetSeed_Output = ResultError | ({ status: 'OK' } & LndSeed)
|
||||||
|
|
||||||
export type GetUsageMetrics_Input = {rpcName:'GetUsageMetrics', req: UsageMetricReq}
|
export type GetSingleUsageMetrics_Input = {rpcName:'GetSingleUsageMetrics', req: SingleUsageMetricReq}
|
||||||
|
export type GetSingleUsageMetrics_Output = ResultError | ({ status: 'OK' } & UsageMetricTlv)
|
||||||
|
|
||||||
|
export type GetUsageMetrics_Input = {rpcName:'GetUsageMetrics', req: LatestUsageMetricReq}
|
||||||
export type GetUsageMetrics_Output = ResultError | ({ status: 'OK' } & UsageMetrics)
|
export type GetUsageMetrics_Output = ResultError | ({ status: 'OK' } & UsageMetrics)
|
||||||
|
|
||||||
export type GetUserInfo_Input = {rpcName:'GetUserInfo'}
|
export type GetUserInfo_Input = {rpcName:'GetUserInfo'}
|
||||||
|
|
@ -318,6 +321,7 @@ export type ServerMethods = {
|
||||||
GetNPubLinkingState?: (req: GetNPubLinkingState_Input & {ctx: AppContext }) => Promise<NPubLinking>
|
GetNPubLinkingState?: (req: GetNPubLinkingState_Input & {ctx: AppContext }) => Promise<NPubLinking>
|
||||||
GetPaymentState?: (req: GetPaymentState_Input & {ctx: UserContext }) => Promise<PaymentState>
|
GetPaymentState?: (req: GetPaymentState_Input & {ctx: UserContext }) => Promise<PaymentState>
|
||||||
GetSeed?: (req: GetSeed_Input & {ctx: AdminContext }) => Promise<LndSeed>
|
GetSeed?: (req: GetSeed_Input & {ctx: AdminContext }) => Promise<LndSeed>
|
||||||
|
GetSingleUsageMetrics?: (req: GetSingleUsageMetrics_Input & {ctx: MetricsContext }) => Promise<UsageMetricTlv>
|
||||||
GetUsageMetrics?: (req: GetUsageMetrics_Input & {ctx: MetricsContext }) => Promise<UsageMetrics>
|
GetUsageMetrics?: (req: GetUsageMetrics_Input & {ctx: MetricsContext }) => Promise<UsageMetrics>
|
||||||
GetUserInfo?: (req: GetUserInfo_Input & {ctx: UserContext }) => Promise<UserInfo>
|
GetUserInfo?: (req: GetUserInfo_Input & {ctx: UserContext }) => Promise<UserInfo>
|
||||||
GetUserOffer?: (req: GetUserOffer_Input & {ctx: UserContext }) => Promise<OfferConfig>
|
GetUserOffer?: (req: GetUserOffer_Input & {ctx: UserContext }) => Promise<OfferConfig>
|
||||||
|
|
@ -1799,6 +1803,25 @@ export const HttpCredsValidate = (o?: HttpCreds, opts: HttpCredsOptions = {}, pa
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type LatestUsageMetricReq = {
|
||||||
|
limit?: number
|
||||||
|
}
|
||||||
|
export type LatestUsageMetricReqOptionalField = 'limit'
|
||||||
|
export const LatestUsageMetricReqOptionalFields: LatestUsageMetricReqOptionalField[] = ['limit']
|
||||||
|
export type LatestUsageMetricReqOptions = OptionsBaseMessage & {
|
||||||
|
checkOptionalsAreSet?: LatestUsageMetricReqOptionalField[]
|
||||||
|
limit_CustomCheck?: (v?: number) => boolean
|
||||||
|
}
|
||||||
|
export const LatestUsageMetricReqValidate = (o?: LatestUsageMetricReq, opts: LatestUsageMetricReqOptions = {}, path: string = 'LatestUsageMetricReq::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 ((o.limit || opts.allOptionalsAreSet || opts.checkOptionalsAreSet?.includes('limit')) && typeof o.limit !== 'number') return new Error(`${path}.limit: is not a number`)
|
||||||
|
if (opts.limit_CustomCheck && !opts.limit_CustomCheck(o.limit)) return new Error(`${path}.limit: custom check failed`)
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
export type LinkNPubThroughTokenRequest = {
|
export type LinkNPubThroughTokenRequest = {
|
||||||
token: string
|
token: string
|
||||||
}
|
}
|
||||||
|
|
@ -2235,30 +2258,15 @@ export const LnurlWithdrawInfoResponseValidate = (o?: LnurlWithdrawInfoResponse,
|
||||||
}
|
}
|
||||||
|
|
||||||
export type MetricsFile = {
|
export type MetricsFile = {
|
||||||
app_id: string
|
|
||||||
metrics_name: string
|
|
||||||
page: number
|
|
||||||
}
|
}
|
||||||
export const MetricsFileOptionalFields: [] = []
|
export const MetricsFileOptionalFields: [] = []
|
||||||
export type MetricsFileOptions = OptionsBaseMessage & {
|
export type MetricsFileOptions = OptionsBaseMessage & {
|
||||||
checkOptionalsAreSet?: []
|
checkOptionalsAreSet?: []
|
||||||
app_id_CustomCheck?: (v: string) => boolean
|
|
||||||
metrics_name_CustomCheck?: (v: string) => boolean
|
|
||||||
page_CustomCheck?: (v: number) => boolean
|
|
||||||
}
|
}
|
||||||
export const MetricsFileValidate = (o?: MetricsFile, opts: MetricsFileOptions = {}, path: string = 'MetricsFile::root.'): Error | null => {
|
export const MetricsFileValidate = (o?: MetricsFile, opts: MetricsFileOptions = {}, path: string = 'MetricsFile::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 (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 !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
|
||||||
|
|
||||||
if (typeof o.app_id !== 'string') return new Error(`${path}.app_id: is not a string`)
|
|
||||||
if (opts.app_id_CustomCheck && !opts.app_id_CustomCheck(o.app_id)) return new Error(`${path}.app_id: custom check failed`)
|
|
||||||
|
|
||||||
if (typeof o.metrics_name !== 'string') return new Error(`${path}.metrics_name: is not a string`)
|
|
||||||
if (opts.metrics_name_CustomCheck && !opts.metrics_name_CustomCheck(o.metrics_name)) return new Error(`${path}.metrics_name: custom check failed`)
|
|
||||||
|
|
||||||
if (typeof o.page !== 'number') return new Error(`${path}.page: is not a number`)
|
|
||||||
if (opts.page_CustomCheck && !opts.page_CustomCheck(o.page)) return new Error(`${path}.page: custom check failed`)
|
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3170,6 +3178,34 @@ export const SetMockInvoiceAsPaidRequestValidate = (o?: SetMockInvoiceAsPaidRequ
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type SingleUsageMetricReq = {
|
||||||
|
app_id: string
|
||||||
|
metrics_name: string
|
||||||
|
page: number
|
||||||
|
}
|
||||||
|
export const SingleUsageMetricReqOptionalFields: [] = []
|
||||||
|
export type SingleUsageMetricReqOptions = OptionsBaseMessage & {
|
||||||
|
checkOptionalsAreSet?: []
|
||||||
|
app_id_CustomCheck?: (v: string) => boolean
|
||||||
|
metrics_name_CustomCheck?: (v: string) => boolean
|
||||||
|
page_CustomCheck?: (v: number) => boolean
|
||||||
|
}
|
||||||
|
export const SingleUsageMetricReqValidate = (o?: SingleUsageMetricReq, opts: SingleUsageMetricReqOptions = {}, path: string = 'SingleUsageMetricReq::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.app_id !== 'string') return new Error(`${path}.app_id: is not a string`)
|
||||||
|
if (opts.app_id_CustomCheck && !opts.app_id_CustomCheck(o.app_id)) return new Error(`${path}.app_id: custom check failed`)
|
||||||
|
|
||||||
|
if (typeof o.metrics_name !== 'string') return new Error(`${path}.metrics_name: is not a string`)
|
||||||
|
if (opts.metrics_name_CustomCheck && !opts.metrics_name_CustomCheck(o.metrics_name)) return new Error(`${path}.metrics_name: custom check failed`)
|
||||||
|
|
||||||
|
if (typeof o.page !== 'number') return new Error(`${path}.page: is not a number`)
|
||||||
|
if (opts.page_CustomCheck && !opts.page_CustomCheck(o.page)) return new Error(`${path}.page: custom check failed`)
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
export type UpdateChannelPolicyRequest = {
|
export type UpdateChannelPolicyRequest = {
|
||||||
policy: ChannelPolicy
|
policy: ChannelPolicy
|
||||||
update: UpdateChannelPolicyRequest_update
|
update: UpdateChannelPolicyRequest_update
|
||||||
|
|
@ -3264,33 +3300,6 @@ export const UsageMetricValidate = (o?: UsageMetric, opts: UsageMetricOptions =
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UsageMetricReq = {
|
|
||||||
limit?: number
|
|
||||||
metrics_file?: MetricsFile
|
|
||||||
}
|
|
||||||
export type UsageMetricReqOptionalField = 'limit' | 'metrics_file'
|
|
||||||
export const UsageMetricReqOptionalFields: UsageMetricReqOptionalField[] = ['limit', 'metrics_file']
|
|
||||||
export type UsageMetricReqOptions = OptionsBaseMessage & {
|
|
||||||
checkOptionalsAreSet?: UsageMetricReqOptionalField[]
|
|
||||||
limit_CustomCheck?: (v?: number) => boolean
|
|
||||||
metrics_file_Options?: MetricsFileOptions
|
|
||||||
}
|
|
||||||
export const UsageMetricReqValidate = (o?: UsageMetricReq, opts: UsageMetricReqOptions = {}, path: string = 'UsageMetricReq::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 ((o.limit || opts.allOptionalsAreSet || opts.checkOptionalsAreSet?.includes('limit')) && typeof o.limit !== 'number') return new Error(`${path}.limit: is not a number`)
|
|
||||||
if (opts.limit_CustomCheck && !opts.limit_CustomCheck(o.limit)) return new Error(`${path}.limit: custom check failed`)
|
|
||||||
|
|
||||||
if (typeof o.metrics_file === 'object' || opts.allOptionalsAreSet || opts.checkOptionalsAreSet?.includes('metrics_file')) {
|
|
||||||
const metrics_fileErr = MetricsFileValidate(o.metrics_file, opts.metrics_file_Options, `${path}.metrics_file`)
|
|
||||||
if (metrics_fileErr !== null) return metrics_fileErr
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
export type UsageMetricTlv = {
|
export type UsageMetricTlv = {
|
||||||
available_chunks: number[]
|
available_chunks: number[]
|
||||||
base_64_tlvs: string[]
|
base_64_tlvs: string[]
|
||||||
|
|
|
||||||
|
|
@ -172,12 +172,18 @@ service LightningPub {
|
||||||
option (nostr) = true;
|
option (nostr) = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
rpc GetUsageMetrics(structs.UsageMetricReq) returns (structs.UsageMetrics) {
|
rpc GetUsageMetrics(structs.LatestUsageMetricReq) returns (structs.UsageMetrics) {
|
||||||
option (auth_type) = "Metrics";
|
option (auth_type) = "Metrics";
|
||||||
option (http_method) = "post";
|
option (http_method) = "post";
|
||||||
option (http_route) = "/api/reports/usage";
|
option (http_route) = "/api/reports/usage";
|
||||||
option (nostr) = true;
|
option (nostr) = true;
|
||||||
}
|
}
|
||||||
|
rpc GetSingleUsageMetrics(structs.SingleUsageMetricReq) returns (structs.UsageMetricTlv) {
|
||||||
|
option (auth_type) = "Metrics";
|
||||||
|
option (http_method) = "post";
|
||||||
|
option (http_route) = "/api/reports/usage/single";
|
||||||
|
option (nostr) = true;
|
||||||
|
}
|
||||||
rpc GetErrorStats(structs.Empty) returns (structs.ErrorStats) {
|
rpc GetErrorStats(structs.Empty) returns (structs.ErrorStats) {
|
||||||
option (auth_type) = "Metrics";
|
option (auth_type) = "Metrics";
|
||||||
option (http_method) = "post";
|
option (http_method) = "post";
|
||||||
|
|
|
||||||
|
|
@ -34,16 +34,19 @@ message ErrorStats {
|
||||||
}
|
}
|
||||||
|
|
||||||
message MetricsFile {
|
message MetricsFile {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
message LatestUsageMetricReq {
|
||||||
|
optional int64 limit = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SingleUsageMetricReq {
|
||||||
string app_id = 1;
|
string app_id = 1;
|
||||||
string metrics_name = 2;
|
string metrics_name = 2;
|
||||||
int64 page = 3;
|
int64 page = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message UsageMetricReq {
|
|
||||||
optional int64 limit = 1;
|
|
||||||
optional MetricsFile metrics_file = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message UsageMetric {
|
message UsageMetric {
|
||||||
int64 processed_at_ms = 1;
|
int64 processed_at_ms = 1;
|
||||||
int64 parsed_in_nano = 2;
|
int64 parsed_in_nano = 2;
|
||||||
|
|
|
||||||
|
|
@ -69,11 +69,12 @@ export default class Handler {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
async GetUsageMetrics(req: Types.UsageMetricReq): Promise<Types.UsageMetrics> {
|
async GetUsageMetrics(req: Types.LatestUsageMetricReq): Promise<Types.UsageMetrics> {
|
||||||
if (!req.metrics_file) {
|
return this.storage.metricsEventStorage.LoadLatestMetrics(req.limit)
|
||||||
return this.storage.metricsEventStorage.LoadLatestMetrics(req.limit)
|
}
|
||||||
}
|
|
||||||
return this.storage.metricsEventStorage.LoadMetricsFile(req.metrics_file.app_id, req.metrics_file.metrics_name, req.metrics_file.page)
|
async GetSingleUsageMetrics(req: Types.SingleUsageMetricReq): Promise<Types.UsageMetricTlv> {
|
||||||
|
return this.storage.metricsEventStorage.LoadMetricsFile(req.app_id, req.metrics_name, req.page)
|
||||||
}
|
}
|
||||||
|
|
||||||
async GetErrorStats(): Promise<Types.ErrorStats> {
|
async GetErrorStats(): Promise<Types.ErrorStats> {
|
||||||
|
|
|
||||||
|
|
@ -132,25 +132,17 @@ export default class {
|
||||||
return metrics
|
return metrics
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadMetricsFile = async (app: string, method: string, chunk: number): Promise<Types.UsageMetrics> => {
|
LoadMetricsFile = async (app: string, method: string, chunk: number): Promise<Types.UsageMetricTlv> => {
|
||||||
if (!this.metaReady || !this.metricsMeta[app] || !this.metricsMeta[app][method] || !this.metricsMeta[app][method].chunks.includes(chunk)) {
|
if (!this.metaReady || !this.metricsMeta[app] || !this.metricsMeta[app][method] || !this.metricsMeta[app][method].chunks.includes(chunk)) {
|
||||||
return { apps: {} }
|
throw new Error("metrics not found")
|
||||||
}
|
}
|
||||||
const fullPath = [this.metricsPath, app, method, `${chunk}.mtlv`].join("/")
|
const fullPath = [this.metricsPath, app, method, `${chunk}.mtlv`].join("/")
|
||||||
const tlv = fs.readFileSync(fullPath)
|
const tlv = fs.readFileSync(fullPath)
|
||||||
const decoded = decodeListTLV(parseTLV(tlv))
|
const decoded = decodeListTLV(parseTLV(tlv))
|
||||||
return {
|
return {
|
||||||
apps: {
|
base_64_tlvs: decoded.map(d => Buffer.from(d).toString('base64')),
|
||||||
[app]: {
|
current_chunk: chunk,
|
||||||
app_metrics: {
|
available_chunks: this.metricsMeta[app][method].chunks
|
||||||
[method]: {
|
|
||||||
base_64_tlvs: decoded.map(d => Buffer.from(d).toString('base64')),
|
|
||||||
current_chunk: chunk,
|
|
||||||
available_chunks: this.metricsMeta[app][method].chunks
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue