Closed loganlinn closed 1 year ago
Thank you for raising this issue. On closer examination, I agree the current design is inflexible compared to the Java API. Using the Java API, the callback could contain arbitrary logic and dynamically record any number of measurements. I will remove the 0-arity observe
function and replace it with something closer to the ObservableMeasurement
Java interface.
As Metrics API support is new for the next clj-otel
release, I am not concerned with breaking changes in this area.
I implemented the first suggestion of allowing observe
to return a sequence of maps.
Implementing the second suggestion is difficult, as the ObservableMeasurement
instance is known only at observation time, not at instrument construction time. Constructing a record!
function instance on each observation is possible, but this is counterproductive to minimising garbage collection.
@steffan-westcott That makes complete sense now. Thank you for considering both and the quick turn around!
Problem
steffan-westcott.clj-otel.api.metrics.instrument/instrument
for creating async instruments, i.e.Observable(Long|Double)(Counter|Gauge|UpDownCounter)
from OpenTelemetry Java API, accepts anobserve
function as 2nd argument.observe
function is currently expected to return a map containing:value
key and optional:attributes
key.ObservableLongMeasurement
/ObservableDoubleMeasurement
, whererecord
can be called multiple times per observationProposal
I see two potential approaches that would move this forward without introducing breaking changes to the current API:
observe
to return a sequence of maps, each corresponding to a underlying call torecord
.observe
usingmap?
and/orsequential?
.(preferred) Introduce a new protocol that could be used for the 2nd argument of
instrument
instead of a function.This protocol could look like:
The
record!
argument is a function that either:observe
API::value
key + optional:attributes
key, OR(preferred) Has two arities to accept these values directly, i.e
The
steffan-westcott.clj-otel.api.metrics.instrument/instrument
function would detect opt-in via(satisfies? Observable observe)
.The
steffan-westcott.clj-otel.api.metrics.instrument
namespace could provide helper function to reify this protocol to reduce burden on end-user.My preference for the 2nd approach, despite being a little more involved, is for performance/efficiency reasons. While I am generally sensitive to premature optimization, using values like
{:value ..., :attributes ...}
to convey the arguments to OpenTelemetry API invocations does introduce objects that must be garbage collected at some point. As a end-user who wants to instrument my application code, I want to incur minimal overhead in doing so. It would be fairly trivial for an and end-user who does prefer a data-oriented approach to accomplish the same effect because therecord!
function can be wrapped.