github.com/Jeffail/benthos/v3@v3.65.0/lib/message/tracing/package.go (about)

     1  // Package tracing implements utility functions for recording opentracing events
     2  // for messages.
     3  //
     4  // Deprecated: Use ./internal/tracing instead.
     5  package tracing
     6  
     7  import (
     8  	"github.com/Jeffail/benthos/v3/lib/message"
     9  	"github.com/Jeffail/benthos/v3/lib/types"
    10  	"github.com/opentracing/opentracing-go"
    11  )
    12  
    13  //------------------------------------------------------------------------------
    14  
    15  // GetSpan returns a span attached to a message part. Returns nil if the part
    16  // doesn't have a span attached.
    17  func GetSpan(p types.Part) opentracing.Span {
    18  	return opentracing.SpanFromContext(message.GetContext(p))
    19  }
    20  
    21  // CreateChildSpan takes a message part, extracts an existing span if there is
    22  // one and returns child span.
    23  func CreateChildSpan(operationName string, part types.Part) opentracing.Span {
    24  	span := GetSpan(part)
    25  	if span == nil {
    26  		span = opentracing.StartSpan(operationName)
    27  	} else {
    28  		span = opentracing.StartSpan(
    29  			operationName,
    30  			opentracing.ChildOf(span.Context()),
    31  		)
    32  	}
    33  	return span
    34  }
    35  
    36  // CreateChildSpans takes a message, extracts spans per message part and returns
    37  // a slice of child spans. The length of the returned slice is guaranteed to
    38  // match the message size.
    39  func CreateChildSpans(operationName string, msg types.Message) []opentracing.Span {
    40  	spans := make([]opentracing.Span, msg.Len())
    41  	msg.Iter(func(i int, part types.Part) error {
    42  		spans[i] = CreateChildSpan(operationName, part)
    43  		return nil
    44  	})
    45  	return spans
    46  }
    47  
    48  // PartsWithChildSpans takes a slice of message parts, extracts spans per part,
    49  // creates new child spans, and returns a new slice of parts with those spans
    50  // embedded. The original parts are unchanged.
    51  func PartsWithChildSpans(operationName string, parts []types.Part) ([]types.Part, []opentracing.Span) {
    52  	spans := make([]opentracing.Span, 0, len(parts))
    53  	newParts := make([]types.Part, len(parts))
    54  	for i, part := range parts {
    55  		if part == nil {
    56  			continue
    57  		}
    58  		ctx := message.GetContext(part)
    59  		span := opentracing.SpanFromContext(ctx)
    60  		if span == nil {
    61  			span = opentracing.StartSpan(operationName)
    62  		} else {
    63  			span = opentracing.StartSpan(
    64  				operationName,
    65  				opentracing.ChildOf(span.Context()),
    66  			)
    67  		}
    68  		ctx = opentracing.ContextWithSpan(ctx, span)
    69  		newParts[i] = message.WithContext(ctx, part)
    70  		spans = append(spans, span)
    71  	}
    72  	return newParts, spans
    73  }
    74  
    75  // WithChildSpans takes a message, extracts spans per message part, creates new
    76  // child spans, and returns a new message with those spans embedded. The
    77  // original message is unchanged.
    78  func WithChildSpans(operationName string, msg types.Message) (types.Message, []opentracing.Span) {
    79  	parts := make([]types.Part, 0, msg.Len())
    80  	msg.Iter(func(i int, p types.Part) error {
    81  		parts = append(parts, p)
    82  		return nil
    83  	})
    84  
    85  	newParts, spans := PartsWithChildSpans(operationName, parts)
    86  	newMsg := message.New(nil)
    87  	newMsg.SetAll(newParts)
    88  
    89  	return newMsg, spans
    90  }
    91  
    92  // WithSiblingSpans takes a message, extracts spans per message part, creates
    93  // new sibling spans, and returns a new message with those spans embedded. The
    94  // original message is unchanged.
    95  func WithSiblingSpans(operationName string, msg types.Message) types.Message {
    96  	parts := make([]types.Part, msg.Len())
    97  	msg.Iter(func(i int, part types.Part) error {
    98  		ctx := message.GetContext(part)
    99  		span := opentracing.SpanFromContext(ctx)
   100  		if span == nil {
   101  			span = opentracing.StartSpan(operationName)
   102  		} else {
   103  			span = opentracing.StartSpan(
   104  				operationName,
   105  				opentracing.FollowsFrom(span.Context()),
   106  			)
   107  		}
   108  		ctx = opentracing.ContextWithSpan(ctx, span)
   109  		parts[i] = message.WithContext(ctx, part)
   110  		return nil
   111  	})
   112  
   113  	newMsg := message.New(nil)
   114  	newMsg.SetAll(parts)
   115  	return newMsg
   116  }
   117  
   118  //------------------------------------------------------------------------------
   119  
   120  // IterateWithChildSpans iterates all the parts of a message and, for each part,
   121  // creates a new span from an existing span attached to the part and calls a
   122  // func with that span before finishing the child span.
   123  func IterateWithChildSpans(operationName string, msg types.Message, iter func(int, opentracing.Span, types.Part) error) error {
   124  	return msg.Iter(func(i int, p types.Part) error {
   125  		span, _ := opentracing.StartSpanFromContext(message.GetContext(p), operationName)
   126  		err := iter(i, span, p)
   127  		span.Finish()
   128  		return err
   129  	})
   130  }
   131  
   132  // InitSpans sets up OpenTracing spans on each message part if one does not
   133  // already exist.
   134  func InitSpans(operationName string, msg types.Message) {
   135  	tracedParts := make([]types.Part, msg.Len())
   136  	msg.Iter(func(i int, p types.Part) error {
   137  		tracedParts[i] = InitSpan(operationName, p)
   138  		return nil
   139  	})
   140  	msg.SetAll(tracedParts)
   141  }
   142  
   143  // InitSpan sets up an OpenTracing span on a message part if one does not
   144  // already exist.
   145  func InitSpan(operationName string, part types.Part) types.Part {
   146  	if GetSpan(part) != nil {
   147  		return part
   148  	}
   149  	span := opentracing.StartSpan(operationName)
   150  	ctx := opentracing.ContextWithSpan(message.GetContext(part), span)
   151  	return message.WithContext(ctx, part)
   152  }
   153  
   154  // InitSpansFromParent sets up OpenTracing spans as children of a parent span on
   155  // each message part if one does not already exist.
   156  func InitSpansFromParent(operationName string, parent opentracing.SpanContext, msg types.Message) {
   157  	tracedParts := make([]types.Part, msg.Len())
   158  	msg.Iter(func(i int, p types.Part) error {
   159  		tracedParts[i] = InitSpanFromParent(operationName, parent, p)
   160  		return nil
   161  	})
   162  	msg.SetAll(tracedParts)
   163  }
   164  
   165  // InitSpanFromParent sets up an OpenTracing span as children of a parent
   166  // span on a message part if one does not already exist.
   167  func InitSpanFromParent(operationName string, parent opentracing.SpanContext, part types.Part) types.Part {
   168  	if GetSpan(part) != nil {
   169  		return part
   170  	}
   171  	span := opentracing.StartSpan(operationName, opentracing.ChildOf(parent))
   172  	ctx := opentracing.ContextWithSpan(message.GetContext(part), span)
   173  	return message.WithContext(ctx, part)
   174  }
   175  
   176  // FinishSpans calls Finish on all message parts containing a span.
   177  func FinishSpans(msg types.Message) {
   178  	msg.Iter(func(i int, p types.Part) error {
   179  		span := GetSpan(p)
   180  		if span == nil {
   181  			return nil
   182  		}
   183  		span.Finish()
   184  		return nil
   185  	})
   186  }
   187  
   188  //------------------------------------------------------------------------------