diff --git a/src/app/(dashboard)/page.tsx b/src/app/(dashboard)/page.tsx
index 8496147..a9b58a2 100644
--- a/src/app/(dashboard)/page.tsx
+++ b/src/app/(dashboard)/page.tsx
@@ -382,7 +382,7 @@ export default function DashboardPage() {
height={200}
/>
}
data={chartData.data?.pipeline.latency ?? {}}
variant="area"
diff --git a/src/app/(dashboard)/pipelines/[id]/metrics/page.tsx b/src/app/(dashboard)/pipelines/[id]/metrics/page.tsx
index 85e0edb..5836a1a 100644
--- a/src/app/(dashboard)/pipelines/[id]/metrics/page.tsx
+++ b/src/app/(dashboard)/pipelines/[id]/metrics/page.tsx
@@ -118,7 +118,7 @@ export default function PipelineMetricsPage() {
- Component Latency
+ Pipeline Latency
diff --git a/src/components/pipeline/metrics-chart.tsx b/src/components/pipeline/metrics-chart.tsx
index e659256..b35a8cf 100644
--- a/src/components/pipeline/metrics-chart.tsx
+++ b/src/components/pipeline/metrics-chart.tsx
@@ -168,7 +168,7 @@ export function PipelineMetricsChart({ pipelineId, hours = 24 }: PipelineMetrics
{/* Latency chart */}
-
Component Latency
+
Pipeline Latency
diff --git a/src/server/services/alert-evaluator.ts b/src/server/services/alert-evaluator.ts
index 6d55027..a05c8db 100644
--- a/src/server/services/alert-evaluator.ts
+++ b/src/server/services/alert-evaluator.ts
@@ -226,12 +226,15 @@ export async function evaluateAlerts(
if (!node) return [];
- // Load all enabled rules for this environment
+ // Load all enabled rules for this environment (include pipeline name for messages)
const rules = await prisma.alertRule.findMany({
where: {
environmentId,
enabled: true,
},
+ include: {
+ pipeline: { select: { name: true } },
+ },
});
const results: FiredAlertEvent[] = [];
@@ -281,7 +284,7 @@ export async function evaluateAlerts(
if (!existingEvent) {
// Create a new firing event
- const message = buildMessage(rule, value);
+ const message = buildMessage(rule, value, rule.pipeline?.name);
const event = await prisma.alertEvent.create({
data: {
alertRuleId: rule.id,
@@ -354,11 +357,34 @@ const CONDITION_LABELS: Record = {
eq: "=",
};
-function buildMessage(rule: AlertRule, value: number): string {
+/** Metrics where the value is binary (0/1) and the numeric details are noise. */
+const BINARY_METRICS = new Set([
+ "pipeline_crashed",
+ "node_unreachable",
+]);
+
+function buildMessage(
+ rule: AlertRule,
+ value: number,
+ pipelineName?: string | null,
+): string {
const metricLabel = METRIC_LABELS[rule.metric] ?? rule.metric;
+
if (!rule.condition || rule.threshold == null) {
- return `${metricLabel} event fired`;
+ return pipelineName
+ ? `${metricLabel}: ${pipelineName}`
+ : `${metricLabel}`;
}
+
+ // Binary metrics: just state what happened, with the pipeline name if available
+ if (BINARY_METRICS.has(rule.metric)) {
+ return pipelineName
+ ? `${metricLabel}: ${pipelineName}`
+ : `${metricLabel}`;
+ }
+
+ // Numeric metrics: include value and threshold for context
const condLabel = CONDITION_LABELS[rule.condition] ?? rule.condition;
- return `${metricLabel} is ${value.toFixed(2)} (threshold: ${condLabel} ${rule.threshold})`;
+ const prefix = pipelineName ? `${pipelineName} — ` : "";
+ return `${prefix}${metricLabel} at ${value.toFixed(2)} (threshold: ${condLabel} ${rule.threshold})`;
}
diff --git a/src/server/services/metric-store.ts b/src/server/services/metric-store.ts
index e7d8907..1ef2d1c 100644
--- a/src/server/services/metric-store.ts
+++ b/src/server/services/metric-store.ts
@@ -7,7 +7,7 @@ export interface MetricSample {
errorCount: number;
errorsRate: number;
discardedRate: number;
- latencyMeanMs: number | null; // mean component latency in ms
+ latencyMeanMs: number | null; // mean pipeline latency in ms
}
interface PrevTotals {