mirror of
https://github.com/fosrl/pangolin.git
synced 2026-06-09 09:03:19 +00:00
Show status in messages
This commit is contained in:
@@ -36,8 +36,8 @@ function getEventMeta(eventType: AlertEventType): {
|
|||||||
heading: string;
|
heading: string;
|
||||||
previewText: string;
|
previewText: string;
|
||||||
summary: string;
|
summary: string;
|
||||||
statusLabel: string;
|
statusLabel: string | null;
|
||||||
statusColor: string;
|
statusColor: string | null;
|
||||||
} {
|
} {
|
||||||
switch (eventType) {
|
switch (eventType) {
|
||||||
case "site_online":
|
case "site_online":
|
||||||
@@ -63,8 +63,8 @@ function getEventMeta(eventType: AlertEventType): {
|
|||||||
heading: "Site Status Changed",
|
heading: "Site Status Changed",
|
||||||
previewText: "A site in your organization has changed status.",
|
previewText: "A site in your organization has changed status.",
|
||||||
summary: "A site in your organization has changed status.",
|
summary: "A site in your organization has changed status.",
|
||||||
statusLabel: "Status Changed",
|
statusLabel: null,
|
||||||
statusColor: "#f59e0b"
|
statusColor: null
|
||||||
};
|
};
|
||||||
case "health_check_healthy":
|
case "health_check_healthy":
|
||||||
return {
|
return {
|
||||||
@@ -93,8 +93,8 @@ function getEventMeta(eventType: AlertEventType): {
|
|||||||
"A health check in your organization has changed status.",
|
"A health check in your organization has changed status.",
|
||||||
summary:
|
summary:
|
||||||
"A health check in your organization has changed status.",
|
"A health check in your organization has changed status.",
|
||||||
statusLabel: "Status Changed",
|
statusLabel: null,
|
||||||
statusColor: "#f59e0b"
|
statusColor: null
|
||||||
};
|
};
|
||||||
case "resource_healthy":
|
case "resource_healthy":
|
||||||
return {
|
return {
|
||||||
@@ -120,8 +120,8 @@ function getEventMeta(eventType: AlertEventType): {
|
|||||||
previewText:
|
previewText:
|
||||||
"A resource in your organization has changed status.",
|
"A resource in your organization has changed status.",
|
||||||
summary: "A resource in your organization has changed status.",
|
summary: "A resource in your organization has changed status.",
|
||||||
statusLabel: "Status Changed",
|
statusLabel: null,
|
||||||
statusColor: "#f59e0b"
|
statusColor: null
|
||||||
};
|
};
|
||||||
default:
|
default:
|
||||||
return {
|
return {
|
||||||
@@ -135,11 +135,26 @@ function getEventMeta(eventType: AlertEventType): {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resolveToggleStatus(status: unknown): { label: string; color: string } {
|
||||||
|
switch (String(status).toLowerCase()) {
|
||||||
|
case "online":
|
||||||
|
return { label: "Online", color: "#16a34a" };
|
||||||
|
case "offline":
|
||||||
|
return { label: "Offline", color: "#dc2626" };
|
||||||
|
case "healthy":
|
||||||
|
return { label: "Healthy", color: "#16a34a" };
|
||||||
|
case "unhealthy":
|
||||||
|
return { label: "Unhealthy", color: "#dc2626" };
|
||||||
|
default:
|
||||||
|
return { label: String(status ?? "Unknown"), color: "#f59e0b" };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function formatDataItems(
|
function formatDataItems(
|
||||||
data: Record<string, unknown>
|
data: Record<string, unknown>
|
||||||
): { label: string; value: React.ReactNode }[] {
|
): { label: string; value: React.ReactNode }[] {
|
||||||
return Object.entries(data)
|
return Object.entries(data)
|
||||||
.filter(([key]) => key !== "orgId")
|
.filter(([key]) => key !== "orgId" && key !== "status")
|
||||||
.map(([key, value]) => ({
|
.map(([key, value]) => ({
|
||||||
label: key
|
label: key
|
||||||
.replace(/([A-Z])/g, " $1")
|
.replace(/([A-Z])/g, " $1")
|
||||||
@@ -154,16 +169,36 @@ export const AlertNotification = (props: AlertNotificationProps) => {
|
|||||||
const meta = getEventMeta(eventType);
|
const meta = getEventMeta(eventType);
|
||||||
const dataItems = formatDataItems(data);
|
const dataItems = formatDataItems(data);
|
||||||
|
|
||||||
|
const isToggle =
|
||||||
|
eventType === "site_toggle" ||
|
||||||
|
eventType === "health_check_toggle" ||
|
||||||
|
eventType === "resource_toggle";
|
||||||
|
|
||||||
|
const resolvedStatus = isToggle
|
||||||
|
? resolveToggleStatus(data.status)
|
||||||
|
: meta.statusLabel != null
|
||||||
|
? { label: meta.statusLabel, color: meta.statusColor! }
|
||||||
|
: null;
|
||||||
|
|
||||||
const allItems: { label: string; value: React.ReactNode }[] = [
|
const allItems: { label: string; value: React.ReactNode }[] = [
|
||||||
{ label: "Organization", value: orgId },
|
{ label: "Organization", value: orgId },
|
||||||
{
|
...(resolvedStatus != null
|
||||||
label: "Status",
|
? [
|
||||||
value: (
|
{
|
||||||
<span style={{ color: meta.statusColor, fontWeight: 600 }}>
|
label: "Status",
|
||||||
{meta.statusLabel}
|
value: (
|
||||||
</span>
|
<span
|
||||||
)
|
style={{
|
||||||
},
|
color: resolvedStatus.color,
|
||||||
|
fontWeight: 600
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{resolvedStatus.label}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
: []),
|
||||||
{ label: "Time", value: new Date().toUTCString() },
|
{ label: "Time", value: new Date().toUTCString() },
|
||||||
...dataItems
|
...dataItems
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ export async function fireHealthCheckHealthyAlert(
|
|||||||
healthCheckId,
|
healthCheckId,
|
||||||
data: {
|
data: {
|
||||||
healthCheckId,
|
healthCheckId,
|
||||||
|
status: "healthy",
|
||||||
...(healthCheckName != null ? { healthCheckName } : {}),
|
...(healthCheckName != null ? { healthCheckName } : {}),
|
||||||
...extra
|
...extra
|
||||||
}
|
}
|
||||||
@@ -133,6 +134,7 @@ export async function fireHealthCheckUnhealthyAlert(
|
|||||||
healthCheckId,
|
healthCheckId,
|
||||||
data: {
|
data: {
|
||||||
healthCheckId,
|
healthCheckId,
|
||||||
|
status: "unhealthy",
|
||||||
...(healthCheckName != null ? { healthCheckName } : {}),
|
...(healthCheckName != null ? { healthCheckName } : {}),
|
||||||
...extra
|
...extra
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ export async function fireResourceHealthyAlert(
|
|||||||
resourceId,
|
resourceId,
|
||||||
data: {
|
data: {
|
||||||
resourceId,
|
resourceId,
|
||||||
|
status: "healthy",
|
||||||
...(resourceName != null ? { resourceName } : {}),
|
...(resourceName != null ? { resourceName } : {}),
|
||||||
...extra
|
...extra
|
||||||
}
|
}
|
||||||
@@ -115,6 +116,7 @@ export async function fireResourceUnhealthyAlert(
|
|||||||
resourceId,
|
resourceId,
|
||||||
data: {
|
data: {
|
||||||
resourceId,
|
resourceId,
|
||||||
|
status: "unhealthy",
|
||||||
...(resourceName != null ? { resourceName } : {}),
|
...(resourceName != null ? { resourceName } : {}),
|
||||||
...extra
|
...extra
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ export async function fireSiteOnlineAlert(
|
|||||||
siteId,
|
siteId,
|
||||||
data: {
|
data: {
|
||||||
siteId,
|
siteId,
|
||||||
|
status: "online",
|
||||||
...(siteName != null ? { siteName } : {}),
|
...(siteName != null ? { siteName } : {}),
|
||||||
...extra
|
...extra
|
||||||
}
|
}
|
||||||
@@ -143,6 +144,7 @@ export async function fireSiteOfflineAlert(
|
|||||||
siteId,
|
siteId,
|
||||||
data: {
|
data: {
|
||||||
siteId,
|
siteId,
|
||||||
|
status: "offline",
|
||||||
...(siteName != null ? { siteName } : {}),
|
...(siteName != null ? { siteName } : {}),
|
||||||
...extra
|
...extra
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ export async function sendAlertWebhook(
|
|||||||
const payload = {
|
const payload = {
|
||||||
event: context.eventType,
|
event: context.eventType,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
|
status: deriveStatus(context.eventType, context.data),
|
||||||
data: {
|
data: {
|
||||||
orgId: context.orgId,
|
orgId: context.orgId,
|
||||||
...context.data
|
...context.data
|
||||||
@@ -117,6 +118,38 @@ export async function sendAlertWebhook(
|
|||||||
throw lastError ?? new Error(`Alert webhook: all ${MAX_RETRIES} attempts failed for "${url}"`);
|
throw lastError ?? new Error(`Alert webhook: all ${MAX_RETRIES} attempts failed for "${url}"`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Status derivation
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function deriveStatus(
|
||||||
|
eventType: AlertContext["eventType"],
|
||||||
|
data: Record<string, unknown>
|
||||||
|
): string {
|
||||||
|
switch (eventType) {
|
||||||
|
case "site_online":
|
||||||
|
return "online";
|
||||||
|
case "site_offline":
|
||||||
|
return "offline";
|
||||||
|
case "site_toggle":
|
||||||
|
return String(data.status ?? "unknown");
|
||||||
|
case "health_check_healthy":
|
||||||
|
case "resource_healthy":
|
||||||
|
return "healthy";
|
||||||
|
case "health_check_unhealthy":
|
||||||
|
case "resource_unhealthy":
|
||||||
|
return "unhealthy";
|
||||||
|
case "health_check_toggle":
|
||||||
|
case "resource_toggle":
|
||||||
|
return String(data.status ?? "unknown");
|
||||||
|
default: {
|
||||||
|
const _exhaustive: never = eventType;
|
||||||
|
void _exhaustive;
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Header construction (mirrors HttpLogDestination.buildHeaders)
|
// Header construction (mirrors HttpLogDestination.buildHeaders)
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user