Repository: open-telemetry/opentelemetry-go
Pull request #2606 (2022-02-14 03:06:33)

Add env support for span limits configuration
Closes #2307



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

[![Impacted file tree graph](https://codecov.io/gh/open-telemetry/opentelemetry-go/pull/2606/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/2606?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   #2606   +/-   ##
=====================================
  Coverage   76.2%   76.2%           
=====================================
  Files        173     173           
  Lines      12238   12243    +5     
=====================================
+ Hits        9326    9333    +7     
+ Misses      2669    2667    -2     
  Partials     243     243           
```


| [Impacted Files](https://codecov.io/gh/open-telemetry/opentelemetry-go/pull/2606?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry) | Coverage Δ | |
|---|---|---|
| [sdk/internal/env/env.go](https://codecov.io/gh/open-telemetry/opentelemetry-go/pull/2606/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry#diff-c2RrL2ludGVybmFsL2Vudi9lbnYuZ28=) | `100.0% <ø> (ø)` | |
| [sdk/trace/config.go](https://codecov.io/gh/open-telemetry/opentelemetry-go/pull/2606/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry#diff-c2RrL3RyYWNlL2NvbmZpZy5nbw==) | `100.0% <100.0%> (ø)` | |
| [sdk/trace/provider.go](https://codecov.io/gh/open-telemetry/opentelemetry-go/pull/2606/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry#diff-c2RrL3RyYWNlL3Byb3ZpZGVyLmdv) | `82.5% <100.0%> (+<0.1%)` | :arrow_up: |
| [sdk/trace/batch\_span\_processor.go](https://codecov.io/gh/open-telemetry/opentelemetry-go/pull/2606/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=open-telemetry#diff-c2RrL3RyYWNlL2JhdGNoX3NwYW5fcHJvY2Vzc29yLmdv) | `82.1% <0.0%> (+0.9%)` | :arrow_up: |

cuichenli: Hi @Aneurysm9 , I have updated the code based on the above comments. Please take a look again. Thanks!

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6b2bcfe0..59d0b7ba 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,16 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
 
 ## [Unreleased]
 
+### Added
+
+- Added support to configure the span limits with environment variables.
+  The following environment variables are used. (#2606)
+  - `OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT`
+  - `OTEL_SPAN_EVENT_COUNT_LIMIT`
+  - `OTEL_SPAN_LINK_COUNT_LIMIT`
+  
+  If the provided environment variables are invalid (negative), the default values would be used.
+
 ### Changed
 
 - Add event and link drop counts to the exported data from the `oltptrace` exporter. (#2601)
diff --git a/sdk/internal/env/env.go b/sdk/internal/env/env.go
index 397fd959..df7a0562 100644
--- a/sdk/internal/env/env.go
+++ b/sdk/internal/env/env.go
@@ -40,6 +40,21 @@ const (
 	// Note: Must be less than or equal to EnvBatchSpanProcessorMaxQueueSize
 	// i.e. 512
 	BatchSpanProcessorMaxExportBatchSizeKey = "OTEL_BSP_MAX_EXPORT_BATCH_SIZE"
+
+	// SpanAttributesCountKey
+	// Maximum allowed span attribute count
+	// Default: 128
+	SpanAttributesCountKey = "OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT"
+
+	// SpanEventCountKey
+	// Maximum allowed span event count
+	// Default: 128
+	SpanEventCountKey = "OTEL_SPAN_EVENT_COUNT_LIMIT"
+
+	// SpanLinkCountKey
+	// Maximum allowed span link count
+	// Default: 128
+	SpanLinkCountKey = "OTEL_SPAN_LINK_COUNT_LIMIT"
 )
 
 // IntEnvOr returns the int value of the environment variable with name key if
diff --git a/sdk/trace/config.go b/sdk/trace/config.go
index 61a30439..efea7b30 100644
--- a/sdk/trace/config.go
+++ b/sdk/trace/config.go
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 package trace // import "go.opentelemetry.io/otel/sdk/trace"
+import "go.opentelemetry.io/otel/sdk/internal/env"
 
 // SpanLimits represents the limits of a span.
 type SpanLimits struct {
@@ -50,14 +51,29 @@ func (sl *SpanLimits) ensureDefault() {
 	}
 }
 
+func (sl *SpanLimits) parsePotentialEnvConfigs() {
+	sl.AttributeCountLimit = env.IntEnvOr(env.SpanAttributesCountKey, sl.AttributeCountLimit)
+	sl.LinkCountLimit = env.IntEnvOr(env.SpanLinkCountKey, sl.LinkCountLimit)
+	sl.EventCountLimit = env.IntEnvOr(env.SpanEventCountKey, sl.EventCountLimit)
+}
+
 const (
 	// DefaultAttributeCountLimit is the default maximum allowed span attribute count.
+	// If not specified via WithSpanLimits, will try to retrieve the value from
+	// environment variable `OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT`.
+	// If Invalid value (negative or zero) is provided, the default value 128 will be used.
 	DefaultAttributeCountLimit = 128
 
 	// DefaultEventCountLimit is the default maximum allowed span event count.
+	// If not specified via WithSpanLimits, will try to retrieve the value from
+	// environment variable `OTEL_SPAN_EVENT_COUNT_LIMIT`.
+	// If Invalid value (negative or zero) is provided, the default value 128 will be used.
 	DefaultEventCountLimit = 128
 
 	// DefaultLinkCountLimit is the default maximum allowed span link count.
+	// If the value is not specified via WithSpanLimits, will try to retrieve the value from
+	// environment variable `OTEL_SPAN_LINK_COUNT_LIMIT`.
+	// If Invalid value (negative or zero) is provided, the default value 128 will be used.
 	DefaultLinkCountLimit = 128
 
 	// DefaultAttributePerEventCountLimit is the default maximum allowed attribute per span event count.
diff --git a/sdk/trace/provider.go b/sdk/trace/provider.go
index c6b311f9..2de79f03 100644
--- a/sdk/trace/provider.go
+++ b/sdk/trace/provider.go
@@ -98,6 +98,7 @@ var _ trace.TracerProvider = &TracerProvider{}
 func NewTracerProvider(opts ...TracerProviderOption) *TracerProvider {
 	o := tracerProviderConfig{}
 
+	o.spanLimits.parsePotentialEnvConfigs()
 	for _, opt := range opts {
 		o = opt.apply(o)
 	}


Test patch:
diff --git a/sdk/trace/provider_test.go b/sdk/trace/provider_test.go
index e2fce31d..0633889b 100644
--- a/sdk/trace/provider_test.go
+++ b/sdk/trace/provider_test.go
@@ -17,8 +17,14 @@ package trace
 import (
 	"context"
 	"errors"
+	"os"
 	"testing"
 
+	"github.com/stretchr/testify/require"
+
+	ottest "go.opentelemetry.io/otel/internal/internaltest"
+	"go.opentelemetry.io/otel/sdk/internal/env"
+
 	"github.com/stretchr/testify/assert"
 
 	"go.opentelemetry.io/otel/trace"
@@ -94,3 +100,58 @@ func TestSchemaURL(t *testing.T) {
 	tracerStruct := tracerIface.(*tracer)
 	assert.EqualValues(t, schemaURL, tracerStruct.instrumentationLibrary.SchemaURL)
 }
+
+func TestNewTraceProviderWithoutSpanLimitConfiguration(t *testing.T) {
+	envStore := ottest.NewEnvStore()
+	defer func() {
+		require.NoError(t, envStore.Restore())
+	}()
+	envStore.Record(env.SpanAttributesCountKey)
+	envStore.Record(env.SpanEventCountKey)
+	envStore.Record(env.SpanLinkCountKey)
+	require.NoError(t, os.Setenv(env.SpanEventCountKey, "111"))
+	require.NoError(t, os.Setenv(env.SpanAttributesCountKey, "222"))
+	require.NoError(t, os.Setenv(env.SpanLinkCountKey, "333"))
+	tp := NewTracerProvider()
+	assert.Equal(t, 111, tp.spanLimits.EventCountLimit)
+	assert.Equal(t, 222, tp.spanLimits.AttributeCountLimit)
+	assert.Equal(t, 333, tp.spanLimits.LinkCountLimit)
+}
+
+func TestNewTraceProviderWithSpanLimitConfigurationFromOptsAndEnvironmentVariable(t *testing.T) {
+	envStore := ottest.NewEnvStore()
+	defer func() {
+		require.NoError(t, envStore.Restore())
+	}()
+	envStore.Record(env.SpanAttributesCountKey)
+	envStore.Record(env.SpanEventCountKey)
+	envStore.Record(env.SpanLinkCountKey)
+	require.NoError(t, os.Setenv(env.SpanEventCountKey, "111"))
+	require.NoError(t, os.Setenv(env.SpanAttributesCountKey, "222"))
+	require.NoError(t, os.Setenv(env.SpanLinkCountKey, "333"))
+	tp := NewTracerProvider(WithSpanLimits(SpanLimits{
+		EventCountLimit:     1,
+		AttributeCountLimit: 2,
+		LinkCountLimit:      3,
+	}))
+	assert.Equal(t, 1, tp.spanLimits.EventCountLimit)
+	assert.Equal(t, 2, tp.spanLimits.AttributeCountLimit)
+	assert.Equal(t, 3, tp.spanLimits.LinkCountLimit)
+}
+
+func TestNewTraceProviderWithInvalidSpanLimitConfigurationFromEnvironmentVariable(t *testing.T) {
+	envStore := ottest.NewEnvStore()
+	defer func() {
+		require.NoError(t, envStore.Restore())
+	}()
+	envStore.Record(env.SpanAttributesCountKey)
+	envStore.Record(env.SpanEventCountKey)
+	envStore.Record(env.SpanLinkCountKey)
+	require.NoError(t, os.Setenv(env.SpanEventCountKey, "-111"))
+	require.NoError(t, os.Setenv(env.SpanAttributesCountKey, "-222"))
+	require.NoError(t, os.Setenv(env.SpanLinkCountKey, "-333"))
+	tp := NewTracerProvider()
+	assert.Equal(t, 128, tp.spanLimits.EventCountLimit)
+	assert.Equal(t, 128, tp.spanLimits.AttributeCountLimit)
+	assert.Equal(t, 128, tp.spanLimits.LinkCountLimit)
+}