-
Notifications
You must be signed in to change notification settings - Fork 91
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add span attribute limit to
auto/sdk
(#1315)
* Configure span limits Add functionality to `auto/sdk` so it can interpret configuration from OTel defined environment variables for tracing limits. * Add attribute limits * Add changelog entry * Change convCappedAttrs return drop count to uint32 * Replace tests with table test * Log failure to parse env var
- Loading branch information
Showing
6 changed files
with
276 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
// Copyright The OpenTelemetry Authors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package sdk | ||
|
||
import ( | ||
"log/slog" | ||
"os" | ||
"strconv" | ||
) | ||
|
||
// maxSpan are the span limits resolved during startup. | ||
var maxSpan = newSpanLimits() | ||
|
||
type spanLimits struct { | ||
// Attrs is the number of allowed attributes for a span. | ||
// | ||
// This is resolved from the environment variable value for the | ||
// OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT key if it exists. Otherwise, the | ||
// environment variable value for OTEL_ATTRIBUTE_COUNT_LIMIT, or 128 if | ||
// that is not set, is used. | ||
Attrs int | ||
// AttrValueLen is the maximum attribute value length allowed for a span. | ||
// | ||
// This is resolved from the environment variable value for the | ||
// OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT key if it exists. Otherwise, the | ||
// environment variable value for OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT, or -1 | ||
// if that is not set, is used. | ||
AttrValueLen int | ||
// Events is the number of allowed events for a span. | ||
// | ||
// This is resolved from the environment variable value for the | ||
// OTEL_SPAN_EVENT_COUNT_LIMIT key, or 128 is used if that is not set. | ||
Events int | ||
// EventAttrs is the number of allowed attributes for a span event. | ||
// | ||
// The is resolved from the environment variable value for the | ||
// OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT key, or 128 is used if that is not set. | ||
EventAttrs int | ||
// Links is the number of allowed Links for a span. | ||
// | ||
// This is resolved from the environment variable value for the | ||
// OTEL_SPAN_LINK_COUNT_LIMIT, or 128 is used if that is not set. | ||
Links int | ||
// LinkAttrs is the number of allowed attributes for a span link. | ||
// | ||
// This is resolved from the environment variable value for the | ||
// OTEL_LINK_ATTRIBUTE_COUNT_LIMIT, or 128 is used if that is not set. | ||
LinkAttrs int | ||
} | ||
|
||
func newSpanLimits() spanLimits { | ||
return spanLimits{ | ||
Attrs: firstEnv( | ||
128, | ||
"OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT", | ||
"OTEL_ATTRIBUTE_COUNT_LIMIT", | ||
), | ||
AttrValueLen: firstEnv( | ||
-1, // Unlimited. | ||
"OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT", | ||
"OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT", | ||
), | ||
Events: firstEnv(128, "OTEL_SPAN_EVENT_COUNT_LIMIT"), | ||
EventAttrs: firstEnv(128, "OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT"), | ||
Links: firstEnv(128, "OTEL_SPAN_LINK_COUNT_LIMIT"), | ||
LinkAttrs: firstEnv(128, "OTEL_LINK_ATTRIBUTE_COUNT_LIMIT"), | ||
} | ||
} | ||
|
||
// firstEnv returns the parsed integer value of the first matching environment | ||
// variable from keys. The defaultVal is returned if the value is not an | ||
// integer or no match is found. | ||
func firstEnv(defaultVal int, keys ...string) int { | ||
for _, key := range keys { | ||
strV := os.Getenv(key) | ||
if strV == "" { | ||
continue | ||
} | ||
|
||
v, err := strconv.Atoi(strV) | ||
if err == nil { | ||
return v | ||
} | ||
slog.Warn( | ||
"invalid limit environment variable", | ||
"error", err, | ||
"key", key, | ||
"value", strV, | ||
) | ||
} | ||
|
||
return defaultVal | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
// Copyright The OpenTelemetry Authors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package sdk | ||
|
||
import ( | ||
"bytes" | ||
"encoding/json" | ||
"log/slog" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestSpanLimit(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
get func(spanLimits) int | ||
zero int | ||
keys []string | ||
}{ | ||
{ | ||
name: "AttributeValueLengthLimit", | ||
get: func(sl spanLimits) int { return sl.AttrValueLen }, | ||
zero: -1, | ||
keys: []string{ | ||
"OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT", | ||
"OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT", | ||
}, | ||
}, | ||
{ | ||
name: "AttributeCountLimit", | ||
get: func(sl spanLimits) int { return sl.Attrs }, | ||
zero: 128, | ||
keys: []string{ | ||
"OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT", | ||
"OTEL_ATTRIBUTE_COUNT_LIMIT", | ||
}, | ||
}, | ||
{ | ||
name: "EventCountLimit", | ||
get: func(sl spanLimits) int { return sl.Events }, | ||
zero: 128, | ||
keys: []string{"OTEL_SPAN_EVENT_COUNT_LIMIT"}, | ||
}, | ||
{ | ||
name: "EventAttributeCountLimit", | ||
get: func(sl spanLimits) int { return sl.EventAttrs }, | ||
zero: 128, | ||
keys: []string{"OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT"}, | ||
}, | ||
{ | ||
name: "LinkCountLimit", | ||
get: func(sl spanLimits) int { return sl.Links }, | ||
zero: 128, | ||
keys: []string{"OTEL_SPAN_LINK_COUNT_LIMIT"}, | ||
}, | ||
{ | ||
name: "LinkAttributeCountLimit", | ||
get: func(sl spanLimits) int { return sl.LinkAttrs }, | ||
zero: 128, | ||
keys: []string{"OTEL_LINK_ATTRIBUTE_COUNT_LIMIT"}, | ||
}, | ||
} | ||
|
||
for _, test := range tests { | ||
t.Run(test.name, func(t *testing.T) { | ||
t.Run("Default", func(t *testing.T) { | ||
assert.Equal(t, test.zero, test.get(newSpanLimits())) | ||
}) | ||
|
||
t.Run("ValidValue", func(t *testing.T) { | ||
for _, key := range test.keys { | ||
t.Run(key, func(t *testing.T) { | ||
t.Setenv(key, "43") | ||
assert.Equal(t, 43, test.get(newSpanLimits())) | ||
}) | ||
} | ||
}) | ||
|
||
t.Run("InvalidValue", func(t *testing.T) { | ||
for _, key := range test.keys { | ||
t.Run(key, func(t *testing.T) { | ||
orig := slog.Default() | ||
t.Cleanup(func() { slog.SetDefault(orig) }) | ||
|
||
var buf bytes.Buffer | ||
h := slog.NewJSONHandler(&buf, &slog.HandlerOptions{}) | ||
slog.SetDefault(slog.New(h)) | ||
|
||
const value = "invalid int value." | ||
t.Setenv(key, value) | ||
assert.Equal(t, test.zero, test.get(newSpanLimits())) | ||
|
||
var data map[string]any | ||
require.NoError(t, json.NewDecoder(&buf).Decode(&data)) | ||
assert.Equal(t, "invalid limit environment variable", data["msg"], "log message") | ||
assert.Equal(t, "WARN", data["level"], "logged level") | ||
assert.Equal(t, key, data["key"], "logged key") | ||
assert.Equal(t, value, data["value"], "logged value") | ||
assert.NotEmpty(t, data["error"], "logged error") | ||
}) | ||
} | ||
}) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters