Repository: open-telemetry/opentelemetry-go
Pull request #1988 (2021-06-09 21:44:50)

Remove dependency on metrics packages
Creates a new `internal/metric` module and moves metric-related internals there.  The metric-related test helpers from `oteltest` have moved to `metric/oteltest`.  This should eliminate all dependence on the metrics API module from modules that will be declared stable at `v1.0.0`.

codecov[bot]: # [Codecov](https://codecov.io/gh/open-telemetry/opentelemetry-go/pull/1988?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) Report
> Merging [#1988](https://codecov.io/gh/open-telemetry/opentelemetry-go/pull/1988?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) (b3edfd5) into [main](https://codecov.io/gh/open-telemetry/opentelemetry-go/commit/7ffe28457d79fea314d3165ded0f9f980ec9b862?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) (7ffe284) will **decrease** coverage by `0.0%`.
> The diff coverage is `100.0%`.

[![Impacted file tree graph](https://codecov.io/gh/open-telemetry/opentelemetry-go/pull/1988/graphs/tree.svg?width=650&height=150&src=pr&token=8efTmh4kvf&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry)](https://codecov.io/gh/open-telemetry/opentelemetry-go/pull/1988?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry)

```diff
@@           Coverage Diff           @@
##            main   #1988     +/-   ##
=======================================
- Coverage   77.2%   77.1%   -0.1%     
=======================================
  Files        161     162      +1     
  Lines       8593    8593             
=======================================
- Hits        6635    6631      -4     
- Misses      1699    1702      +3     
- Partials     259     260      +1     
```


| [Impacted Files](https://codecov.io/gh/open-telemetry/opentelemetry-go/pull/1988?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) | Coverage Δ | |
|---|---|---|
| [internal/global/state.go](https://codecov.io/gh/open-telemetry/opentelemetry-go/pull/1988/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry#diff-aW50ZXJuYWwvZ2xvYmFsL3N0YXRlLmdv) | `100.0% <ø> (ø)` | |
| [internal/metric/global/meter.go](https://codecov.io/gh/open-telemetry/opentelemetry-go/pull/1988/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry#diff-aW50ZXJuYWwvbWV0cmljL2dsb2JhbC9tZXRlci5nbw==) | `90.3% <ø> (ø)` | |
| [metric/global/metric.go](https://codecov.io/gh/open-telemetry/opentelemetry-go/pull/1988/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry#diff-bWV0cmljL2dsb2JhbC9tZXRyaWMuZ28=) | `66.6% <ø> (-33.4%)` | :arrow_down: |
| [metric/oteltest/meter.go](https://codecov.io/gh/open-telemetry/opentelemetry-go/pull/1988/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry#diff-bWV0cmljL290ZWx0ZXN0L21ldGVyLmdv) | `98.6% <ø> (ø)` | |
| [internal/metric/global/metric.go](https://codecov.io/gh/open-telemetry/opentelemetry-go/pull/1988/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry#diff-aW50ZXJuYWwvbWV0cmljL2dsb2JhbC9tZXRyaWMuZ28=) | `100.0% <100.0%> (ø)` | |
| [internal/internaltest/alignment.go](https://codecov.io/gh/open-telemetry/opentelemetry-go/pull/1988/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry#diff-aW50ZXJuYWwvaW50ZXJuYWx0ZXN0L2FsaWdubWVudC5nbw==) | `0.0% <0.0%> (-37.5%)` | :arrow_down: |
| [metric/config.go](https://codecov.io/gh/open-telemetry/opentelemetry-go/pull/1988/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry#diff-bWV0cmljL2NvbmZpZy5nbw==) | `91.6% <0.0%> (-8.4%)` | :arrow_down: |
| [sdk/trace/batch\_span\_processor.go](https://codecov.io/gh/open-telemetry/opentelemetry-go/pull/1988/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry#diff-c2RrL3RyYWNlL2JhdGNoX3NwYW5fcHJvY2Vzc29yLmdv) | `84.0% <0.0%> (-3.1%)` | :arrow_down: |
| [metric/metric\_instrument.go](https://codecov.io/gh/open-telemetry/opentelemetry-go/pull/1988/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry#diff-bWV0cmljL21ldHJpY19pbnN0cnVtZW50Lmdv) | `87.4% <0.0%> (-0.7%)` | :arrow_down: |
| ... and [3 more](https://codecov.io/gh/open-telemetry/opentelemetry-go/pull/1988/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) | |


Patch:
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 95816ded..de7125cd 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -186,6 +186,16 @@ updates:
     schedule:
       day: sunday
       interval: weekly
+  -
+    package-ecosystem: gomod
+    directory: /internal/metric
+    labels:
+      - dependencies
+      - go
+      - "Skip Changelog"
+    schedule:
+      day: sunday
+      interval: weekly
   -
     package-ecosystem: gomod
     directory: /internal/tools
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c95fd82c..a97fa679 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -81,6 +81,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
 - Rename `NewExporter` to `New` in the `go.opentelemetry.io/otel/exporters/otlp` package. (#1985)
 - Rename `NewUnstartedExporter` to `NewUnstarted` in the `go.opentelemetry.io/otel/exporters/otlp` package. (#1985)
 - The `go.opentelemetry.io/otel/semconv` package has been moved to `go.opentelemetry.io/otel/semconv/v1.4.0` to allow for multiple [telemetry schema](https://github.com/open-telemetry/oteps/blob/main/text/0152-telemetry-schemas.md) versions to be used concurrently. (#1987)
+- Metrics test helpers in `go.opentelemetry.io/otel/oteltest` have been moved to `go.opentelemetry.io/otel/metric/metrictest`. (#1988)
 
 ### Deprecated
 
diff --git a/bridge/opencensus/go.mod b/bridge/opencensus/go.mod
index a788bbfa..58522141 100644
--- a/bridge/opencensus/go.mod
+++ b/bridge/opencensus/go.mod
@@ -63,3 +63,5 @@ replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../../exporters/otl
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../../exporters/otlp/otlptrace/otlptracegrpc
 
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../../exporters/otlp/otlptrace/otlptracehttp
+
+replace go.opentelemetry.io/otel/internal/metric => ../../internal/metric
diff --git a/bridge/opentracing/go.mod b/bridge/opentracing/go.mod
index 70304940..1e3e825a 100644
--- a/bridge/opentracing/go.mod
+++ b/bridge/opentracing/go.mod
@@ -59,3 +59,5 @@ replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../../exporters/otl
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../../exporters/otlp/otlptrace/otlptracegrpc
 
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../../exporters/otlp/otlptrace/otlptracehttp
+
+replace go.opentelemetry.io/otel/internal/metric => ../../internal/metric
diff --git a/example/jaeger/go.mod b/example/jaeger/go.mod
index 51b95ae2..ff9d694e 100644
--- a/example/jaeger/go.mod
+++ b/example/jaeger/go.mod
@@ -59,3 +59,5 @@ replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../../exporters/otl
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../../exporters/otlp/otlptrace/otlptracegrpc
 
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../../exporters/otlp/otlptrace/otlptracehttp
+
+replace go.opentelemetry.io/otel/internal/metric => ../../internal/metric
diff --git a/example/namedtracer/go.mod b/example/namedtracer/go.mod
index 9de96a9e..35245f15 100644
--- a/example/namedtracer/go.mod
+++ b/example/namedtracer/go.mod
@@ -60,3 +60,5 @@ replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../../exporters/otl
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../../exporters/otlp/otlptrace/otlptracegrpc
 
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../../exporters/otlp/otlptrace/otlptracehttp
+
+replace go.opentelemetry.io/otel/internal/metric => ../../internal/metric
diff --git a/example/opencensus/go.mod b/example/opencensus/go.mod
index 6d24147a..c3193709 100644
--- a/example/opencensus/go.mod
+++ b/example/opencensus/go.mod
@@ -61,3 +61,5 @@ replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../../exporters/otl
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../../exporters/otlp/otlptrace/otlptracegrpc
 
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../../exporters/otlp/otlptrace/otlptracehttp
+
+replace go.opentelemetry.io/otel/internal/metric => ../../internal/metric
diff --git a/example/otel-collector/go.mod b/example/otel-collector/go.mod
index c992f277..f8f54302 100644
--- a/example/otel-collector/go.mod
+++ b/example/otel-collector/go.mod
@@ -63,3 +63,5 @@ replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../../exporters/otl
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../../exporters/otlp/otlptrace/otlptracegrpc
 
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../../exporters/otlp/otlptrace/otlptracehttp
+
+replace go.opentelemetry.io/otel/internal/metric => ../../internal/metric
diff --git a/example/passthrough/go.mod b/example/passthrough/go.mod
index af55e50a..7c6da39c 100644
--- a/example/passthrough/go.mod
+++ b/example/passthrough/go.mod
@@ -61,3 +61,5 @@ replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../../exporters/otl
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../../exporters/otlp/otlptrace/otlptracegrpc
 
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../../exporters/otlp/otlptrace/otlptracehttp
+
+replace go.opentelemetry.io/otel/internal/metric => ../../internal/metric
diff --git a/example/prom-collector/go.mod b/example/prom-collector/go.mod
index bf47db5d..717c031a 100644
--- a/example/prom-collector/go.mod
+++ b/example/prom-collector/go.mod
@@ -62,3 +62,5 @@ replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../../exporters/otl
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../../exporters/otlp/otlptrace/otlptracegrpc
 
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../../exporters/otlp/otlptrace/otlptracehttp
+
+replace go.opentelemetry.io/otel/internal/metric => ../../internal/metric
diff --git a/example/prometheus/go.mod b/example/prometheus/go.mod
index a841cd7e..26629cb3 100644
--- a/example/prometheus/go.mod
+++ b/example/prometheus/go.mod
@@ -61,3 +61,5 @@ replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../../exporters/otl
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../../exporters/otlp/otlptrace/otlptracegrpc
 
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../../exporters/otlp/otlptrace/otlptracehttp
+
+replace go.opentelemetry.io/otel/internal/metric => ../../internal/metric
diff --git a/example/zipkin/go.mod b/example/zipkin/go.mod
index bb8f45d8..c57da075 100644
--- a/example/zipkin/go.mod
+++ b/example/zipkin/go.mod
@@ -60,3 +60,5 @@ replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../../exporters/otl
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../../exporters/otlp/otlptrace/otlptracegrpc
 
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../../exporters/otlp/otlptrace/otlptracehttp
+
+replace go.opentelemetry.io/otel/internal/metric => ../../internal/metric
diff --git a/exporters/metric/prometheus/go.mod b/exporters/metric/prometheus/go.mod
index 99fbb49e..78802ce8 100644
--- a/exporters/metric/prometheus/go.mod
+++ b/exporters/metric/prometheus/go.mod
@@ -64,3 +64,5 @@ replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../../otlp/otlptrac
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../../otlp/otlptrace/otlptracegrpc
 
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../../otlp/otlptrace/otlptracehttp
+
+replace go.opentelemetry.io/otel/internal/metric => ../../../internal/metric
diff --git a/exporters/otlp/go.mod b/exporters/otlp/go.mod
index d60ec7d7..acdf29f1 100644
--- a/exporters/otlp/go.mod
+++ b/exporters/otlp/go.mod
@@ -71,3 +71,5 @@ replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ./otl
 replace go.opentelemetry.io/otel/example/passthrough => ../../example/passthrough
 
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ./otlptrace/otlptracehttp
+
+replace go.opentelemetry.io/otel/internal/metric => ../../internal/metric
diff --git a/exporters/otlp/otlptrace/go.mod b/exporters/otlp/otlptrace/go.mod
index 5a0e2db6..64c4366c 100644
--- a/exporters/otlp/otlptrace/go.mod
+++ b/exporters/otlp/otlptrace/go.mod
@@ -67,3 +67,5 @@ replace go.opentelemetry.io/otel/sdk/metric => ../../../sdk/metric
 replace go.opentelemetry.io/otel/example/passthrough => ../../../example/passthrough
 
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ./otlptracehttp
+
+replace go.opentelemetry.io/otel/internal/metric => ../../../internal/metric
diff --git a/exporters/otlp/otlptrace/otlptracegrpc/go.mod b/exporters/otlp/otlptrace/otlptracegrpc/go.mod
index 2fd6143b..9a3b5cd8 100644
--- a/exporters/otlp/otlptrace/otlptracegrpc/go.mod
+++ b/exporters/otlp/otlptrace/otlptracegrpc/go.mod
@@ -64,3 +64,5 @@ replace go.opentelemetry.io/otel/sdk/metric => ../../../../sdk/metric
 replace go.opentelemetry.io/otel/example/passthrough => ../../../../example/passthrough
 
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../otlptracehttp
+
+replace go.opentelemetry.io/otel/internal/metric => ../../../../internal/metric
diff --git a/exporters/otlp/otlptrace/otlptracehttp/go.mod b/exporters/otlp/otlptrace/otlptracehttp/go.mod
index 5073e83b..f9ecba64 100644
--- a/exporters/otlp/otlptrace/otlptracehttp/go.mod
+++ b/exporters/otlp/otlptrace/otlptracehttp/go.mod
@@ -61,3 +61,5 @@ replace go.opentelemetry.io/otel/sdk/export/metric => ../../../../sdk/export/met
 replace go.opentelemetry.io/otel/sdk/metric => ../../../../sdk/metric
 
 replace go.opentelemetry.io/otel/trace => ../../../../trace
+
+replace go.opentelemetry.io/otel/internal/metric => ../../../../internal/metric
diff --git a/exporters/stdout/go.mod b/exporters/stdout/go.mod
index 5b927d14..94fef1a7 100644
--- a/exporters/stdout/go.mod
+++ b/exporters/stdout/go.mod
@@ -65,3 +65,5 @@ replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../otlp/otlptrace
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../otlp/otlptrace/otlptracegrpc
 
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../otlp/otlptrace/otlptracehttp
+
+replace go.opentelemetry.io/otel/internal/metric => ../../internal/metric
diff --git a/exporters/trace/jaeger/go.mod b/exporters/trace/jaeger/go.mod
index 8fd0f8bc..045826d5 100644
--- a/exporters/trace/jaeger/go.mod
+++ b/exporters/trace/jaeger/go.mod
@@ -62,3 +62,5 @@ replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../../otlp/otlptrac
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../../otlp/otlptrace/otlptracegrpc
 
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../../otlp/otlptrace/otlptracehttp
+
+replace go.opentelemetry.io/otel/internal/metric => ../../../internal/metric
diff --git a/exporters/trace/zipkin/go.mod b/exporters/trace/zipkin/go.mod
index 7d084e68..921db6c4 100644
--- a/exporters/trace/zipkin/go.mod
+++ b/exporters/trace/zipkin/go.mod
@@ -63,3 +63,5 @@ replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../../otlp/otlptrac
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../../otlp/otlptrace/otlptracegrpc
 
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../../otlp/otlptrace/otlptracehttp
+
+replace go.opentelemetry.io/otel/internal/metric => ../../../internal/metric
diff --git a/go.mod b/go.mod
index 3b37117f..9dad82a2 100644
--- a/go.mod
+++ b/go.mod
@@ -5,7 +5,6 @@ go 1.15
 require (
 	github.com/google/go-cmp v0.5.6
 	github.com/stretchr/testify v1.7.0
-	go.opentelemetry.io/otel/metric v0.20.0
 	go.opentelemetry.io/otel/oteltest v0.20.0
 	go.opentelemetry.io/otel/trace v0.20.0
 )
@@ -44,6 +43,8 @@ replace go.opentelemetry.io/otel/internal/tools => ./internal/tools
 
 replace go.opentelemetry.io/otel/sdk => ./sdk
 
+replace go.opentelemetry.io/otel/internal/metric => ./internal/metric
+
 replace go.opentelemetry.io/otel/metric => ./metric
 
 replace go.opentelemetry.io/otel/oteltest => ./oteltest
diff --git a/internal/global/state.go b/internal/global/state.go
index f3bf0035..c5534557 100644
--- a/internal/global/state.go
+++ b/internal/global/state.go
@@ -18,7 +18,6 @@ import (
 	"sync"
 	"sync/atomic"
 
-	"go.opentelemetry.io/otel/metric"
 	"go.opentelemetry.io/otel/propagation"
 	"go.opentelemetry.io/otel/trace"
 )
@@ -28,10 +27,6 @@ type (
 		tp trace.TracerProvider
 	}
 
-	meterProviderHolder struct {
-		mp metric.MeterProvider
-	}
-
 	propagatorsHolder struct {
 		tm propagation.TextMapPropagator
 	}
@@ -39,10 +34,8 @@ type (
 
 var (
 	globalTracer      = defaultTracerValue()
-	globalMeter       = defaultMeterValue()
 	globalPropagators = defaultPropagatorsValue()
 
-	delegateMeterOnce             sync.Once
 	delegateTraceOnce             sync.Once
 	delegateTextMapPropagatorOnce sync.Once
 )
@@ -69,28 +62,6 @@ func SetTracerProvider(tp trace.TracerProvider) {
 	globalTracer.Store(tracerProviderHolder{tp: tp})
 }
 
-// MeterProvider is the internal implementation for global.MeterProvider.
-func MeterProvider() metric.MeterProvider {
-	return globalMeter.Load().(meterProviderHolder).mp
-}
-
-// SetMeterProvider is the internal implementation for global.SetMeterProvider.
-func SetMeterProvider(mp metric.MeterProvider) {
-	delegateMeterOnce.Do(func() {
-		current := MeterProvider()
-
-		if current == mp {
-			// Setting the provider to the prior default is nonsense, panic.
-			// Panic is acceptable because we are likely still early in the
-			// process lifetime.
-			panic("invalid MeterProvider, the global instance cannot be reinstalled")
-		} else if def, ok := current.(*meterProvider); ok {
-			def.setDelegate(mp)
-		}
-	})
-	globalMeter.Store(meterProviderHolder{mp: mp})
-}
-
 // TextMapPropagator is the internal implementation for global.TextMapPropagator.
 func TextMapPropagator() propagation.TextMapPropagator {
 	return globalPropagators.Load().(propagatorsHolder).tm
@@ -120,12 +91,6 @@ func defaultTracerValue() *atomic.Value {
 	return v
 }
 
-func defaultMeterValue() *atomic.Value {
-	v := &atomic.Value{}
-	v.Store(meterProviderHolder{mp: newMeterProvider()})
-	return v
-}
-
 func defaultPropagatorsValue() *atomic.Value {
 	v := &atomic.Value{}
 	v.Store(propagatorsHolder{tm: newTextMapPropagator()})
@@ -135,9 +100,7 @@ func defaultPropagatorsValue() *atomic.Value {
 // ResetForTest restores the initial global state, for testing purposes.
 func ResetForTest() {
 	globalTracer = defaultTracerValue()
-	globalMeter = defaultMeterValue()
 	globalPropagators = defaultPropagatorsValue()
-	delegateMeterOnce = sync.Once{}
 	delegateTraceOnce = sync.Once{}
 	delegateTextMapPropagatorOnce = sync.Once{}
 }
diff --git a/internal/metric/global/metric.go b/internal/metric/global/metric.go
new file mode 100644
index 00000000..be95ff61
--- /dev/null
+++ b/internal/metric/global/metric.go
@@ -0,0 +1,66 @@
+// Copyright The OpenTelemetry Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package global
+
+import (
+	"sync"
+	"sync/atomic"
+
+	"go.opentelemetry.io/otel/metric"
+)
+
+type meterProviderHolder struct {
+	mp metric.MeterProvider
+}
+
+var (
+	globalMeter = defaultMeterValue()
+
+	delegateMeterOnce sync.Once
+)
+
+// MeterProvider is the internal implementation for global.MeterProvider.
+func MeterProvider() metric.MeterProvider {
+	return globalMeter.Load().(meterProviderHolder).mp
+}
+
+// SetMeterProvider is the internal implementation for global.SetMeterProvider.
+func SetMeterProvider(mp metric.MeterProvider) {
+	delegateMeterOnce.Do(func() {
+		current := MeterProvider()
+
+		if current == mp {
+			// Setting the provider to the prior default is nonsense, panic.
+			// Panic is acceptable because we are likely still early in the
+			// process lifetime.
+			panic("invalid MeterProvider, the global instance cannot be reinstalled")
+		} else if def, ok := current.(*meterProvider); ok {
+			def.setDelegate(mp)
+		}
+	})
+	globalMeter.Store(meterProviderHolder{mp: mp})
+}
+
+func defaultMeterValue() *atomic.Value {
+	v := &atomic.Value{}
+	v.Store(meterProviderHolder{mp: newMeterProvider()})
+	return v
+}
+
+// ResetForTest restores the initial global state, for testing purposes.
+func ResetForTest() {
+	globalMeter = defaultMeterValue()
+	delegateMeterOnce = sync.Once{}
+}
diff --git a/internal/metric/go.mod b/internal/metric/go.mod
new file mode 100644
index 00000000..a605bfe8
--- /dev/null
+++ b/internal/metric/go.mod
@@ -0,0 +1,63 @@
+module go.opentelemetry.io/otel/internal/metric
+
+go 1.15
+
+require (
+	github.com/stretchr/testify v1.7.0
+	go.opentelemetry.io/otel v0.20.0
+	go.opentelemetry.io/otel/metric v0.20.0
+)
+
+replace go.opentelemetry.io/otel => ../..
+
+replace go.opentelemetry.io/otel/metric => ../../metric
+
+replace go.opentelemetry.io/otel/internal/metric => ./
+
+replace go.opentelemetry.io/otel/bridge/opencensus => ../../bridge/opencensus
+
+replace go.opentelemetry.io/otel/bridge/opentracing => ../../bridge/opentracing
+
+replace go.opentelemetry.io/otel/example/jaeger => ../../example/jaeger
+
+replace go.opentelemetry.io/otel/example/namedtracer => ../../example/namedtracer
+
+replace go.opentelemetry.io/otel/example/opencensus => ../../example/opencensus
+
+replace go.opentelemetry.io/otel/example/otel-collector => ../../example/otel-collector
+
+replace go.opentelemetry.io/otel/example/passthrough => ../../example/passthrough
+
+replace go.opentelemetry.io/otel/example/prom-collector => ../../example/prom-collector
+
+replace go.opentelemetry.io/otel/example/prometheus => ../../example/prometheus
+
+replace go.opentelemetry.io/otel/example/zipkin => ../../example/zipkin
+
+replace go.opentelemetry.io/otel/exporters/metric/prometheus => ../../exporters/metric/prometheus
+
+replace go.opentelemetry.io/otel/exporters/otlp => ../../exporters/otlp
+
+replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../../exporters/otlp/otlptrace
+
+replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../../exporters/otlp/otlptrace/otlptracegrpc
+
+replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../../exporters/otlp/otlptrace/otlptracehttp
+
+replace go.opentelemetry.io/otel/exporters/stdout => ../../exporters/stdout
+
+replace go.opentelemetry.io/otel/exporters/trace/jaeger => ../../exporters/trace/jaeger
+
+replace go.opentelemetry.io/otel/exporters/trace/zipkin => ../../exporters/trace/zipkin
+
+replace go.opentelemetry.io/otel/internal/tools => ../tools
+
+replace go.opentelemetry.io/otel/oteltest => ../../oteltest
+
+replace go.opentelemetry.io/otel/sdk => ../../sdk
+
+replace go.opentelemetry.io/otel/sdk/export/metric => ../../sdk/export/metric
+
+replace go.opentelemetry.io/otel/sdk/metric => ../../sdk/metric
+
+replace go.opentelemetry.io/otel/trace => ../../trace
diff --git a/internal/metric/go.sum b/internal/metric/go.sum
new file mode 100644
index 00000000..f212493d
--- /dev/null
+++ b/internal/metric/go.sum
@@ -0,0 +1,15 @@
+github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
+github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/internal/tools/go.mod b/internal/tools/go.mod
index 5e30ea68..a2850a14 100644
--- a/internal/tools/go.mod
+++ b/internal/tools/go.mod
@@ -63,3 +63,5 @@ replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../../exporters/otl
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../../exporters/otlp/otlptrace/otlptracegrpc
 
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../../exporters/otlp/otlptrace/otlptracehttp
+
+replace go.opentelemetry.io/otel/internal/metric => ../metric
diff --git a/metric/global/metric.go b/metric/global/metric.go
index 8d16d34d..14ba8620 100644
--- a/metric/global/metric.go
+++ b/metric/global/metric.go
@@ -15,7 +15,7 @@
 package global // import "go.opentelemetry.io/otel/metric/global"
 
 import (
-	"go.opentelemetry.io/otel/internal/global"
+	"go.opentelemetry.io/otel/internal/metric/global"
 	"go.opentelemetry.io/otel/metric"
 )
 
diff --git a/metric/go.mod b/metric/go.mod
index 82ac8852..096fd460 100644
--- a/metric/go.mod
+++ b/metric/go.mod
@@ -50,7 +50,7 @@ require (
 	github.com/google/go-cmp v0.5.6
 	github.com/stretchr/testify v1.7.0
 	go.opentelemetry.io/otel v0.20.0
-	go.opentelemetry.io/otel/oteltest v0.20.0
+	go.opentelemetry.io/otel/internal/metric v0.20.0
 )
 
 replace go.opentelemetry.io/otel/example/passthrough => ../example/passthrough
@@ -60,3 +60,5 @@ replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../exporters/otlp/o
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../exporters/otlp/otlptrace/otlptracegrpc
 
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../exporters/otlp/otlptrace/otlptracehttp
+
+replace go.opentelemetry.io/otel/internal/metric => ../internal/metric
diff --git a/sdk/export/metric/go.mod b/sdk/export/metric/go.mod
index f1b6b0ec..422805c7 100644
--- a/sdk/export/metric/go.mod
+++ b/sdk/export/metric/go.mod
@@ -60,3 +60,5 @@ replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../../../exporters/
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../../../exporters/otlp/otlptrace/otlptracegrpc
 
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../../../exporters/otlp/otlptrace/otlptracehttp
+
+replace go.opentelemetry.io/otel/internal/metric => ../../../internal/metric
diff --git a/sdk/go.mod b/sdk/go.mod
index 79cbbf0f..42c0abfc 100644
--- a/sdk/go.mod
+++ b/sdk/go.mod
@@ -61,3 +61,5 @@ replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../exporters/otlp/o
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../exporters/otlp/otlptrace/otlptracegrpc
 
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../exporters/otlp/otlptrace/otlptracehttp
+
+replace go.opentelemetry.io/otel/internal/metric => ../internal/metric
diff --git a/sdk/metric/go.mod b/sdk/metric/go.mod
index 488eb2bd..e2e908cc 100644
--- a/sdk/metric/go.mod
+++ b/sdk/metric/go.mod
@@ -50,6 +50,7 @@ require (
 	github.com/benbjohnson/clock v1.1.0 // do not upgrade to v1.1.x because it would require Go >= 1.15
 	github.com/stretchr/testify v1.7.0
 	go.opentelemetry.io/otel v0.20.0
+	go.opentelemetry.io/otel/internal/metric v0.20.0
 	go.opentelemetry.io/otel/metric v0.20.0
 	go.opentelemetry.io/otel/sdk v0.20.0
 	go.opentelemetry.io/otel/sdk/export/metric v0.20.0
@@ -62,3 +63,5 @@ replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../../exporters/otl
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../../exporters/otlp/otlptrace/otlptracegrpc
 
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../../exporters/otlp/otlptrace/otlptracehttp
+
+replace go.opentelemetry.io/otel/internal/metric => ../../internal/metric
diff --git a/trace/go.mod b/trace/go.mod
index ced132c7..01069d8c 100644
--- a/trace/go.mod
+++ b/trace/go.mod
@@ -59,3 +59,5 @@ replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../exporters/otlp/o
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../exporters/otlp/otlptrace/otlptracegrpc
 
 replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../exporters/otlp/otlptrace/otlptracehttp
+
+replace go.opentelemetry.io/otel/internal/metric => ../internal/metric


Test patch:
diff --git a/internal/global/benchmark_test.go b/internal/global/benchmark_test.go
index ea06b7dd..ef37194f 100644
--- a/internal/global/benchmark_test.go
+++ b/internal/global/benchmark_test.go
@@ -19,28 +19,9 @@ import (
 	"testing"
 
 	"go.opentelemetry.io/otel"
-	"go.opentelemetry.io/otel/attribute"
 	"go.opentelemetry.io/otel/internal/global"
-	metricglobal "go.opentelemetry.io/otel/metric/global"
 )
 
-func BenchmarkGlobalInt64CounterAddNoSDK(b *testing.B) {
-	// Compare with BenchmarkGlobalInt64CounterAddWithSDK() in
-	// ../../sdk/metric/benchmark_test.go to see the overhead of the
-	// global no-op system against a registered SDK.
-	global.ResetForTest()
-	ctx := context.Background()
-	sdk := metricglobal.Meter("test")
-	labs := []attribute.KeyValue{attribute.String("A", "B")}
-	cnt := Must(sdk).NewInt64Counter("int64.counter")
-
-	b.ResetTimer()
-
-	for i := 0; i < b.N; i++ {
-		cnt.Add(ctx, 1, labs...)
-	}
-}
-
 func BenchmarkStartEndSpanNoSDK(b *testing.B) {
 	// Compare with BenchmarkStartEndSpan() in
 	// ../../sdk/trace/benchmark_test.go.
diff --git a/internal/global/state_test.go b/internal/global/state_test.go
index cf5ce254..9e812083 100644
--- a/internal/global/state_test.go
+++ b/internal/global/state_test.go
@@ -29,9 +29,6 @@ func TestResetsOfGlobalsPanic(t *testing.T) {
 		"SetTracerProvider": func() {
 			global.SetTracerProvider(global.TracerProvider())
 		},
-		"SetMeterProvider": func() {
-			global.SetMeterProvider(global.MeterProvider())
-		},
 	}
 
 	for name, test := range tests {
diff --git a/internal/metric/global/benchmark_test.go b/internal/metric/global/benchmark_test.go
new file mode 100644
index 00000000..05cab62d
--- /dev/null
+++ b/internal/metric/global/benchmark_test.go
@@ -0,0 +1,41 @@
+// Copyright The OpenTelemetry Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package global_test
+
+import (
+	"context"
+	"testing"
+
+	"go.opentelemetry.io/otel/attribute"
+	internalglobal "go.opentelemetry.io/otel/internal/metric/global"
+	metricglobal "go.opentelemetry.io/otel/metric/global"
+)
+
+func BenchmarkGlobalInt64CounterAddNoSDK(b *testing.B) {
+	// Compare with BenchmarkGlobalInt64CounterAddWithSDK() in
+	// ../../sdk/metric/benchmark_test.go to see the overhead of the
+	// global no-op system against a registered SDK.
+	internalglobal.ResetForTest()
+	ctx := context.Background()
+	sdk := metricglobal.Meter("test")
+	labs := []attribute.KeyValue{attribute.String("A", "B")}
+	cnt := Must(sdk).NewInt64Counter("int64.counter")
+
+	b.ResetTimer()
+
+	for i := 0; i < b.N; i++ {
+		cnt.Add(ctx, 1, labs...)
+	}
+}
diff --git a/internal/global/internal_test.go b/internal/metric/global/internal_test.go
similarity index 95%
rename from internal/global/internal_test.go
rename to internal/metric/global/internal_test.go
index ff332fea..44e1904a 100644
--- a/internal/global/internal_test.go
+++ b/internal/metric/global/internal_test.go
@@ -18,8 +18,8 @@ import (
 	"os"
 	"testing"
 
-	"go.opentelemetry.io/otel/internal/global"
 	ottest "go.opentelemetry.io/otel/internal/internaltest"
+	"go.opentelemetry.io/otel/internal/metric/global"
 )
 
 // Ensure struct alignment prior to running tests.
diff --git a/internal/global/meter.go b/internal/metric/global/meter.go
similarity index 100%
rename from internal/global/meter.go
rename to internal/metric/global/meter.go
diff --git a/internal/global/meter_test.go b/internal/metric/global/meter_test.go
similarity index 85%
rename from internal/global/meter_test.go
rename to internal/metric/global/meter_test.go
index 830ef074..be3d63b7 100644
--- a/internal/global/meter_test.go
+++ b/internal/metric/global/meter_test.go
@@ -22,11 +22,11 @@ import (
 	"github.com/stretchr/testify/require"
 
 	"go.opentelemetry.io/otel/attribute"
-	"go.opentelemetry.io/otel/internal/global"
+	"go.opentelemetry.io/otel/internal/metric/global"
 	"go.opentelemetry.io/otel/metric"
 	metricglobal "go.opentelemetry.io/otel/metric/global"
+	"go.opentelemetry.io/otel/metric/metrictest"
 	"go.opentelemetry.io/otel/metric/number"
-	"go.opentelemetry.io/otel/oteltest"
 )
 
 var Must = metric.Must
@@ -66,7 +66,7 @@ func TestDirect(t *testing.T) {
 	second.Record(ctx, 1, labels3...)
 	second.Record(ctx, 2, labels3...)
 
-	mock, provider := oteltest.NewMeterProvider()
+	mock, provider := metrictest.NewMeterProvider()
 	metricglobal.SetMeterProvider(provider)
 
 	counter.Add(ctx, 1, labels1...)
@@ -75,56 +75,56 @@ func TestDirect(t *testing.T) {
 
 	mock.RunAsyncInstruments()
 
-	measurements := oteltest.AsStructs(mock.MeasurementBatches)
+	measurements := metrictest.AsStructs(mock.MeasurementBatches)
 
 	require.EqualValues(t,
-		[]oteltest.Measured{
+		[]metrictest.Measured{
 			{
 				Name:                   "test.counter",
 				InstrumentationName:    "test1",
 				InstrumentationVersion: "semver:v1.0.0",
-				Labels:                 oteltest.LabelsToMap(labels1...),
+				Labels:                 metrictest.LabelsToMap(labels1...),
 				Number:                 asInt(1),
 			},
 			{
 				Name:                   "test.valuerecorder",
 				InstrumentationName:    "test1",
 				InstrumentationVersion: "semver:v1.0.0",
-				Labels:                 oteltest.LabelsToMap(labels1...),
+				Labels:                 metrictest.LabelsToMap(labels1...),
 				Number:                 asFloat(3),
 			},
 			{
 				Name:                "test.second",
 				InstrumentationName: "test2",
-				Labels:              oteltest.LabelsToMap(labels3...),
+				Labels:              metrictest.LabelsToMap(labels3...),
 				Number:              asFloat(3),
 			},
 			{
 				Name:                   "test.valueobserver.float",
 				InstrumentationName:    "test1",
 				InstrumentationVersion: "semver:v1.0.0",
-				Labels:                 oteltest.LabelsToMap(labels1...),
+				Labels:                 metrictest.LabelsToMap(labels1...),
 				Number:                 asFloat(1),
 			},
 			{
 				Name:                   "test.valueobserver.float",
 				InstrumentationName:    "test1",
 				InstrumentationVersion: "semver:v1.0.0",
-				Labels:                 oteltest.LabelsToMap(labels2...),
+				Labels:                 metrictest.LabelsToMap(labels2...),
 				Number:                 asFloat(2),
 			},
 			{
 				Name:                   "test.valueobserver.int",
 				InstrumentationName:    "test1",
 				InstrumentationVersion: "semver:v1.0.0",
-				Labels:                 oteltest.LabelsToMap(labels1...),
+				Labels:                 metrictest.LabelsToMap(labels1...),
 				Number:                 asInt(1),
 			},
 			{
 				Name:                   "test.valueobserver.int",
 				InstrumentationName:    "test1",
 				InstrumentationVersion: "semver:v1.0.0",
-				Labels:                 oteltest.LabelsToMap(labels2...),
+				Labels:                 metrictest.LabelsToMap(labels2...),
 				Number:                 asInt(2),
 			},
 		},
@@ -151,28 +151,28 @@ func TestBound(t *testing.T) {
 	boundM.Record(ctx, 1)
 	boundM.Record(ctx, 2)
 
-	mock, provider := oteltest.NewMeterProvider()
+	mock, provider := metrictest.NewMeterProvider()
 	metricglobal.SetMeterProvider(provider)
 
 	boundC.Add(ctx, 1)
 	boundM.Record(ctx, 3)
 
 	require.EqualValues(t,
-		[]oteltest.Measured{
+		[]metrictest.Measured{
 			{
 				Name:                "test.counter",
 				InstrumentationName: "test",
-				Labels:              oteltest.LabelsToMap(labels1...),
+				Labels:              metrictest.LabelsToMap(labels1...),
 				Number:              asFloat(1),
 			},
 			{
 				Name:                "test.valuerecorder",
 				InstrumentationName: "test",
-				Labels:              oteltest.LabelsToMap(labels1...),
+				Labels:              metrictest.LabelsToMap(labels1...),
 				Number:              asInt(3),
 			},
 		},
-		oteltest.AsStructs(mock.MeasurementBatches))
+		metrictest.AsStructs(mock.MeasurementBatches))
 
 	boundC.Unbind()
 	boundM.Unbind()
@@ -199,7 +199,7 @@ func TestUnbindThenRecordOne(t *testing.T) {
 	global.ResetForTest()
 
 	ctx := context.Background()
-	mock, provider := oteltest.NewMeterProvider()
+	mock, provider := metrictest.NewMeterProvider()
 
 	meter := metricglobal.Meter("test")
 	counter := Must(meter).NewInt64Counter("test.counter")
@@ -238,7 +238,7 @@ func TestErrorInDeferredConstructor(t *testing.T) {
 	c1 := Must(meter).NewInt64Counter("test")
 	c2 := Must(meter).NewInt64Counter("test")
 
-	_, provider := oteltest.NewMeterProvider()
+	_, provider := metrictest.NewMeterProvider()
 	sdk := &meterProviderWithConstructorError{provider}
 
 	require.Panics(t, func() {
@@ -264,7 +264,7 @@ func TestImplementationIndirection(t *testing.T) {
 	ival := counter.Measurement(1).SyncImpl().Implementation()
 	require.NotNil(t, ival)
 
-	_, ok := ival.(*oteltest.Sync)
+	_, ok := ival.(*metrictest.Sync)
 	require.False(t, ok)
 
 	// Async: no SDK yet
@@ -276,11 +276,11 @@ func TestImplementationIndirection(t *testing.T) {
 	ival = valueobserver.AsyncImpl().Implementation()
 	require.NotNil(t, ival)
 
-	_, ok = ival.(*oteltest.Async)
+	_, ok = ival.(*metrictest.Async)
 	require.False(t, ok)
 
 	// Register the SDK
-	_, provider := oteltest.NewMeterProvider()
+	_, provider := metrictest.NewMeterProvider()
 	metricglobal.SetMeterProvider(provider)
 
 	// Repeat the above tests
@@ -289,14 +289,14 @@ func TestImplementationIndirection(t *testing.T) {
 	ival = counter.Measurement(1).SyncImpl().Implementation()
 	require.NotNil(t, ival)
 
-	_, ok = ival.(*oteltest.Sync)
+	_, ok = ival.(*metrictest.Sync)
 	require.True(t, ok)
 
 	// Async
 	ival = valueobserver.AsyncImpl().Implementation()
 	require.NotNil(t, ival)
 
-	_, ok = ival.(*oteltest.Async)
+	_, ok = ival.(*metrictest.Async)
 	require.True(t, ok)
 }
 
@@ -309,19 +309,19 @@ func TestRecordBatchMock(t *testing.T) {
 
 	meter.RecordBatch(context.Background(), nil, counter.Measurement(1))
 
-	mock, provider := oteltest.NewMeterProvider()
+	mock, provider := metrictest.NewMeterProvider()
 	metricglobal.SetMeterProvider(provider)
 
 	meter.RecordBatch(context.Background(), nil, counter.Measurement(1))
 
 	require.EqualValues(t,
-		[]oteltest.Measured{
+		[]metrictest.Measured{
 			{
 				Name:                "test.counter",
 				InstrumentationName: "builtin",
-				Labels:              oteltest.LabelsToMap(),
+				Labels:              metrictest.LabelsToMap(),
 				Number:              asInt(1),
 			},
 		},
-		oteltest.AsStructs(mock.MeasurementBatches))
+		metrictest.AsStructs(mock.MeasurementBatches))
 }
diff --git a/internal/global/registry_test.go b/internal/metric/global/registry_test.go
similarity index 100%
rename from internal/global/registry_test.go
rename to internal/metric/global/registry_test.go
diff --git a/internal/metric/global/state_test.go b/internal/metric/global/state_test.go
new file mode 100644
index 00000000..526eac7f
--- /dev/null
+++ b/internal/metric/global/state_test.go
@@ -0,0 +1,45 @@
+// Copyright The OpenTelemetry Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package global_test
+
+import (
+	"testing"
+
+	internalglobal "go.opentelemetry.io/otel/internal/metric/global"
+	metricglobal "go.opentelemetry.io/otel/metric/global"
+)
+
+func TestResetsOfGlobalsPanic(t *testing.T) {
+	internalglobal.ResetForTest()
+	tests := map[string]func(){
+		"SetMeterProvider": func() {
+			metricglobal.SetMeterProvider(metricglobal.GetMeterProvider())
+		},
+	}
+
+	for name, test := range tests {
+		shouldPanic(t, name, test)
+	}
+}
+
+func shouldPanic(t *testing.T, name string, f func()) {
+	defer func() {
+		if r := recover(); r == nil {
+			t.Errorf("calling %s with default global did not panic", name)
+		}
+	}()
+
+	f()
+}
diff --git a/metric/metric_test.go b/metric/metric_test.go
index 899cc273..45566a29 100644
--- a/metric/metric_test.go
+++ b/metric/metric_test.go
@@ -21,9 +21,9 @@ import (
 
 	"go.opentelemetry.io/otel/attribute"
 	"go.opentelemetry.io/otel/metric"
+	"go.opentelemetry.io/otel/metric/metrictest"
 	"go.opentelemetry.io/otel/metric/number"
 	"go.opentelemetry.io/otel/metric/unit"
-	"go.opentelemetry.io/otel/oteltest"
 
 	"github.com/google/go-cmp/cmp"
 	"github.com/stretchr/testify/assert"
@@ -119,14 +119,14 @@ func TestPrecomputedSum(t *testing.T) {
 	}
 }
 
-func checkSyncBatches(ctx context.Context, t *testing.T, labels []attribute.KeyValue, mock *oteltest.MeterImpl, nkind number.Kind, mkind metric.InstrumentKind, instrument metric.InstrumentImpl, expected ...float64) {
+func checkSyncBatches(ctx context.Context, t *testing.T, labels []attribute.KeyValue, mock *metrictest.MeterImpl, nkind number.Kind, mkind metric.InstrumentKind, instrument metric.InstrumentImpl, expected ...float64) {
 	t.Helper()
 
 	batchesCount := len(mock.MeasurementBatches)
 	if len(mock.MeasurementBatches) != len(expected) {
 		t.Errorf("Expected %d recorded measurement batches, got %d", batchesCount, len(mock.MeasurementBatches))
 	}
-	recorded := oteltest.AsStructs(mock.MeasurementBatches)
+	recorded := metrictest.AsStructs(mock.MeasurementBatches)
 
 	for i, batch := range mock.MeasurementBatches {
 		if len(batch.Measurements) != 1 {
@@ -136,11 +136,11 @@ func checkSyncBatches(ctx context.Context, t *testing.T, labels []attribute.KeyV
 		measurement := batch.Measurements[0]
 		descriptor := measurement.Instrument.Descriptor()
 
-		expected := oteltest.Measured{
+		expected := metrictest.Measured{
 			Name:                descriptor.Name(),
 			InstrumentationName: descriptor.InstrumentationName(),
-			Labels:              oteltest.LabelsToMap(labels...),
-			Number:              oteltest.ResolveNumberByKind(t, nkind, expected[i]),
+			Labels:              metrictest.LabelsToMap(labels...),
+			Number:              metrictest.ResolveNumberByKind(t, nkind, expected[i]),
 		}
 		require.Equal(t, expected, recorded[i])
 	}
@@ -308,7 +308,7 @@ func TestCounter(t *testing.T) {
 	// N.B. the API does not check for negative
 	// values, that's the SDK's responsibility.
 	t.Run("float64 counter", func(t *testing.T) {
-		mockSDK, meter := oteltest.NewMeter()
+		mockSDK, meter := metrictest.NewMeter()
 		c := Must(meter).NewFloat64Counter("test.counter.float")
 		ctx := context.Background()
 		labels := []attribute.KeyValue{attribute.String("A", "B")}
@@ -321,7 +321,7 @@ func TestCounter(t *testing.T) {
 		)
 	})
 	t.Run("int64 counter", func(t *testing.T) {
-		mockSDK, meter := oteltest.NewMeter()
+		mockSDK, meter := metrictest.NewMeter()
 		c := Must(meter).NewInt64Counter("test.counter.int")
 		ctx := context.Background()
 		labels := []attribute.KeyValue{attribute.String("A", "B"), attribute.String("C", "D")}
@@ -335,7 +335,7 @@ func TestCounter(t *testing.T) {
 
 	})
 	t.Run("int64 updowncounter", func(t *testing.T) {
-		mockSDK, meter := oteltest.NewMeter()
+		mockSDK, meter := metrictest.NewMeter()
 		c := Must(meter).NewInt64UpDownCounter("test.updowncounter.int")
 		ctx := context.Background()
 		labels := []attribute.KeyValue{attribute.String("A", "B"), attribute.String("C", "D")}
@@ -348,7 +348,7 @@ func TestCounter(t *testing.T) {
 		)
 	})
 	t.Run("float64 updowncounter", func(t *testing.T) {
-		mockSDK, meter := oteltest.NewMeter()
+		mockSDK, meter := metrictest.NewMeter()
 		c := Must(meter).NewFloat64UpDownCounter("test.updowncounter.float")
 		ctx := context.Background()
 		labels := []attribute.KeyValue{attribute.String("A", "B"), attribute.String("C", "D")}
@@ -364,7 +364,7 @@ func TestCounter(t *testing.T) {
 
 func TestValueRecorder(t *testing.T) {
 	t.Run("float64 valuerecorder", func(t *testing.T) {
-		mockSDK, meter := oteltest.NewMeter()
+		mockSDK, meter := metrictest.NewMeter()
 		m := Must(meter).NewFloat64ValueRecorder("test.valuerecorder.float")
 		ctx := context.Background()
 		labels := []attribute.KeyValue{}
@@ -377,7 +377,7 @@ func TestValueRecorder(t *testing.T) {
 		)
 	})
 	t.Run("int64 valuerecorder", func(t *testing.T) {
-		mockSDK, meter := oteltest.NewMeter()
+		mockSDK, meter := metrictest.NewMeter()
 		m := Must(meter).NewInt64ValueRecorder("test.valuerecorder.int")
 		ctx := context.Background()
 		labels := []attribute.KeyValue{attribute.Int("I", 1)}
@@ -394,7 +394,7 @@ func TestValueRecorder(t *testing.T) {
 func TestObserverInstruments(t *testing.T) {
 	t.Run("float valueobserver", func(t *testing.T) {
 		labels := []attribute.KeyValue{attribute.String("O", "P")}
-		mockSDK, meter := oteltest.NewMeter()
+		mockSDK, meter := metrictest.NewMeter()
 		o := Must(meter).NewFloat64ValueObserver("test.valueobserver.float", func(_ context.Context, result metric.Float64ObserverResult) {
 			result.Observe(42.1, labels...)
 		})
@@ -405,7 +405,7 @@ func TestObserverInstruments(t *testing.T) {
 	})
 	t.Run("int valueobserver", func(t *testing.T) {
 		labels := []attribute.KeyValue{}
-		mockSDK, meter := oteltest.NewMeter()
+		mockSDK, meter := metrictest.NewMeter()
 		o := Must(meter).NewInt64ValueObserver("test.observer.int", func(_ context.Context, result metric.Int64ObserverResult) {
 			result.Observe(-142, labels...)
 		})
@@ -416,7 +416,7 @@ func TestObserverInstruments(t *testing.T) {
 	})
 	t.Run("float sumobserver", func(t *testing.T) {
 		labels := []attribute.KeyValue{attribute.String("O", "P")}
-		mockSDK, meter := oteltest.NewMeter()
+		mockSDK, meter := metrictest.NewMeter()
 		o := Must(meter).NewFloat64SumObserver("test.sumobserver.float", func(_ context.Context, result metric.Float64ObserverResult) {
 			result.Observe(42.1, labels...)
 		})
@@ -427,7 +427,7 @@ func TestObserverInstruments(t *testing.T) {
 	})
 	t.Run("int sumobserver", func(t *testing.T) {
 		labels := []attribute.KeyValue{}
-		mockSDK, meter := oteltest.NewMeter()
+		mockSDK, meter := metrictest.NewMeter()
 		o := Must(meter).NewInt64SumObserver("test.observer.int", func(_ context.Context, result metric.Int64ObserverResult) {
 			result.Observe(-142, labels...)
 		})
@@ -438,7 +438,7 @@ func TestObserverInstruments(t *testing.T) {
 	})
 	t.Run("float updownsumobserver", func(t *testing.T) {
 		labels := []attribute.KeyValue{attribute.String("O", "P")}
-		mockSDK, meter := oteltest.NewMeter()
+		mockSDK, meter := metrictest.NewMeter()
 		o := Must(meter).NewFloat64UpDownSumObserver("test.updownsumobserver.float", func(_ context.Context, result metric.Float64ObserverResult) {
 			result.Observe(42.1, labels...)
 		})
@@ -449,7 +449,7 @@ func TestObserverInstruments(t *testing.T) {
 	})
 	t.Run("int updownsumobserver", func(t *testing.T) {
 		labels := []attribute.KeyValue{}
-		mockSDK, meter := oteltest.NewMeter()
+		mockSDK, meter := metrictest.NewMeter()
 		o := Must(meter).NewInt64UpDownSumObserver("test.observer.int", func(_ context.Context, result metric.Int64ObserverResult) {
 			result.Observe(-142, labels...)
 		})
@@ -461,7 +461,7 @@ func TestObserverInstruments(t *testing.T) {
 }
 
 func TestBatchObserverInstruments(t *testing.T) {
-	mockSDK, meter := oteltest.NewMeter()
+	mockSDK, meter := metrictest.NewMeter()
 
 	var obs1 metric.Int64ValueObserver
 	var obs2 metric.Float64ValueObserver
@@ -486,8 +486,8 @@ func TestBatchObserverInstruments(t *testing.T) {
 
 	require.Len(t, mockSDK.MeasurementBatches, 1)
 
-	impl1 := obs1.AsyncImpl().Implementation().(*oteltest.Async)
-	impl2 := obs2.AsyncImpl().Implementation().(*oteltest.Async)
+	impl1 := obs1.AsyncImpl().Implementation().(*metrictest.Async)
+	impl2 := obs2.AsyncImpl().Implementation().(*metrictest.Async)
 
 	require.NotNil(t, impl1)
 	require.NotNil(t, impl2)
@@ -497,21 +497,21 @@ func TestBatchObserverInstruments(t *testing.T) {
 	require.Len(t, got.Measurements, 2)
 
 	m1 := got.Measurements[0]
-	require.Equal(t, impl1, m1.Instrument.Implementation().(*oteltest.Async))
-	require.Equal(t, 0, m1.Number.CompareNumber(number.Int64Kind, oteltest.ResolveNumberByKind(t, number.Int64Kind, 42)))
+	require.Equal(t, impl1, m1.Instrument.Implementation().(*metrictest.Async))
+	require.Equal(t, 0, m1.Number.CompareNumber(number.Int64Kind, metrictest.ResolveNumberByKind(t, number.Int64Kind, 42)))
 
 	m2 := got.Measurements[1]
-	require.Equal(t, impl2, m2.Instrument.Implementation().(*oteltest.Async))
-	require.Equal(t, 0, m2.Number.CompareNumber(number.Float64Kind, oteltest.ResolveNumberByKind(t, number.Float64Kind, 42)))
+	require.Equal(t, impl2, m2.Instrument.Implementation().(*metrictest.Async))
+	require.Equal(t, 0, m2.Number.CompareNumber(number.Float64Kind, metrictest.ResolveNumberByKind(t, number.Float64Kind, 42)))
 }
 
-func checkObserverBatch(t *testing.T, labels []attribute.KeyValue, mock *oteltest.MeterImpl, nkind number.Kind, mkind metric.InstrumentKind, observer metric.AsyncImpl, expected float64) {
+func checkObserverBatch(t *testing.T, labels []attribute.KeyValue, mock *metrictest.MeterImpl, nkind number.Kind, mkind metric.InstrumentKind, observer metric.AsyncImpl, expected float64) {
 	t.Helper()
 	assert.Len(t, mock.MeasurementBatches, 1)
 	if len(mock.MeasurementBatches) < 1 {
 		return
 	}
-	o := observer.Implementation().(*oteltest.Async)
+	o := observer.Implementation().(*metrictest.Async)
 	if !assert.NotNil(t, o) {
 		return
 	}
@@ -523,8 +523,8 @@ func checkObserverBatch(t *testing.T, labels []attribute.KeyValue, mock *oteltes
 	}
 	measurement := got.Measurements[0]
 	require.Equal(t, mkind, measurement.Instrument.Descriptor().InstrumentKind())
-	assert.Equal(t, o, measurement.Instrument.Implementation().(*oteltest.Async))
-	ft := oteltest.ResolveNumberByKind(t, nkind, expected)
+	assert.Equal(t, o, measurement.Instrument.Implementation().(*metrictest.Async))
+	ft := metrictest.ResolveNumberByKind(t, nkind, expected)
 	assert.Equal(t, 0, measurement.Number.CompareNumber(nkind, ft))
 }
 
@@ -561,7 +561,7 @@ func TestWrappedInstrumentError(t *testing.T) {
 
 func TestNilCallbackObserverNoop(t *testing.T) {
 	// Tests that a nil callback yields a no-op observer without error.
-	_, meter := oteltest.NewMeter()
+	_, meter := metrictest.NewMeter()
 
 	observer := Must(meter).NewInt64ValueObserver("test.observer", nil)
 
diff --git a/oteltest/alignment_test.go b/metric/metrictest/alignment_test.go
similarity index 98%
rename from oteltest/alignment_test.go
rename to metric/metrictest/alignment_test.go
index 816ea311..183d46bd 100644
--- a/oteltest/alignment_test.go
+++ b/metric/metrictest/alignment_test.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package oteltest
+package metrictest
 
 import (
 	"os"
diff --git a/oteltest/meter.go b/metric/metrictest/meter.go
similarity index 98%
rename from oteltest/meter.go
rename to metric/metrictest/meter.go
index bef72d23..a70d12b0 100644
--- a/oteltest/meter.go
+++ b/metric/metrictest/meter.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package oteltest // import "go.opentelemetry.io/otel/oteltest"
+package metrictest // import "go.opentelemetry.io/otel/metric/metrictest"
 
 import (
 	"context"
diff --git a/metric/registry/registry_test.go b/metric/registry/registry_test.go
index ed86ba73..3e021f13 100644
--- a/metric/registry/registry_test.go
+++ b/metric/registry/registry_test.go
@@ -22,8 +22,8 @@ import (
 	"github.com/stretchr/testify/require"
 
 	"go.opentelemetry.io/otel/metric"
+	"go.opentelemetry.io/otel/metric/metrictest"
 	"go.opentelemetry.io/otel/metric/registry"
-	"go.opentelemetry.io/otel/oteltest"
 )
 
 type (
@@ -72,7 +72,7 @@ func unwrap(impl interface{}, err error) (metric.InstrumentImpl, error) {
 
 func TestRegistrySameInstruments(t *testing.T) {
 	for _, nf := range allNew {
-		_, provider := oteltest.NewMeterProvider()
+		_, provider := metrictest.NewMeterProvider()
 
 		meter := provider.Meter("meter")
 		inst1, err1 := nf(meter, "this")
@@ -86,7 +86,7 @@ func TestRegistrySameInstruments(t *testing.T) {
 
 func TestRegistryDifferentNamespace(t *testing.T) {
 	for _, nf := range allNew {
-		_, provider := oteltest.NewMeterProvider()
+		_, provider := metrictest.NewMeterProvider()
 
 		meter1 := provider.Meter("meter1")
 		meter2 := provider.Meter("meter2")
@@ -101,7 +101,7 @@ func TestRegistryDifferentNamespace(t *testing.T) {
 
 func TestRegistryDiffInstruments(t *testing.T) {
 	for origName, origf := range allNew {
-		_, provider := oteltest.NewMeterProvider()
+		_, provider := metrictest.NewMeterProvider()
 		meter := provider.Meter("meter")
 
 		_, err := origf(meter, "this")
@@ -121,7 +121,7 @@ func TestRegistryDiffInstruments(t *testing.T) {
 }
 
 func TestMeterProvider(t *testing.T) {
-	impl, _ := oteltest.NewMeter()
+	impl, _ := metrictest.NewMeter()
 	p := registry.NewMeterProvider(impl)
 	m1 := p.Meter("m1")
 	m1p := p.Meter("m1")
diff --git a/oteltest/go.mod b/oteltest/go.mod
index f3ac5942..c6e2342f 100644
--- a/oteltest/go.mod
+++ b/oteltest/go.mod
@@ -36,6 +36,8 @@ replace go.opentelemetry.io/otel/internal/tools => ../internal/tools
 
 replace go.opentelemetry.io/otel/metric => ../metric
 
+replace go.opentelemetry.io/otel/internal/metric => ../internal/metric
+
 replace go.opentelemetry.io/otel/oteltest => ./
 
 replace go.opentelemetry.io/otel/sdk => ../sdk
@@ -49,7 +51,6 @@ replace go.opentelemetry.io/otel/trace => ../trace
 require (
 	github.com/stretchr/testify v1.7.0
 	go.opentelemetry.io/otel v0.20.0
-	go.opentelemetry.io/otel/metric v0.20.0
 	go.opentelemetry.io/otel/trace v0.20.0
 )