Skip to content
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

Ignore noop children when polling composite meters #4093

Open
wants to merge 1 commit into
base: 1.9.x
Choose a base branch
from

Conversation

jonatan-ivanov
Copy link
Member

When a CompositeMeterRegistry is used and one of its CompositeMeters is polled (its value is fetched), the returned value can depend on the order of the registries inside of the composite if the composite contains a registry that has any NoopMeters.

Example: a CompositeMeterRegistry contains two registries, A and B. We create a counter in the composite and increment it once. After this both A and B contain one counter but lets say that in A the counter is ignored so it will be noop.
When the count called on CompositeCounter, it can return either 0 (if NoopCounter was used)
or 1 (if the non-noop counter was used).

In order to fix this, we can ignore the NoopMeters when Meters are polled in a composite registry.

Closes gh-1441

When a CompositeMeterRegistry is used and one of its CompositeMeters
is polled (its value is fetched), the returned value can depend on
the order of the registries inside of the composite if the composite
contains a registry that has any NoopMeters.

Example: a CompositeMeterRegistry contains two registries, A and B.
We create a counter in the composite and increment it once.
After this both A and B contain one counter but lets say that
in A the counter is ignored so it will be noop.
When the count called on CompositeCounter, it can return
either 0 (if NoopCounter was used)
or 1 (if the non-noop counter was used).

In order to fix this, we can ignore the NoopMeters
when Meters are polled in a composite registry.

Closes micrometer-metricsgh-1441
@jonatan-ivanov jonatan-ivanov changed the base branch from main to 1.9.x September 22, 2023 00:57
final Iterator<T> i = children.values().iterator();
if (i.hasNext())
return i.next();
for (T next : children.values()) {
Copy link
Member Author

Choose a reason for hiding this comment

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

This should not be on the "hot path" (i.e.: recording a measurement or retrieving meters) but it will be called every time a value is fetched for publishing.

I'm thinking if there might be another way to implement this: modifying the children collection so that it has some priority ordering so the non-noop meters in it take precedence and will be "in front" of the collection (if any). That solution though might be more problematic since it seems a bit more complicated and it can be on a "hotter" path (meter creation).

Choose a reason for hiding this comment

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

Have you seen this PR? The approach is completely different but certainly more efficient. We should understand if there is any hidden side effect if the meter is not added..

Copy link
Member Author

Choose a reason for hiding this comment

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

I guess #1442 is also connected.
I would not do what is in #1443, it is somewhat similar to the priority ordering solution I explained before so its path is "hotter" and it omits meters from the registry.

if (!(next instanceof NoopMeter)) {
return next;
}
}

// There are no child meters. Return a lazily instantiated no-op meter.
final T noopMeter = this.noopMeter;
Copy link
Member Author

Choose a reason for hiding this comment

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

If we are at this point, the children collection was either empty or contains only noop meters. In the second case we could return it the first value (like we did before this change) but I'm not sure it worth the hassle.

@stefano-salmaso
Copy link

stefano-salmaso commented Sep 22, 2023

You are merging this into micrometer-metrics:1.9.x, why not in main?

@jonatan-ivanov
Copy link
Member Author

You are merging this into micrometer-metrics:1.9.x, why not in main?

Because I think we should consider this as a bug not a new feature.
If we would merge this in main only 1.12.x and newer versions will have this fix. If we merge this into 1.9.x, then that and newer versions will have the fix (1.9, 1.10, 1.11, 1.12, ...)

@klau-nagy-cs
Copy link

Hi,
Are there any news on this PR? Do you know when this fix will be merged and released?
We have the same problem using version 1.11 and this fix would solve our issue.
Thank you!

@jkemming
Copy link

Hi @jonatan-ivanov,

I've implemented a solution on top of your PR that addresses the "hot path" issue, please have a look. Feel free to incorporate the changes here, or if you want I can open a separate PR.

Also, there are two alternative solutions I have considered. If any of those sound better to you, please let me know:

  • If atomic updates to children and firstNonNoopChild aren't required, the inner class could essentially be inlined.
  • Alternatively, we could keep the calculation on the "hot path" and cache the result, clearing the cache when children is updated.

@jonatan-ivanov
Copy link
Member Author

@klau-nagy-cs

Are there any news on this PR? Do you know when this fix will be merged and released?
We have the same problem using version 1.11 and this fix would solve our issue.

Szia, No news, we need to review and discuss it. Adding 👍🏼 to the issue could help with prioritizing.

@jkemming

I've implemented a solution on top of your PR that addresses the "hot path" issue, please have a look. Feel free to incorporate the changes here, or if you want I can open a separate PR.

Hi, I'm not sure I understand, My comment about the "hot path" is saying that what I'm doing in the PR should not be on the hot path so it should not have a hot path issue. That part of the code should only called once per every publishing but depending on the setup add/remove registries could be even less frequent, we should definitely consider this option too.

@jkemming
Copy link

I'm afraid I misunderstood your comment then, sorry for that... Should there be anything I can do to help, please let me know.

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.

CompositeMeters don't ignore NoopMeters when forwarding value get calls to child.
4 participants