github.com/Jeffail/benthos/v3@v3.65.0/internal/component/input/span_reader.go (about) 1 package input 2 3 import ( 4 "context" 5 "time" 6 7 "github.com/Jeffail/benthos/v3/internal/bloblang/mapping" 8 "github.com/Jeffail/benthos/v3/internal/docs" 9 "github.com/Jeffail/benthos/v3/internal/interop" 10 "github.com/Jeffail/benthos/v3/internal/tracing" 11 "github.com/Jeffail/benthos/v3/lib/input/reader" 12 "github.com/Jeffail/benthos/v3/lib/log" 13 "github.com/Jeffail/benthos/v3/lib/types" 14 ) 15 16 // ExtractTracingSpanMappingDocs returns a docs spec for a mapping field. 17 var ExtractTracingSpanMappingDocs = docs.FieldBloblang( 18 "extract_tracing_map", "EXPERIMENTAL: A [Bloblang mapping](/docs/guides/bloblang/about) that attempts to extract an object containing tracing propagation information, which will then be used as the root tracing span for the message. The specification of the extracted fields must match the format used by the service wide tracer.", 19 `root = meta()`, 20 `root = this.meta.span`, 21 ).AtVersion("3.45.0").Advanced() 22 23 // SpanReader wraps an async reader with a mechanism for extracting tracing 24 // spans from the consumed message using a Bloblang mapping. 25 type SpanReader struct { 26 inputName string 27 28 mgr types.Manager 29 log log.Modular 30 31 mapping *mapping.Executor 32 rdr reader.Async 33 } 34 35 // NewSpanReader wraps an async reader with a mechanism for extracting tracing 36 // spans from the consumed message using a Bloblang mapping. 37 func NewSpanReader(inputName, mapping string, rdr reader.Async, mgr types.Manager, logger log.Modular) (reader.Async, error) { 38 exe, err := interop.NewBloblangMapping(mgr, mapping) 39 if err != nil { 40 return nil, err 41 } 42 return &SpanReader{inputName, mgr, logger, exe, rdr}, nil 43 } 44 45 // ConnectWithContext attempts to establish a connection to the source, if 46 // unsuccessful returns an error. If the attempt is successful (or not 47 // necessary) returns nil. 48 func (s *SpanReader) ConnectWithContext(ctx context.Context) error { 49 return s.rdr.ConnectWithContext(ctx) 50 } 51 52 // ReadWithContext attempts to read a new message from the source. If 53 // successful a message is returned along with a function used to 54 // acknowledge receipt of the returned message. It's safe to process the 55 // returned message and read the next message asynchronously. 56 func (s *SpanReader) ReadWithContext(ctx context.Context) (types.Message, reader.AsyncAckFn, error) { 57 m, afn, err := s.rdr.ReadWithContext(ctx) 58 if err != nil { 59 return nil, nil, err 60 } 61 62 spanPart, err := s.mapping.MapPart(0, m) 63 if err != nil { 64 s.log.Errorf("Mapping failed for tracing span: %v", err) 65 return m, afn, nil 66 } 67 68 structured, err := spanPart.JSON() 69 if err != nil { 70 s.log.Errorf("Mapping failed for tracing span: %v", err) 71 return m, afn, nil 72 } 73 74 spanMap, ok := structured.(map[string]interface{}) 75 if !ok { 76 s.log.Errorf("Mapping failed for tracing span, expected an object, got: %T", structured) 77 return m, afn, nil 78 } 79 80 if err := tracing.InitSpansFromParentTextMap("input_"+s.inputName, spanMap, m); err != nil { 81 s.log.Errorf("Extraction of parent tracing span failed: %v", err) 82 } 83 return m, afn, nil 84 } 85 86 // CloseAsync triggers the shut down of this component but should not block 87 // the calling goroutine. 88 func (s *SpanReader) CloseAsync() { 89 s.rdr.CloseAsync() 90 } 91 92 // WaitForClose is a blocking call to wait until the component has finished 93 // shutting down and cleaning up resources. 94 func (s *SpanReader) WaitForClose(timeout time.Duration) error { 95 return s.rdr.WaitForClose(timeout) 96 }