diff --git a/src/App.tsx b/src/App.tsx
index 465b937..c09d495 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,9 +1,8 @@
-import useSWR from 'swr'
import './App.css'
-import { sentryFetcher } from './utils'
import WATcloudLogo from './assets/watcloud-logo'
import { HealthchecksioStatus } from './healthchecksio'
import { useState } from 'react'
+import { SentryStatus } from './sentry'
function App() {
// Parse options from the URL
@@ -22,10 +21,6 @@ function App() {
}
const [showInternal, setShowInternal] = useState(globalOptions.showInternal);
- const { data: sentryDataRaw, error: sentryError, isLoading: sentryIsLoading } = useSWR('/api/0/organizations/watonomous/monitors/', sentryFetcher, { refreshInterval: 5000 });
-
- console.log("==================")
- console.log(sentryDataRaw, sentryError, sentryIsLoading);
return (
<>
@@ -53,8 +48,7 @@ function App() {
Sentry
- {sentryIsLoading &&
Loading...
}
- {sentryError &&
Error: {sentryError.message}. Is your adblocker blocking the request?
}
+
>
)
diff --git a/src/constants.ts b/src/constants.ts
index ee21d7b..3370ee0 100644
--- a/src/constants.ts
+++ b/src/constants.ts
@@ -13,8 +13,14 @@ export const HEALTHCHECKSIO_API_KEY = 'tCsst0GSKpfvslmpmlsmivRrUCRuv6Iv'
// https://github.com/getsentry/sentry/issues/15310#issuecomment-650443556
export const SENTRY_API_KEY = '53ab13b4337a937bc66eec3a4b3f836b14dd51890fde15fd51b9523eb598382c'
+export enum Status {
+ Good = 'good',
+ Neutral = 'neutral',
+ Bad = 'bad',
+}
+
export const STATUS_SYMBOLS = {
- good: 'π’',
- neutral: 'π‘',
- bad: 'π΄',
+ [Status.Good]: 'π’',
+ [Status.Neutral]: 'π‘',
+ [Status.Bad]: 'π΄',
} as const;
diff --git a/src/healthchecksio.tsx b/src/healthchecksio.tsx
index f82c233..a548ba6 100644
--- a/src/healthchecksio.tsx
+++ b/src/healthchecksio.tsx
@@ -1,7 +1,7 @@
import { useState } from "react";
import useSWR from "swr";
import { groupBy, healthchecksioFetcher, removePrefix, removeSuffix, timeSinceShort } from "./utils";
-import { STATUS_SYMBOLS } from "./constants";
+import { Status, STATUS_SYMBOLS } from "./constants";
import { StatusSummary } from "./summary";
import { OptionGroup } from "./option-group";
@@ -45,22 +45,24 @@ function processHCData(data: any): HealthchecksioCheck[] | undefined {
});
}
-function getStatusSymbol(status: HealthchecksioCheckStatus) {
+function getStatus(status: HealthchecksioCheckStatus) {
return {
- new: STATUS_SYMBOLS.neutral,
- up: STATUS_SYMBOLS.good,
- grace: STATUS_SYMBOLS.good,
- down: STATUS_SYMBOLS.bad,
- paused: 'βΈοΈ',
+ new: Status.Neutral,
+ up: Status.Good,
+ grace: Status.Good,
+ down: Status.Bad,
+ paused: 'paused',
}[status];
}
-function CheckStatus({ status }: { status: HealthchecksioCheckStatus }) {
- return (
-
- {getStatusSymbol(status)}
-
- );
+function getStatusSymbol(status: HealthchecksioCheckStatus) {
+ return {
+ new: STATUS_SYMBOLS[Status.Neutral],
+ up: STATUS_SYMBOLS[Status.Good],
+ grace: STATUS_SYMBOLS[Status.Good],
+ down: STATUS_SYMBOLS[Status.Bad],
+ paused: 'βΈοΈ',
+ }[status];
}
const GROUP_KEYS = ['host', 'check'] as const;
@@ -78,7 +80,7 @@ export function HealthchecksioStatus({ showInternal, initialGroupKey = "" }: { s
const [groupKey, setGroupKey] = useState((GROUP_KEYS.includes(initialGroupKey as any) ? initialGroupKey : GROUP_KEYS[0]) as typeof GROUP_KEYS[number]);
const { data: dataRaw, error, isLoading } = useSWR('/api/v3/checks/', healthchecksioFetcher, { refreshInterval: 5000 });
- const checks = (processHCData(dataRaw) || []).filter(check => check.tags_dict.public !== 'False' || showInternal);
+ const checks = (processHCData(dataRaw) || []).filter(check => check.tags_dict.public !== 'False' || showInternal).sort((a, b) => a.name.localeCompare(b.name));
const groupedChecks = groupBy(checks, c => c.tags_dict[groupKey]);
return (
@@ -87,7 +89,7 @@ export function HealthchecksioStatus({ showInternal, initialGroupKey = "" }: { s
{error && Error: {error.message}
}
{checks && checks.length > 0 && (
<>
- getStatusSymbol(check.status))} symbolClassName="text-xl" className="mb-4" />
+ getStatus(check.status))} symbolClassName="text-xl" className="mb-4" />
Group by:
{shortenCheckName(groupKey, group, check.name)} {timeSinceShort(new Date(check.last_ping))} ago
-
+ {getStatusSymbol(check.status)}
))}
diff --git a/src/sentry.tsx b/src/sentry.tsx
new file mode 100644
index 0000000..28b3212
--- /dev/null
+++ b/src/sentry.tsx
@@ -0,0 +1,59 @@
+import useSWR from "swr";
+import { sentryFetcher, timeSinceShort } from "./utils";
+import { STATUS_SYMBOLS, Status } from "./constants";
+import { StatusSummary } from "./summary";
+
+// The API docs just says "string" lol. We can add to this list if we find more
+export type SentryStatus = "ok" | "error";
+
+function getStatus(status: SentryStatus) {
+ return {
+ ok: Status.Good,
+ error: Status.Bad,
+ }[status] || Status.Neutral;
+}
+
+function getStatusSymbol(status: SentryStatus) {
+ return STATUS_SYMBOLS[getStatus(status)];
+}
+
+export function SentryStatus() {
+ const { data: monitors, error, isLoading } = useSWR('/api/0/organizations/watonomous/monitors/', sentryFetcher, { refreshInterval: 5000 });
+
+ // process data
+ if (monitors) {
+ for (const monitor of monitors) {
+ // Remove checks for the dev environment
+ monitor.environments = monitor.environments?.filter((environment: any) => environment.name != 'dev').sort((a: any, b: any) => a.name.localeCompare(b.name));
+ }
+ monitors.sort((a: any, b: any) => a.name.localeCompare(b.name));
+ }
+
+ return (
+
+ {isLoading &&
Loading...
}
+ {error &&
Error: {error.message}
}
+ {monitors && monitors.length > 0 && (
+ <>
+
monitor.environments?.map((environment: any) => getStatus(environment.status)))} symbolClassName="text-xl" className="mb-4" />
+
+ {monitors.map((monitor: any) => (
+
+
{monitor.name}
+
+ {monitor.environments?.map((environment: any) => (
+ -
+ {environment.name} {timeSinceShort(new Date(environment.lastCheckIn))} ago
+ {getStatusSymbol(environment.status)}
+
+ ))}
+
+
+ ))}
+
+ >
+ )}
+
+ )
+}
\ No newline at end of file
diff --git a/src/summary.tsx b/src/summary.tsx
index d5192a0..3f12d3b 100644
--- a/src/summary.tsx
+++ b/src/summary.tsx
@@ -1,21 +1,21 @@
-import { STATUS_SYMBOLS } from "./constants";
+import { Status, STATUS_SYMBOLS } from "./constants";
import { cn } from "./utils";
-export function StatusSummary({ symbols, className, symbolClassName }: {
- symbols: string[], className?: string, symbolClassName?: string
+export function StatusSummary({ statuses, className, symbolClassName }: {
+ statuses: string[], className?: string, symbolClassName?: string
}) {
- const summary = Object.fromEntries(Object.values(STATUS_SYMBOLS).map(symbol => [symbol, 0]));
- for (const symbol of symbols) {
- if (symbol in summary) {
- summary[symbol] += 1;
+ const summary = statuses.reduce((acc, status) => {
+ if (Object.values(Status).includes(status as any)) {
+ acc[status as Status]++;
}
- }
+ return acc;
+ }, Object.fromEntries(Object.values(Status).map(status => [status, 0])) as Record);
return (
- {Object.entries(summary).map(([symbol, count]) => (
-
-
{symbol}
+ {Object.entries(summary).map(([status, count]) => (
+
+ {STATUS_SYMBOLS[status as Status]}
{count}
))}