Skip to content

Commit cecffcc

Browse files
committed
feat: webhook analytics tab
1 parent 26c080f commit cecffcc

File tree

12 files changed

+728
-58
lines changed

12 files changed

+728
-58
lines changed

apps/dashboard/src/@/api/analytics.ts

Lines changed: 43 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import type {
1313
UserOpStats,
1414
WalletStats,
1515
WalletUserStats,
16+
WebhookLatencyStats,
17+
WebhookRequestStats,
1618
WebhookSummaryStats,
1719
} from "@/types/analytics";
1820
import { getAuthToken } from "./auth-token";
@@ -426,44 +428,56 @@ export async function getEngineCloudMethodUsage(
426428
return json.data as EngineCloudStats[];
427429
}
428430

429-
export async function getWebhookMetrics(params: {
430-
teamId: string;
431-
projectId: string;
432-
webhookId: string;
433-
period?: "day" | "week" | "month" | "year" | "all";
434-
from?: Date;
435-
to?: Date;
436-
}): Promise<{ data: WebhookSummaryStats[] } | { error: string }> {
437-
const searchParams = new URLSearchParams();
438-
439-
// Required params
440-
searchParams.append("teamId", params.teamId);
441-
searchParams.append("projectId", params.projectId);
431+
export async function getWebhookSummary(
432+
params: AnalyticsQueryParams & { webhookId: string },
433+
): Promise<{ data: WebhookSummaryStats[] } | { error: string }> {
434+
const searchParams = buildSearchParams(params);
442435
searchParams.append("webhookId", params.webhookId);
443436

444-
// Optional params
445-
if (params.period) {
446-
searchParams.append("period", params.period);
447-
}
448-
if (params.from) {
449-
searchParams.append("from", params.from.toISOString());
437+
const res = await fetchAnalytics(
438+
`v2/webhook/summary?${searchParams.toString()}`,
439+
);
440+
if (!res.ok) {
441+
const reason = await res.text();
442+
return { error: reason };
450443
}
451-
if (params.to) {
452-
searchParams.append("to", params.to.toISOString());
444+
445+
return (await res.json()) as { data: WebhookSummaryStats[] };
446+
}
447+
448+
export async function getWebhookRequests(
449+
params: AnalyticsQueryParams & { webhookId?: string },
450+
): Promise<{ data: WebhookRequestStats[] } | { error: string }> {
451+
const searchParams = buildSearchParams(params);
452+
if (params.webhookId) {
453+
searchParams.append("webhookId", params.webhookId);
453454
}
454455

455456
const res = await fetchAnalytics(
456-
`v2/webhook/summary?${searchParams.toString()}`,
457-
{
458-
method: "GET",
459-
},
457+
`v2/webhook/requests?${searchParams.toString()}`,
460458
);
459+
if (!res.ok) {
460+
const reason = await res.text();
461+
return { error: reason };
462+
}
461463

464+
return (await res.json()) as { data: WebhookRequestStats[] };
465+
}
466+
467+
export async function getWebhookLatency(
468+
params: AnalyticsQueryParams & { webhookId?: string },
469+
): Promise<{ data: WebhookLatencyStats[] } | { error: string }> {
470+
const searchParams = buildSearchParams(params);
471+
if (params.webhookId) {
472+
searchParams.append("webhookId", params.webhookId);
473+
}
474+
const res = await fetchAnalytics(
475+
`v2/webhook/latency?${searchParams.toString()}`,
476+
);
462477
if (!res.ok) {
463-
const reason = await res?.text();
478+
const reason = await res.text();
464479
return { error: reason };
465480
}
466-
return (await res.json()) as {
467-
data: WebhookSummaryStats[];
468-
};
481+
482+
return (await res.json()) as { data: WebhookLatencyStats[] };
469483
}

apps/dashboard/src/@/api/webhook-metrics.ts

Lines changed: 0 additions & 16 deletions
This file was deleted.

apps/dashboard/src/@/types/analytics.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,29 @@ export interface UniversalBridgeWalletStats {
7272
developerFeeUsdCents: number;
7373
}
7474

75+
export interface WebhookRequestStats {
76+
date: string;
77+
webhookId: string;
78+
httpStatusCode: number;
79+
totalRequests: number;
80+
}
81+
82+
export interface WebhookLatencyStats {
83+
date: string;
84+
webhookId: string;
85+
p50LatencyMs: number;
86+
p90LatencyMs: number;
87+
p99LatencyMs: number;
88+
}
89+
7590
export interface WebhookSummaryStats {
7691
webhookId: string;
7792
totalRequests: number;
7893
successRequests: number;
7994
errorRequests: number;
8095
successRate: number;
8196
avgLatencyMs: number;
82-
errorBreakdown: Record<string, unknown>;
97+
errorBreakdown: Record<string, number>;
8398
}
8499

85100
export interface AnalyticsQueryParams {
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
"use server";
2+
3+
import { getWebhookSummary } from "@/api/analytics";
4+
import type { WebhookSummaryStats } from "@/types/analytics";
5+
6+
export async function getWebhookSummaryAction(params: {
7+
teamId: string;
8+
projectId: string;
9+
webhookId: string;
10+
period?: "day" | "week" | "month" | "year" | "all";
11+
from?: Date;
12+
to?: Date;
13+
}): Promise<WebhookSummaryStats | null> {
14+
try {
15+
const result = await getWebhookSummary(params);
16+
17+
if ("error" in result) {
18+
console.error("Failed to fetch webhook summary:", result.error);
19+
return null;
20+
}
21+
22+
return result.data[0] ?? null;
23+
} catch (error) {
24+
console.error("Unexpected error fetching webhook summary:", error);
25+
return null;
26+
}
27+
}

0 commit comments

Comments
 (0)