Skip to content

Commit

Permalink
Improve OTTL error message (#31233)
Browse files Browse the repository at this point in the history
**Description:**
Improve OTTL context error messages when an unknown path is used.

The new error message will look like:

```
Error: invalid configuration: processors::transform: unable to parse OTTL statement "set(attributes[\"test\"], trace_id.hex)": error while parsing arguments for call to "set": invalid argument at position 1: trace_id.hex is not a valid path for the Span context - review https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/pkg/ottl/contexts/ottlspan to see all valid paths
```

**Link to tracking Issue:** <Issue number if applicable>

Related to
#29871
Closes
#29922

**Testing:** <Describe what testing was performed and which tests were
added.>

Unit tests

---------

Co-authored-by: Evan Bradley <[email protected]>
  • Loading branch information
TylerHelmuth and evan-bradley authored Feb 23, 2024
1 parent e5aeace commit 3652b44
Show file tree
Hide file tree
Showing 11 changed files with 147 additions and 58 deletions.
22 changes: 22 additions & 0 deletions pkg/ottl/contexts/internal/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package internal // import "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl/contexts/internal"

import "fmt"

const (
DefaultErrorMessage = "segment %q from path %q is not a valid path nor a valid OTTL keyword for the %v context - review %v to see all valid paths"

ResourceContextRef = "https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/pkg/ottl/contexts/ottlresource"
InstrumentationScopeRef = "https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/pkg/ottl/contexts/ottlscope"
SpanRef = "https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/pkg/ottl/contexts/ottlspan"
SpanEventRef = "https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/pkg/ottl/contexts/ottlspanevent"
MetricRef = "https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/pkg/ottl/contexts/ottlmetric"
DataPointRef = "https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/pkg/ottl/contexts/ottldatapoint"
LogRef = "https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/pkg/ottl/contexts/ottllog"
)

func FormatDefaultErrorMessage(pathSegment, fullPath, context, ref string) error {
return fmt.Errorf(DefaultErrorMessage, pathSegment, fullPath, context, ref)
}
3 changes: 1 addition & 2 deletions pkg/ottl/contexts/internal/metric.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ package internal // import "github.com/open-telemetry/opentelemetry-collector-co

import (
"context"
"fmt"

"go.opentelemetry.io/collector/pdata/pmetric"

Expand Down Expand Up @@ -48,7 +47,7 @@ func MetricPathGetSetter[K MetricContext](path ottl.Path[K]) (ottl.GetSetter[K],
case "data_points":
return accessDataPoints[K](), nil
default:
return nil, fmt.Errorf("invalid metric path expression %v", path)
return nil, FormatDefaultErrorMessage(path.Name(), path.String(), "Metric", MetricRef)
}
}

Expand Down
4 changes: 4 additions & 0 deletions pkg/ottl/contexts/internal/path.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ func (p *TestPath[K]) Keys() []ottl.Key[K] {
return p.KeySlice
}

func (p *TestPath[K]) String() string {
return p.N
}

var _ ottl.Key[any] = &TestKey[any]{}

type TestKey[K any] struct {
Expand Down
3 changes: 1 addition & 2 deletions pkg/ottl/contexts/internal/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ package internal // import "github.com/open-telemetry/opentelemetry-collector-co

import (
"context"
"fmt"

"go.opentelemetry.io/collector/pdata/pcommon"

Expand All @@ -29,7 +28,7 @@ func ResourcePathGetSetter[K ResourceContext](path ottl.Path[K]) (ottl.GetSetter
case "dropped_attributes_count":
return accessResourceDroppedAttributesCount[K](), nil
default:
return nil, fmt.Errorf("invalid resource path expression %v", path)
return nil, FormatDefaultErrorMessage(path.Name(), path.String(), "Resource", ResourceContextRef)
}
}

Expand Down
3 changes: 1 addition & 2 deletions pkg/ottl/contexts/internal/scope.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ package internal // import "github.com/open-telemetry/opentelemetry-collector-co

import (
"context"
"fmt"

"go.opentelemetry.io/collector/pdata/pcommon"

Expand Down Expand Up @@ -34,7 +33,7 @@ func ScopePathGetSetter[K InstrumentationScopeContext](path ottl.Path[K]) (ottl.
case "dropped_attributes_count":
return accessInstrumentationScopeDroppedAttributesCount[K](), nil
default:
return nil, fmt.Errorf("invalid scope path expression %v", path)
return nil, FormatDefaultErrorMessage(path.Name(), path.String(), "Instrumentation Scope", InstrumentationScopeRef)
}
}

Expand Down
44 changes: 25 additions & 19 deletions pkg/ottl/contexts/internal/span.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ import (
"github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl"
)

const (
SpanContextName = "Span"
)

type SpanContext interface {
GetSpan() ptrace.Span
}
Expand All @@ -39,35 +43,38 @@ func SpanPathGetSetter[K SpanContext](path ottl.Path[K]) (ottl.GetSetter[K], err
}
switch path.Name() {
case "trace_id":
if path.Next() != nil {
if path.Next().Name() == "string" {
nextPath := path.Next()
if nextPath != nil {
if nextPath.Name() == "string" {
return accessStringTraceID[K](), nil
}
} else {
return accessTraceID[K](), nil
return nil, FormatDefaultErrorMessage(nextPath.Name(), nextPath.String(), SpanContextName, SpanRef)
}
return accessTraceID[K](), nil
case "span_id":
if path.Next() != nil {
if path.Next().Name() == "string" {
nextPath := path.Next()
if nextPath != nil {
if nextPath.Name() == "string" {
return accessStringSpanID[K](), nil
}
} else {
return accessSpanID[K](), nil
return nil, FormatDefaultErrorMessage(nextPath.Name(), nextPath.String(), SpanContextName, SpanRef)
}
return accessSpanID[K](), nil
case "trace_state":
mapKey := path.Keys()
if mapKey == nil {
return accessTraceState[K](), nil
}
return accessTraceStateKey[K](mapKey)
case "parent_span_id":
if path.Next() != nil {
if path.Next().Name() == "string" {
nextPath := path.Next()
if nextPath != nil {
if nextPath.Name() == "string" {
return accessStringParentSpanID[K](), nil
}
} else {
return accessParentSpanID[K](), nil
return nil, FormatDefaultErrorMessage(nextPath.Name(), nextPath.String(), SpanContextName, SpanRef)
}
return accessParentSpanID[K](), nil
case "name":
return accessSpanName[K](), nil
case "kind":
Expand All @@ -79,11 +86,10 @@ func SpanPathGetSetter[K SpanContext](path ottl.Path[K]) (ottl.GetSetter[K], err
case "deprecated_string":
return accessDeprecatedStringKind[K](), nil
default:
return nil, fmt.Errorf("invalid span path expression %v", nextPath.Name())
return nil, FormatDefaultErrorMessage(nextPath.Name(), nextPath.String(), SpanContextName, SpanRef)
}
} else {
return accessKind[K](), nil
}
return accessKind[K](), nil
case "start_time_unix_nano":
return accessStartTimeUnixNano[K](), nil
case "end_time_unix_nano":
Expand Down Expand Up @@ -117,13 +123,13 @@ func SpanPathGetSetter[K SpanContext](path ottl.Path[K]) (ottl.GetSetter[K], err
case "message":
return accessStatusMessage[K](), nil
default:
return nil, fmt.Errorf("invalid span path expression %v", nextPath.Name())
return nil, FormatDefaultErrorMessage(nextPath.Name(), nextPath.String(), SpanContextName, SpanRef)
}
} else {
return accessStatus[K](), nil
}
return accessStatus[K](), nil
default:
return nil, FormatDefaultErrorMessage(path.Name(), path.String(), SpanContextName, SpanRef)
}
return nil, fmt.Errorf("invalid span path expression %v", path)
}

func accessSpan[K SpanContext]() ottl.StandardGetSetter[K] {
Expand Down
17 changes: 10 additions & 7 deletions pkg/ottl/contexts/ottldatapoint/datapoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ import (
"github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl/contexts/internal"
)

const (
contextName = "DataPoint"
)

var _ internal.ResourceContext = TransformContext{}
var _ internal.InstrumentationScopeContext = TransformContext{}

Expand Down Expand Up @@ -197,11 +201,10 @@ func (pep *pathExpressionParser) parsePath(path ottl.Path[TransformContext]) (ot
case "bucket_counts":
return accessPositiveBucketCounts(), nil
default:
return nil, fmt.Errorf("invalid span path expression %v", nextPath.Name())
return nil, internal.FormatDefaultErrorMessage(nextPath.Name(), path.String(), contextName, internal.DataPointRef)
}
} else {
return accessPositive(), nil
}
return accessPositive(), nil
case "negative":
nextPath := path.Next()
if nextPath != nil {
Expand All @@ -211,15 +214,15 @@ func (pep *pathExpressionParser) parsePath(path ottl.Path[TransformContext]) (ot
case "bucket_counts":
return accessNegativeBucketCounts(), nil
default:
return nil, fmt.Errorf("invalid span path expression %v", nextPath.Name())
return nil, internal.FormatDefaultErrorMessage(nextPath.Name(), path.String(), contextName, internal.DataPointRef)
}
} else {
return accessNegative(), nil
}
return accessNegative(), nil
case "quantile_values":
return accessQuantileValues(), nil
default:
return nil, internal.FormatDefaultErrorMessage(path.Name(), path.String(), contextName, internal.DataPointRef)
}
return nil, fmt.Errorf("invalid path expression %v", path)
}

func accessCache() ottl.StandardGetSetter[TransformContext] {
Expand Down
40 changes: 24 additions & 16 deletions pkg/ottl/contexts/ottllog/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ import (
"github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl/internal/ottlcommon"
)

const (
contextName = "Log"
)

var _ internal.ResourceContext = TransformContext{}
var _ internal.InstrumentationScopeContext = TransformContext{}

Expand Down Expand Up @@ -173,16 +177,17 @@ func (pep *pathExpressionParser) parsePath(path ottl.Path[TransformContext]) (ot
case "severity_text":
return accessSeverityText(), nil
case "body":
if path.Next() != nil {
if path.Next().Name() == "string" {
nextPath := path.Next()
if nextPath != nil {
if nextPath.Name() == "string" {
return accessStringBody(), nil
}
} else {
if path.Keys() == nil {
return accessBody(), nil
}
return accessBodyKey(path.Keys()), nil
return nil, internal.FormatDefaultErrorMessage(nextPath.Name(), nextPath.String(), contextName, internal.LogRef)
}
if path.Keys() == nil {
return accessBody(), nil
}
return accessBodyKey(path.Keys()), nil
case "attributes":
if path.Keys() == nil {
return accessAttributes(), nil
Expand All @@ -193,23 +198,26 @@ func (pep *pathExpressionParser) parsePath(path ottl.Path[TransformContext]) (ot
case "flags":
return accessFlags(), nil
case "trace_id":
if path.Next() != nil {
if path.Next().Name() == "string" {
nextPath := path.Next()
if nextPath != nil {
if nextPath.Name() == "string" {
return accessStringTraceID(), nil
}
} else {
return accessTraceID(), nil
return nil, internal.FormatDefaultErrorMessage(nextPath.Name(), nextPath.String(), contextName, internal.LogRef)
}
return accessTraceID(), nil
case "span_id":
if path.Next() != nil {
if path.Next().Name() == "string" {
nextPath := path.Next()
if nextPath != nil {
if nextPath.Name() == "string" {
return accessStringSpanID(), nil
}
} else {
return accessSpanID(), nil
return nil, internal.FormatDefaultErrorMessage(nextPath.Name(), path.String(), contextName, internal.LogRef)
}
return accessSpanID(), nil
default:
return nil, internal.FormatDefaultErrorMessage(path.Name(), path.String(), contextName, internal.LogRef)
}
return nil, fmt.Errorf("invalid path expression %v", path)
}

func accessCache() ottl.StandardGetSetter[TransformContext] {
Expand Down
3 changes: 2 additions & 1 deletion pkg/ottl/contexts/ottlspanevent/span_events.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,10 @@ func (pep *pathExpressionParser) parsePath(path ottl.Path[TransformContext]) (ot
return accessSpanEventAttributesKey(path.Keys()), nil
case "dropped_attributes_count":
return accessSpanEventDroppedAttributeCount(), nil
default:
return nil, internal.FormatDefaultErrorMessage(path.Name(), path.String(), "Span Event", internal.SpanEventRef)
}

return nil, fmt.Errorf("invalid scope path expression %v", path)
}
func accessCache() ottl.StandardGetSetter[TransformContext] {
return ottl.StandardGetSetter[TransformContext]{
Expand Down
Loading

0 comments on commit 3652b44

Please sign in to comment.