Pattern diff
Compare pattern presence in two adjacent windows when the question is "what changed across this boundary?". Returns four ranked sets (new, retired, persistent, re_emerged) plus co-emergence clusters of patterns whose first_seen timestamps cluster within a tight window. Pattern identity is stable across log-format drift, so the set diff stays coherent across time boundaries.
Example
You
what changed since yesterday in payment?
Log10x
Pattern diff over yesterday vs today in payment: 7 new, 3 retired, 41 persistent, 2 re-emerged. 1 co-emergence cluster: 5 patterns first seen within 14s around 09:42 UTC. Worth checking the deploy log around that timestamp.
More to ask
- "diff patterns this week vs last week"
- "what new error patterns showed up today in checkout-svc"
- "any re-emerged patterns over the last 7d"
Prerequisites
Reporter deployed with at least one full timeRange of metrics on each side of the boundary. Re-emergence and co-emergence enrichments need first_seen state, which the Reporter accumulates from first install.
Schema and samples
Input example
Representative call (synthetic, not captured from the live demo env).
Input schema
Agent-facing JSON Schema (the canonical shape the MCP server publishes via tools/list):
{
"type": "object",
"properties": {
"timeRange": {
"type": "string",
"enum": [
"1h",
"6h",
"1d",
"7d",
"30d"
],
"default": "1d",
"description": "Window size on both sides of the boundary. The tool compares the most recent `timeRange` (\"after\") against the immediately preceding `timeRange` (\"before\"). Example: `timeRange: \"1d\"` compares today vs yesterday."
},
"service": {
"type": "string",
"description": "Service name to scope. Omit for all services."
},
"severity": {
"type": "string",
"description": "Severity to scope (e.g. `ERROR`, `CRITICAL`)."
},
"limit": {
"type": "number",
"minimum": 1,
"maximum": 50,
"default": 20,
"description": "Max rows per category (new / retired / persistent / re_emerged). Default 20."
},
"co_emergence_window_seconds": {
"type": "number",
"minimum": 10,
"maximum": 600,
"default": 60,
"description": "Time spread for clustering co-emergent patterns. Default 60s — tight enough to fingerprint a single deploy."
},
"min_co_emergence_cluster_size": {
"type": "number",
"minimum": 2,
"maximum": 20,
"default": 3,
"description": "Minimum cluster size to emit. Default 3 — 2 patterns sharing a timestamp is often coincidence."
},
"analyzerCost": {
"type": "number",
"description": "SIEM ingestion cost in $/GB. Auto-detected from profile."
},
"environment": {
"type": "string",
"description": "Environment nickname (for multi-env setups)."
},
"view": {
"type": "string",
"enum": [
"summary",
"markdown"
],
"default": "summary",
"description": "Output format."
}
},
"additionalProperties": false
}
Source: src/tools/pattern-diff.ts.
Output example
Representative envelope (synthetic, not captured from the live demo env). view: "summary" returns the full StructuredOutput with typed data.
Headline (the 1-line agent-facing answer):
Pattern diff over yesterday vs today: 7 new, 3 retired, 2 re-emerged, 41 persistent.
{
"schema_version": "1.0",
"schema_epoch": "2026-05-25",
"tool": "log10x_pattern_diff",
"generated_at": "2026-06-05T12:00:00.000Z",
"view": "summary",
"summary": {
"headline": "Pattern diff over yesterday vs today: 7 new, 3 retired, 2 re-emerged, 41 persistent.",
"callout": "1 co-emergence cluster detected (3+ patterns sharing first_seen within 60s) — consider checking your deploy log around the cluster timestamps."
},
"data": {
"time_range": "yesterday vs today",
"after_window_label": "last 1d",
"before_window_label": "prior 1d",
"new": [
{
"pattern_hash": "k4Lp9wQrTuV",
"symbol_message": "PaymentProcessor checkout timeout after retries",
"severities": ["ERROR"],
"bytes_now": 142500000,
"bytes_before": 0,
"cost_now_usd": 0.21,
"cost_before_usd": 0,
"first_seen_age_seconds": 18420,
"services": [
{
"name": "payment",
"severity": "ERROR",
"bytes_now": 142500000,
"bytes_before": 0,
"cost_now_usd": 0.21,
"cost_before_usd": 0
}
]
},
"... 6 more elided"
],
"retired": [
{
"pattern_hash": "rT8mNxYzAbC",
"symbol_message": "PaymentProcessor legacy SOAP path hit",
"severities": ["WARN"],
"bytes_now": 0,
"bytes_before": 88200000,
"cost_now_usd": 0,
"cost_before_usd": 0.13,
"first_seen_age_seconds": 2592000,
"services": [
{
"name": "payment",
"severity": "WARN",
"bytes_now": 0,
"bytes_before": 88200000,
"cost_now_usd": 0,
"cost_before_usd": 0.13
}
]
},
"... 2 more elided"
],
"persistent": [
"... 20 rows elided"
],
"re_emerged": [
{
"pattern_hash": "zX2qPpLmKjH",
"symbol_message": "InventoryCheck stale cache fallback",
"severities": ["WARN"],
"bytes_now": 51200000,
"bytes_before": 0,
"cost_now_usd": 0.07,
"cost_before_usd": 0,
"first_seen_age_seconds": 5184000,
"services": [
{
"name": "payment",
"severity": "WARN",
"bytes_now": 51200000,
"bytes_before": 0,
"cost_now_usd": 0.07,
"cost_before_usd": 0
}
]
},
"... 1 more elided"
],
"co_emergence_clusters": [
{
"patterns": ["k4Lp9wQrTuV", "n7Xm3qPzVbR", "j9KlMnOpQsT", "h2GfHaSdFgY", "p1WeRtYuIoP"],
"first_seen_window_ts": [1748090520, 1748090534],
"cluster_size": 5
}
],
"totals": {
"new": 7,
"retired": 3,
"persistent": 41,
"re_emerged": 2
}
},
"actions": [
{
"tool": "log10x_pattern_examples",
"args": {
"pattern": "k4Lp9wQrTuV",
"timeRange": "1d"
},
"reason": "see what the top new pattern actually looks like"
},
{
"tool": "log10x_pattern_trend",
"args": {
"pattern": "zX2qPpLmKjH",
"timeRange": "30d"
},
"reason": "inspect the re-emerged pattern's full trajectory — when did it go silent, when did it come back"
},
{
"tool": "log10x_pattern_examples",
"args": {
"pattern": "k4Lp9wQrTuV",
"timeRange": "1d"
},
"reason": "inspect the first pattern in the largest co-emergence cluster (5 patterns at 2026-06-04T09:42:00.000Z)"
}
],
"truncated": false,
"warnings": []
}
Output schema
The data block inside the StructuredOutput envelope:
interface ToolData {
time_range: string;
after_window_label: string;
before_window_label: string;
new: Array<{
pattern_hash: string;
symbol_message: string;
severities: string[];
bytes_now: number;
bytes_before: number;
cost_now_usd: number;
cost_before_usd: number;
first_seen_age_seconds: number | null;
services: Array<{
name: string;
severity: string;
bytes_now: number;
bytes_before: number;
cost_now_usd: number;
cost_before_usd: number;
}>;
}>;
retired: Array<{ /* same shape as new[] */ }>;
persistent: Array<{ /* same shape as new[] */ }>;
re_emerged: Array<{ /* same shape as new[] */ }>;
co_emergence_clusters: Array<{
patterns: string[];
first_seen_window_ts: [number, number];
cluster_size: number;
}>;
totals: {
new: number;
retired: number;
persistent: number;
re_emerged: number;
};
}
Envelope-level fields the agent should also read: summary.headline (1-line answer), summary.callout (co-emergence or re-emergence narrative when present), actions[] (next-call chain hints as {tool, args, reason}), truncated: boolean, schema_epoch (engine-ID stability boundary).