Skip to content

fix(aws_elb_metrics_otel): filter TargetGroup/AvailabilityZone rollup… - #20870

Open
mrg-elastic wants to merge 6 commits into
elastic:mainfrom
mrg-elastic:fix/aws-elb-otel-dimension-rollup
Open

fix(aws_elb_metrics_otel): filter TargetGroup/AvailabilityZone rollup…#20870
mrg-elastic wants to merge 6 commits into
elastic:mainfrom
mrg-elastic:fix/aws-elb-otel-dimension-rollup

Conversation

@mrg-elastic

Copy link
Copy Markdown
Contributor

… rows to prevent metric overcounting

Proposed commit message

Checklist

  • I have reviewed tips for building integrations and this pull request is aligned with them.
  • I have verified that all data streams collect metrics or logs.
  • I have added an entry to my package's changelog.yml file.
  • I have verified that Kibana version constraints are current according to guidelines.
  • I have verified that any added dashboard complies with Kibana's Dashboard good practices

Author's Checklist

  • [ ]

How to test this PR locally

Related issues

Screenshots

@github-actions

Copy link
Copy Markdown
Contributor

✅ Elastic Docs Style Checker (Vale)

No issues found on modified lines!


The Vale linter checks documentation changes against the Elastic Docs style guide. To use Vale locally or report issues, refer to Elastic style guide for Vale.

@mrg-elastic
mrg-elastic marked this pull request as ready for review August 24, 2026 10:30
@mrg-elastic
mrg-elastic requested a review from a team as a code owner August 24, 2026 10:30
@agithomas

Copy link
Copy Markdown
Contributor

nit:
Try to include AND stat == "Sum" or as to reduce the documents being scanned.

Example: Single metric panel, Detailed dashboard

Diff (original → suggested):
        --- original
        +++ suggested
        @@ -1,7 +1,7 @@
         SET unmapped_fields = "nullify";
         FROM metrics-aws.elb.otel-*
        -| WHERE LoadBalancer IS NOT NULL AND LoadBalancer != "" AND STARTS_WITH(LoadBalancer, "app/")
        +| WHERE LoadBalancer IS NOT NULL AND LoadBalancer != "" AND STARTS_WITH(LoadBalancer, "app/") AND stat == "Sum"
        -| STATS last_seen = MAX(@timestamp) BY LoadBalancer
        +| STATS last_seen = MAX(@timestamp) BY LoadBalancer, cloud.region
         | INLINE STATS latest_global = MAX(last_seen)
         | WHERE DATE_DIFF("minutes", last_seen, latest_global) <= 5
         | STATS count = COUNT(*), names = VALUES(LoadBalancer)

@agithomas

Copy link
Copy Markdown
Contributor

Detailed dashboard / Account ID:

        -| STATS account = MAX(cloud.account.id)
        +| STATS account = VALUES(cloud.account.id)

@agithomas

Copy link
Copy Markdown
Contributor
image

Please increase the value precision instead of using human-friendly values.

…shboard

14 panels were missing TargetGroup IS NULL and/or AvailabilityZone IS NULL,
causing ~95% overcounting from CloudWatch multi-dimension rollup duplicates.
All metric panels in the overview now filter to load-balancer-level granularity.
@agithomas

Copy link
Copy Markdown
Contributor

The backend 5xx error count is 0, but the graph next to it shows the values.

image

Check if the values of Healthy hosts and unhealthy hosts (4 panels are loading). In the Discover view, the value appears, but not in the kibana dashboard. Please recheck

image

Check possible double-counting issue with Active connections

SET unmapped_fields = "nullify";
        -TS metrics-aws.elb.otel-* | WHERE LoadBalancer IS NOT NULL AND LoadBalancer != "" AND STARTS_WITH(LoadBalancer, "app/") | WHERE stat == "Sum" AND `metrics.amazonaws.com/AWS/ApplicationELB/ActiveConnectionCount` IS NOT NULL | STATS col_activeconn = SUM(sum_over_time(`metrics.amazonaws.com/AWS/ApplicationELB/ActiveConnectionCount`)) BY timestamp = TBUCKET(50, ?_tstart, ?_tend), LoadBalancer, cloud.region | SORT timestamp ASC
        +TS metrics-aws.elb.otel-* | WHERE LoadBalancer IS NOT NULL AND LoadBalancer != "" AND STARTS_WITH(LoadBalancer, "app/") AND TargetGroup IS NULL AND AvailabilityZone IS NULL | WHERE `metrics.amazonaws.com/AWS/ApplicationELB/ActiveConnectionCount` IS NOT NULL | STATS col_activeconn = SUM(sum_over_time(CASE(stat == "Sum", `metrics.amazonaws.com/AWS/ApplicationELB/ActiveConnectionCount`, NULL))) BY timestamp = TBUCKET(50, ?_tstart, ?_tend), LoadBalancer, cloud.region | SORT timestamp ASC, col_activeconn DESC | LIMIT 10 BY timestamp

…im-filtering

Three classes of fixes across ALB, NLB, and GWLB detail dashboards:

1. HealthyHostCount / UnHealthyHostCount: remove TargetGroup IS NULL — these
   metrics are only published at the LoadBalancer+TargetGroup dimension level,
   never at LoadBalancer-only, so the filter emptied all 12 panels in ALB/NLB.

2. Backend 5XX error rate card (ALB): remove RequestCount IS NOT NULL pre-filter
   from WHERE — it excluded 5XX documents causing the aggregation to always return
   0. Both metrics now use CASE(stat == "Sum", metric, NULL) inside STATS.

3. Aggregation dimension filtering: move stat == "X" pre-filter from WHERE into
   CASE(stat == "X", metric, NULL) inside every *_over_time() and raw STATS
   aggregation, making it explicit which CloudWatch statistic contributes to each
   data point and preventing future double-counting if new stat types are added.
@agithomas

Copy link
Copy Markdown
Contributor

Panel title: Active connections over time (sum)

Qn? Do you want to consider removing the suffix (sum) from the title?

Do you want to consider

-TS metrics-aws.elb.otel-* | WHERE LoadBalancer IS NOT NULL AND LoadBalancer != "" AND TargetGroup IS NULL AND AvailabilityZone IS NULL | WHERE stat == "Sum" | STATS active_conn = SUM(sum_over_time(`metrics.amazonaws.com/AWS/ApplicationELB/ActiveConnectionCount`)) BY ts = TBUCKET(50, ?_tstart, ?_tend) | SORT ts ASC
 
+TS metrics-aws.elb.otel-* | WHERE LoadBalancer IS NOT NULL AND LoadBalancer != "" AND TargetGroup IS NULL AND AvailabilityZone IS NULL | WHERE stat == "Average" | STATS active_conn = SUM(avg_over_time(`metrics.amazonaws.com/AWS/ApplicationELB/ActiveConnectionCount`)) BY ts = TBUCKET(50, ?_tstart, ?_tend) | SORT ts ASC

@agithomas

Copy link
Copy Markdown
Contributor

Panel name : Primary metric: Browse other AWS OTel dashboards

--- original
+++ suggested
@@ -1,2 +1 @@
-SET unmapped_fields = "nullify";
 ROW value = "AWS-Managed-OTel" | KEEP value

@agithomas

Copy link
Copy Markdown
Contributor

Every NLB detail panel queries the ALB stream metrics-aws.elb.otel-. You may have to retarget them to metrics-aws.elb_network.otel- and the matching dataset. Please check for the gateway load balancer.

This has an impact on the Overview dashboards, as these are different datasets - the data shown in the Overview dashboard (count, table view, hexmap) presently is ALB specific, might not be covering other LB types. So, you may have to revisit the Overview dashboard as well.

@agithomas

Copy link
Copy Markdown
Contributor

ELB - NLB Details dashboard

  1. Load balancer (single metric) / Account / Region

Please add the stat == "Sum"

  --- original
  +++ suggested
   FROM metrics-aws.elb_network.otel-*
  -| WHERE LoadBalancer IS NOT NULL AND LoadBalancer != "" AND STARTS_WITH(LoadBalancer, "net/")
  +| WHERE LoadBalancer IS NOT NULL AND LoadBalancer != "" AND STARTS_WITH(LoadBalancer, "net/") AND stat == "Sum"
-| WHERE LoadBalancer IS NOT NULL AND LoadBalancer != "" AND STARTS_WITH(LoadBalancer, "net/")
+| WHERE LoadBalancer IS NOT NULL AND LoadBalancer != "" AND STARTS_WITH(LoadBalancer, "net/") AND stat == "Sum"
  1. Status timeline:
-| STATS unhealthy_max = MAX(max_over_time(CASE(stat == "Maximum", `metrics.amazonaws.com/AWS/NetworkELB/UnHealthyHostCount`, NULL)))
+| STATS unhealthy_max = MAX(max_over_time(CASE(stat == "Maximum" AND TargetGroup IS NOT NULL, `metrics.amazonaws.com/AWS/NetworkELB/UnHealthyHostCount`, NULL)))

@elastic-vault-github-plugin-prod

Copy link
Copy Markdown
Contributor

✅ All changelog entries have the correct PR link.

@infra-vault-gh-plugin-prod

Copy link
Copy Markdown

💚 Build Succeeded

History

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants