Skip to content

SED-4758 Implement Label Value Cardinality Safeguards for Custom Metrics Ingestion#660

Open
david-stephan wants to merge 4 commits into
masterfrom
SED-4758-implement-label-value-cardinality-safeguards-for-custom-metrics-ingestion
Open

SED-4758 Implement Label Value Cardinality Safeguards for Custom Metrics Ingestion#660
david-stephan wants to merge 4 commits into
masterfrom
SED-4758-implement-label-value-cardinality-safeguards-for-custom-metrics-ingestion

Conversation

@david-stephan

Copy link
Copy Markdown
Contributor

No description provided.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a per-execution label cardinality safeguard to prevent high cardinality on user-defined metric and measurement labels, along with a new execution notice system to raise and resolve lightweight, non-blocking warnings. Key changes include updating TimeSeriesMetricSamplesHandler to enforce unique-value quotas, introducing ExecutionNoticeManager and related classes to manage notices, and synchronizing ExecutionManager.updateExecution to handle concurrent updates safely. The review feedback suggests improving test assertions in ExecutionNoticeManagerTest and ExecutionNoticeResolverTest by using specific assertEquals checks instead of assertTrue with contains for deterministic outcomes.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

* is raised once per label.</li>
* </ul>
*/
private String maskIfOverQuota(ExecutionContext executionContext, String execId, String metricName,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It took me time to understand that value means labelValue and not the value of the metric itself

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactored

if (values.contains(value)) {
return value;
}
if (values.size() < maxUniqueLabelValues) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we do the check to ensure that the number of label values per label remains under the defined max. Don't we want to also ensure that we don't exceed the number of labels?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added now also a quota on the number of labels per exec id and measurement/metric name

}
Map<String, String> params = (parameters != null) ? parameters : Collections.emptyMap();
Matcher matcher = PLACEHOLDER.matcher(template);
StringBuffer result = new StringBuffer();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I learnt many years ago that StringBuilder is more efficient. Not sure if still the case in 2026 and if this method is performance sensible

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, this should be a StringBuilder

*/
public class ResolvedExecutionNotice {

private String typeId;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could use public fields instead

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using public mutable fields breaks encapsulation, making code fragile because any external class can modify the DTO's data at runtime. If the goal was to achieve immutability (the primary reason someone would use a constructor-based @JsonCreator), making the fields public completely defeated that purpose. Now with target Java 21 we can use "record" instead.

*/
public class ExecutionNotice {

private String typeId;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could use public fields instead of getters / setters or maybe records?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually using public field is an anti pattern and should not be used here. Luckily now that we moved to target Java 21 we can use the recommended approach for immutable Pojo with (de)serialization support: records, I made the change.

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