使用CDK通过Lambda上报CloudWatch指标后仪表板无数据求助
CloudWatch仪表板无数据,但指标查询有数据的排查与解决
我用CDK创建了CloudWatch仪表板跟踪Lambda错误指标,Lambda的指标发布函数运行正常,CloudWatch多源查询能看到数据,但CDK生成的图表始终显示“无可用数据,请调整时间范围”。相关代码如下:
CDK堆栈代码
// Stack // ----- { ... const overviewDashboard = cloudwatchFactory.createDashboard('overview'); this.loadOverviewDashboard(overviewDashboard); } private loadOverviewDashboard(dashboard: cdk.aws_cloudwatch.Dashboard) { dashboard.addWidgets( new GraphWidget({ title: 'Critical Overview', left: [ new Metric({ namespace: 'MonkeyIoT', metricName: 'CriticalFailure', dimensionsMap: { Stack: 'Critical' }, statistic: cdk.aws_cloudwatch.Stats.SUM, label: "All Failures", color: cdk.aws_cloudwatch.Color.RED, period: cdk.Duration.minutes(1), }) ], width: 24, height: 6, legendPosition: cdk.aws_cloudwatch.LegendPosition.RIGHT, }) ) }
Lambda指标发布函数
async function publishMetric(metricName, value = 1, unit = "Count", dimensions = {}) { try { const client = getCloudWatchClient(); // Convert dimensions object to array format required by CloudWatch const dimensionsArray = Object.entries(dimensions).map(([name, value]) => ({ Name: name, Value: String(value) })); // Always include Stack dimension if (!dimensions.Stack) { dimensionsArray.push({ Name: "Stack", Value: process.env.STACK_NAME || "Unknown" }); } const command = new PutMetricDataCommand({ Namespace: "MonkeyIoT", MetricData: [ { MetricName: metricName, Value: value, Unit: unit, Dimensions: dimensionsArray } ] }); const response = await client.send(command); return response; }
Lambda调用方式
await publishMetric("CriticalFailure", 1, "Count", { Stack: "Critical", Operation: "ObsPut", Lambda: process.env.AWS_LAMBDA_FUNCTION_NAME, Stage: stage, DeviceType: deviceType || "Unknown", ErrorType: err.name || "Unknown" });
根因分析
核心问题是CloudWatch的维度匹配逻辑:你发布的CriticalFailure指标包含Stack+Operation+Lambda等多个维度的组合,每个不同的维度组合都是一个独立的时间序列。但CDK中定义的Metric只指定了Stack: 'Critical'这一个维度,CloudWatch会默认匹配仅包含该维度、没有其他额外维度的指标时间序列——而你的实际指标都带有其他维度,因此找不到匹配的数据。
解决方案
方案1:用MathExpression聚合所有符合条件的指标
修改CDK中的Metric定义,使用MathExpression对所有带有Stack='Critical'的CriticalFailure指标进行SUM聚合,忽略其他维度:
private loadOverviewDashboard(dashboard: cdk.aws_cloudwatch.Dashboard) { dashboard.addWidgets( new GraphWidget({ title: 'Critical Overview', left: [ new cdk.aws_cloudwatch.MathExpression({ expression: 'SUM(METRICS())', label: "All Failures", color: cdk.aws_cloudwatch.Color.RED, usingMetrics: { metric: new cdk.aws_cloudwatch.Metric({ namespace: 'MonkeyIoT', metricName: 'CriticalFailure', dimensionsMap: { Stack: 'Critical' }, statistic: cdk.aws_cloudwatch.Stats.SUM, period: cdk.Duration.minutes(1), }) } }) ], width: 24, height: 6, legendPosition: cdk.aws_cloudwatch.LegendPosition.RIGHT, }) ) }
方案2:发布指标时同时发送仅含Stack维度的版本
修改Lambda的publishMetric函数,在发送多维度指标的同时,额外发送一个只带Stack维度的CriticalFailure指标,让CDK的原Metric能匹配到:
async function publishMetric(metricName, value = 1, unit = "Count", dimensions = {}) { try { const client = getCloudWatchClient(); // 处理带所有维度的指标 const dimensionsArray = Object.entries(dimensions).map(([name, value]) => ({ Name: name, Value: String(value) })); // 确保Stack维度存在 const stackValue = dimensions.Stack || (process.env.STACK_NAME || "Unknown"); if (!dimensions.Stack) { dimensionsArray.push({ Name: "Stack", Value: stackValue }); } // 准备MetricData:包含多维度和仅Stack维度的两个指标 const metricData = [ { MetricName: metricName, Value: value, Unit: unit, Dimensions: dimensionsArray }, { MetricName: metricName, Value: value, Unit: unit, Dimensions: [{ Name: "Stack", Value: stackValue }] } ]; const command = new PutMetricDataCommand({ Namespace: "MonkeyIoT", MetricData: metricData }); const response = await client.send(command); return response; } catch (err) { console.error('Failed to publish metric:', err); throw err; } }
方案3:使用SearchMetric匹配多维度指标
CDK支持用fromSearchQuery直接复用你在控制台使用的多源查询逻辑,自动匹配所有符合条件的指标:
private loadOverviewDashboard(dashboard: cdk.aws_cloudwatch.Dashboard) { dashboard.addWidgets( new GraphWidget({ title: 'Critical Overview', left: [ cdk.aws_cloudwatch.Metric.fromSearchQuery({ searchQuery: 'namespace="MonkeyIoT" metric="CriticalFailure" Stack="Critical"', statistic: cdk.aws_cloudwatch.Stats.SUM, label: "All Failures", color: cdk.aws_cloudwatch.Color.RED, period: cdk.Duration.minutes(1), }) ], width: 24, height: 6, legendPosition: cdk.aws_cloudwatch.LegendPosition.RIGHT, }) ) }
内容的提问来源于stack exchange,提问作者monkey
相关产品推荐
相关产品推荐

