Skip to content

Make ServiceMetricEvent immutable, do not allow null dimension values#18272

Merged
kfaraz merged 6 commits intoapache:masterfrom
kfaraz:fix_service_metric_event
Jul 18, 2025
Merged

Make ServiceMetricEvent immutable, do not allow null dimension values#18272
kfaraz merged 6 commits intoapache:masterfrom
kfaraz:fix_service_metric_event

Conversation

@kfaraz
Copy link
Copy Markdown
Contributor

@kfaraz kfaraz commented Jul 17, 2025

Follow up to #18255 to handle null dimension values in ServiceMetricEvent

Related comment: #17170 (comment)

ServiceMetricEvent should ideally be immutable.
Otherwise, there can be a race if the ServiceMetricEvent.Builder is reused while the first event
is still being emitted.

Changes

  • Make ServiceMetricEvent immutable. All fields were already immutable. Fix up userDims to be immutable too.
  • Do not allow null dimension names or values
  • Remove ServiceMetricEvent.copy as the event is already immutable.

This PR has:

  • been self-reviewed.
  • added documentation for new or modified features or behaviors.
  • a release note entry in the PR description.
  • added Javadocs for most classes and all non-trivial methods. Linked related entities via Javadoc links.
  • added or updated version, license, or notice information in licenses.yaml
  • added comments explaining the "why" and the intent of the code wherever would not be obvious for an unfamiliar reader.
  • added unit tests or modified existing tests to cover new code paths, ensuring the threshold for code coverage is met.
  • added integration tests.
  • been tested in a test Druid cluster.

@Akshat-Jain Akshat-Jain reopened this Jul 17, 2025
@kfaraz kfaraz changed the title Handle null dimension values in ServiceMetricEvent.copy Make ServiceMetricEvent immutable, do not allow null dimension values Jul 17, 2025
@Akshat-Jain Akshat-Jain reopened this Jul 17, 2025
@Akshat-Jain Akshat-Jain reopened this Jul 17, 2025
@kfaraz kfaraz requested review from Akshat-Jain and kgyrtkirk July 17, 2025 16:36
// This change is done to keep the code coverage tool happy by exercising the implementation
queryMetrics.sqlQueryId("dummy");
queryMetrics.queryId("dummy");
queryMetrics.reportQueryTime(0).emit(serviceEmitter);
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.

Why was this change needed? 🤔

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.

Need to emit the event after all the dimensions are set. Otherwise, this test would fail.

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.

public Builder setDimension(String dim, Object value) and public Builder setDimensionIfNotNull(String dim, Object value) could probably be collapsed into a single method I think? Any reason for keeping them separate? is it to avoid widespread changes across the codebase?

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.

Yes, it keeps the patch small.
Also, the setDimensionIfNotNull is essentially a short hand which does the null check for you, while the other throws exception on nulls.

*/
public Builder setDimensionIfNotNull(String dim, Object value)
{
if (dim == null) {
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.

nit: as the name setDimensionIfNotNull suggests, consider only keep value check in this function, move the dim check and userDims.put logic to setDimension. Also consider use StringUtils.isEmpty to check dim is not empty string as well.

this.createdTime = createdTime != null ? createdTime : DateTimes.nowUtc();
this.serviceDims = serviceDims;
this.userDims = userDims;
this.userDims = userDims == null ? Map.of() : Map.copyOf(userDims);
Copy link
Copy Markdown
Contributor

@cecemei cecemei Jul 17, 2025

Choose a reason for hiding this comment

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

nit: userDims could also be ImmutableMap in line 50.

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.

Yeah, that would make for better symmetry with the other field serviceDims, let me do that.

@Akshat-Jain Akshat-Jain reopened this Jul 18, 2025
@kfaraz
Copy link
Copy Markdown
Contributor Author

kfaraz commented Jul 18, 2025

I think we can merge this PR since the IT failure is due to some issue with the k8s cluster setup for ITNestedQueryPushDownTest, which is unrelated to the changes here.

@kfaraz
Copy link
Copy Markdown
Contributor Author

kfaraz commented Jul 18, 2025

Thanks a lot for the reviews, @Akshat-Jain , @cecemei !
(and also @Akshat-Jain for triggering the CI 😃 )

@kfaraz kfaraz merged commit 98c63de into apache:master Jul 18, 2025
140 of 142 checks passed
@kfaraz kfaraz deleted the fix_service_metric_event branch July 18, 2025 07:34
ashibhardwaj pushed a commit to ashibhardwaj/druid that referenced this pull request Jul 23, 2025
…apache#18272)

Changes:
- Make `ServiceMetricEvent` immutable. All fields were already immutable except `userDims`.
- Do not allow null dimension names or values.
- Remove `ServiceMetricEvent.copy` as the event is already immutable.
@cecemei cecemei added this to the 35.0.0 milestone Oct 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants