Repository: lightstep/otel-launcher-go (go)

Issue:
Implement "lowmemory" (was "stateless")
**Is your feature request related to a problem? Please describe.**

https://github.com/open-telemetry/opentelemetry-specification/issues/2738

**Describe the solution you'd like**

Add "lowmemory" equal to the current "stateless" preference.


Pull request description:
Add lowmemory preference, keep stateless as an alias
Update "stateless" names to "lowmemory" throughout the code, for clarity.

**Description:** 

**Link to tracking Issue:** 

Fixes #347.

**Documentation:** Updated.

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 50d01a8..abe3acd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
 
 ## Unreleased
 
+- Add "lowmemory" temporality naming, leaving "stateless" as an alias. [#597](https://github.com/lightstep/otel-launcher-go/pull/597)
+
 ## [1.23.0](https://github.com/lightstep/otel-launcher-go/releases/tag/v1.23.0) - 2023-12-20)
 
 - Update to OTel-Arrow v0.13.0 dependencies. [#591](https://github.com/lightstep/otel-launcher-go/pull/591)
diff --git a/README.md b/README.md
index ef3f3cd..3ee6842 100644
--- a/README.md
+++ b/README.md
@@ -188,16 +188,16 @@ to be maintained.  The temporality preference is configured by calling
 `OTEL_EXPORTER_OTLP_METRIC_TEMPORALITY_PREFERENCE` environment
 variable.
 
-The launcher supports a "stateless" temporality preference.  This
-selection configures the ideal behavior for Lightstep by mixing
-temporality setings.
+The launcher supports the standard "lowmemory" temporality preference,
+also known as "stateless" in this library.  This selection configures
+the ideal behavior for Lightstep by mixing temporality setings.
 
 The 1.x launcher release series configures the "cumulative"
 temporality preference by default.  The next major release of launcher
-will configure the "stateless" temporality preference.
+will configure the "lowmemory" temporality preference.
 
 Lightstep users are recommended to select either the "cumulative" or
-"stateless" preference.  The OpenTelemetry-specified "delta"
+"lowmemory" preference.  The OpenTelemetry-specified "delta"
 temporality preference is not recommended for Lightstep users.
 
 ------
diff --git a/lightstep/sdk/metric/README.md b/lightstep/sdk/metric/README.md
index d0af584..583b1bf 100644
--- a/lightstep/sdk/metric/README.md
+++ b/lightstep/sdk/metric/README.md
@@ -25,7 +25,7 @@ Differences from the OpenTelemetry metrics SDK specification:
    point](https://opentelemetry.io/docs/reference/specification/metrics/datamodel/#histogram).
    Note that this aggregation only encodes the `.Min` and `.Max`
    fields when configured with delta temporality.  [Consider using the
-   "stateless" temporality preference in the launcher.](../../../README.md#temporality-settings).
+   "lowmemory" temporality preference in the launcher.](../../../README.md#temporality-settings).
 3. Synchronous Gauge instrument behavior is [supported using an API 
    hint](#metric-instrument-hints-api).
 4. The OTLP exporter is the only provided exporter.  The OTLP exporter
diff --git a/lightstep/sdk/metric/internal/viewstate/collectors.go b/lightstep/sdk/metric/internal/viewstate/collectors.go
index 97642bd..dd2a7b3 100644
--- a/lightstep/sdk/metric/internal/viewstate/collectors.go
+++ b/lightstep/sdk/metric/internal/viewstate/collectors.go
@@ -42,13 +42,13 @@ func (p *statefulSyncInstrument[N, Storage, Methods]) Collect(seq data.Sequence,
 	}
 }
 
-// statelessSyncInstrument is a synchronous instrument that maintains no state.
-type statelessSyncInstrument[N number.Any, Storage any, Methods aggregator.Methods[N, Storage]] struct {
+// lowmemorySyncInstrument is a synchronous instrument that maintains no state.
+type lowmemorySyncInstrument[N number.Any, Storage any, Methods aggregator.Methods[N, Storage]] struct {
 	compiledSyncBase[N, Storage, Methods]
 }
 
 // Collect for synchronous delta temporality.
-func (p *statelessSyncInstrument[N, Storage, Methods]) Collect(seq data.Sequence, output *[]data.Instrument) {
+func (p *lowmemorySyncInstrument[N, Storage, Methods]) Collect(seq data.Sequence, output *[]data.Instrument) {
 	var methods Methods
 
 	p.instLock.Lock()
@@ -91,14 +91,14 @@ func (p *statelessSyncInstrument[N, Storage, Methods]) Collect(seq data.Sequence
 	}
 }
 
-// statelessAsyncInstrument is an asynchronous instrument that keeps
+// lowmemoryAsyncInstrument is an asynchronous instrument that keeps
 // maintains no state.
-type statelessAsyncInstrument[N number.Any, Storage any, Methods aggregator.Methods[N, Storage]] struct {
+type lowmemoryAsyncInstrument[N number.Any, Storage any, Methods aggregator.Methods[N, Storage]] struct {
 	compiledAsyncBase[N, Storage, Methods]
 }
 
 // Collect for asynchronous cumulative temporality.
-func (p *statelessAsyncInstrument[N, Storage, Methods]) Collect(seq data.Sequence, output *[]data.Instrument) {
+func (p *lowmemoryAsyncInstrument[N, Storage, Methods]) Collect(seq data.Sequence, output *[]data.Instrument) {
 	p.instLock.Lock()
 	defer p.instLock.Unlock()
 
diff --git a/lightstep/sdk/metric/internal/viewstate/viewstate.go b/lightstep/sdk/metric/internal/viewstate/viewstate.go
index e403316..3ead627 100644
--- a/lightstep/sdk/metric/internal/viewstate/viewstate.go
+++ b/lightstep/sdk/metric/internal/viewstate/viewstate.go
@@ -410,9 +410,9 @@ func buildView[N number.Any, Traits number.Traits[N]](behavior singleBehavior) l
 }
 
 // newSyncView returns a compiled synchronous instrument.  If the view
-// calls for delta temporality, a stateless instrument is returned,
+// calls for delta temporality, a lowmemory instrument is returned,
 // otherwise for cumulative temporality a stateful instrument will be
-// used.  I.e., Delta->Stateless, Cumulative->Stateful.
+// used.  I.e., Delta->Lowmemory, Cumulative->Stateful.
 func newSyncView[
 	N number.Any,
 	Storage any,
@@ -435,7 +435,7 @@ func newSyncView[
 		instrumentBase: metric, //nolint:govet
 	}
 	if behavior.tempo == aggregation.DeltaTemporality {
-		return &statelessSyncInstrument[N, Storage, Methods]{
+		return &lowmemorySyncInstrument[N, Storage, Methods]{
 			compiledSyncBase: instrument, //nolint:govet
 		}
 	}
@@ -487,8 +487,8 @@ func compileSync[N number.Any, Traits number.Traits[N]](behavior singleBehavior)
 
 // newAsyncView returns a compiled asynchronous instrument.  If the
 // view calls for delta temporality, a stateful instrument is
-// returned, otherwise for cumulative temporality a stateless
-// instrument will be used.  I.e., Cumulative->Stateless,
+// returned, otherwise for cumulative temporality a lowmemory
+// instrument will be used.  I.e., Cumulative->Lowmemory,
 // Delta->Stateful.
 func newAsyncView[
 	N number.Any,
@@ -518,11 +518,11 @@ func newAsyncView[
 				compiledAsyncBase: instrument, //nolint:govet
 			}
 		}
-		// Gauges fall through to the stateless behavior
+		// Gauges fall through to the lowmemory behavior
 		// regardless of delta temporality.
 	}
 
-	return &statelessAsyncInstrument[N, Storage, Methods]{
+	return &lowmemoryAsyncInstrument[N, Storage, Methods]{
 		compiledAsyncBase: instrument, //nolint:govet
 	}
 }
diff --git a/pipelines/common.go b/pipelines/common.go
index 4ae453a..26efc7b 100644
--- a/pipelines/common.go
+++ b/pipelines/common.go
@@ -52,7 +52,7 @@ type PipelineConfig struct {
 	//  cputime: v1 is lightstep/instrumentation/cputime
 	MetricsBuiltinLibraries []string
 
-	// TemporalityPreference is one of "cumulative", "delta", or "stateless"
+	// TemporalityPreference is one of "cumulative", "delta", or "lowmemory" (a.k.a. "stateless")
 	TemporalityPreference string
 
 	// Credentials carries the TLS settings.
diff --git a/pipelines/metrics.go b/pipelines/metrics.go
index f928bc9..97bb288 100644
--- a/pipelines/metrics.go
+++ b/pipelines/metrics.go
@@ -249,7 +249,7 @@ func tempoOptions(c PipelineConfig) (view.Option, otelsdkmetric.TemporalitySelec
 		otelSelector = func(otelsdkmetric.InstrumentKind) metricdata.Temporality {
 			return metricdata.DeltaTemporality
 		}
-	case "stateless":
+	case "stateless", "lowmemory":
 		// asyncPref set above.
 		syncPref = aggregation.DeltaTemporality
 


Test patch:
diff --git a/launcher/config_test.go b/launcher/config_test.go
index 0ca6d75..70e8c22 100644
--- a/launcher/config_test.go
+++ b/launcher/config_test.go
@@ -417,7 +417,7 @@ func (suite *testSuite) TestConfigurationOverrides() {
 		WithSpanExporterInsecure(false),
 		WithMetricExporterEndpoint("override-metrics-url"),
 		WithMetricExporterInsecure(false),
-		WithMetricExporterTemporalityPreference("stateless"),
+		WithMetricExporterTemporalityPreference("lowmemory"),
 		WithLogLevel("info"),
 		WithLogger(&suite.testLogger),
 		WithErrorHandler(&suite.testErrorHandler),
@@ -447,7 +447,7 @@ func (suite *testSuite) TestConfigurationOverrides() {
 		MetricExporterEndpoint:              "override-metrics-url",
 		MetricExporterEndpointInsecure:      false,
 		MetricReportingPeriod:               "30s",
-		MetricExporterTemporalityPreference: "stateless",
+		MetricExporterTemporalityPreference: "lowmemory",
 		Headers:                             map[string]string{"lightstep-access-token": "override-access-token"},
 		LogLevel:                            "info",
 		Propagators:                         []string{"b3"},
diff --git a/lightstep/sdk/metric/internal/viewstate/viewstate_test.go b/lightstep/sdk/metric/internal/viewstate/viewstate_test.go
index b99d182..c227cdd 100644
--- a/lightstep/sdk/metric/internal/viewstate/viewstate_test.go
+++ b/lightstep/sdk/metric/internal/viewstate/viewstate_test.go
@@ -1393,7 +1393,7 @@ func TestSyncDeltaTemporalityMapDeletion(t *testing.T) {
 	acc2.(Updater[float64]).Update(1)
 
 	// There are two references to one entry in the map.
-	require.Equal(t, 1, len(inst.(*statelessSyncInstrument[float64, sum.MonotonicFloat64, sum.MonotonicFloat64Methods]).data))
+	require.Equal(t, 1, len(inst.(*lowmemorySyncInstrument[float64, sum.MonotonicFloat64, sum.MonotonicFloat64Methods]).data))
 
 	acc1.SnapshotAndProcess(false)
 	acc2.SnapshotAndProcess(true)
@@ -1408,7 +1408,7 @@ func TestSyncDeltaTemporalityMapDeletion(t *testing.T) {
 		),
 	)
 
-	require.Equal(t, 1, len(inst.(*statelessSyncInstrument[float64, sum.MonotonicFloat64, sum.MonotonicFloat64Methods]).data))
+	require.Equal(t, 1, len(inst.(*lowmemorySyncInstrument[float64, sum.MonotonicFloat64, sum.MonotonicFloat64Methods]).data))
 
 	acc1.SnapshotAndProcess(true)
 
@@ -1419,7 +1419,7 @@ func TestSyncDeltaTemporalityMapDeletion(t *testing.T) {
 		),
 	)
 
-	require.Equal(t, 0, len(inst.(*statelessSyncInstrument[float64, sum.MonotonicFloat64, sum.MonotonicFloat64Methods]).data))
+	require.Equal(t, 0, len(inst.(*lowmemorySyncInstrument[float64, sum.MonotonicFloat64, sum.MonotonicFloat64Methods]).data))
 }
 
 func TestRegexpMatch(t *testing.T) {