github.com/Jeffail/benthos/v3@v3.65.0/lib/processor/metadata.go (about) 1 package processor 2 3 import ( 4 "fmt" 5 "strings" 6 "time" 7 8 "github.com/Jeffail/benthos/v3/internal/bloblang/field" 9 "github.com/Jeffail/benthos/v3/internal/docs" 10 "github.com/Jeffail/benthos/v3/internal/interop" 11 "github.com/Jeffail/benthos/v3/internal/tracing" 12 "github.com/Jeffail/benthos/v3/lib/log" 13 "github.com/Jeffail/benthos/v3/lib/metrics" 14 "github.com/Jeffail/benthos/v3/lib/types" 15 ) 16 17 //------------------------------------------------------------------------------ 18 19 func init() { 20 Constructors[TypeMetadata] = TypeSpec{ 21 constructor: NewMetadata, 22 Status: docs.StatusDeprecated, 23 Footnotes: ` 24 ## Alternatives 25 26 All functionality of this processor has been superseded by the 27 [bloblang](/docs/components/processors/bloblang) processor.`, 28 FieldSpecs: docs.FieldSpecs{ 29 docs.FieldCommon("operator", "The operator to apply to messages.").HasOptions("set", "delete", "delete_all", "delete_prefix"), 30 docs.FieldCommon("key", "The metadata key to target with the chosen operator.").IsInterpolated(), 31 docs.FieldCommon("value", "The metadata value to use with the chosen operator.").IsInterpolated(), 32 PartsFieldSpec, 33 }, 34 } 35 } 36 37 //------------------------------------------------------------------------------ 38 39 // MetadataConfig contains configuration fields for the Metadata processor. 40 type MetadataConfig struct { 41 Parts []int `json:"parts" yaml:"parts"` 42 Operator string `json:"operator" yaml:"operator"` 43 Key string `json:"key" yaml:"key"` 44 Value string `json:"value" yaml:"value"` 45 } 46 47 // NewMetadataConfig returns a MetadataConfig with default values. 48 func NewMetadataConfig() MetadataConfig { 49 return MetadataConfig{ 50 Parts: []int{}, 51 Operator: "set", 52 Key: "example", 53 Value: `${!hostname()}`, 54 } 55 } 56 57 //------------------------------------------------------------------------------ 58 59 type metadataOperator func(m types.Metadata, key, value string) error 60 61 func newMetadataSetOperator() metadataOperator { 62 return func(m types.Metadata, key, value string) error { 63 m.Set(key, value) 64 return nil 65 } 66 } 67 68 func newMetadataDeleteAllOperator() metadataOperator { 69 return func(m types.Metadata, key, value string) error { 70 m.Iter(func(k, _ string) error { 71 m.Delete(k) 72 return nil 73 }) 74 return nil 75 } 76 } 77 78 func newMetadataDeleteOperator() metadataOperator { 79 return func(m types.Metadata, key, value string) error { 80 target := value 81 if target == "" && len(key) > 0 { 82 target = key 83 } 84 m.Delete(target) 85 return nil 86 } 87 } 88 89 func newMetadataDeletePrefixOperator() metadataOperator { 90 return func(m types.Metadata, key, value string) error { 91 prefix := value 92 if prefix == "" && len(key) > 0 { 93 prefix = key 94 } 95 m.Iter(func(k, _ string) error { 96 if strings.HasPrefix(k, prefix) { 97 m.Delete(k) 98 } 99 return nil 100 }) 101 return nil 102 } 103 } 104 105 func getMetadataOperator(opStr string) (metadataOperator, error) { 106 switch opStr { 107 case "set": 108 return newMetadataSetOperator(), nil 109 case "delete": 110 return newMetadataDeleteOperator(), nil 111 case "delete_all": 112 return newMetadataDeleteAllOperator(), nil 113 case "delete_prefix": 114 return newMetadataDeletePrefixOperator(), nil 115 } 116 return nil, fmt.Errorf("operator not recognised: %v", opStr) 117 } 118 119 //------------------------------------------------------------------------------ 120 121 // Metadata is a processor that performs an operation on the Metadata of a 122 // message. 123 type Metadata struct { 124 value *field.Expression 125 key *field.Expression 126 127 operator metadataOperator 128 129 parts []int 130 131 conf Config 132 log log.Modular 133 stats metrics.Type 134 135 mCount metrics.StatCounter 136 mErr metrics.StatCounter 137 mSent metrics.StatCounter 138 mBatchSent metrics.StatCounter 139 } 140 141 // NewMetadata returns a Metadata processor. 142 func NewMetadata( 143 conf Config, mgr types.Manager, log log.Modular, stats metrics.Type, 144 ) (Type, error) { 145 value, err := interop.NewBloblangField(mgr, conf.Metadata.Value) 146 if err != nil { 147 return nil, fmt.Errorf("failed to parse value expression: %v", err) 148 } 149 key, err := interop.NewBloblangField(mgr, conf.Metadata.Key) 150 if err != nil { 151 return nil, fmt.Errorf("failed to parse key expression: %v", err) 152 } 153 m := &Metadata{ 154 conf: conf, 155 log: log, 156 stats: stats, 157 158 parts: conf.Metadata.Parts, 159 160 value: value, 161 key: key, 162 163 mCount: stats.GetCounter("count"), 164 mErr: stats.GetCounter("error"), 165 mSent: stats.GetCounter("sent"), 166 mBatchSent: stats.GetCounter("batch.sent"), 167 } 168 169 if m.operator, err = getMetadataOperator(conf.Metadata.Operator); err != nil { 170 return nil, err 171 } 172 return m, nil 173 } 174 175 //------------------------------------------------------------------------------ 176 177 // ProcessMessage applies the processor to a message, either creating >0 178 // resulting messages or a response to be sent back to the message source. 179 func (p *Metadata) ProcessMessage(msg types.Message) ([]types.Message, types.Response) { 180 p.mCount.Incr(1) 181 newMsg := msg.Copy() 182 183 proc := func(index int, span *tracing.Span, part types.Part) error { 184 key := p.key.StringLegacy(index, msg) 185 value := p.value.StringLegacy(index, msg) 186 187 if err := p.operator(part.Metadata(), key, value); err != nil { 188 p.mErr.Incr(1) 189 p.log.Debugf("Failed to apply operator: %v\n", err) 190 return err 191 } 192 return nil 193 } 194 195 IteratePartsWithSpanV2(TypeMetadata, p.parts, newMsg, proc) 196 197 msgs := [1]types.Message{newMsg} 198 199 p.mBatchSent.Incr(1) 200 p.mSent.Incr(int64(newMsg.Len())) 201 return msgs[:], nil 202 } 203 204 // CloseAsync shuts down the processor and stops processing requests. 205 func (p *Metadata) CloseAsync() { 206 } 207 208 // WaitForClose blocks until the processor has closed down. 209 func (p *Metadata) WaitForClose(timeout time.Duration) error { 210 return nil 211 } 212 213 //------------------------------------------------------------------------------