-
Notifications
You must be signed in to change notification settings - Fork 882
Spatial aggregation for async instruments with filtering views #7264
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
base: main
Are you sure you want to change the base?
Spatial aggregation for async instruments with filtering views #7264
Conversation
|
I'd like to discuss the test here. I would expect a cumulative sum instrument to aggregate all occurrences with empty attributes. Thus, I would expect to see To preserve this behavior, I clear the values for all the attributes at every collection, which is why |
Oh I forgot about a fundamental detail of asynchronous instruments: conceptually, when you make an observation with a cumulative instrument, we say that you are observing a cumulative value. Thus, if we have a reader with cumulative temporality which reads twice and invokes the callbacks twice, and the callback records the same value 3 each time, the reported value should indeed be 3 and not 6. Consider it from the perspective of this instrumentation which records information about classes loaded. If in sequential reads the callback records that 100 classes have been loaded, the output of a cumulative reader should always be 100, not N*100 (where N is the number of times the callback has been invoked). Instrumentation is not responsible for managing state and recording only the delta. |
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.
Thanks for working on this. This is pretty complex code when you consider the combinations of cumulative + delta, reusable + immutable data mode, and our desire to maintain zero memory allocations with reusable data mode after the application reaches steady state.
So reviews need to be slow / careful, but I am definitely interested in getting this issue resolved!
for (AsynchronousMetricStorage<?, ?> storage : storages) { | ||
if (storage.getRegisteredReader().equals(activeReader)) { | ||
storage.record(measurement); | ||
storage.setEpochInformation(startEpochNanos, epochNanos); | ||
storage.record(attributes, value); |
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.
Can we combine these into a single operation?
return MetricStorage.CARDINALITY_OVERFLOW; | ||
} | ||
|
||
if (aggregatorHandles.containsKey( |
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.
I don't think this log message makes sense anymore: Previously we knew that that the instrument itself had recorded multiple values for the same attributes. Now we have know way of telling whether it was the instrumentation that recorded the same attributes, or that the attributes were the same after applying the view attribute filter.
We could continue this logging by maintaining state that tracks the unique original unfiltered attributes recorded, but that seems too expensive.
} else { | ||
lastPoints = new HashMap<>(); | ||
points = new HashMap<>(); |
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.
It looks like you've replaced the reused points
hash map with a local variable Map<Attributes, T> currentPoints = new HashMap<>();
in the collect method.
We've got to reuse resources to continue to achieve our goal not allocating any additional memory once the SDK reaches steady state. Details available here: https://opentelemetry.io/blog/2024/java-metric-systems-compared/#opentelemetry-java-metrics
...ics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/AsynchronousMetricStorage.java
Outdated
Show resolved
Hide resolved
assertThat(passedMeasurement.longValue()).isEqualTo(5); | ||
assertThat(passedMeasurement.startEpochNanos()).isEqualTo(0); | ||
assertThat(passedMeasurement.epochNanos()).isEqualTo(10); | ||
verify(mockAsyncStorage1).record(Attributes.empty(), 5); |
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.
Let's retain the asserts to verify the epoch informatinon was set. Applies to other tests as well.
verify(mockAsyncStorage1).record(Attributes.empty(), 5); | |
verify(mockAsyncStorage1).setEpochInformation(0, 10); | |
verify(mockAsyncStorage1).record(Attributes.empty(), 5); |
Co-authored-by: jack-berg <[email protected]>
Fixes #4901
I propose the following changes:
AsynchronousMetricStorage
now declaresvoid record(Attributes, long)
andvoid record(Attributes, double)
instead of a singlevoid record(Measurement)
, to enable usingAggregatorHandle
within the class.AsynchronousMetricStorage
now contains twolong
fields (startEpochNanos
,epochNanos
) which are injected before running the callbacks, as an alternative to passing aMeasurement
object.AsynchronousMetricStorage