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

Adding MinMax to Histograms #2735

Merged
merged 164 commits into from
Oct 14, 2022
Merged

Adding MinMax to Histograms #2735

merged 164 commits into from
Oct 14, 2022

Conversation

mic-max
Copy link
Contributor

@mic-max mic-max commented Dec 8, 2021

Fixes #2560

Changes

Histograms will now record the minimum and maximum measurement values.

For significant contributions please make sure you have completed the following items:

  • Appropriate CHANGELOG.md updated for non-trivial changes
  • Design discussion issue #
  • Changes in public API reviewed

mic-max and others added 25 commits September 23, 2021 14:10
commit 080927d
Author: Cijo Thomas <cithomas@microsoft.com>
Date:   Thu Sep 23 10:07:05 2021 -0700

    Changelog update for 1.2.0.alpha4 (#2407)

commit 61aaf2e
Author: Reiley Yang <reyang@microsoft.com>
Date:   Thu Sep 23 09:37:18 2021 -0700

    Simplify tutorials (#2406)

commit 78baf7c
Author: Reiley Yang <reyang@microsoft.com>
Date:   Thu Sep 23 08:02:09 2021 -0700

    Implement the metrics dispose/shutdown logic (#2404)

commit 256fc2d
Author: Michael Maxwell <micmax@microsoft.com>
Date:   Wed Sep 22 17:35:15 2021 -0400

    Use `Stopwatch.StartNew()` (#2403)
…her.cs


yes thank you, good catch

Co-authored-by: Robert Pająk <pellared@hotmail.com>
@codecov
Copy link

codecov bot commented Dec 8, 2021

Codecov Report

Merging #2735 (a282844) into main (af7ab89) will decrease coverage by 0.42%.
The diff coverage is 76.59%.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #2735      +/-   ##
==========================================
- Coverage   87.35%   86.92%   -0.43%     
==========================================
  Files         277      278       +1     
  Lines       10068    10151      +83     
==========================================
+ Hits         8795     8824      +29     
- Misses       1273     1327      +54     
Impacted Files Coverage Δ
...ry/Metrics/ExplicitBucketHistogramConfiguration.cs 83.33% <ø> (+22.22%) ⬆️
src/OpenTelemetry/Metrics/MetricPoint.cs 75.00% <71.79%> (-8.00%) ⬇️
...tryProtocol/Implementation/MetricItemExtensions.cs 93.95% <100.00%> (+0.12%) ⬆️
src/OpenTelemetry/Metrics/HistogramBuckets.cs 100.00% <100.00%> (ø)
...rc/OpenTelemetry/Metrics/HistogramConfiguration.cs 100.00% <100.00%> (ø)
src/OpenTelemetry/Metrics/Metric.cs 95.50% <100.00%> (+1.12%) ⬆️
src/OpenTelemetry/Metrics/MetricReaderExt.cs 86.36% <100.00%> (+1.81%) ⬆️
src/OpenTelemetry/Metrics/MetricStreamIdentity.cs 90.62% <100.00%> (+0.62%) ⬆️
...entation/ExportClient/OtlpGrpcTraceExportClient.cs 35.71% <0.00%> (-42.86%) ⬇️
...xporter.OpenTelemetryProtocol/OtlpTraceExporter.cs 36.36% <0.00%> (-40.91%) ⬇️
... and 14 more

@cijothomas
Copy link
Member

#2718 changes the layout, so this will be affected.

@cijothomas
Copy link
Member

https://github.com/open-telemetry/opentelemetry-dotnet/pull/2705/files - need to bring this back as well. (it was reverted)

@cijothomas
Copy link
Member

@mic-max mic-max changed the title draft adding min and max to histogram Adding Min & Max to Histograms Dec 8, 2021
Copy link
Member

@cijothomas cijothomas left a comment

Choose a reason for hiding this comment

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

The PR looks good except for 2 things:

  1. MinMwx should be part of Identity. Must be fixed in this PR.
  2. Other exporters will break with this change. The fix is in other exporters, but blocking PR to prevent accidental merge until exporters are hotfixed. See https://github.com/open-telemetry/opentelemetry-dotnet/pull/2735/files#r989476122

@cijothomas
Copy link
Member

The PR looks good except for 2 things:

  1. MinMwx should be part of Identity. Must be fixed in this PR.
  2. Other exporters will break with this change. The fix is in other exporters, but blocking PR to prevent accidental merge until exporters are hotfixed. See https://github.com/open-telemetry/opentelemetry-dotnet/pull/2735/files#r989476122

if we keep the metric type same, then it wont break existing exporters. and can use Nan/Infinity to indicate lack of min/max

@@ -257,6 +257,18 @@ internal static OtlpMetrics.Metric ToOtlpMetric(this Metric metric)
dataPoint.Count = (ulong)metricPoint.GetHistogramCount();
dataPoint.Sum = metricPoint.GetHistogramSum();

var max = metricPoint.GetHistogramMax();
if (!double.IsNegativeInfinity(max))
Copy link
Member

Choose a reason for hiding this comment

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

double.IsNaN instead?

Copy link
Member

Choose a reason for hiding this comment

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

Would that work? Reading this

IsNaN returns false if a Double value is either PositiveInfinity or NegativeInfinity. To test for these values, use the IsInfinity, IsPositiveInfinity, and IsNegativeInfinity methods.

Copy link
Member

Choose a reason for hiding this comment

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

Though, I will admit that !double.IsNegativeInfinity(max) does hurt my 🧠 just a little. Maybe we should push the implementation details of negative/positive infinity meaning "unset" somewhere else.

Maybe something like

var maxIsSet = metricPoint.TryGetHistogramMax(out var max)

Copy link
Member

Choose a reason for hiding this comment

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

Another thought... would it ever be the case where max is set but min is not? Maybe it would be nicer for an exporter author to be able to write something like

if (metricPoint.HasMinMax()) // This new method does the negative/positive infinity check
{
    dataPoint.Min = metricPoint.GetHistogramMin();
    dataPoint.Max = metricPoint.GetHistogramMax();
}

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 liked the TryGetHistogramMax way so switched it to that.

Copy link
Member

Choose a reason for hiding this comment

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

would it ever be the case where max is set but min is not

^ I cannot think of such case. I like the HasMinMax() slightly better. TryGetHistogramMax/Min() is okay as well. Will unblock PR, and we can adjust if needed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well, I set the value of Max to -Inf and Min to +Inf at initialization. So, if you record a value of -Inf then the Min and Max will be set to -Inf and the TryGetHistogramMax would incorrectly return false. Maybe I could switch the initial values to double.NaN instead.

Copy link
Contributor Author

@mic-max mic-max Oct 12, 2022

Choose a reason for hiding this comment

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

Is recording an infinity value something we should support?
Setting max default to -Inf, allows double.MinValue to be returned in the first max = Math.max(curMax, double.MinValue) at least.

Math.Min(a, b) will return NaN when a == NaN || b == NaN which I am hoping to be able to use Math.Min directly without adding another if statement for perf reasons

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 think I will go with the HasMinMax way now after evaluating more carefully. It also seems like this is what Java did. It is complex to use just the current value to determine if a Min/Max is present :P

Copy link
Member

@alanwest alanwest Oct 13, 2022

Choose a reason for hiding this comment

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

Is recording an infinity value something we should support?

The spec address this:

Implementations SHOULD NOT incorporate non-normal values (i.e., +Inf, -Inf, and NaNs) into the sum, min, and max fields, because these values do not map into a valid bucket.

Edit: I guess this is specifically a statement as applied to the exponential histogram aggregation. That said, I think this should equally apply to explicit bounds as well. No one wants a single non-normal value measurement to blow up their min and max...

Copy link
Member

@cijothomas cijothomas left a comment

Choose a reason for hiding this comment

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

https://github.com/open-telemetry/opentelemetry-dotnet/pull/2735/files#r993773985
See the above.

Rest all looks good. We definitely need to add more tests for validation, esp. the delta/cumulate, and across multiple snapshots. But it can be a future PR.

@cijothomas cijothomas merged commit 8db45a3 into open-telemetry:main Oct 14, 2022
@cijothomas
Copy link
Member

Merging. @alanwest please take a final look and share any issues you see!

/// ensure a valid value is returned.
/// </summary>
/// <returns>A minimum and maximum value exist.</returns>
public bool HasMinMax()
Copy link
Member

Choose a reason for hiding this comment

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

@mic-max Should this be HasMinMaxHistogram or something like that? All the other histogram specific methods have it in their names so this one feels a bit off.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ya that's valid, we could change to HistogramHasMinMax maybe?
Please share any other nits I can take care of before inclusion in its initial release :)

Copy link
Member

Choose a reason for hiding this comment

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

the initial release train just left the station 🤣 . Lets include it in next beta. (its okay to break between betas)

Copy link
Member

Choose a reason for hiding this comment

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

HistogramHasMinMax works for me!

Please share any other nits I can take care of before inclusion in its initial release :)

I was going to suggest maybe folding it all into a single method like...

bool TryGetHistogramMinMaxValues(out double histogramMinimumValue, out double histogramMaximumValue)

That might be faster (probably needs inlining) with less API surface but not totally sure. Would need to measure it to see feel free to try if you are interested.

Copy link
Member

Choose a reason for hiding this comment

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

@cijothomas Hey I was just looking at this API as part of some other work. I think we should change it! Reason being, as it is right now...

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public double GetHistogramMin()
        {
            return this.histogramBuckets.SnapshotMin;
        }

...that is a NullRef just waiting to be thrown 🤣 All the other methods in here validate the type before accessing the value.

This would be much safer and have comparable perf...

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool TryGetHistogramMinMaxValues(out double histogramMinimumValue, out double histogramMaximumValue)
{
   if (this.aggType == AggregationType.HistogramMinMax ||
                   this.aggType == AggregationType.HistogramSumCountMinMax)
   {
      Debug.Assert(this.histogramBuckets != null, "histogramBuckets was null");

      histogramMinimumValue = this.histogramBuckets.SnapshotMin;
      histogramMaximumValue = this.histogramBuckets.SnapshotMax;
      return true;
   }

   histogramMinimumValue = 0;
   histogramMaximumValue = 0;
   return false;
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of returning true or false, could we follow the pattern used for other public methods in MetricPoint such as GetSumLong etc. of throwing a not supported metric type exception when called for a non-applicable metric type?

Copy link
Member

Choose a reason for hiding this comment

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

Works for me. The reason I have the "Try"/bool bit is because the existing API has a "HasMinMax" check before looking at the values. Not sure if there was a reason for that or not. One thing I think we should avoid is two calls (eg GetHistogramMin & GetHistogramMax) which each have to do the validation because that would suck for perf.

Copy link
Member

Choose a reason for hiding this comment

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

this is slightly different. Its possible to be histogram, but min/max is not there (as min max is optional).

@mic-max mic-max deleted the hist-min-max branch October 17, 2022 21:00
CodeBlanch added a commit that referenced this pull request Oct 24, 2022
* [Logs] Fix buffered log scopes being reused (#3731)

* Fix buffered log scopes being reused.

* CHANGELOG update.

* Test fixes.

Co-authored-by: Cijo Thomas <cithomas@microsoft.com>

* clarify that Prometheus HttpListner is not for production at this moment (#3737)

* [HttpClient] Export spans corresponding to retries (#3732)

* Minor update to OTLP readme (#3739)

* Nit fixes to prometheus readme

* Add minor clarification about OTLP logs

* Update workflow (#3741)

* Minor improvement to log message (#3742)

* [SDK + Jaeger] Support loading environment variables from IConfiguration in Traces & Metrics (#3720)

* Support retrieval of environment variables through IConfiguration in SDK.

* Update Jaeger to load environment variables through IConfiguration.

* Warning fix.

* CHANGELOG patch.

* Bug fixes.

* Warning cleanup.

* Code review.

* [Zipkin] Support loading envvars from IConfiguration (#3759)

* Support loading envvars from IConfiguration in Zipkin exporter.

* CHANGELOG patch.

* SqlClient Instrumentation to leverage native Activity Status. (#3751)

* [Metrics] Update default buckets for Explicit Bucket Histogram from spec (#3722)

* [Logs] Fix: Respect AttributeValueLengthLimit when building otlp LogRecord data (#3684)

* Respect SdkConfiguration.AttributeValueLengthLimit so otlp data points are not rejected by monitoring tools

* Respect maxAttributeCount and use OtlpKeyValueTransformer in AddStringAttribute and in AddIntAttribute

* Extend CHANGELOG.md

Co-authored-by: Mikel Blanchard <mblanchard@macrosssoftware.com>

* Bump actions/setup-dotnet from 3.0.1 to 3.0.2 (#3764)

Bumps [actions/setup-dotnet](https://github.com/actions/setup-dotnet) from 3.0.1 to 3.0.2.
- [Release notes](https://github.com/actions/setup-dotnet/releases)
- [Commits](actions/setup-dotnet@v3.0.1...v3.0.2)

---
updated-dependencies:
- dependency-name: actions/setup-dotnet
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* [Repo] Attempting to stabilize the API Compatibility CI job (#3766)

* Attempting to stablize the API Compatibility CI.

* Tweak.

* More logging.

* Increase build logging level for api compat ci job.

* Tweak.

* Tweak.

* Revert extra logging in ci job.

* Switched some logging back to debug.

* Adding MinMax to Histograms (#2735)

* Logging state during building of TracerProvider (#3746)

* [HttpClient] Add unit tests for `RecordException` case (#3761)

* Add a separate example project for Logs redaction (#3744)

* Update CHANGELOG for 1.4.0-beta.2 release (#3772)

* [SDK + Otlp] Support loading envvars from IConfiguration (#3760)

* Updated Otlp Trace & Metrics exporters to load envvars from IConfiguration.

* Patch CHANGELOGs.

* Fix up otlp log exporter for SdkOptions changes.

* Revert SdkOptions public api.

* Restore tests.

* Fix benchmarks.

* SdkLimitOptions IConfiguration test.

* OtlpExporterOptions IConfiguration test.

* MetricReaderOptions IConfiguration test.

* Bug fix.

* Nit.

* [SqlClient] Add support for Filter expression (#3743)

* [SDK, Jaeger, Zipkin, & Otlp] Support loading envvars for BatchExportActivityProcessorOptions from IConfiguration (#3776)

* Support loading envvars for ExportActivityProcessorOptions & BatchExportActivityProcessorOptions from IConfiguration.

* Update src/OpenTelemetry/CHANGELOG.md

Co-authored-by: Piotr Kiełkowicz <pkiekowicz@splunk.com>

* Patch CHANGELOG.

* Unit test.

Co-authored-by: Cijo Thomas <cithomas@microsoft.com>
Co-authored-by: Piotr Kiełkowicz <pkiekowicz@splunk.com>

* Remove Env from CI `DOTNET_MULTILEVEL_LOOKUP = 1` (#3779)

* Link to .NET docs about different ports (#3704)

* Update DS to rc2 (#3781)

* ConsoleLogExporter to output full exception (#3784)

* [ASP.NET Core] Add back netstandard2.0 and 2.1 targets (#3755)

* [HttpClient] Add back netstandard2.0 target (#3787)

* Add back netstandard2.0 target

* changelog

* public api files

* Bump System.Text.Json version due to CVE-2021-26701 (#3789)

* Auto-generated Semantic Conventions (#2069)

* [SDK] Support dependency injection in ResourceBuilder and load envvars from IConfiguration (#3782)

* Add Vishwesh as an Approver (#3783)

Co-authored-by: Cijo Thomas <cijo.thomas@gmail.com>

* Move more SDK docs to docs folder (#3794)

* [Prometheus AspNetCore] Support named options in pipeline extensions (#3780)

* Support named options in Prometheus AspNetCore pipeline extensions.

* Patch CHANGELOG.

Co-authored-by: Cijo Thomas <cijo.thomas@gmail.com>

* [Logs] UnitTest: LogRecord attribute limits (#3758)

* Unittest for LogRecord attribute limits

* Remove maxValueLength from LogRecordExtensions.AddIntAttribute.

Change requested from #3684 (comment)

* Pr commits addressed

Co-authored-by: Mikel Blanchard <mblanchard@macrosssoftware.com>

* Add MinMax to console and doc additions (#3795)

* Mark private and internal classes as sealed (#3799)

Co-authored-by: Cijo Thomas <cijo.thomas@gmail.com>

* Move more docs to docs folder (#3801)

* [ASP.NET Core] Update enrich callbacks to use specific type. (#3749)

* [Http] Update enrich callbacks for http (#3792)

* [SDK] Support dependency injection in the GetDefaultResource API (#3798)

* Support dependency injection in the GetDefaultResource API.

* CHANGELOG patch.

* Test tweaks.

Co-authored-by: Cijo Thomas <cijo.thomas@gmail.com>

* Fix circular reference issue building up tracer provider. (#3803)

* [SDK] Add some missing nullable annotations (#3796)

* Added some missing nullable annotations in SDK.

* Handle null span names in SamplingParameters.

* Warning cleanup.

* Warning cleanup.

* Added link to issue in comment.

Co-authored-by: Alan West <3676547+alanwest@users.noreply.github.com>

* Guard.Range now uses invariant culture for error message (#3778)

Co-authored-by: Utkarsh Umesan Pillai <utpilla@microsoft.com>

* Fix circular reference issue building up meter provider. (#3806)

Co-authored-by: Utkarsh Umesan Pillai <utpilla@microsoft.com>

* Add missing end of code block backticks (#3807)

* More doc tweaks (#3805)

* More doc tweaks

* remove draft staatus

* Update grpc client enrich callbacks (#3804)

* Port refactor from main-logs branch. (#3808)

Co-authored-by: Cijo Thomas <cijo.thomas@gmail.com>

* Merge fixes.

* Merge fixes.

* Merge fix.

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Cijo Thomas <cithomas@microsoft.com>
Co-authored-by: Reiley Yang <reyang@microsoft.com>
Co-authored-by: Vishwesh Bankwar <vishweshbankwar@users.noreply.github.com>
Co-authored-by: Cijo Thomas <cijo.thomas@gmail.com>
Co-authored-by: Yun-Ting Lin <yunl@microsoft.com>
Co-authored-by: Sebastian Schoder Moreno <35150382+schoder-moreno@users.noreply.github.com>
Co-authored-by: Jonathan Wilhelm <Jonathan.wilhelm@sage.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Michael Maxwell <micmax@microsoft.com>
Co-authored-by: ggoel <gaurav.goel111@gmail.com>
Co-authored-by: Utkarsh Umesan Pillai <utpilla@microsoft.com>
Co-authored-by: Pavel Steinl <pavel.steinl@gmail.com>
Co-authored-by: Piotr Kiełkowicz <pkiekowicz@splunk.com>
Co-authored-by: aristotelos <arisvd@gmail.com>
Co-authored-by: Joao Grassi <joao@joaograssi.com>
Co-authored-by: Alan West <3676547+alanwest@users.noreply.github.com>
Co-authored-by: benhall_io <3179852+benbhall@users.noreply.github.com>
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.

Histogram aggregation should support Min Max