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

Apply Splunk span limit defaults #723

Merged
merged 11 commits into from
Mar 30, 2022
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
(#720)
- The `OTEL_TRACES_SAMPLER` environment variable is now honored instead of only
defaulting to an always-on sampler. (#724)
- Set span limits to the Splunk defaults (the link count is limited to 1000,
the attribute value length is limited to 12000, and all other limts are set
to be unlimited) if they are not set by the user with environment variables.
(#723)

### Fixed

Expand Down
7 changes: 3 additions & 4 deletions distro/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,6 @@ const (
// Logging level to set when using the default logger.
otelLogLevelKey = "OTEL_LOG_LEVEL"

// FIXME: support OTEL_SPAN_LINK_COUNT_LIMIT
// FIXME: support OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT

// splunkMetricsEndpointKey defines the endpoint Splunk specific metrics
// are sent. This is not currently supported.
splunkMetricsEndpointKey = "SPLUNK_METRICS_ENDPOINT"
Expand All @@ -74,6 +71,7 @@ type exporterConfig struct {
type config struct {
Logger logr.Logger
Propagator propagation.TextMapPropagator
SpanLimits *trace.SpanLimits

ExportConfig *exporterConfig
TraceExporterFunc traceExporterFunc
Expand All @@ -82,7 +80,8 @@ type config struct {
// newConfig returns a validated config with Splunk defaults.
func newConfig(opts ...Option) *config {
c := &config{
Logger: logger(zapConfig(envOr(otelLogLevelKey, defaultLogLevel))),
Logger: logger(zapConfig(envOr(otelLogLevelKey, defaultLogLevel))),
SpanLimits: newSpanLimits(),
ExportConfig: &exporterConfig{
AccessToken: envOr(accessTokenKey, defaultAccessToken),
},
Expand Down
76 changes: 76 additions & 0 deletions distro/limits.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Copyright Splunk Inc.
//
// 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 distro

import (
"os"

"go.opentelemetry.io/otel/sdk/trace"
)

const (
attributeValueLengthKey = "OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT"
spanAttributeValueLengthKey = "OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT"
spanAttributeValueLengthDefault = 12000

attributeCountKey = "OTEL_ATTRIBUTE_COUNT_LIMIT"
spanAttributeCountKey = "OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT"
spanAttributeCountDefault = -1 // Unlimited.

spanEventCountKey = "OTEL_SPAN_EVENT_COUNT_LIMIT"
spanEventCountDefault = -1 // Unlimited.

spanEventAttributeCountKey = "OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT"
spanEventAttributeCountDefault = -1 // Unlimited.

spanLinkCountKey = "OTEL_SPAN_LINK_COUNT_LIMIT"
spanLinkCountDefault = 1000

spanLinkAttributeCountKey = "OTEL_LINK_ATTRIBUTE_COUNT_LIMIT"
spanLinkAttributeCountDefault = -1 // Unlimited.
)

// newSpanLimits returns new span limits that use Splunk defaults (the link
// count is limited to 1000, the attribute value length is limited to 12000,
// and all other limts are set to be unlimited) or the corresponding OTel
// environment variable value if it is set.
func newSpanLimits() *trace.SpanLimits {
// Use trace.NewSpanLimits here to ensure any future additions are not set
// to zero, which would happen if we delared with &trace.SpanLimits{...}.
limits := trace.NewSpanLimits()

// limits will use OTel defaults or the applicable environment variable if
// they are set. The Splunk defaults need to be applied only if the
// environment variables were unset.
limits.AttributeValueLengthLimit = limitValue(limits.AttributeValueLengthLimit, spanAttributeValueLengthDefault, attributeValueLengthKey, spanAttributeValueLengthKey)
limits.AttributeCountLimit = limitValue(limits.AttributeCountLimit, spanAttributeCountDefault, attributeCountKey, spanAttributeCountKey)
limits.EventCountLimit = limitValue(limits.EventCountLimit, spanEventCountDefault, spanEventCountKey)
limits.LinkCountLimit = limitValue(limits.LinkCountLimit, spanLinkCountDefault, spanLinkCountKey)
limits.AttributePerEventCountLimit = limitValue(limits.AttributePerEventCountLimit, spanEventAttributeCountDefault, spanEventAttributeCountKey)
limits.AttributePerLinkCountLimit = limitValue(limits.AttributePerLinkCountLimit, spanLinkAttributeCountDefault, spanLinkAttributeCountKey)

return &limits
}

// limitValue returns the current limit value if it was set because one of
// envs is defined, otherwise it returns the limit zero value.
func limitValue(current, zero int, envs ...string) int {
for _, env := range envs {
if _, ok := os.LookupEnv(env); ok {
return current
}
}
return zero
}
111 changes: 111 additions & 0 deletions distro/limits_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// Copyright Splunk Inc.
//
// 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 distro

import (
"testing"

"github.com/stretchr/testify/assert"
"go.opentelemetry.io/otel/sdk/trace"
)

func expectedSL(aLen, aN, eN, lN, aPerE, aPerL int) *trace.SpanLimits {
return &trace.SpanLimits{
AttributeValueLengthLimit: aLen,
AttributeCountLimit: aN,
EventCountLimit: eN,
LinkCountLimit: lN,
AttributePerEventCountLimit: aPerE,
AttributePerLinkCountLimit: aPerL,
}
}

func TestNewSpanLimits(t *testing.T) {
tests := []struct {
name string
envs map[string]string
want *trace.SpanLimits
}{
{
name: "defaults",
want: expectedSL(12000, -1, -1, 1000, -1, -1),
},
{
name: attributeValueLengthKey,
envs: map[string]string{
attributeValueLengthKey: "10",
},
want: expectedSL(10, -1, -1, 1000, -1, -1),
},
{
name: spanAttributeValueLengthKey,
envs: map[string]string{
spanAttributeValueLengthKey: "10",
},
want: expectedSL(10, -1, -1, 1000, -1, -1),
},
{
name: attributeCountKey,
envs: map[string]string{
attributeCountKey: "10",
},
want: expectedSL(12000, 10, -1, 1000, -1, -1),
},
{
name: spanAttributeCountKey,
envs: map[string]string{
spanAttributeCountKey: "10",
},
want: expectedSL(12000, 10, -1, 1000, -1, -1),
},
{
name: spanEventCountKey,
envs: map[string]string{
spanEventCountKey: "10",
},
want: expectedSL(12000, -1, 10, 1000, -1, -1),
},
{
name: spanEventAttributeCountKey,
envs: map[string]string{
spanEventAttributeCountKey: "10",
},
want: expectedSL(12000, -1, -1, 1000, 10, -1),
},
{
name: spanLinkCountKey,
envs: map[string]string{
spanLinkCountKey: "10",
},
want: expectedSL(12000, -1, -1, 10, -1, -1),
},
{
name: spanLinkAttributeCountKey,
envs: map[string]string{
spanLinkAttributeCountKey: "10",
},
want: expectedSL(12000, -1, -1, 1000, -1, 10),
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
for key, val := range test.envs {
t.Cleanup(Setenv(key, val))
}
assert.Equal(t, test.want, newSpanLimits())
})
}
}
1 change: 1 addition & 0 deletions distro/otel.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ func Run(opts ...Option) (SDK, error) {

o := []trace.TracerProviderOption{
trace.WithResource(res),
trace.WithRawSpanLimits(*c.SpanLimits),
trace.WithSpanProcessor(trace.NewBatchSpanProcessor(exp)),
}
if _, ok := os.LookupEnv(tracesSamplerKey); !ok {
Expand Down