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

Use strings.Cut() instead of string.SplitN() #4049

Merged
merged 1 commit into from
May 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- The `go.opentelemetry.io/otel/semconv/v1.20.0` package.
The package contains semantic conventions from the `v1.20.0` version of the OpenTelemetry specification. (#4078)

### Changed

- Use `strings.Cut()` instead of `string.SplitN()` for better readability and memory use. (#4049)

### Removed

- The deprecated `go.opentelemetry.io/otel/metric/instrument` package is removed.
Expand Down
56 changes: 24 additions & 32 deletions baggage/baggage.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,45 +289,37 @@ func parseMember(member string) (Member, error) {
props properties
)

parts := strings.SplitN(member, propertyDelimiter, 2)
switch len(parts) {
case 2:
keyValue, properties, found := strings.Cut(member, propertyDelimiter)
if found {
// Parse the member properties.
for _, pStr := range strings.Split(parts[1], propertyDelimiter) {
for _, pStr := range strings.Split(properties, propertyDelimiter) {
p, err := parseProperty(pStr)
if err != nil {
return newInvalidMember(), err
}
props = append(props, p)
}
fallthrough
case 1:
// Parse the member key/value pair.

// Take into account a value can contain equal signs (=).
kv := strings.SplitN(parts[0], keyValueDelimiter, 2)
if len(kv) != 2 {
return newInvalidMember(), fmt.Errorf("%w: %q", errInvalidMember, member)
}
// "Leading and trailing whitespaces are allowed but MUST be trimmed
// when converting the header into a data structure."
key = strings.TrimSpace(kv[0])
var err error
value, err = url.QueryUnescape(strings.TrimSpace(kv[1]))
if err != nil {
return newInvalidMember(), fmt.Errorf("%w: %q", err, value)
}
if !keyRe.MatchString(key) {
return newInvalidMember(), fmt.Errorf("%w: %q", errInvalidKey, key)
}
if !valueRe.MatchString(value) {
return newInvalidMember(), fmt.Errorf("%w: %q", errInvalidValue, value)
}
default:
// This should never happen unless a developer has changed the string
// splitting somehow. Panic instead of failing silently and allowing
// the bug to slip past the CI checks.
panic("failed to parse baggage member")
}
// Parse the member key/value pair.

// Take into account a value can contain equal signs (=).
k, v, found := strings.Cut(keyValue, keyValueDelimiter)
if !found {
return newInvalidMember(), fmt.Errorf("%w: %q", errInvalidMember, member)
}
// "Leading and trailing whitespaces are allowed but MUST be trimmed
// when converting the header into a data structure."
key = strings.TrimSpace(k)
var err error
value, err = url.QueryUnescape(strings.TrimSpace(v))
if err != nil {
return newInvalidMember(), fmt.Errorf("%w: %q", err, value)
}
if !keyRe.MatchString(key) {
return newInvalidMember(), fmt.Errorf("%w: %q", errInvalidKey, key)
}
if !valueRe.MatchString(value) {
return newInvalidMember(), fmt.Errorf("%w: %q", errInvalidValue, value)
}

return Member{key: key, value: value, properties: props, hasData: true}, nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,15 +160,13 @@ func (t *TMultiplexedProcessor) ProcessorMap() map[string]TProcessorFunction {
// the given ProcessorName or if all that is given is the FunctionName and there
// is no DefaultProcessor set.
func (t *TMultiplexedProcessor) AddToProcessorMap(name string, processorFunc TProcessorFunction) {
components := strings.SplitN(name, MULTIPLEXED_SEPARATOR, 2)
if len(components) != 2 {
if t.DefaultProcessor != nil && len(components) == 1 {
t.DefaultProcessor.AddToProcessorMap(components[0], processorFunc)
processorName, funcName, found := strings.Cut(name, MULTIPLEXED_SEPARATOR)
if !found {
if t.DefaultProcessor != nil {
t.DefaultProcessor.AddToProcessorMap(processorName, processorFunc)
}
return
}
processorName := components[0]
funcName := components[1]
if processor, ok := t.serviceProcessorMap[processorName]; ok {
processor.AddToProcessorMap(funcName, processorFunc)
}
Expand Down Expand Up @@ -197,9 +195,9 @@ func (t *TMultiplexedProcessor) Process(ctx context.Context, in, out TProtocol)
if typeId != CALL && typeId != ONEWAY {
return false, NewTProtocolException(fmt.Errorf("Unexpected message type %v", typeId))
}
//extract the service name
v := strings.SplitN(name, MULTIPLEXED_SEPARATOR, 2)
if len(v) != 2 {
// extract the service name
processorName, funcName, found := strings.Cut(name, MULTIPLEXED_SEPARATOR)
if !found {
if t.DefaultProcessor != nil {
smb := NewStoredMessageProtocol(in, name, typeId, seqid)
return t.DefaultProcessor.Process(ctx, smb, out)
Expand All @@ -209,18 +207,18 @@ func (t *TMultiplexedProcessor) Process(ctx context.Context, in, out TProtocol)
name,
))
}
actualProcessor, ok := t.serviceProcessorMap[v[0]]
actualProcessor, ok := t.serviceProcessorMap[processorName]
if !ok {
return false, NewTProtocolException(fmt.Errorf(
"Service name not found: %s. Did you forget to call registerProcessor()?",
v[0],
processorName,
))
}
smb := NewStoredMessageProtocol(in, v[1], typeId, seqid)
smb := NewStoredMessageProtocol(in, funcName, typeId, seqid)
return actualProcessor.Process(ctx, smb, out)
}

//Protocol that use stored message for ReadMessageBegin
// Protocol that use stored message for ReadMessageBegin
type storedMessageProtocol struct {
TProtocol
name string
Expand Down
14 changes: 7 additions & 7 deletions exporters/otlp/internal/envconfig/envconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,20 +166,20 @@ func stringToHeader(value string) map[string]string {
headers := make(map[string]string)

for _, header := range headersPairs {
nameValue := strings.SplitN(header, "=", 2)
if len(nameValue) < 2 {
global.Error(errors.New("missing '="), "parse headers", "input", nameValue)
n, v, found := strings.Cut(header, "=")
if !found {
global.Error(errors.New("missing '="), "parse headers", "input", header)
continue
}
name, err := url.QueryUnescape(nameValue[0])
name, err := url.QueryUnescape(n)
if err != nil {
global.Error(err, "escape header key", "key", nameValue[0])
global.Error(err, "escape header key", "key", n)
continue
}
trimmedName := strings.TrimSpace(name)
value, err := url.QueryUnescape(nameValue[1])
value, err := url.QueryUnescape(v)
if err != nil {
global.Error(err, "escape header value", "value", nameValue[1])
global.Error(err, "escape header value", "value", v)
continue
}
trimmedValue := strings.TrimSpace(value)
Expand Down
6 changes: 3 additions & 3 deletions internal/internaltest/text_map_propagator.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ func newState(encoded string) state {
if encoded == "" {
return state{}
}
split := strings.SplitN(encoded, ",", 2)
injects, _ := strconv.ParseUint(split[0], 10, 64)
extracts, _ := strconv.ParseUint(split[1], 10, 64)
s0, s1, _ := strings.Cut(encoded, ",")
injects, _ := strconv.ParseUint(s0, 10, 64)
extracts, _ := strconv.ParseUint(s1, 10, 64)
return state{
Injections: injects,
Extractions: extracts,
Expand Down
14 changes: 7 additions & 7 deletions sdk/resource/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,23 +82,23 @@ func constructOTResources(s string) (*Resource, error) {
return Empty(), nil
}
pairs := strings.Split(s, ",")
attrs := []attribute.KeyValue{}
var attrs []attribute.KeyValue
var invalid []string
for _, p := range pairs {
field := strings.SplitN(p, "=", 2)
if len(field) != 2 {
k, v, found := strings.Cut(p, "=")
if !found {
invalid = append(invalid, p)
continue
}
k := strings.TrimSpace(field[0])
v, err := url.QueryUnescape(strings.TrimSpace(field[1]))
key := strings.TrimSpace(k)
val, err := url.QueryUnescape(strings.TrimSpace(v))
if err != nil {
// Retain original value if decoding fails, otherwise it will be
// an empty string.
v = field[1]
val = v
otel.Handle(err)
}
attrs = append(attrs, attribute.String(k, v))
attrs = append(attrs, attribute.String(key, val))
}
var err error
if len(invalid) > 0 {
Expand Down
8 changes: 4 additions & 4 deletions sdk/resource/os_release_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,14 @@ func skip(line string) bool {
// parse attempts to split the provided line on the first '=' character, and then
// sanitize each side of the split before returning them as a key-value pair.
func parse(line string) (string, string, bool) {
parts := strings.SplitN(line, "=", 2)
k, v, found := strings.Cut(line, "=")

if len(parts) != 2 || len(parts[0]) == 0 {
if !found || len(k) == 0 {
return "", "", false
}

key := strings.TrimSpace(parts[0])
value := unescape(unquote(strings.TrimSpace(parts[1])))
key := strings.TrimSpace(k)
value := unescape(unquote(strings.TrimSpace(v)))

return key, value, true
}
Expand Down
8 changes: 5 additions & 3 deletions semconv/internal/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,10 +232,12 @@ func (sc *SemanticConventions) HTTPServerAttributesFromHTTPRequest(serverName, r
if route != "" {
attrs = append(attrs, sc.HTTPRouteKey.String(route))
}
if values, ok := request.Header["X-Forwarded-For"]; ok && len(values) > 0 {
if addresses := strings.SplitN(values[0], ",", 2); len(addresses) > 0 {
attrs = append(attrs, sc.HTTPClientIPKey.String(addresses[0]))
if values := request.Header["X-Forwarded-For"]; len(values) > 0 {
addr := values[0]
if i := strings.Index(addr, ","); i > 0 {
addr = addr[:i]
}
attrs = append(attrs, sc.HTTPClientIPKey.String(addr))
}
ash2k marked this conversation as resolved.
Show resolved Hide resolved

return append(attrs, sc.httpCommonAttributesFromHTTPRequest(request)...)
Expand Down