Skip to content
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

Swap old Metrics API for currently specified Metrics API #3423

Merged
merged 28 commits into from
Aug 5, 2021

Conversation

jsuereth
Copy link
Contributor

  • Implement, as best as possible, the latest version of the metrics API specification, with feedback from Java SiG from the prototype.
  • Wire the new API into all other SDK usages of the API.
  • This PR touches the SDK as little as possible. It does the LEAST amount of renaming, rewiring and reworking to get things working. This is only meant to be an API swap, with a LOT of follow on PRs to come (based on the prototype). This leaves a lot of wonky behavior such as:
    • The SDK references labels everywhere, including a LabelsProcessor for views. This will be refactored to match the SDK specifcaiton in follow-up PR.
    • The SDK currently has "value observer" and "value recorder" instead of "gauge" and "histogram" instruments. We keep those in the SDK to minimize the diff-set to view, but they will be cleaned up in a follow on PR.
    • The Histogram instrument is producing Summary metrics right now. This will be fixed when the new SDK implementation lands.
    • The InstrumentDescriptor API has NOT BEEN touched, so instrument names are out of date. This will also be fixed in a follow up PR.

@codecov
Copy link

codecov bot commented Jul 25, 2021

Codecov Report

Merging #3423 (a0d4252) into main (20f872d) will decrease coverage by 0.29%.
The diff coverage is 92.09%.

❗ Current head a0d4252 differs from pull request most recent head 0413b69. Consider uploading reports for the commit 0413b69 to get more accurate results
Impacted file tree graph

@@             Coverage Diff              @@
##               main    #3423      +/-   ##
============================================
- Coverage     90.94%   90.65%   -0.30%     
+ Complexity     3258     3194      -64     
============================================
  Files           369      362       -7     
  Lines         10035     9904     -131     
  Branches       1019      998      -21     
============================================
- Hits           9126     8978     -148     
- Misses          597      613      +16     
- Partials        312      313       +1     
Impacted Files Coverage Δ
.../opentelemetry/sdk/metrics/AbstractInstrument.java 72.72% <ø> (-15.28%) ⬇️
...try/sdk/metrics/AbstractSynchronousInstrument.java 100.00% <ø> (ø)
...pentelemetry/sdk/metrics/DoubleSumObserverSdk.java 100.00% <ø> (ø)
...emetry/sdk/metrics/DoubleUpDownSumObserverSdk.java 100.00% <ø> (ø)
...opentelemetry/sdk/metrics/InstrumentProcessor.java 95.00% <ø> (ø)
.../opentelemetry/sdk/metrics/LongSumObserverSdk.java 100.00% <ø> (ø)
...elemetry/sdk/metrics/LongUpDownSumObserverSdk.java 100.00% <ø> (ø)
...io/opentelemetry/sdk/metrics/SdkMeterProvider.java 100.00% <ø> (ø)
...s/aggregator/AbstractMinMaxSumCountAggregator.java 100.00% <ø> (ø)
...entelemetry/sdk/metrics/aggregator/Aggregator.java 0.00% <ø> (ø)
... and 47 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 20f872d...0413b69. Read the comment docs.

Copy link
Contributor

@anuraaga anuraaga left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just nits, all-in-all looks good

*
* @param instrumentationName The name of the instrumentation library, not the name of the
* instrument*ed* library.
* @return a tracer instance.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😂

/** Returns an assertion for {@link DoubleHistogramPointData}. */
public static DoubleHistogramPointDataAssert assertThat(DoubleHistogramPointData point) {
return new DoubleHistogramPointDataAssert(point);
}

/** Returns an assertion for {@link DoubleSummaryPointData}. */
public static DoubleSummaryPointDataAssert assertThat(DoubleSummaryPointData point) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉

/**
* Adds the given {@code increment} to the current value.
* Records a value.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure this one makes sense to change. same with other add function comment change.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went for consistency across instruments here. There's an 'oddity' here where users can actually use aggregators to change what happens when recording values. E.g. by default this would add an increment to current value, but you can use a View to convert this to a histogram or other behavior, which is why I went with record a value consistently across instruments.


@Override
void unbind();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think all the unbind()s are going to need javadoc without the super interface.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added, copying previous javadoc. Kinda unhappy with both bind + unbind's documentation on why/how they exists.

Thinking about discussing how (theoretically) if you only use BOUND instruments you should never see memory allocations in the hot path of your applications as, AFAIK, this is a guarantee from the metrics SDK. However, this is just the API so that guarantee isn't assured, only possible. WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, we can't guarantee this in the API javadoc, unfortunately.

*
* @param callback A state-capturing callback used to observe values on-demand.
*/
void buildWithCallback(Consumer<ObservableDoubleMeasurement> callback);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here's the case with both sync and async in the same builder. :)

*
* <p>see {@link ObservableDoubleMeasurement} or {@link ObservableLongMeasurement}.
*/
public interface ObservableMeasurement {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with no methods and no types does this have enough value to keep?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It helped in the SDK implementation. I can remove it, but you don't see the code which uses this yet.

@jkwatson
Copy link
Contributor

jkwatson commented Aug 3, 2021

Just a few minor comments. Looks good! Thanks!

Copy link
Contributor

@jkwatson jkwatson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved, pending API discussion and a tiny capitalization nit.

@anuraaga
Copy link
Contributor

anuraaga commented Aug 5, 2021

@jkwatson I think it's ok to merge first and follow up on the API discussion given this is an alpha artifact and the PR is huge. What do you think?

@jkwatson
Copy link
Contributor

jkwatson commented Aug 5, 2021

@jkwatson I think it's ok to merge first and follow up on the API discussion given this is an alpha artifact and the PR is huge. What do you think?

This actually needs a rebase, since there have been additional API usages added since it was last rebased against main.

public static MeterBuilder meterBuilder(String instrumentationName) {
return get().meterBuilder(instrumentationName);
public static void set(MeterProvider provider) {
globalMeterProvider = (provider == null) ? NoopMeterProvider.getInstance() : provider;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Equating null = NoopMeterProvider.getInstance() is strange IMO.

I think this should return or throw if null is passed. Throwing is inconsistent with current behavior, so I say return.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Existing behavior is to return a Noop meter provider on "get" if the meter provider is null. This just short-circuits that on the set side. i.e this is not a behavioral change.

Additionally, this entire class will disappear once metrics stabilize.

*
* <p>TODO: Update comment.
* <p>A Meter is generally associated with an instrumentation library, e.g. "I monitor apache
* httpclient".
*/
@ThreadSafe
public interface Meter {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The async instruments are accessible via the buildWithCallback methods from the respective builders, rather than from the Meter.

Is this allowed according to the spec?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say so. You still get the builder via the Meter. The spec isn't supposed to precisely define the language-specific APIs, but the capabilities that must be provided.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was deemed a Java-specific deviation to abide by the common builder pattern in Java. I like the simplicity it acheived, but it is something we should discuss and can migrate to having separate builders by-async type instead of a builder per-metric-type and then having the async builder + sync builder coexist.

*
* @param callback A state-capturing callback used to observe values on-demand.
*/
void buildWithCallback(Consumer<ObservableLongMeasurement> callback);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to see "observable" somehow incorporated into the naming convention of methods that access async instruments. Its recommended in the spec and I think it better clarifies the async distinction than "callback".

Maybe buildObservable?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jkwatson @anuraaga for comment. This was a specific deviation to fit the java "builder" convention, so I defer to Java SiG here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The spec calls this an "observable" I think? In that case, probably migrating to that verbiage would be helpful. I don't want to hold up this PR for that change, though.

@jkwatson
Copy link
Contributor

jkwatson commented Aug 5, 2021

I'm going to merge this, so we can build from it. Thanks, @jsuereth !

@jkwatson jkwatson merged commit 0ef1929 into open-telemetry:main Aug 5, 2021
@jsuereth jsuereth deleted the wip-api-only-changes branch August 6, 2021 21:16
This was referenced Dec 19, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants