You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 05:25:56