Guide · AWS CloudWatch · Log Analysis
CloudWatch Contributor Insights for MCP Servers — Find Top-N Error Sources in Logs
CloudWatch Contributor Insights continuously evaluates rules against your CloudWatch Logs streams and produces real-time top-N reports identifying which endpoints, tool names, source IPs, or error codes are contributing the most events — without you needing to write and re-run Logs Insights queries manually. For AliveMCP probe workers that log one structured JSON record per probe result, a Contributor Insights rule can instantly surface the answer to "which MCP endpoints account for the most probe failures this hour?" — the kind of operational question that normally requires a dashboard query. For querying logs ad-hoc, see CloudWatch Logs Insights for MCP server debugging; for threshold alarms on probe metrics, see CloudWatch Alarms for MCP servers.
TL;DR
Create a Contributor Insights rule that targets your probe result log group (/mcp/probe-results), filters for error events ($.status IN ["error", "timeout", "auth_failure"]), and aggregates on the $.endpoint key. CloudWatch samples ~25% of log events (or 100% if you enable full scan) and shows a continuously updated chart of the top-100 endpoints by error count — updated every minute. You pay $0.02/hour per active rule plus $0.035 per million sampled log events.
Contributor Insights vs. Logs Insights for operational questions
Both services analyze CloudWatch Logs data, but they answer different question types:
| Question type | Logs Insights | Contributor Insights |
|---|---|---|
| Ad-hoc investigation: "what happened at 3:42 PM?" | Excellent — query historical data for any time range | Not suitable — reports only show top-N contributors, not individual events |
| Operational monitoring: "which endpoint is failing most right now?" | Requires repeated manual queries | Excellent — continuous real-time top-N updates |
| Dashboard widget: "top-10 error sources this week" | Can embed via metric math, but expensive at high volume | Native top-N charts embeddable in CloudWatch dashboards |
| Alert on a specific contributor crossing a threshold | Not possible natively | Supported via Contributor Insights metric alarms (requires full-scan mode) |
| Cost at 100M log events/day | $0.005/GB scanned (charged per query) | $0.035/million sampled events (~$3.50/day at 100M events) |
For AliveMCP's probe worker logging, Contributor Insights is the right tool for the "which servers are currently flapping most?" operational dashboard — and Logs Insights is the right tool for post-incident investigation queries like "show me every probe for api.mcp-broken.com in the last 2 hours."
Rule structure
A Contributor Insights rule is a JSON document with five main fields:
{
"Schema": {
"Name": "CloudWatchLogRule",
"Version": 1
},
"LogGroupNames": ["/mcp/probe-results"], // up to 5 log groups
"LogFormat": "JSON", // JSON or CLF (Apache access log)
"Contribution": {
"Keys": ["$.endpoint"], // group-by fields (up to 4 keys)
"ValueOf": "$.latency_ms", // optional: sum/max this field (omit for Count)
"Filters": [ // AND-combined filters
{
"Match": "$.status",
"In": ["error", "timeout", "auth_failure"]
}
]
},
"AggregateOn": "Count" // Count or Sum (requires ValueOf for Sum)
}
The Keys array defines the contributor identifier — CloudWatch creates one time-series per unique combination of key values. With Keys: ["$.endpoint"], each unique endpoint URL is a separate contributor. With Keys: ["$.endpoint", "$.region"], each endpoint-region pair is a contributor — useful for identifying region-specific failures on multi-region MCP deployments.
Maximum cardinality: Contributor Insights tracks up to 10,000 unique contributor values per rule per hour. For MCP endpoint monitoring with <10,000 registered servers, this limit is not a concern.
Creating rules for MCP probe logs
Assuming your probe worker writes structured JSON log lines like this to CloudWatch Logs:
// Example probe result log line (one per probe execution)
{
"timestamp": "2026-10-31T08:00:01.234Z",
"endpoint": "https://api.mcp-example.com/mcp",
"server_slug": "mcp-example",
"region": "us-east-1",
"status": "error",
"http_code": 503,
"latency_ms": 8432,
"error_class": "upstream_timeout",
"registry": "mcp.so"
}
# Rule 1: Top endpoints by error count
aws cloudwatch put-insight-rule \
--rule-name "mcp-top-failing-endpoints" \
--rule-state ENABLED \
--rule-definition '{
"Schema": {"Name": "CloudWatchLogRule", "Version": 1},
"LogGroupNames": ["/mcp/probe-results"],
"LogFormat": "JSON",
"Contribution": {
"Keys": ["$.endpoint"],
"Filters": [{"Match": "$.status", "In": ["error", "timeout", "auth_failure"]}]
},
"AggregateOn": "Count"
}'
# Rule 2: Top endpoints by total accumulated latency (finds slow but not erroring servers)
aws cloudwatch put-insight-rule \
--rule-name "mcp-top-slow-endpoints" \
--rule-state ENABLED \
--rule-definition '{
"Schema": {"Name": "CloudWatchLogRule", "Version": 1},
"LogGroupNames": ["/mcp/probe-results"],
"LogFormat": "JSON",
"Contribution": {
"Keys": ["$.endpoint"],
"ValueOf": "$.latency_ms",
"Filters": [{"Match": "$.status", "NotIn": ["error"]}]
},
"AggregateOn": "Sum"
}'
# Rule 3: Top error classes by registry (which MCP registry has worst server quality?)
aws cloudwatch put-insight-rule \
--rule-name "mcp-error-class-by-registry" \
--rule-state ENABLED \
--rule-definition '{
"Schema": {"Name": "CloudWatchLogRule", "Version": 1},
"LogGroupNames": ["/mcp/probe-results"],
"LogFormat": "JSON",
"Contribution": {
"Keys": ["$.registry", "$.error_class"],
"Filters": [{"Match": "$.status", "In": ["error"]}]
},
"AggregateOn": "Count"
}'
Querying rule results via API
Rule results are viewable in the CloudWatch console under "Contributor Insights," but you can also query them programmatically to feed a dashboard or build automated reports:
// Query top-10 failing endpoints for the last 1 hour
const { GetInsightRuleReportCommand } = require('@aws-sdk/client-cloudwatch');
const report = await cloudwatch.send(new GetInsightRuleReportCommand({
RuleName: 'mcp-top-failing-endpoints',
StartTime: new Date(Date.now() - 3600 * 1000),
EndTime: new Date(),
Period: 3600, // aggregate over the full hour into one data point
MaxContributorCount: 10,
Metrics: ['UniqueContributors', 'MaxContributorValue', 'SampleCount', 'Sum'],
OrderBy: 'Sum', // sort by total error count descending
}));
report.Contributors.forEach(contributor => {
const endpoint = contributor.Keys[0];
const totalErrors = contributor.Approximation;
console.log(`${endpoint}: ${totalErrors} errors in last hour`);
});
// report.AggregateValue = total errors across ALL contributors (not just top-10)
console.log('Total errors across all endpoints:', report.AggregateValue);
The Approximation field name reflects that sampled mode (default) provides statistical approximations, not exact counts. At the default 25% sampling rate, the approximation is ±15% at the 95th confidence level. For exact counts, enable full-scan mode with InsightRuleSamplingPercentage: 100 when creating the rule — this doubles the cost per log event analyzed.
Alarming on top contributor values
In full-scan mode, Contributor Insights publishes CloudWatch metric data that you can alarm on. This enables alerts like "fire if any single endpoint accounts for more than 5% of all probe errors" — a signal that a single bad actor endpoint is skewing your overall health metrics:
# Step 1: Update rule to full-scan mode to get CloudWatch metric data
aws cloudwatch put-insight-rule \
--rule-name "mcp-top-failing-endpoints" \
--rule-state ENABLED \
--rule-definition '{
"Schema": {"Name": "CloudWatchLogRule", "Version": 1},
"LogGroupNames": ["/mcp/probe-results"],
"LogFormat": "JSON",
"Contribution": {
"Keys": ["$.endpoint"],
"Filters": [{"Match": "$.status", "In": ["error", "timeout", "auth_failure"]}]
},
"AggregateOn": "Count",
"InsightRuleSamplingPercentage": 100
}'
# Step 2: Alarm on MaxContributorValue — fires if any single endpoint spikes
# CloudWatch publishes metrics under namespace "CloudWatchLogs" for Contributor Insights rules
aws cloudwatch put-metric-alarm \
--alarm-name "mcp-single-endpoint-error-spike" \
--namespace "CloudWatchLogs" \
--metric-name "MaxContributorValue" \
--dimensions Name=RuleName,Value=mcp-top-failing-endpoints \
--statistic Maximum \
--period 300 \
--evaluation-periods 2 \
--threshold 100 \
--comparison-operator GreaterThanOrEqualToThreshold \
--alarm-actions arn:aws:sns:us-east-1:123456789012:mcp-alerts
Sampling vs. full-scan cost analysis
| Mode | Accuracy | Cost per million log events | Use case |
|---|---|---|---|
| Sampled (default, 25%) | ~±15% for high-volume contributors; good for top-10 trends | $0.035 (~$0.00875 for 25% sample) | Operational dashboard, rough top-N identification |
| Full scan (100%) | Exact counts | $0.07 | Alarming on exact contributor values; compliance reporting; exact audits |
At 50M probe log events per day (AliveMCP scale at ~580 probes/second across 2,000 endpoints), sampled mode costs approximately $0.00875 × 50 = $0.44/day per rule, or $13/month. Full-scan doubles this to $26/month per rule. For a 3-rule setup, expect $39–$78/month — modest for the operational visibility gained.
Failure modes
| Symptom | Cause | Fix |
|---|---|---|
| Rule shows no contributors; rule state is ENABLED | Log group name is wrong, log group has no events in the selected time window, or the JSON filter path ($.status) does not match the actual log line structure | Verify log group name with aws logs describe-log-groups; test filter path with aws logs filter-log-events --log-group-name ... --filter-pattern '{ $.status = "error" }' |
| Contributor Insights rule rejects JSON definition at creation | Embedded JSON rule definition needs escaping when passed as a CLI string; $. paths with array indexing or bracket notation may not be supported | Save the rule definition to a file and pass via --rule-definition file://rule.json; test rule definition syntax in the CloudWatch console before automating |
| Top-N chart shows endpoints but counts look too low | Sampled mode is active (default 25%); reported counts are approximations scaled from the sample | Expected behavior for sampled mode; switch to full-scan (InsightRuleSamplingPercentage: 100) for exact counts if accuracy is critical |
| CloudWatch Logs / namespace metrics not available for alarming | Metrics are only published by Contributor Insights rules in full-scan mode; sampled rules do not emit CloudWatch metrics | Update rule to full-scan mode; allow 5–10 minutes for metrics to start appearing after mode change |
| Rule exceeds 10,000 unique contributors per hour | High-cardinality key combination (e.g., endpoint + request ID) or legitimate explosion in unique endpoints | Remove high-cardinality fields from the Keys array; use bounded keys like server registry, error class, or region instead of per-request fields |