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

Use generics for metric instrument API #3973

Closed
wants to merge 13 commits into from

Conversation

MrAlias
Copy link
Contributor

@MrAlias MrAlias commented Apr 6, 2023

This refactors the go.opentelemetry.io/otel/metric/instrument package to use generics for instruments and their configuration. Additionally, this adds benchmarks for the global metric implementation to ensure no performance regression.

This reverses the decision made in #2494 because of the following reasons:

  • The project is already not buildable with Go < 1.17 (due to newer API use by logr) and cannot be managed with go mod for any Go < 1.18
  • The upstream Go API already exports generic types
  • Generalizing the instrument package would cut all exported types/functionss in half
  • Merging Add options to measurement methods #3971 will mean that implementation cannot use a generic instrument implementation anymore unless the API is generalized

With #3971 planned to be merged, it will add 18 new configuration declarations if we do not generalize on the number type. It will only add 9 if we do.

Benchmarks

otel/sdk/metric

$ benchstat old.txt new.txt
name                                   old time/op    new time/op    delta
CounterAddNoAttrs-8                      41.7ns ± 4%    42.6ns ± 5%     ~     (p=0.066 n=10+10)
CounterAddOneAttr-8                       249ns ± 4%     255ns ± 8%     ~     (p=0.219 n=9+10)
CounterAddOneInvalidAttr-8                361ns ± 5%     362ns ± 4%     ~     (p=0.546 n=9+9)
CounterAddSingleUseAttrs-8                854ns ± 3%     854ns ± 3%     ~     (p=0.824 n=10+9)
CounterAddSingleUseInvalidAttrs-8        1.23µs ± 3%    1.24µs ± 4%     ~     (p=0.897 n=10+10)
CounterAddSingleUseFilteredAttrs-8       1.38µs ± 3%    1.38µs ± 2%     ~     (p=0.560 n=10+9)
CounterCollectOneAttr-8                   305ns ±12%     304ns ± 2%     ~     (p=0.549 n=10+9)
CounterCollectTenAttrs-8                 2.85µs ±12%    2.92µs ± 6%     ~     (p=0.105 n=10+10)
CollectHistograms/1-8                     413ns ± 2%     423ns ± 6%     ~     (p=0.139 n=9+10)
CollectHistograms/5-8                    1.80µs ± 5%    1.77µs ± 5%     ~     (p=0.211 n=10+9)
CollectHistograms/10-8                   3.49µs ± 9%    3.59µs ± 7%     ~     (p=0.143 n=10+10)
CollectHistograms/25-8                   8.46µs ± 6%    8.53µs ± 3%     ~     (p=0.248 n=9+9)
Instrument/instrumentImpl/aggregate-8    3.69µs ±16%    3.75µs ±16%     ~     (p=0.724 n=10+10)
Instrument/observable/observe-8          3.58µs ±14%    3.68µs ±15%     ~     (p=0.436 n=10+10)
ManualReader/Collect-8                   1.21µs ± 1%    1.23µs ± 2%   +1.54%  (p=0.012 n=10+10)
InstrumentCreation-8                     8.03µs ± 3%    7.68µs ± 4%   -4.31%  (p=0.006 n=9+10)
PeriodicReader/Collect-8                 1.25µs ± 2%    1.27µs ± 2%   +1.75%  (p=0.004 n=10+8)

name                                   old alloc/op   new alloc/op   delta
CounterAddNoAttrs-8                       0.00B          0.00B          ~     (all equal)
CounterAddOneAttr-8                        128B ± 0%      128B ± 0%     ~     (all equal)
CounterAddOneInvalidAttr-8                 256B ± 0%      256B ± 0%     ~     (all equal)
CounterAddSingleUseAttrs-8                 227B ± 1%      227B ± 1%     ~     (p=0.899 n=10+9)
CounterAddSingleUseInvalidAttrs-8          379B ± 0%      379B ± 0%     ~     (all equal)
CounterAddSingleUseFilteredAttrs-8         571B ± 0%      571B ± 0%     ~     (all equal)
CounterCollectOneAttr-8                    144B ± 0%      144B ± 0%     ~     (all equal)
CounterCollectTenAttrs-8                 1.30kB ± 0%    1.30kB ± 0%     ~     (all equal)
CollectHistograms/1-8                      480B ± 0%      480B ± 0%     ~     (all equal)
CollectHistograms/5-8                    2.40kB ± 0%    2.40kB ± 0%     ~     (all equal)
CollectHistograms/10-8                   4.80kB ± 0%    4.80kB ± 0%     ~     (all equal)
CollectHistograms/25-8                   12.0kB ± 0%    12.0kB ± 0%     ~     (all equal)
Instrument/instrumentImpl/aggregate-8      868B ±20%      916B ± 6%     ~     (p=0.811 n=10+8)
Instrument/observable/observe-8            838B ±17%      833B ±17%     ~     (p=0.517 n=10+10)
ManualReader/Collect-8                     160B ± 0%      160B ± 0%     ~     (all equal)
InstrumentCreation-8                     3.19kB ± 0%    2.71kB ± 0%  -15.07%  (p=0.000 n=10+10)
PeriodicReader/Collect-8                   160B ± 0%      160B ± 0%     ~     (all equal)

name                                   old allocs/op  new allocs/op  delta
CounterAddNoAttrs-8                        0.00           0.00          ~     (all equal)
CounterAddOneAttr-8                        2.00 ± 0%      2.00 ± 0%     ~     (all equal)
CounterAddOneInvalidAttr-8                 2.00 ± 0%      2.00 ± 0%     ~     (all equal)
CounterAddSingleUseAttrs-8                 2.00 ± 0%      2.00 ± 0%     ~     (all equal)
CounterAddSingleUseInvalidAttrs-8          2.00 ± 0%      2.00 ± 0%     ~     (all equal)
CounterAddSingleUseFilteredAttrs-8         4.00 ± 0%      4.00 ± 0%     ~     (all equal)
CounterCollectOneAttr-8                    3.00 ± 0%      3.00 ± 0%     ~     (all equal)
CounterCollectTenAttrs-8                   21.0 ± 0%      21.0 ± 0%     ~     (all equal)
CollectHistograms/1-8                      4.00 ± 0%      4.00 ± 0%     ~     (all equal)
CollectHistograms/5-8                      20.0 ± 0%      20.0 ± 0%     ~     (all equal)
CollectHistograms/10-8                     40.0 ± 0%      40.0 ± 0%     ~     (all equal)
CollectHistograms/25-8                      100 ± 0%       100 ± 0%     ~     (all equal)
Instrument/instrumentImpl/aggregate-8      2.00 ± 0%      2.00 ± 0%     ~     (all equal)
Instrument/observable/observe-8            2.00 ± 0%      2.00 ± 0%     ~     (all equal)
ManualReader/Collect-8                     5.00 ± 0%      5.00 ± 0%     ~     (all equal)
InstrumentCreation-8                       70.0 ± 0%      64.0 ± 0%   -8.57%  (p=0.000 n=10+10)
PeriodicReader/Collect-8                   5.00 ± 0%      5.00 ± 0%     ~     (all equal)

otel/internal/global

$ benchstat old.txt new.txt
name                                                                  old time/op    new time/op    delta
MetricMeter/GetDefault-8                                                35.4ns ± 2%    34.9ns ± 1%   ~     (p=0.200 n=3+3)
MetricMeter/UseDefault/CreateInt64Counter-8                              182ns ±40%     150ns ± 8%   ~     (p=1.000 n=3+3)
MetricMeter/UseDefault/CreateInt64UpDownCounter-8                        157ns ± 8%     143ns ± 3%   ~     (p=0.100 n=3+3)
MetricMeter/UseDefault/CreateInt64Histogram-8                            159ns ± 4%     160ns ±10%   ~     (p=1.000 n=3+3)
MetricMeter/UseDefault/CreateInt64ObservableCounter-8                    172ns ± 4%     171ns ±14%   ~     (p=1.000 n=3+3)
MetricMeter/UseDefault/CreateInt64ObservableUpDownCounter-8              180ns ± 4%     180ns ±11%   ~     (p=1.000 n=3+3)
MetricMeter/UseDefault/CreateInt64ObservableGauge-8                      182ns ± 4%     182ns ± 7%   ~     (p=0.700 n=3+3)
MetricMeter/UseDefault/CreateFloat64Counter-8                            173ns ± 8%     189ns ±16%   ~     (p=0.800 n=3+3)
MetricMeter/UseDefault/CreateFloat64UpDownCounter-8                      160ns ± 4%     170ns ±11%   ~     (p=1.000 n=3+3)
MetricMeter/UseDefault/CreateFloat64Histogram-8                          165ns ± 3%     167ns ± 7%   ~     (p=1.000 n=3+3)
MetricMeter/UseDefault/CreateFloat64ObservableCounter-8                  179ns ± 7%     184ns ± 2%   ~     (p=0.700 n=3+3)
MetricMeter/UseDefault/CreateFloat64ObservableUpDownCounter-8            172ns ± 9%     172ns ± 5%   ~     (p=1.000 n=3+3)
MetricMeter/UseDefault/CreateFloat64ObservableGauge-8                    174ns ± 5%     171ns ± 6%   ~     (p=1.000 n=3+3)
MetricMeter/UseDefault/RegisterCallback-8                                919ns ±24%     495ns ±33%   ~     (p=0.100 n=3+3)
MetricMeter/GetDelegated-8                                              40.8ns ± 4%    42.4ns ± 2%   ~     (p=0.200 n=3+3)
MetricMeter/UseDelegated/CreateInt64Counter-8                           77.3ns ± 6%    74.8ns ± 0%   ~     (p=0.700 n=3+3)
MetricMeter/UseDelegated/CreateInt64UpDownCounter-8                     74.8ns ± 1%    74.4ns ± 2%   ~     (p=1.000 n=3+3)
MetricMeter/UseDelegated/CreateInt64Histogram-8                         76.0ns ± 4%    76.6ns ± 1%   ~     (p=1.000 n=3+3)
MetricMeter/UseDelegated/CreateInt64ObservableCounter-8                 75.4ns ± 1%    77.2ns ± 1%   ~     (p=0.100 n=3+3)
MetricMeter/UseDelegated/CreateInt64ObservableUpDownCounter-8           74.5ns ± 3%    77.9ns ± 3%   ~     (p=0.200 n=3+3)
MetricMeter/UseDelegated/CreateInt64ObservableGauge-8                   78.3ns ± 1%    75.9ns ± 2%   ~     (p=0.200 n=3+3)
MetricMeter/UseDelegated/CreateFloat64Counter-8                         81.0ns ± 9%    72.8ns ± 2%   ~     (p=0.100 n=3+3)
MetricMeter/UseDelegated/CreateFloat64UpDownCounter-8                   76.8ns ± 6%    74.8ns ± 2%   ~     (p=0.700 n=3+3)
MetricMeter/UseDelegated/CreateFloat64Histogram-8                       77.2ns ± 8%    73.4ns ± 1%   ~     (p=0.700 n=3+3)
MetricMeter/UseDelegated/CreateFloat64ObservableCounter-8               79.6ns ± 2%    79.0ns ± 5%   ~     (p=1.000 n=3+3)
MetricMeter/UseDelegated/CreateFloat64ObservableUpDownCounter-8         81.9ns ± 5%    77.1ns ± 4%   ~     (p=0.200 n=3+3)
MetricMeter/UseDelegated/CreateFloat64ObservableGauge-8                 78.5ns ± 8%    78.0ns ± 2%   ~     (p=0.700 n=3+3)
MetricMeter/UseDelegated/RegisterCallback-8                              128ns ± 3%     137ns ± 3%   ~     (p=0.100 n=3+3)
MetricMeter/SetDelegate-8                                                225ns ± 4%     228ns ± 4%   ~     (p=1.000 n=3+3)
MetricInstruments/Default/Int64Counter.Add-8                            3.72ns ± 3%    5.29ns ± 1%   ~     (p=0.100 n=3+3)
MetricInstruments/Default/Int64UpDownCounter.Add-8                      3.58ns ± 1%    4.96ns ± 0%   ~     (p=0.100 n=3+3)
MetricInstruments/Default/Int64Histogram.Record-8                       3.46ns ± 2%    4.98ns ± 2%   ~     (p=0.100 n=3+3)
MetricInstruments/Default/Int64ObservableCounter.Observe-8              7.54ns ± 3%    7.62ns ± 4%   ~     (p=1.000 n=3+3)
MetricInstruments/Default/Int64ObservableUpDownCounter.Observe-8        8.13ns ± 4%    7.00ns ± 1%   ~     (p=0.100 n=3+3)
MetricInstruments/Default/Int64ObservableGauge.Observe-8                7.85ns ± 2%    7.53ns ± 4%   ~     (p=0.200 n=3+3)
MetricInstruments/Default/Float64Counter.Add-8                          3.43ns ± 1%    4.97ns ± 4%   ~     (p=0.100 n=3+3)
MetricInstruments/Default/Float64UpDownCounter.Add-8                    3.54ns ± 4%    4.97ns ± 0%   ~     (p=0.100 n=3+3)
MetricInstruments/Default/Float64Histogram.Record-8                     3.40ns ± 0%    4.95ns ± 4%   ~     (p=0.100 n=3+3)
MetricInstruments/Default/Float64ObservableCounter.Observe-8            8.82ns ± 1%    6.91ns ± 4%   ~     (p=0.100 n=3+3)
MetricInstruments/Default/Float64ObservableUpDownCounter.Observe-8      8.06ns ± 4%    7.07ns ± 4%   ~     (p=0.100 n=3+3)
MetricInstruments/Default/Float64ObservableGauge.Observe-8              8.12ns ± 3%    7.44ns ± 2%   ~     (p=0.100 n=3+3)
MetricInstruments/Delegated/Int64Counter.Add-8                          2.18ns ± 2%    2.25ns ± 4%   ~     (p=0.400 n=3+3)
MetricInstruments/Delegated/Int64UpDownCounter.Add-8                    2.18ns ± 2%    2.16ns ± 3%   ~     (p=0.500 n=3+3)
MetricInstruments/Delegated/Int64Histogram.Record-8                     2.25ns ± 4%    2.21ns ± 4%   ~     (p=1.000 n=3+3)
MetricInstruments/Delegated/Int64ObservableCounter.Observe-8            7.47ns ± 3%    9.11ns ± 3%   ~     (p=0.100 n=3+3)
MetricInstruments/Delegated/Int64ObservableUpDownCounter.Observe-8      9.31ns ± 3%    8.48ns ± 4%   ~     (p=0.100 n=3+3)
MetricInstruments/Delegated/Int64ObservableGauge.Observe-8              7.82ns ± 2%    7.45ns ± 4%   ~     (p=0.200 n=3+3)
MetricInstruments/Delegated/Float64Counter.Add-8                        2.22ns ± 3%    2.18ns ± 2%   ~     (p=0.400 n=3+3)
MetricInstruments/Delegated/Float64UpDownCounter.Add-8                  2.17ns ± 1%    2.18ns ± 0%   ~     (p=0.700 n=3+3)
MetricInstruments/Delegated/Float64Histogram.Record-8                   2.22ns ± 4%    2.26ns ± 5%   ~     (p=0.400 n=3+3)
MetricInstruments/Delegated/Float64ObservableCounter.Observe-8          8.01ns ± 4%    6.99ns ± 4%   ~     (p=0.100 n=3+3)
MetricInstruments/Delegated/Float64ObservableUpDownCounter.Observe-8    7.44ns ± 1%    7.51ns ± 4%   ~     (p=1.000 n=3+3)
MetricInstruments/Delegated/Float64ObservableGauge.Observe-8            8.52ns ± 1%    6.94ns ± 4%   ~     (p=0.100 n=3+3)

name                                                                  old alloc/op   new alloc/op   delta
MetricMeter/GetDefault-8                                                 0.00B          0.00B        ~     (all equal)
MetricMeter/UseDefault/CreateInt64Counter-8                               181B ± 4%      179B ± 2%   ~     (p=0.700 n=3+3)
MetricMeter/UseDefault/CreateInt64UpDownCounter-8                         178B ± 5%      176B ± 5%   ~     (p=0.700 n=3+3)
MetricMeter/UseDefault/CreateInt64Histogram-8                             175B ± 4%      178B ± 5%   ~     (p=0.500 n=3+3)
MetricMeter/UseDefault/CreateInt64ObservableCounter-8                     195B ± 4%      191B ± 4%   ~     (p=0.700 n=3+3)
MetricMeter/UseDefault/CreateInt64ObservableUpDownCounter-8               191B ± 3%      197B ± 3%   ~     (p=0.400 n=3+3)
MetricMeter/UseDefault/CreateInt64ObservableGauge-8                       191B ± 5%      192B ± 4%   ~     (p=1.000 n=3+3)
MetricMeter/UseDefault/CreateFloat64Counter-8                             176B ± 1%      179B ± 4%   ~     (p=0.800 n=3+3)
MetricMeter/UseDefault/CreateFloat64UpDownCounter-8                       172B ± 2%      176B ± 0%   ~     (p=0.400 n=3+3)
MetricMeter/UseDefault/CreateFloat64Histogram-8                           176B ± 3%      176B ± 4%   ~     (p=1.000 n=3+3)
MetricMeter/UseDefault/CreateFloat64ObservableCounter-8                   191B ± 4%      193B ± 5%   ~     (p=1.000 n=3+3)
MetricMeter/UseDefault/CreateFloat64ObservableUpDownCounter-8             191B ± 6%      192B ± 4%   ~     (p=1.000 n=3+3)
MetricMeter/UseDefault/CreateFloat64ObservableGauge-8                     191B ± 4%      193B ± 3%   ~     (p=0.800 n=3+3)
MetricMeter/UseDefault/RegisterCallback-8                                 232B ± 0%      232B ± 0%   ~     (all equal)
MetricMeter/GetDelegated-8                                               16.0B ± 0%     16.0B ± 0%   ~     (all equal)
MetricMeter/UseDelegated/CreateInt64Counter-8                            23.0B ± 0%     23.0B ± 0%   ~     (all equal)
MetricMeter/UseDelegated/CreateInt64UpDownCounter-8                      23.0B ± 0%     23.0B ± 0%   ~     (all equal)
MetricMeter/UseDelegated/CreateInt64Histogram-8                          23.0B ± 0%     23.0B ± 0%   ~     (all equal)
MetricMeter/UseDelegated/CreateInt64ObservableCounter-8                  39.0B ± 0%     39.0B ± 0%   ~     (all equal)
MetricMeter/UseDelegated/CreateInt64ObservableUpDownCounter-8            39.0B ± 0%     39.0B ± 0%   ~     (all equal)
MetricMeter/UseDelegated/CreateInt64ObservableGauge-8                    39.0B ± 0%     39.0B ± 0%   ~     (all equal)
MetricMeter/UseDelegated/CreateFloat64Counter-8                          23.0B ± 0%     23.0B ± 0%   ~     (all equal)
MetricMeter/UseDelegated/CreateFloat64UpDownCounter-8                    23.0B ± 0%     23.0B ± 0%   ~     (all equal)
MetricMeter/UseDelegated/CreateFloat64Histogram-8                        23.0B ± 0%     23.0B ± 0%   ~     (all equal)
MetricMeter/UseDelegated/CreateFloat64ObservableCounter-8                39.0B ± 0%     39.0B ± 0%   ~     (all equal)
MetricMeter/UseDelegated/CreateFloat64ObservableUpDownCounter-8          39.0B ± 0%     39.0B ± 0%   ~     (all equal)
MetricMeter/UseDelegated/CreateFloat64ObservableGauge-8                  39.0B ± 0%     39.0B ± 0%   ~     (all equal)
MetricMeter/UseDelegated/RegisterCallback-8                               112B ± 0%      112B ± 0%   ~     (all equal)
MetricMeter/SetDelegate-8                                                 112B ± 0%      112B ± 0%   ~     (all equal)
MetricInstruments/Default/Int64Counter.Add-8                             0.00B          0.00B        ~     (all equal)
MetricInstruments/Default/Int64UpDownCounter.Add-8                       0.00B          0.00B        ~     (all equal)
MetricInstruments/Default/Int64Histogram.Record-8                        0.00B          0.00B        ~     (all equal)
MetricInstruments/Default/Int64ObservableCounter.Observe-8               0.00B          0.00B        ~     (all equal)
MetricInstruments/Default/Int64ObservableUpDownCounter.Observe-8         0.00B          0.00B        ~     (all equal)
MetricInstruments/Default/Int64ObservableGauge.Observe-8                 0.00B          0.00B        ~     (all equal)
MetricInstruments/Default/Float64Counter.Add-8                           0.00B          0.00B        ~     (all equal)
MetricInstruments/Default/Float64UpDownCounter.Add-8                     0.00B          0.00B        ~     (all equal)
MetricInstruments/Default/Float64Histogram.Record-8                      0.00B          0.00B        ~     (all equal)
MetricInstruments/Default/Float64ObservableCounter.Observe-8             0.00B          0.00B        ~     (all equal)
MetricInstruments/Default/Float64ObservableUpDownCounter.Observe-8       0.00B          0.00B        ~     (all equal)
MetricInstruments/Default/Float64ObservableGauge.Observe-8               0.00B          0.00B        ~     (all equal)
MetricInstruments/Delegated/Int64Counter.Add-8                           0.00B          0.00B        ~     (all equal)
MetricInstruments/Delegated/Int64UpDownCounter.Add-8                     0.00B          0.00B        ~     (all equal)
MetricInstruments/Delegated/Int64Histogram.Record-8                      0.00B          0.00B        ~     (all equal)
MetricInstruments/Delegated/Int64ObservableCounter.Observe-8             0.00B          0.00B        ~     (all equal)
MetricInstruments/Delegated/Int64ObservableUpDownCounter.Observe-8       0.00B          0.00B        ~     (all equal)
MetricInstruments/Delegated/Int64ObservableGauge.Observe-8               0.00B          0.00B        ~     (all equal)
MetricInstruments/Delegated/Float64Counter.Add-8                         0.00B          0.00B        ~     (all equal)
MetricInstruments/Delegated/Float64UpDownCounter.Add-8                   0.00B          0.00B        ~     (all equal)
MetricInstruments/Delegated/Float64Histogram.Record-8                    0.00B          0.00B        ~     (all equal)
MetricInstruments/Delegated/Float64ObservableCounter.Observe-8           0.00B          0.00B        ~     (all equal)
MetricInstruments/Delegated/Float64ObservableUpDownCounter.Observe-8     0.00B          0.00B        ~     (all equal)
MetricInstruments/Delegated/Float64ObservableGauge.Observe-8             0.00B          0.00B        ~     (all equal)

name                                                                  old allocs/op  new allocs/op  delta
MetricMeter/GetDefault-8                                                  0.00           0.00        ~     (all equal)
MetricMeter/UseDefault/CreateInt64Counter-8                               1.00 ± 0%      1.00 ± 0%   ~     (all equal)
MetricMeter/UseDefault/CreateInt64UpDownCounter-8                         1.00 ± 0%      1.00 ± 0%   ~     (all equal)
MetricMeter/UseDefault/CreateInt64Histogram-8                             1.00 ± 0%      1.00 ± 0%   ~     (all equal)
MetricMeter/UseDefault/CreateInt64ObservableCounter-8                     1.00 ± 0%      1.00 ± 0%   ~     (all equal)
MetricMeter/UseDefault/CreateInt64ObservableUpDownCounter-8               1.00 ± 0%      1.00 ± 0%   ~     (all equal)
MetricMeter/UseDefault/CreateInt64ObservableGauge-8                       1.00 ± 0%      1.00 ± 0%   ~     (all equal)
MetricMeter/UseDefault/CreateFloat64Counter-8                             1.00 ± 0%      1.00 ± 0%   ~     (all equal)
MetricMeter/UseDefault/CreateFloat64UpDownCounter-8                       1.00 ± 0%      1.00 ± 0%   ~     (all equal)
MetricMeter/UseDefault/CreateFloat64Histogram-8                           1.00 ± 0%      1.00 ± 0%   ~     (all equal)
MetricMeter/UseDefault/CreateFloat64ObservableCounter-8                   1.00 ± 0%      1.00 ± 0%   ~     (all equal)
MetricMeter/UseDefault/CreateFloat64ObservableUpDownCounter-8             1.00 ± 0%      1.00 ± 0%   ~     (all equal)
MetricMeter/UseDefault/CreateFloat64ObservableGauge-8                     1.00 ± 0%      1.00 ± 0%   ~     (all equal)
MetricMeter/UseDefault/RegisterCallback-8                                 4.00 ± 0%      4.00 ± 0%   ~     (all equal)
MetricMeter/GetDelegated-8                                                1.00 ± 0%      1.00 ± 0%   ~     (all equal)
MetricMeter/UseDelegated/CreateInt64Counter-8                             1.00 ± 0%      1.00 ± 0%   ~     (all equal)
MetricMeter/UseDelegated/CreateInt64UpDownCounter-8                       1.00 ± 0%      1.00 ± 0%   ~     (all equal)
MetricMeter/UseDelegated/CreateInt64Histogram-8                           1.00 ± 0%      1.00 ± 0%   ~     (all equal)
MetricMeter/UseDelegated/CreateInt64ObservableCounter-8                   1.00 ± 0%      1.00 ± 0%   ~     (all equal)
MetricMeter/UseDelegated/CreateInt64ObservableUpDownCounter-8             1.00 ± 0%      1.00 ± 0%   ~     (all equal)
MetricMeter/UseDelegated/CreateInt64ObservableGauge-8                     1.00 ± 0%      1.00 ± 0%   ~     (all equal)
MetricMeter/UseDelegated/CreateFloat64Counter-8                           1.00 ± 0%      1.00 ± 0%   ~     (all equal)
MetricMeter/UseDelegated/CreateFloat64UpDownCounter-8                     1.00 ± 0%      1.00 ± 0%   ~     (all equal)
MetricMeter/UseDelegated/CreateFloat64Histogram-8                         1.00 ± 0%      1.00 ± 0%   ~     (all equal)
MetricMeter/UseDelegated/CreateFloat64ObservableCounter-8                 1.00 ± 0%      1.00 ± 0%   ~     (all equal)
MetricMeter/UseDelegated/CreateFloat64ObservableUpDownCounter-8           1.00 ± 0%      1.00 ± 0%   ~     (all equal)
MetricMeter/UseDelegated/CreateFloat64ObservableGauge-8                   1.00 ± 0%      1.00 ± 0%   ~     (all equal)
MetricMeter/UseDelegated/RegisterCallback-8                               2.00 ± 0%      2.00 ± 0%   ~     (all equal)
MetricMeter/SetDelegate-8                                                 5.00 ± 0%      5.00 ± 0%   ~     (all equal)
MetricInstruments/Default/Int64Counter.Add-8                              0.00           0.00        ~     (all equal)
MetricInstruments/Default/Int64UpDownCounter.Add-8                        0.00           0.00        ~     (all equal)
MetricInstruments/Default/Int64Histogram.Record-8                         0.00           0.00        ~     (all equal)
MetricInstruments/Default/Int64ObservableCounter.Observe-8                0.00           0.00        ~     (all equal)
MetricInstruments/Default/Int64ObservableUpDownCounter.Observe-8          0.00           0.00        ~     (all equal)
MetricInstruments/Default/Int64ObservableGauge.Observe-8                  0.00           0.00        ~     (all equal)
MetricInstruments/Default/Float64Counter.Add-8                            0.00           0.00        ~     (all equal)
MetricInstruments/Default/Float64UpDownCounter.Add-8                      0.00           0.00        ~     (all equal)
MetricInstruments/Default/Float64Histogram.Record-8                       0.00           0.00        ~     (all equal)
MetricInstruments/Default/Float64ObservableCounter.Observe-8              0.00           0.00        ~     (all equal)
MetricInstruments/Default/Float64ObservableUpDownCounter.Observe-8        0.00           0.00        ~     (all equal)
MetricInstruments/Default/Float64ObservableGauge.Observe-8                0.00           0.00        ~     (all equal)
MetricInstruments/Delegated/Int64Counter.Add-8                            0.00           0.00        ~     (all equal)
MetricInstruments/Delegated/Int64UpDownCounter.Add-8                      0.00           0.00        ~     (all equal)
MetricInstruments/Delegated/Int64Histogram.Record-8                       0.00           0.00        ~     (all equal)
MetricInstruments/Delegated/Int64ObservableCounter.Observe-8              0.00           0.00        ~     (all equal)
MetricInstruments/Delegated/Int64ObservableUpDownCounter.Observe-8        0.00           0.00        ~     (all equal)
MetricInstruments/Delegated/Int64ObservableGauge.Observe-8                0.00           0.00        ~     (all equal)
MetricInstruments/Delegated/Float64Counter.Add-8                          0.00           0.00        ~     (all equal)
MetricInstruments/Delegated/Float64UpDownCounter.Add-8                    0.00           0.00        ~     (all equal)
MetricInstruments/Delegated/Float64Histogram.Record-8                     0.00           0.00        ~     (all equal)
MetricInstruments/Delegated/Float64ObservableCounter.Observe-8            0.00           0.00        ~     (all equal)
MetricInstruments/Delegated/Float64ObservableUpDownCounter.Observe-8      0.00           0.00        ~     (all equal)
MetricInstruments/Delegated/Float64ObservableGauge.Observe-8              0.00           0.00        ~     (all equal)

@MrAlias MrAlias changed the title PoC using generics for instrument API Use generics for metric instrument API Apr 7, 2023
@codecov
Copy link

codecov bot commented Apr 7, 2023

Codecov Report

Merging #3973 (a528dbd) into main (1b97d78) will increase coverage by 0.0%.
The diff coverage is 97.3%.

Additional details and impacted files

Impacted file tree graph

@@          Coverage Diff           @@
##            main   #3973    +/-   ##
======================================
  Coverage   82.1%   82.1%            
======================================
  Files        174     172     -2     
  Lines      12975   12758   -217     
======================================
- Hits       10655   10482   -173     
+ Misses      2100    2067    -33     
+ Partials     220     209    -11     
Impacted Files Coverage Δ
sdk/metric/instrument.go 95.5% <ø> (-0.5%) ⬇️
internal/global/meter.go 92.7% <91.8%> (-1.2%) ⬇️
sdk/metric/meter.go 88.8% <95.8%> (-0.8%) ⬇️
internal/global/instruments.go 88.8% <100.0%> (+28.0%) ⬆️
metric/instrument/async.go 100.0% <100.0%> (ø)
metric/instrument/instrument.go 100.0% <100.0%> (ø)
metric/instrument/sync.go 100.0% <100.0%> (ø)
metric/noop/noop.go 100.0% <100.0%> (ø)

... and 1 file with indirect coverage changes

@MrAlias MrAlias marked this pull request as draft April 7, 2023 17:12
@MrAlias MrAlias marked this pull request as ready for review April 7, 2023 21:21
Comment on lines +39 to +42
type CounterConfig[N int64 | float64] struct {
description string
unit string
}
Copy link
Member

Choose a reason for hiding this comment

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

Do you need config per record type? A.k.a what about CounterConfig not having the generic type.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The Observable configs need to be split on number type given the callback from WithCallback is defined by number. It was done for all the configurations to provide consistency, but also to ensure the forward compatibility with OTel if they decide in the future to add options that are defined by number.

Copy link
Member

Choose a reason for hiding this comment

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

Not sure I understand the "but also to ensure the forward compatibility with OTel if they decide in the future to add options that are defined by number." unless the capability is exactly the same but the implementation differs by the number type (which I believe you can solve at the construction time) I am failing to understand this benefit, maybe an example would be good.

For WithCallback is only for async, and you can do a runtime error during construction if you want by keeping the WithCallback generic and return a non generic Option and validate the type during construction (meter.NewFoo).

Comment on lines +145 to +147
ObserveFloat64(obsrv instrument.ObservableT[float64], value float64, attributes ...attribute.KeyValue)
// ObserveInt64 records the int64 value with attributes for obsrv.
ObserveInt64(obsrv instrument.Int64Observable, value int64, attributes ...attribute.KeyValue)
ObserveInt64(obsrv instrument.ObservableT[int64], value int64, attributes ...attribute.KeyValue)
Copy link
Member

Choose a reason for hiding this comment

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

Not clear what advantage has this design where you ask users to call this vs asking users to call "Observe" on the ObservableT directly, since they have to have the ObservableT instances when registering the callback.

If we do that, we don't need ObservableT to be public anymore.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The types implementing ObservableT do not have and Observe method anymore. This was a follow up to a decision to refactor the RegisterCallback API so it can provide the guarantees the specification recommends and requires.

The other way of allowing users to directly call Observe did not clearly restrict when they can call it and therefore provided potential for unintentional bugs from the user. It also wasn't a design we could make compliant with the specification given we couldn't completely restrict that method to only be called in a callback registered with the instrument.

Copy link
Member

Choose a reason for hiding this comment

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

I missed the Observe removing part, was familiar with Java where they have that. Makes sense then the overall design, just make sure you are allowed to extend the Callback interface to allow recording more "types" in the future.

@MrAlias
Copy link
Contributor Author

MrAlias commented Apr 10, 2023

I could be helpful to users if we deprecate the old types (as type aliases) for a release.

@MadVikingGod
Copy link
Contributor

If #3971 does get merged, will there be a follow-up to genericitize the options?

@MrAlias
Copy link
Contributor Author

MrAlias commented Apr 11, 2023

If #3971 does get merged, will there be a follow-up to genericitize the options?

Yeah that was my plan 👍

(I'm already buckled in and ready for the merge conflict pain 😉).

@MrAlias
Copy link
Contributor Author

MrAlias commented Apr 11, 2023

Two things from conversations IRL about this PR:

  1. The WithUnit[N] and WithDescription[N] options are not ideal. They are defined on a type that will never apply to their output.
    • An alternative approach could be to keep the instrument options/configuration non-generic.
      • This means WithUnit and WithDescription will "make sense", but With{Int,Float}64Callback will still need to be two functions
      • It might make sense, if this approach is taken, to move the instrument options/configuration to the otel/sdk/metric package. That is only place these types are used and it would follow suit with the Meter interface that remains non-generic.
  2. Adding a generic parameter means if we in the future extend that parameter it will not be a backwards compatible change for SDKs. It will be similar to our approach of adding methods to interfaces but it is not something we currently call out in our versioning and compatibility policy.

@pellared
Copy link
Member

The project is already not buildable with Go < 1.17 (due to newer API use by logr) and cannot be managed with go mod for any Go < 1.18

  1. As far as I see logr supports >= Go 1.15 and go.mod says go 1.16.
  2. Going with generics for API would make it impossible to build an API implementation for Go < 1.18. If we don't use generics the API could still be used for unsupported versions of Go. It may be a good scenario for automatic instrumentation.

Initially, I was leaning towards having generics in both API and SDK. However, right now I start to hesitate. I got a feeling that when I see generics in SDK the generics just make the things "more concrete" and remove noise in docs and API. While in the API it makes another layer of abstraction which makes it harder for me to reason about the API (e.g. #3973 (comment)).

I am sorry that my comment is so unprecise. I decided to leave some comment at this point rather than not leaving any feedback at all.

@MrAlias
Copy link
Contributor Author

MrAlias commented Apr 13, 2023

I'm leaning towards closing this PR.

  1. The WithUnit[N] and WithDescription[N] options are not ideal. They are defined on a type that will never apply to their output.

Base on this, using generics only seems like a half-way "good fit" for the configuration. It has the benefit of unifying WithInt64Callback and WithFloat64Callback, but at the expense of adding the unneeded type parameter to WithUnit and WithDescription.

As mentioned above we could keep the instrument options/configuration non-generic and only make the changes for the instruments. However, I'm not sure the benefit of generic instruments outweighs future compatibility issue we will need to document and address for SDKs.

@MrAlias
Copy link
Contributor Author

MrAlias commented Apr 13, 2023

Closing based on consensus from SIG meeting.

@MrAlias MrAlias closed this Apr 13, 2023
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.

None yet

4 participants