-
Notifications
You must be signed in to change notification settings - Fork 249
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
feat: add basic implementation of asynchronous metrics #1610
base: main
Are you sure you want to change the base?
feat: add basic implementation of asynchronous metrics #1610
Conversation
…o metrics-asynchronous
…o metrics-asynchronous
👋 This pull request has been marked as stale because it has been open with no activity. You can: comment on the issue or remove the stale label to hold stale off for a while, add the |
end | ||
end | ||
|
||
def create_callback(callbacks) |
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 think create_callback
is a bit of left over from some experimentation. We should probably remove it.
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.
Yes, thanks!
class ObservableCounter < OpenTelemetry::Metrics::Instrument::ObservableCounter | ||
attr_reader :name, :unit, :description | ||
# {ObservableCounter} is the SDK implementation of {OpenTelemetry::SDK::Metrics::Instrument::AsynchronousInstrument}. | ||
# Asynchronous Counter is an asynchronous Instrument which reports non-additive, monotonically increasing value(s) when the instrument is being observed. |
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.
This comment is a bit confusing. I think it should read
Asynchronous Counter is an asynchronous Instrument which reports monotonically increasing value(s) when the instrument is being observed.
Any chance one of the code owners could take a look at this PR? |
I think there are a few other things to consider here; top of my list would be the ability to return multiple values from a callback, meaning the callback should also be able to return arbitrary attributes (perhaps in addition to the attributes declared when the instrument is created). An example might be reporting variable-length statistics about the current state of the system, like activity-per-cpu or RSS for each pid: callback = lambda do |state|
state.observe(2000, { 'pid' => 12, 'process_name' => 'puma' })
state.observe(2500, { 'pid' => 14, 'process_name' => 'sidekiq' })
end (In this example, the state object is some data container that exists for this callback invocation; the next operation would be to loop over each observed result and call The spec has a few other examples similar to this. |
As far as I can tell, the expected modes of the callback are:
Since the actual API of the callback isn't defined by the spec, it should be valid to specify that in order to return multiple values, a helper object should be used. Otherwise, for simple cases it should be ok to just return a value. This was the thing I prototyped (before noticing this PR): class `
attr_reader :data
def initialize
@data = []
end
def observe(value, attributes = nil)
@data << [value, attributes]
self
end
def self.enum_for(value)
if value.is_a?(self)
value.data.to_enum
else
# assume we have a single value
[[value, nil]].to_enum
end
end
end invoke_callback would be: def invoke_callback(timeout, attributes)
@mutex.synchronize do
Timeout.timeout(timeout || 30) do
@callback.each do |cb|
observations = CallbackObservations.new
CallbackObservations.enum_for(cb.call(observations)).each do |value, attributes|
@aggregation.update(value, attributes || {}, @data_points)
end
end
end
end
end ... and then callbacks could be any of the following: -> (obs) do
obs.observe(1)
end
-> (obs) do
obs.observe(1, cpu: 1)
end
-> () { 1 } This is sort of maximally flexible without needing to do nested type-checking (but doesn't yet include any validation on the return values of the callbacks — they are assumed to be the observations object or a single value). A safer version would be to enforce that all observations are recorded via |
Thanks @zvkemp , I think your solution may work. I am thinking this as an additional improvement (single value export -> multi-value export) on asy instrument, and you can open a pr once this one get merged (not sure if you can direct open a pr based on this branch; but if that works, please do so). |
I have a fork of your branch here: https://github.com/zvkemp/opentelemetry-ruby/tree/metrics-asynchronous (but no PR yet, but it supports this proposal: zvkemp/opentelemetry-ruby-contrib#1). This implementation uses the more restrictive version, where all observations need to go on the recorder argument. |
I've been doing some additional thinking on the 'multi-value export' issue, and I would suggest that the simple case may be too simple if the eventual goal is to support multiple values — i.e., if the callback is allowed to return a value, an array of values, a 'tuple' (array) of a value plus attributes, an array of tuples, or nothing, it seems like there's too much room for error or ambiguity. The other SDKs I've looked at (python, rust, javascript, and go) require observations to be forwarded to the callback argument, or have defined an |
I agree, @zvkemp. I think we should support multi-value exports from the start. I like where you're headed in your fork of this branch. |
Description
I'd like to make contribution on basic implementation on asynchronous metrics.
Related: #1386, Asynchronous Up Down Counter card, Asynchronous Gauge.
Spec: asynchronous-instrument-api
WIP: