github.com/Jeffail/benthos/v3@v3.65.0/internal/component/metrics/mapping.go (about)

     1  package metrics
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  
     7  	"github.com/Jeffail/benthos/v3/internal/bloblang/mapping"
     8  	"github.com/Jeffail/benthos/v3/internal/bloblang/parser"
     9  	"github.com/Jeffail/benthos/v3/internal/bloblang/query"
    10  	"github.com/Jeffail/benthos/v3/internal/docs"
    11  	"github.com/Jeffail/benthos/v3/internal/interop"
    12  	"github.com/Jeffail/benthos/v3/lib/log"
    13  	"github.com/Jeffail/benthos/v3/lib/message"
    14  	"github.com/Jeffail/benthos/v3/lib/types"
    15  )
    16  
    17  // MappingFieldSpec is a field spec that describes a Bloblang mapping for
    18  // renaming metrics.
    19  func MappingFieldSpec() docs.FieldSpec {
    20  	examples := []interface{}{
    21  		`this.replace(".foo.count", ".count")`,
    22  		`if ![ "count", "error", "latency" ].contains(this) { deleted() }`,
    23  	}
    24  	summary := "An optional [Bloblang mapping](/docs/guides/bloblang/about) that allows you to rename or prevent certain metrics paths from being exported."
    25  	return docs.FieldBloblang("metrics_mapping", summary, examples...).HasDefault("")
    26  }
    27  
    28  // Mapping is a compiled Bloblang mapping used to rewrite metrics.
    29  type Mapping struct {
    30  	m      *mapping.Executor
    31  	logger log.Modular
    32  }
    33  
    34  // NewMapping parses a Bloblang mapping and returns a metrics mapping.
    35  func NewMapping(mgr types.Manager, mapping string, logger log.Modular) (*Mapping, error) {
    36  	if mapping == "" {
    37  		return &Mapping{m: nil, logger: logger}, nil
    38  	}
    39  	m, err := interop.NewBloblangMapping(mgr, mapping)
    40  	if err != nil {
    41  		if perr, ok := err.(*parser.Error); ok {
    42  			return nil, fmt.Errorf("%v", perr.ErrorAtPosition([]rune(mapping)))
    43  		}
    44  		return nil, err
    45  	}
    46  	return &Mapping{m, logger}, nil
    47  }
    48  
    49  func (m *Mapping) mapPath(path string, labelNames, labelValues []string) (outPath string, outLabelNames, outLabelValues []string) {
    50  	if m == nil || m.m == nil {
    51  		return path, labelNames, labelValues
    52  	}
    53  
    54  	part := message.NewPart(nil)
    55  	if err := part.SetJSON(path); err != nil {
    56  		m.logger.Errorf("Failed to apply path mapping on '%v': %v\n", path, err)
    57  		return path, labelNames, labelValues
    58  	}
    59  	for i, v := range labelNames {
    60  		part.Metadata().Set(v, labelValues[i])
    61  	}
    62  	msg := message.New(nil)
    63  	msg.Append(part)
    64  
    65  	outPart := part.Copy()
    66  	outMeta := outPart.Metadata()
    67  
    68  	var input interface{} = path
    69  	vars := map[string]interface{}{}
    70  
    71  	var v interface{} = query.Nothing(nil)
    72  	if err := m.m.ExecOnto(query.FunctionContext{
    73  		Maps:     m.m.Maps(),
    74  		Vars:     vars,
    75  		MsgBatch: msg,
    76  		NewMsg:   outPart,
    77  	}.WithValue(input), mapping.AssignmentContext{
    78  		Vars:  vars,
    79  		Meta:  outMeta,
    80  		Value: &v,
    81  	}); err != nil {
    82  		m.logger.Errorf("Failed to apply path mapping on '%v': %v\n", path, err)
    83  		return path, nil, nil
    84  	}
    85  
    86  	outMeta.Iter(func(k, v string) error {
    87  		outLabelNames = append(outLabelNames, k)
    88  		return nil
    89  	})
    90  	if len(outLabelNames) > 0 {
    91  		sort.Strings(outLabelNames)
    92  		for _, k := range outLabelNames {
    93  			v := outMeta.Get(k)
    94  			m.logger.Tracef("Metrics label '%v' created with static value '%v'.\n", k, v)
    95  			outLabelValues = append(outLabelValues, v)
    96  		}
    97  	}
    98  
    99  	switch t := v.(type) {
   100  	case query.Delete:
   101  		m.logger.Tracef("Deleting metrics path: %v\n", path)
   102  		return "", nil, nil
   103  	case query.Nothing:
   104  		m.logger.Tracef("Metrics path '%v' registered unchanged.\n", path)
   105  		outPath = path
   106  		return
   107  	case string:
   108  		m.logger.Tracef("Updated metrics path '%v' to: %v\n", path, t)
   109  		outPath = t
   110  		return
   111  	}
   112  	m.logger.Errorf("Path mapping returned invalid result, expected string, found %T\n", v)
   113  	return path, labelNames, labelValues
   114  }