diff --git a/dealer/src/Dealer.ts b/dealer/src/Dealer.ts index aff8417e..e297e6fe 100644 --- a/dealer/src/Dealer.ts +++ b/dealer/src/Dealer.ts @@ -14,6 +14,7 @@ import { FundingRate, FundingYieldMetrics, InFlightTransfer, + InFlightTransfersMetrics, TradingFeesMetrics, Transaction, } from "./database/models" @@ -528,6 +529,14 @@ export class Dealer { return result.value } + public async getInFlightTransfersMetrics(): Promise { + const result = await database.inFlightTransfers.getMetrics() + if (!result.ok) { + return {} as InFlightTransfersMetrics + } + return result.value + } + public async getTradingFeesMetrics(): Promise { const result = await database.transactions.getTradingFeesMetrics() if (!result.ok) { diff --git a/dealer/src/database/models.ts b/dealer/src/database/models.ts index f79de489..e0d501a4 100644 --- a/dealer/src/database/models.ts +++ b/dealer/src/database/models.ts @@ -86,6 +86,14 @@ export enum TransactionBillSubtypeToId { FundingFeeIncome = 174, } +export type InFlightTransfersMetrics = { + totalInFlightTransfersCount: number + completedDepositCount: number + completedWithdrawalCount: number + pendingDepositCount: number + pendingWithdrawalCount: number +} + export type TradingFeesMetrics = { tradingFeesTotalInSats: number tradingFeesBuyInSats: number diff --git a/dealer/src/database/repositories/InFlightTransfersRepository.ts b/dealer/src/database/repositories/InFlightTransfersRepository.ts index 05bec626..a883ab7e 100644 --- a/dealer/src/database/repositories/InFlightTransfersRepository.ts +++ b/dealer/src/database/repositories/InFlightTransfersRepository.ts @@ -1,7 +1,7 @@ import pino from "pino" import { IDatabase, IMain } from "pg-promise" import { IResult } from "pg-promise/typescript/pg-subset" -import { InFlightTransfer } from "../models" +import { InFlightTransfer, InFlightTransfersMetrics } from "../models" import { inFlightTransfersQueries as sql } from "../sql" import { Result } from "../../Result" @@ -180,6 +180,33 @@ export class InFlightTransfersRepository { } } + private static inFlightTransfersMetricsCallback( + metrics: InFlightTransfersMetrics, + ): InFlightTransfersMetrics { + metrics.totalInFlightTransfersCount = Number(metrics.totalInFlightTransfersCount) + metrics.completedDepositCount = Number(metrics.completedDepositCount) + metrics.completedWithdrawalCount = Number(metrics.completedWithdrawalCount) + metrics.pendingDepositCount = Number(metrics.pendingDepositCount) + metrics.pendingWithdrawalCount = Number(metrics.pendingWithdrawalCount) + return metrics + } + + public async getMetrics(): Promise> { + try { + const rowCount = await this.db.one( + sql.get_metrics, + [], + InFlightTransfersRepository.inFlightTransfersMetricsCallback, + ) + this.logger.info({ rowCount }, "getMetrics() returned: {result}.") + + return { ok: true, value: rowCount } + } catch (error) { + this.logger.error({ error }, "Error: getMetrics() failed.") + return { ok: false, error: error } + } + } + public async clearAll(): Promise> { try { await this.db.none(sql.clear) diff --git a/dealer/src/database/sql/in_flight_transfers/get_metrics.sql b/dealer/src/database/sql/in_flight_transfers/get_metrics.sql new file mode 100644 index 00000000..d533a9e1 --- /dev/null +++ b/dealer/src/database/sql/in_flight_transfers/get_metrics.sql @@ -0,0 +1,7 @@ +SELECT + count(*) AS total_in_flight_transfers_count, + count(*) FILTER (WHERE ifl.is_deposit_on_exchange = true and ifl.is_completed = true) AS completed_deposit_count, + count(*) FILTER (WHERE ifl.is_deposit_on_exchange = false and ifl.is_completed = true) AS completed_withdrawal_count, + count(*) FILTER (WHERE ifl.is_deposit_on_exchange = true and ifl.is_completed = false) AS pending_deposit_count, + count(*) FILTER (WHERE ifl.is_deposit_on_exchange = false and ifl.is_completed = false) AS pending_withdrawal_count +FROM dealer.in_flight ifl diff --git a/dealer/src/database/sql/index.ts b/dealer/src/database/sql/index.ts index ed81e4bb..32a4ef53 100644 --- a/dealer/src/database/sql/index.ts +++ b/dealer/src/database/sql/index.ts @@ -15,6 +15,8 @@ export const inFlightTransfersQueries = { get_pending_withdraw: sql("in_flight_transfers/get_pending_withdraw.sql"), get_this: sql("in_flight_transfers/get_this.sql"), + get_metrics: sql("in_flight_transfers/get_metrics.sql"), + clear: sql("in_flight_transfers/clear.sql"), } diff --git a/dealer/src/servers/exporter/exporter.ts b/dealer/src/servers/exporter/exporter.ts index 58ff5257..2af1899c 100644 --- a/dealer/src/servers/exporter/exporter.ts +++ b/dealer/src/servers/exporter/exporter.ts @@ -142,6 +142,41 @@ const metrics: { [key: string]: IMetricData } = { help: "trading fees sell count", }), }, + totalInFlightTransfersCount: { + value: NaN, + gauge: new client.Gauge({ + name: `${prefix}_totalInFlightTransfersCount`, + help: "total in-flight transfers count", + }), + }, + completedDepositCount: { + value: NaN, + gauge: new client.Gauge({ + name: `${prefix}_completedDepositCount`, + help: "completed in-flight deposit count", + }), + }, + completedWithdrawalCount: { + value: NaN, + gauge: new client.Gauge({ + name: `${prefix}_completedWithdrawalCount`, + help: "complete in-flight withdrawal count", + }), + }, + pendingDepositCount: { + value: NaN, + gauge: new client.Gauge({ + name: `${prefix}_pendingDepositCount`, + help: "pending in-flight deposit count", + }), + }, + pendingWithdrawalCount: { + value: NaN, + gauge: new client.Gauge({ + name: `${prefix}_pendingWithdrawalCount`, + help: "pending in-flight withdrawal count", + }), + }, fundingFeesTotalInSats: { value: NaN, gauge: new client.Gauge({ @@ -603,6 +638,29 @@ export async function exporter() { const strategyUPnlInUsd = spotUPnlInUsd + swapUPnlInUsd Metrics.set(metrics["strategyUPnlInUsd"], strategyUPnlInUsd) + // InFlight Transfers + const inFlightTransfersMetrics = await dealer.getInFlightTransfersMetrics() + Metrics.set( + metrics["totalInFlightTransfersCount"], + inFlightTransfersMetrics.totalInFlightTransfersCount, + ) + Metrics.set( + metrics["completedDepositCount"], + inFlightTransfersMetrics.completedDepositCount, + ) + Metrics.set( + metrics["completedWithdrawalCount"], + inFlightTransfersMetrics.completedWithdrawalCount, + ) + Metrics.set( + metrics["pendingDepositCount"], + inFlightTransfersMetrics.pendingDepositCount, + ) + Metrics.set( + metrics["pendingWithdrawalCount"], + inFlightTransfersMetrics.pendingWithdrawalCount, + ) + // Trading Fees const tradingFeesMetrics = await dealer.getTradingFeesMetrics() Metrics.set( diff --git a/grafana/provisioning/dashboards/galoy-dealer.json b/grafana/provisioning/dashboards/galoy-dealer.json index bddde151..4eb3433b 100644 --- a/grafana/provisioning/dashboards/galoy-dealer.json +++ b/grafana/provisioning/dashboards/galoy-dealer.json @@ -3403,6 +3403,89 @@ ], "title": "Exchange Status", "type": "timeseries" + }, + { + "datasource": null, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 18, + "y": 42 + }, + "id": 66, + "options": { + "displayMode": "lcd", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showUnfilled": true, + "text": {} + }, + "pluginVersion": "8.1.1", + "targets": [ + { + "exemplar": true, + "expr": "avg by (container)(galoy_dealer_completedDepositCount)", + "interval": "", + "legendFormat": "done deposit cnt", + "refId": "A" + }, + { + "exemplar": true, + "expr": "avg by (container)(galoy_dealer_pendingDepositCount)", + "hide": false, + "interval": "", + "legendFormat": "pend deposit cnt", + "refId": "B" + }, + { + "exemplar": true, + "expr": "avg by (container)(galoy_dealer_completedWithdrawalCount)", + "hide": false, + "interval": "", + "legendFormat": "done withdraw cnt", + "refId": "C" + }, + { + "exemplar": true, + "expr": "avg by (container)(galoy_dealer_pendingWithdrawalCount)", + "hide": false, + "interval": "", + "legendFormat": "pending withdraw cnt", + "refId": "D" + }, + { + "exemplar": true, + "expr": "avg by (container)(galoy_dealer_totalInFlightTransfersCount)", + "hide": false, + "interval": "", + "legendFormat": "total transfer cnt", + "refId": "E" + } + ], + "title": "InFlight Transfers", + "type": "bargauge" } ], "refresh": false, @@ -3420,5 +3503,5 @@ "timezone": "", "title": "Galoy Dealer", "uid": "pTEP9n47k", - "version": 38 + "version": 66 }