Skip to content

Commit 05d344d

Browse files
committed
refactor(rpc): simplify anomalies router
Trims the anomalies router down to the procedures actually used by the dashboard.
1 parent 429e22f commit 05d344d

1 file changed

Lines changed: 15 additions & 100 deletions

File tree

packages/rpc/src/routers/anomalies.ts

Lines changed: 15 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@ import { and, db, eq } from "@databuddy/db";
22
import { alarms } from "@databuddy/db/schema";
33
import {
44
buildAnomalyNotificationPayload,
5-
type NotificationChannel,
65
NotificationClient,
76
} from "@databuddy/notifications";
87
import { z } from "zod";
8+
import { toNotificationConfig } from "../lib/alarm-notifications";
99
import {
10-
type AnomalyDetectionConfig,
1110
detectAnomalies,
1211
fetchAnomalyTimeSeries,
1312
} from "../lib/anomaly-detection";
@@ -65,26 +64,7 @@ export const anomaliesRouter = {
6564
permissions: ["read"],
6665
});
6766

68-
const clientId = workspace.website.id;
69-
const config: Partial<AnomalyDetectionConfig> = {};
70-
71-
if (input.config?.warningThreshold !== undefined) {
72-
config.warningThreshold = input.config.warningThreshold;
73-
}
74-
if (input.config?.criticalThreshold !== undefined) {
75-
config.criticalThreshold = input.config.criticalThreshold;
76-
}
77-
if (input.config?.baselineDays !== undefined) {
78-
config.baselineDays = input.config.baselineDays;
79-
}
80-
if (input.config?.minimumBaselineCount !== undefined) {
81-
config.minimumBaselineCount = input.config.minimumBaselineCount;
82-
}
83-
if (input.config?.percentChangeFallback !== undefined) {
84-
config.percentChangeFallback = input.config.percentChangeFallback;
85-
}
86-
87-
return detectAnomalies(clientId, config);
67+
return detectAnomalies(workspace.website.id, input.config ?? {});
8868
}),
8969

9070
timeSeries: protectedProcedure
@@ -157,17 +137,9 @@ export const anomaliesRouter = {
157137
with: { destinations: true },
158138
});
159139

160-
const relevantAlarms = matchingAlarms.filter((alarm) => {
161-
if (alarm.triggerType === "traffic_spike") {
162-
return detected.some(
163-
(a) => a.metric === "pageviews" || a.metric === "custom_events"
164-
);
165-
}
166-
if (alarm.triggerType === "error_rate") {
167-
return detected.some((a) => a.metric === "errors");
168-
}
169-
return false;
170-
});
140+
const relevantAlarms = matchingAlarms.filter((alarm) =>
141+
detected.some((a) => matchesTrigger(alarm.triggerType, a.metric))
142+
);
171143

172144
let notificationsSent = 0;
173145

@@ -179,15 +151,9 @@ export const anomaliesRouter = {
179151
continue;
180152
}
181153

182-
const relevantAnomalies = detected.filter((a) => {
183-
if (alarm.triggerType === "traffic_spike") {
184-
return a.metric === "pageviews" || a.metric === "custom_events";
185-
}
186-
if (alarm.triggerType === "error_rate") {
187-
return a.metric === "errors";
188-
}
189-
return false;
190-
});
154+
const relevantAnomalies = detected.filter((a) =>
155+
matchesTrigger(alarm.triggerType, a.metric)
156+
);
191157

192158
for (const anomaly of relevantAnomalies) {
193159
const payload = buildAnomalyNotificationPayload({
@@ -204,9 +170,9 @@ export const anomaliesRouter = {
204170
eventName: anomaly.eventName,
205171
});
206172

207-
const clientConfig = buildClientConfig(alarm.destinations);
208-
const channels = getChannels(alarm.destinations);
209-
173+
const { clientConfig, channels } = toNotificationConfig(
174+
alarm.destinations
175+
);
210176
if (channels.length === 0) {
211177
continue;
212178
}
@@ -224,60 +190,9 @@ export const anomaliesRouter = {
224190
}),
225191
};
226192

227-
interface AlarmDest {
228-
config: unknown;
229-
identifier: string;
230-
type: string;
231-
}
232-
233-
function buildClientConfig(
234-
destinations: AlarmDest[]
235-
): Record<string, Record<string, unknown>> {
236-
const config: Record<string, Record<string, unknown>> = {};
237-
238-
for (const dest of destinations) {
239-
const cfg = (dest.config ?? {}) as Record<string, unknown>;
240-
241-
if (dest.type === "slack") {
242-
config.slack = { webhookUrl: dest.identifier };
243-
} else if (dest.type === "discord") {
244-
config.discord = { webhookUrl: dest.identifier };
245-
} else if (dest.type === "teams") {
246-
config.teams = { webhookUrl: dest.identifier };
247-
} else if (dest.type === "google_chat") {
248-
config.googleChat = { webhookUrl: dest.identifier };
249-
} else if (dest.type === "telegram") {
250-
config.telegram = {
251-
botToken: cfg.botToken as string,
252-
chatId: dest.identifier || (cfg.chatId as string),
253-
};
254-
} else if (dest.type === "webhook") {
255-
config.webhook = {
256-
url: dest.identifier,
257-
headers: cfg.headers as Record<string, string> | undefined,
258-
};
259-
}
260-
}
261-
262-
return config;
263-
}
264-
265-
function getChannels(destinations: AlarmDest[]): NotificationChannel[] {
266-
const channels: NotificationChannel[] = [];
267-
for (const dest of destinations) {
268-
if (dest.type === "slack") {
269-
channels.push("slack");
270-
} else if (dest.type === "discord") {
271-
channels.push("discord");
272-
} else if (dest.type === "teams") {
273-
channels.push("teams");
274-
} else if (dest.type === "google_chat") {
275-
channels.push("google-chat");
276-
} else if (dest.type === "telegram") {
277-
channels.push("telegram");
278-
} else if (dest.type === "webhook") {
279-
channels.push("webhook");
280-
}
193+
function matchesTrigger(triggerType: string, metric: string): boolean {
194+
if (triggerType === "traffic_spike") {
195+
return metric === "pageviews" || metric === "custom_events";
281196
}
282-
return channels;
197+
return triggerType === "error_rate" && metric === "errors";
283198
}

0 commit comments

Comments
 (0)