taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit 5885cc498cf4effb4774305383e24eddb2910019
parent 48764f27bc67764112665b792668099c9d175eb5
Author: Iván Ávalos <avalos@disroot.org>
Date:   Wed, 11 Mar 2026 16:12:32 +0100

wallet-core: improved performance stats

Diffstat:
Mpackages/taler-util/src/notifications.ts | 3+++
Mpackages/taler-util/src/observability.ts | 3+++
Mpackages/taler-util/src/performance.ts | 40+++++++++++++++++++++++++++++++++++++---
Mpackages/taler-util/src/types-taler-wallet.ts | 2+-
Mpackages/taler-wallet-core/src/wallet-api-types.ts | 4++--
5 files changed, 46 insertions(+), 6 deletions(-)

diff --git a/packages/taler-util/src/notifications.ts b/packages/taler-util/src/notifications.ts @@ -248,6 +248,7 @@ export type ObservabilityEvent = when: AbsoluteTime; type: ObservabilityEventType.HttpFetchStart; url: string; + longPolling: boolean; } | { id: string; @@ -256,6 +257,7 @@ export type ObservabilityEvent = url: string; status: number; durationMs: number; + longPolling: boolean; } | { id: string; @@ -264,6 +266,7 @@ export type ObservabilityEvent = url: string; error: TalerErrorDetail; durationMs: number; + longPolling: boolean; } | { type: ObservabilityEventType.DbQueryStart; diff --git a/packages/taler-util/src/observability.ts b/packages/taler-util/src/observability.ts @@ -66,6 +66,7 @@ export class ObservableHttpClientLibrary implements HttpRequestLibrary { when: AbsoluteTime.now(), type: ObservabilityEventType.HttpFetchStart, url: url, + longPolling: !opt?.cancellationToken, }); const optsWithCancel = opt ?? {}; @@ -81,6 +82,7 @@ export class ObservableHttpClientLibrary implements HttpRequestLibrary { url, status: res.status, durationMs: performanceDelta(start, end), + longPolling: !opt?.cancellationToken, }; this.oc.observe(event); return res; @@ -93,6 +95,7 @@ export class ObservableHttpClientLibrary implements HttpRequestLibrary { url, error: getErrorDetailFromException(e), durationMs: performanceDelta(start, end), + longPolling: !opt?.cancellationToken, }); throw e; } finally { diff --git a/packages/taler-util/src/performance.ts b/packages/taler-util/src/performance.ts @@ -37,32 +37,47 @@ export type PerformanceStat = | { type: PerformanceStatType.HttpFetch; url: string; + avgDurationMs: number; maxDurationMs: number; + minDurationMs: number; + totalDurationMs: number; count: number; } | { type: PerformanceStatType.DbQuery; name: string; location: string; + avgDurationMs: number; maxDurationMs: number; + minDurationMs: number; + totalDurationMs: number; count: number; } | { type: PerformanceStatType.Crypto; operation: string; + avgDurationMs: number; maxDurationMs: number; + minDurationMs: number; + totalDurationMs: number; count: number; } | { type: PerformanceStatType.WalletRequest; operation: string; + avgDurationMs: number; maxDurationMs: number; + minDurationMs: number; + totalDurationMs: number; count: number; } | { type: PerformanceStatType.WalletTask; taskId: string; + avgDurationMs: number; maxDurationMs: number; + minDurationMs: number; + totalDurationMs: number; count: number; }; @@ -71,13 +86,17 @@ export namespace PerformanceStat { evt: ObservabilityEvent & { durationMs: number }, ): PerformanceStat | undefined { if ( - evt.type === ObservabilityEventType.HttpFetchFinishSuccess || - evt.type === ObservabilityEventType.HttpFetchFinishError + (evt.type === ObservabilityEventType.HttpFetchFinishSuccess || + evt.type === ObservabilityEventType.HttpFetchFinishError + ) && !evt.longPolling ) { return { type: PerformanceStatType.HttpFetch, url: evt.url, + avgDurationMs: evt.durationMs, maxDurationMs: evt.durationMs, + minDurationMs: evt.durationMs, + totalDurationMs: evt.durationMs, count: 1, }; } else if ( @@ -88,7 +107,10 @@ export namespace PerformanceStat { type: PerformanceStatType.DbQuery, name: evt.name, location: evt.location, + avgDurationMs: evt.durationMs, maxDurationMs: evt.durationMs, + minDurationMs: evt.durationMs, + totalDurationMs: evt.durationMs, count: 1, }; } else if ( @@ -98,7 +120,10 @@ export namespace PerformanceStat { return { type: PerformanceStatType.Crypto, operation: evt.operation, + avgDurationMs: evt.durationMs, maxDurationMs: evt.durationMs, + minDurationMs: evt.durationMs, + totalDurationMs: evt.durationMs, count: 1, }; } else if ( @@ -108,14 +133,20 @@ export namespace PerformanceStat { return { type: PerformanceStatType.WalletRequest, operation: evt.operation, + avgDurationMs: evt.durationMs, maxDurationMs: evt.durationMs, + minDurationMs: evt.durationMs, + totalDurationMs: evt.durationMs, count: 1, }; } else if (evt.type === ObservabilityEventType.ShepherdTaskResult) { return { type: PerformanceStatType.WalletTask, taskId: evt.taskId, + avgDurationMs: evt.durationMs, maxDurationMs: evt.durationMs, + minDurationMs: evt.durationMs, + totalDurationMs: evt.durationMs, count: 1, }; } @@ -198,7 +229,10 @@ export namespace PerformanceTable { tab[stat.type]?.push(stat); } else { const existing = tab[stat.type]!![index]; + existing.avgDurationMs = Math.floor((existing.avgDurationMs + stat.totalDurationMs) / 2); existing.maxDurationMs = Math.max(existing.maxDurationMs, stat.maxDurationMs); + existing.minDurationMs = Math.min(existing.minDurationMs, stat.minDurationMs); + existing.totalDurationMs = existing.totalDurationMs + stat.totalDurationMs; existing.count += 1; tab[stat.type]!![index] = existing; } @@ -210,7 +244,7 @@ export namespace PerformanceTable { function sort(tab: PerformanceTable) { for (const k of Object.keys(tab)) { const key = k as keyof typeof tab - tab[key]!!.sort((a, b) => b.maxDurationMs - a.maxDurationMs); + tab[key]!!.sort((a, b) => b.avgDurationMs - a.avgDurationMs); } } diff --git a/packages/taler-util/src/types-taler-wallet.ts b/packages/taler-util/src/types-taler-wallet.ts @@ -4522,7 +4522,7 @@ export interface GetBankingChoicesForPaytoResponse { export interface GetPerformanceStatsRequest { /** - * Limit to N largest performance stats of each table. + * Limit to N largest average performance stats of each table. * * When undefined, all performance stats will be returned. */ diff --git a/packages/taler-wallet-core/src/wallet-api-types.ts b/packages/taler-wallet-core/src/wallet-api-types.ts @@ -1531,8 +1531,8 @@ export type GetActiveTasksOp = { * current running wallet instance are generated from observability events and * stored in memory. * - * Under each table, only the highest duration for each operation - * (e.g. `getBalances` wallet request) is included. + * Under each table, different types of duration for each operation + * (e.g. `getBalances` wallet request) are included. */ export type GetPerformanceStatsOp = { op: WalletApiOperation.TestingGetPerformanceStats;