Files
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
e57aaeecc5 Bump the opentelemetry-contrib group with 8 updates (#5474)
Bumps the opentelemetry-contrib group with 8 updates:

| Package | From | To |
| --- | --- | --- |
| [github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/jaeger](https://github.com/open-telemetry/opentelemetry-collector-contrib) | `0.130.0` | `0.131.0` |
| [github.com/open-telemetry/opentelemetry-collector-contrib/exporter/zipkinexporter](https://github.com/open-telemetry/opentelemetry-collector-contrib) | `0.130.0` | `0.131.0` |
| [github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl](https://github.com/open-telemetry/opentelemetry-collector-contrib) | `0.130.0` | `0.131.0` |
| [github.com/open-telemetry/opentelemetry-collector-contrib/processor/filterprocessor](https://github.com/open-telemetry/opentelemetry-collector-contrib) | `0.130.0` | `0.131.0` |
| [github.com/open-telemetry/opentelemetry-collector-contrib/receiver/jaegerreceiver](https://github.com/open-telemetry/opentelemetry-collector-contrib) | `0.130.0` | `0.131.0` |
| [github.com/open-telemetry/opentelemetry-collector-contrib/receiver/kafkareceiver](https://github.com/open-telemetry/opentelemetry-collector-contrib) | `0.130.0` | `0.131.0` |
| [github.com/open-telemetry/opentelemetry-collector-contrib/receiver/opencensusreceiver](https://github.com/open-telemetry/opentelemetry-collector-contrib) | `0.130.0` | `0.131.0` |
| [github.com/open-telemetry/opentelemetry-collector-contrib/receiver/zipkinreceiver](https://github.com/open-telemetry/opentelemetry-collector-contrib) | `0.130.0` | `0.131.0` |


Updates `github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/jaeger` from 0.130.0 to 0.131.0
- [Release notes](https://github.com/open-telemetry/opentelemetry-collector-contrib/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/CHANGELOG-API.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-collector-contrib/compare/v0.130.0...v0.131.0)

Updates `github.com/open-telemetry/opentelemetry-collector-contrib/exporter/zipkinexporter` from 0.130.0 to 0.131.0
- [Release notes](https://github.com/open-telemetry/opentelemetry-collector-contrib/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/CHANGELOG-API.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-collector-contrib/compare/v0.130.0...v0.131.0)

Updates `github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl` from 0.130.0 to 0.131.0
- [Release notes](https://github.com/open-telemetry/opentelemetry-collector-contrib/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/CHANGELOG-API.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-collector-contrib/compare/v0.130.0...v0.131.0)

Updates `github.com/open-telemetry/opentelemetry-collector-contrib/processor/filterprocessor` from 0.130.0 to 0.131.0
- [Release notes](https://github.com/open-telemetry/opentelemetry-collector-contrib/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/CHANGELOG-API.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-collector-contrib/compare/v0.130.0...v0.131.0)

Updates `github.com/open-telemetry/opentelemetry-collector-contrib/receiver/jaegerreceiver` from 0.130.0 to 0.131.0
- [Release notes](https://github.com/open-telemetry/opentelemetry-collector-contrib/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/CHANGELOG-API.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-collector-contrib/compare/v0.130.0...v0.131.0)

Updates `github.com/open-telemetry/opentelemetry-collector-contrib/receiver/kafkareceiver` from 0.130.0 to 0.131.0
- [Release notes](https://github.com/open-telemetry/opentelemetry-collector-contrib/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/CHANGELOG-API.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-collector-contrib/compare/v0.130.0...v0.131.0)

Updates `github.com/open-telemetry/opentelemetry-collector-contrib/receiver/opencensusreceiver` from 0.130.0 to 0.131.0
- [Release notes](https://github.com/open-telemetry/opentelemetry-collector-contrib/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/CHANGELOG-API.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-collector-contrib/compare/v0.130.0...v0.131.0)

Updates `github.com/open-telemetry/opentelemetry-collector-contrib/receiver/zipkinreceiver` from 0.130.0 to 0.131.0
- [Release notes](https://github.com/open-telemetry/opentelemetry-collector-contrib/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/CHANGELOG-API.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-collector-contrib/compare/v0.130.0...v0.131.0)

---
updated-dependencies:
- dependency-name: github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/jaeger
  dependency-version: 0.131.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: opentelemetry-contrib
- dependency-name: github.com/open-telemetry/opentelemetry-collector-contrib/exporter/zipkinexporter
  dependency-version: 0.131.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: opentelemetry-contrib
- dependency-name: github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl
  dependency-version: 0.131.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: opentelemetry-contrib
- dependency-name: github.com/open-telemetry/opentelemetry-collector-contrib/processor/filterprocessor
  dependency-version: 0.131.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: opentelemetry-contrib
- dependency-name: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/jaegerreceiver
  dependency-version: 0.131.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: opentelemetry-contrib
- dependency-name: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/kafkareceiver
  dependency-version: 0.131.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: opentelemetry-contrib
- dependency-name: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/opencensusreceiver
  dependency-version: 0.131.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: opentelemetry-contrib
- dependency-name: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/zipkinreceiver
  dependency-version: 0.131.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: opentelemetry-contrib
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-13 10:28:40 +00:00

597 lines
13 KiB
Go

// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package ottl // import "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl"
import (
"encoding/hex"
"fmt"
"strings"
"github.com/alecthomas/participle/v2/lexer"
)
// parsedStatement represents a parsed statement. It is the entry point into the statement DSL.
type parsedStatement struct {
Editor editor `parser:"(@@"`
// If converter is matched then return error
Converter *converter `parser:"|@@)"`
WhereClause *booleanExpression `parser:"( 'where' @@ )?"`
}
func (p *parsedStatement) checkForCustomError() error {
validator := &grammarCustomErrorsVisitor{}
if p.Converter != nil {
validator.add(fmt.Errorf("editor names must start with a lowercase letter but got '%v'", p.Converter.Function))
}
p.Editor.accept(validator)
if p.WhereClause != nil {
p.WhereClause.accept(validator)
}
return validator.join()
}
type constExpr struct {
Boolean *boolean `parser:"( @Boolean"`
Converter *converter `parser:"| @@ )"`
}
// booleanValue represents something that evaluates to a boolean --
// either an equality or inequality, explicit true or false, or
// a parenthesized subexpression.
type booleanValue struct {
Negation *string `parser:"@OpNot?"`
Comparison *comparison `parser:"( @@"`
ConstExpr *constExpr `parser:"| @@"`
SubExpr *booleanExpression `parser:"| '(' @@ ')' )"`
}
func (b *booleanValue) accept(v grammarVisitor) {
if b.Comparison != nil {
b.Comparison.accept(v)
}
if b.ConstExpr != nil && b.ConstExpr.Converter != nil {
b.ConstExpr.Converter.accept(v)
}
if b.SubExpr != nil {
b.SubExpr.accept(v)
}
}
// opAndBooleanValue represents the right side of an AND boolean expression.
type opAndBooleanValue struct {
Operator string `parser:"@OpAnd"`
Value *booleanValue `parser:"@@"`
}
func (b *opAndBooleanValue) accept(v grammarVisitor) {
if b.Value != nil {
b.Value.accept(v)
}
}
// term represents an arbitrary number of boolean values joined by AND.
type term struct {
Left *booleanValue `parser:"@@"`
Right []*opAndBooleanValue `parser:"@@*"`
}
func (b *term) accept(v grammarVisitor) {
if b.Left != nil {
b.Left.accept(v)
}
for _, r := range b.Right {
if r != nil {
r.accept(v)
}
}
}
// opOrTerm represents the right side of an OR boolean expression.
type opOrTerm struct {
Operator string `parser:"@OpOr"`
Term *term `parser:"@@"`
}
func (b *opOrTerm) accept(v grammarVisitor) {
if b.Term != nil {
b.Term.accept(v)
}
}
// booleanExpression represents a true/false decision expressed
// as an arbitrary number of terms separated by OR.
type booleanExpression struct {
Left *term `parser:"@@"`
Right []*opOrTerm `parser:"@@*"`
}
func (b *booleanExpression) checkForCustomError() error {
validator := &grammarCustomErrorsVisitor{}
b.accept(validator)
return validator.join()
}
func (b *booleanExpression) accept(v grammarVisitor) {
if b.Left != nil {
b.Left.accept(v)
}
for _, r := range b.Right {
if r != nil {
r.accept(v)
}
}
}
// compareOp is the type of a comparison operator.
type compareOp int
// These are the allowed values of a compareOp
const (
eq compareOp = iota
ne
lt
lte
gte
gt
)
// a fast way to get from a string to a compareOp
var compareOpTable = map[string]compareOp{
"==": eq,
"!=": ne,
"<": lt,
"<=": lte,
">": gt,
">=": gte,
}
// Capture is how the parser converts an operator string to a compareOp.
func (c *compareOp) Capture(values []string) error {
op, ok := compareOpTable[values[0]]
if !ok {
return fmt.Errorf("'%s' is not a valid operator", values[0])
}
*c = op
return nil
}
// String() for compareOp gives us more legible test results and error messages.
func (c *compareOp) String() string {
switch *c {
case eq:
return "eq"
case ne:
return "ne"
case lt:
return "lt"
case lte:
return "lte"
case gte:
return "gte"
case gt:
return "gt"
default:
return "UNKNOWN OP!"
}
}
// comparison represents an optional boolean condition.
type comparison struct {
Left value `parser:"@@"`
Op compareOp `parser:"@OpComparison"`
Right value `parser:"@@"`
}
func (c *comparison) accept(v grammarVisitor) {
c.Left.accept(v)
c.Right.accept(v)
}
// editor represents the function call of a statement.
type editor struct {
Function string `parser:"@(Lowercase(Uppercase | Lowercase)*)"`
Arguments []argument `parser:"'(' ( @@ ( ',' @@ )* )? ')'"`
// If keys are matched return an error
Keys []key `parser:"( @@ )*"`
}
func (i *editor) accept(v grammarVisitor) {
v.visitEditor(i)
for _, arg := range i.Arguments {
arg.accept(v)
}
}
// converter represents a converter function call.
type converter struct {
Function string `parser:"@(Uppercase(Uppercase | Lowercase)*)"`
Arguments []argument `parser:"'(' ( @@ ( ',' @@ )* )? ')'"`
Keys []key `parser:"( @@ )*"`
}
func (c *converter) accept(v grammarVisitor) {
v.visitConverter(c)
if c.Arguments != nil {
for _, a := range c.Arguments {
a.accept(v)
}
}
}
type argument struct {
Name string `parser:"(@(Lowercase(Uppercase | Lowercase)*) Equal)?"`
Value value `parser:"( @@"`
FunctionName *string `parser:"| @(Uppercase(Uppercase | Lowercase)*) )"`
}
func (a *argument) accept(v grammarVisitor) {
a.Value.accept(v)
}
// value represents a part of a parsed statement which is resolved to a value of some sort. This can be a telemetry path
// mathExpression, function call, or literal.
type value struct {
IsNil *isNil `parser:"( @'nil'"`
Literal *mathExprLiteral `parser:"| @@ (?! OpAddSub | OpMultDiv)"`
MathExpression *mathExpression `parser:"| @@"`
Bytes *byteSlice `parser:"| @Bytes"`
String *string `parser:"| @String"`
Bool *boolean `parser:"| @Boolean"`
Enum *enumSymbol `parser:"| @Uppercase (?! Lowercase)"`
Map *mapValue `parser:"| @@"`
List *list `parser:"| @@)"`
}
func (v *value) checkForCustomError() error {
validator := &grammarCustomErrorsVisitor{}
v.accept(validator)
return validator.join()
}
func (v *value) accept(vis grammarVisitor) {
vis.visitValue(v)
if v.Literal != nil {
v.Literal.accept(vis)
}
if v.MathExpression != nil {
v.MathExpression.accept(vis)
}
if v.Map != nil {
v.Map.accept(vis)
}
if v.List != nil {
for _, i := range v.List.Values {
i.accept(vis)
}
}
}
// path represents a telemetry path mathExpression.
type path struct {
Pos lexer.Position
Context string `parser:"(@Lowercase '.')?"`
Fields []field `parser:"@@ ( '.' @@ )*"`
}
func (p *path) accept(v grammarVisitor) {
v.visitPath(p)
for _, field := range p.Fields {
field.accept(v)
}
}
// field is an item within a path.
type field struct {
Name string `parser:"@Lowercase"`
Keys []key `parser:"( @@ )*"`
}
func (f *field) accept(v grammarVisitor) {
for _, key := range f.Keys {
key.accept(v)
}
}
type key struct {
String *string `parser:"'[' (@String "`
Int *int64 `parser:"| @Int"`
MathExpression *mathExpression `parser:"| @@"`
Expression *mathExprLiteral `parser:"| @@ ) ']'"`
}
func (k *key) accept(v grammarVisitor) {
if k.MathExpression != nil {
k.MathExpression.accept(v)
}
if k.Expression != nil {
k.Expression.accept(v)
}
}
type list struct {
Values []value `parser:"'[' (@@)* (',' @@)* ']'"`
}
type mapValue struct {
Values []mapItem `parser:"'{' (@@ ','?)* '}'"`
}
func (m *mapValue) accept(v grammarVisitor) {
for _, i := range m.Values {
if i.Value != nil {
i.Value.accept(v)
}
}
}
type mapItem struct {
Key *string `parser:"@String ':'"`
Value *value `parser:"@@"`
}
// byteSlice type for capturing byte slices
type byteSlice []byte
func (b *byteSlice) Capture(values []string) error {
rawStr := values[0][2:]
newBytes, err := hex.DecodeString(rawStr)
if err != nil {
return err
}
*b = newBytes
return nil
}
// boolean Type for capturing booleans, see:
// https://github.com/alecthomas/participle#capturing-boolean-value
type boolean bool
func (b *boolean) Capture(values []string) error {
*b = values[0] == "true"
return nil
}
type isNil bool
func (n *isNil) Capture(_ []string) error {
*n = true
return nil
}
type mathExprLiteral struct {
// If editor is matched then error
Editor *editor `parser:"( @@"`
Converter *converter `parser:"| @@"`
Float *float64 `parser:"| @Float"`
Int *int64 `parser:"| @Int"`
Path *path `parser:"| @@ )"`
}
func (m *mathExprLiteral) accept(v grammarVisitor) {
v.visitMathExprLiteral(m)
if m.Path != nil {
m.Path.accept(v)
}
if m.Editor != nil {
m.Editor.accept(v)
}
if m.Converter != nil {
m.Converter.accept(v)
}
}
type mathValue struct {
Literal *mathExprLiteral `parser:"( @@"`
SubExpression *mathExpression `parser:"| '(' @@ ')' )"`
}
func (m *mathValue) accept(v grammarVisitor) {
if m.Literal != nil {
m.Literal.accept(v)
}
if m.SubExpression != nil {
m.SubExpression.accept(v)
}
}
type opMultDivValue struct {
Operator mathOp `parser:"@OpMultDiv"`
Value *mathValue `parser:"@@"`
}
func (m *opMultDivValue) accept(v grammarVisitor) {
if m.Value != nil {
m.Value.accept(v)
}
}
type addSubTerm struct {
Left *mathValue `parser:"@@"`
Right []*opMultDivValue `parser:"@@*"`
}
func (m *addSubTerm) accept(v grammarVisitor) {
if m.Left != nil {
m.Left.accept(v)
}
for _, r := range m.Right {
if r != nil {
r.accept(v)
}
}
}
type opAddSubTerm struct {
Operator mathOp `parser:"@OpAddSub"`
Term *addSubTerm `parser:"@@"`
}
func (r *opAddSubTerm) accept(v grammarVisitor) {
if r.Term != nil {
r.Term.accept(v)
}
}
type mathExpression struct {
Left *addSubTerm `parser:"@@"`
Right []*opAddSubTerm `parser:"@@*"`
}
func (m *mathExpression) accept(v grammarVisitor) {
if m.Left != nil {
m.Left.accept(v)
}
if m.Right != nil {
for _, r := range m.Right {
if r != nil {
r.accept(v)
}
}
}
}
type mathOp int
const (
add mathOp = iota
sub
mult
div
)
var mathOpTable = map[string]mathOp{
"+": add,
"-": sub,
"*": mult,
"/": div,
}
func (m *mathOp) Capture(values []string) error {
op, ok := mathOpTable[values[0]]
if !ok {
return fmt.Errorf("'%s' is not a valid operator", values[0])
}
*m = op
return nil
}
func (m *mathOp) String() string {
switch *m {
case add:
return "+"
case sub:
return "-"
case mult:
return "*"
case div:
return "/"
default:
return "UNKNOWN OP!"
}
}
type enumSymbol string
// buildLexer constructs a SimpleLexer definition.
// Note that the ordering of these rules matters.
// It's in a separate function so it can be easily tested alone (see lexer_test.go).
func buildLexer() *lexer.StatefulDefinition {
return lexer.MustSimple([]lexer.SimpleRule{
{Name: `Bytes`, Pattern: `0x[a-fA-F0-9]+`},
{Name: `Float`, Pattern: `[-+]?\d*\.\d+([eE][-+]?\d+)?`},
{Name: `Int`, Pattern: `[-+]?\d+`},
{Name: `String`, Pattern: `"(\\.|[^\\"])*"`},
{Name: `OpNot`, Pattern: `\b(not)\b`},
{Name: `OpOr`, Pattern: `\b(or)\b`},
{Name: `OpAnd`, Pattern: `\b(and)\b`},
{Name: `OpComparison`, Pattern: `==|!=|>=|<=|>|<`},
{Name: `OpAddSub`, Pattern: `\+|\-`},
{Name: `OpMultDiv`, Pattern: `\/|\*`},
{Name: `Boolean`, Pattern: `\b(true|false)\b`},
{Name: `Equal`, Pattern: `=`},
{Name: `LParen`, Pattern: `\(`},
{Name: `RParen`, Pattern: `\)`},
{Name: `LBrace`, Pattern: `\{`},
{Name: `RBrace`, Pattern: `\}`},
{Name: `Colon`, Pattern: `\:`},
{Name: `Punct`, Pattern: `[,.\[\]]`},
{Name: `Uppercase`, Pattern: `[A-Z][A-Z0-9_]*`},
{Name: `Lowercase`, Pattern: `[a-z][a-z0-9_]*`},
{Name: "whitespace", Pattern: `\s+`},
})
}
// grammarCustomError represents a grammar error in which the statement has a valid syntax
// according to the grammar's definition, but is still logically invalid.
type grammarCustomError struct {
errs []error
}
// Error returns all errors messages separate by semicolons.
func (e *grammarCustomError) Error() string {
switch len(e.errs) {
case 0:
return ""
case 1:
return e.errs[0].Error()
default:
var b strings.Builder
b.WriteString(e.errs[0].Error())
for _, err := range e.errs[1:] {
b.WriteString("; ")
b.WriteString(err.Error())
}
return b.String()
}
}
func (e *grammarCustomError) Unwrap() []error {
return e.errs
}
// grammarVisitor allows accessing the grammar AST nodes using the visitor pattern.
type grammarVisitor interface {
visitPath(v *path)
visitEditor(v *editor)
visitConverter(v *converter)
visitValue(v *value)
visitMathExprLiteral(v *mathExprLiteral)
}
// grammarCustomErrorsVisitor is used to execute custom validations on the grammar AST.
type grammarCustomErrorsVisitor struct {
errs []error
}
func (g *grammarCustomErrorsVisitor) add(err error) {
g.errs = append(g.errs, err)
}
func (g *grammarCustomErrorsVisitor) join() error {
if len(g.errs) == 0 {
return nil
}
return &grammarCustomError{errs: g.errs}
}
func (*grammarCustomErrorsVisitor) visitPath(*path) {}
func (*grammarCustomErrorsVisitor) visitValue(*value) {}
func (*grammarCustomErrorsVisitor) visitConverter(*converter) {}
func (g *grammarCustomErrorsVisitor) visitEditor(v *editor) {
if v.Keys != nil {
g.add(fmt.Errorf("only paths and converters may be indexed, not editors, but got %s%s", v.Function, buildOriginalKeysText(v.Keys)))
}
}
func (g *grammarCustomErrorsVisitor) visitMathExprLiteral(v *mathExprLiteral) {
if v.Editor != nil {
g.add(fmt.Errorf("converter names must start with an uppercase letter but got '%v'", v.Editor.Function))
}
}