-
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
fix(tracemetrics): Improve metrics analytics #104495
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This elides metric counts when the metric name is empty, and improves testing around metric panel etc.
| table_result_length: resultLengthBox.current, | ||
| table_result_missing_root: 0, | ||
| table_result_mode: 'metric samples', | ||
| table_result_mode: resultMode, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Aggregate mode reports wrong table result length
The getAttributes function always uses resultLengthBox.current (samples table length) for table_result_length, regardless of whether resultMode is 'aggregates' or 'metric samples'. When in aggregate mode, it should use aggregatesResultLengthBox.current instead. This causes incorrect analytics data to be reported for the aggregates table result length.
| table_result_length: resultLengthBox.current, | ||
| table_result_missing_root: 0, | ||
| table_result_mode: 'metric samples', | ||
| table_result_mode: resultMode, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Aggregate mode reports wrong table result sort
The getAttributes function always uses formattedSortBysBox.current (samples sort) for table_result_sort, regardless of whether resultMode is 'aggregates' or 'metric samples'. When in aggregate mode, it should use formattedAggregateSortBysBox.current instead. The formattedAggregateSortBysBox is defined and included in the aggregates useEffect dependency array but is never actually used in the analytics payload.
| const metricPanelsWithGroupBys = metricQueries | ||
| .filter(mq => !isEmptyTraceMetric(mq.metric)) | ||
| .map(mq => mq.queryParams.groupBys.some((gb: string) => gb.trim().length > 0)).length; | ||
| const metricPanelsWithFilters = metricQueries | ||
| .filter(mq => !isEmptyTraceMetric(mq.metric)) | ||
| .map(mq => mq.queryParams.query.trim().length > 0).length; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: metricPanelsWithGroupBys and metricPanelsWithFilters incorrectly count all non-empty metrics due to .map().length instead of filtering for specific conditions.
Severity: MEDIUM | Confidence: High
🔍 Detailed Analysis
The metricPanelsWithGroupBys and metricPanelsWithFilters variables are intended to count the number of metricQueries that satisfy specific conditions (having group-bys or filters) after filtering out empty trace metrics. However, the current implementation uses .map() to transform the filtered metricQueries into an array of booleans, and then .length is called on this array. This incorrectly counts the total number of non-empty metricQueries (the length of the boolean array) instead of counting only those metricQueries for which the boolean condition was true. For example, if there are two non-empty metrics but only one has group-bys, the code will return 2 instead of 1, leading to an overcounting of these panel types.
💡 Suggested Fix
Replace the .map().length pattern with a single .filter() call that combines the initial non-empty metric check with the specific condition. For example: metricQueries.filter(mq => !isEmptyTraceMetric(mq.metric) && mq.queryParams.groupBys.some((gb: string) => gb.trim().length > 0)).length;
🤖 Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.
Location: static/app/views/explore/hooks/useAnalytics.tsx#L912-L917
Potential issue: The `metricPanelsWithGroupBys` and `metricPanelsWithFilters` variables
are intended to count the number of `metricQueries` that satisfy specific conditions
(having group-bys or filters) after filtering out empty trace metrics. However, the
current implementation uses `.map()` to transform the filtered `metricQueries` into an
array of booleans, and then `.length` is called on this array. This incorrectly counts
the total number of non-empty `metricQueries` (the length of the boolean array) instead
of counting only those `metricQueries` for which the boolean condition was `true`. For
example, if there are two non-empty metrics but only one has group-bys, the code will
return `2` instead of `1`, leading to an overcounting of these panel types.
Did we get this right? 👍 / 👎 to inform future reviews.
Reference ID: 6298179
| metric_queries_count: ${String(metricQueries.length)} | ||
| metric_panels_with_group_bys_count: ${String(metricPanelsWithGroupBysCount.current)} | ||
| metric_panels_with_filters_count: ${String(metricPanelsWithFiltersCount.current)} | ||
| metric_panels_with_group_bys_count: ${String(metricPanelsWithGroupBys)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Info log uses total count, analytics uses filtered count
The trackAnalytics call uses nonEmptyMetricQueries.length for metric_queries_count, but the info log uses metricQueries.length. This inconsistency means the analytics event and the info log report different values for the same metric. Based on the PR's intent to elide empty metrics, the info call likely needs to use nonEmptyMetricQueries.length as well.
Additional Locations (1)
This elides metric counts when the metric name is empty, and improves testing around metric panel etc.
This elides metric counts when the metric name is empty, and improves testing around metric panel etc.