In implementing our design for the metrics API and SDK we ran into a problem regarding nostd::shared_ptr and we are unsure how to proceed from here.
The OpenTelemetry specification states here that functions and components related to the querying and exporting of metric data (such as aggregators, controller, etc.) are to be handled in the SDK; the API merely provides the components and functionality necessary to create metric instruments and capture measurements.
However, the API is also the user facing portion of the code. This means that any time we are passed an argument to a function by the user, that component only has access to functions defined in the API, as well as any virtual functions that may be overriden in derived classes. So it seems we are left with no choice but to explicitly downcast.
One such case where we need to do this is in the controller. When the user creates a controller, they will pass a unique pointer to an instance of the API Meter class. The controller will need to downcast this to an SDK meter to be able to access the Collect() function which checkpoints aggregators and sends metric data to the processor. Essentially, there are functions which we need from each component which we are not allowed to declare in the API and thus must be in the SDK according to the spec.
Possible Solutions
- Add functionality to the nostd::shared_ptr class to support dynamic_pointer_cast and static_pointer_cast. This would allow us to do the casting that we need in a memory-safe manner. In order to implement this, I believe that a new constructor would need to be added to the nostd::shared_ptr class called the aliasing constructor.
- Change the OpenTelemetry specification to allow functions and components related to the querying and exporting of metric data to live in the API. This would allow us to add virtual functions to these classes that we can use to collect and export with and eliminates the need for explicit casting. This is a large change to the specification which would require substantial debate outside the C++ repo.
- Use dynamic_cast instead of dynamic_pointer_cast but this leads to a problem: If we do this then, for at least a brief time, we would have a raw pointer and a smart pointer pointing to the same memory. This is dangerous as it can can easily lead to seg-faults and, as is the case for the meter class, make the code very unstable.
My recommendation would be to use solution 1 given it is the cleanest implementation and most optimal choice. However, if there is another way to solve this issue that we are missing please let us know!
We would greatly appreciate any advice or help on solving this issue as it is currently blocking us from completing a working version of the metrics API and SDK.
cc: @alolita @reyang @maxgolov
In implementing our design for the metrics API and SDK we ran into a problem regarding nostd::shared_ptr and we are unsure how to proceed from here.
The OpenTelemetry specification states here that functions and components related to the querying and exporting of metric data (such as aggregators, controller, etc.) are to be handled in the SDK; the API merely provides the components and functionality necessary to create metric instruments and capture measurements.
However, the API is also the user facing portion of the code. This means that any time we are passed an argument to a function by the user, that component only has access to functions defined in the API, as well as any virtual functions that may be overriden in derived classes. So it seems we are left with no choice but to explicitly downcast.
One such case where we need to do this is in the controller. When the user creates a controller, they will pass a unique pointer to an instance of the API Meter class. The controller will need to downcast this to an SDK meter to be able to access the Collect() function which checkpoints aggregators and sends metric data to the processor. Essentially, there are functions which we need from each component which we are not allowed to declare in the API and thus must be in the SDK according to the spec.
Possible Solutions
My recommendation would be to use solution 1 given it is the cleanest implementation and most optimal choice. However, if there is another way to solve this issue that we are missing please let us know!
We would greatly appreciate any advice or help on solving this issue as it is currently blocking us from completing a working version of the metrics API and SDK.
cc: @alolita @reyang @maxgolov