New APIs to add/remove metric readers at run-time#4863
New APIs to add/remove metric readers at run-time#4863JP-MY wants to merge 1 commit intoopen-telemetry:mainfrom
Conversation
|
|
opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/measurement_consumer.py
Outdated
Show resolved
Hide resolved
opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/measurement_consumer.py
Outdated
Show resolved
Hide resolved
opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/__init__.py
Outdated
Show resolved
Hide resolved
opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/measurement_consumer.py
Outdated
Show resolved
Hide resolved
opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/__init__.py
Outdated
Show resolved
Hide resolved
opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/measurement_consumer.py
Outdated
Show resolved
Hide resolved
aabmass
left a comment
There was a problem hiding this comment.
Thanks for the PR, sorry for the delay here.
opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/measurement_consumer.py
Outdated
Show resolved
Hide resolved
opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/measurement_consumer.py
Show resolved
Hide resolved
| raise ValueError( | ||
| f"MetricReader {metric_reader} has not been registered!" | ||
| ) | ||
| self._measurement_consumer.remove_metric_reader(metric_reader) |
There was a problem hiding this comment.
It's a little unfortunate to have multiple copies of the readers on these two classes. Any ideas to get around it?
There was a problem hiding this comment.
unfortunately I can't think of an easy way to decouple these as meter provider heavily realies on internals of measurment consumer from what I can see. I agree it'd be better to simplify and happy to implement changes if you have an idea on what should be done.
There was a problem hiding this comment.
This code currently assumes that self._reader_storages is immutable. The goal was to prevent having a single MeterProvider wide lock for all metrics.
Can you help me understand the consequences of this variable being mutable now? E.g. dropped measurements, safety of iterating over values() in event another thread modifies the dict, etc
There was a problem hiding this comment.
in terms of thread safety: because of GIL (I'm aware it is becoming optional and possibly removed in the future, lets ignore that for now) all built in types are thread safe so the dict can't be pushed to / popped when iterating over values(). The only edge cases are when you call add / remove while this iteration is happening meaning you get one last set of extra data if you were trying to remove and you don't get the first batch of data if you were trying to add which should be fine as we did not provide any real time gurantees for these operations.
P.S. please correct me if I'm wrong but that is my understanding
There was a problem hiding this comment.
I don't think that is thread safe actually, you probably need to copy the keys or values into a list which is atomic operation with GIL held
>>> d = {"hello": "world"}
>>> v = d.values()
>>> v
dict_values(['world'])
>>> iter(v)
<dict_valueiterator object at 0x7f52311f13a0>
>>> i = iter(v)
>>> d["bar"] = "bar"
>>> next(i)
Traceback (most recent call last):
File "<python-input-14>", line 1, in <module>
next(i)
~~~~^^^
RuntimeError: dictionary changed size during iterationSo besides the mechanical issues, I just wanted to make sure you've thought about these problems.
There was a problem hiding this comment.
I ran a small test and you are correct, I can get it to raise runtime error, so will have to add a lock around this as well (or do you prefer the copy to a list variation) to avoid concurrency issues. We have indeed thought about this but losing some data at the very start of adding/ very end of removing the metric reader is acceptable for our use case.
Back on the concurency issue: I prefer using a lock as it avoids extra overhead of copying data and adding GC pressure but please let me know which approach I should use.
There was a problem hiding this comment.
We'd probably want to use a lock here, and then create a copy of the values as a WeakSet with the lock held. We probably don't want to have the lock held during this entire process since there might be instances where consume_measurement could block (not sure on this one).
There was a problem hiding this comment.
Tested to make sure this approach works and updated the PR accordingly
|
I'm not sure why the lint is failing for protected access, I can see the same protected access in the same file. Should I add a |
Description
This change adds two public functions to MeterProvider that allow registering and deleting metric readers at run-time.
Fixes #4818
Type of change
Please delete options that are not relevant.
How Has This Been Tested?
Does This PR Require a Contrib Repo Change?
Checklist: