github.com/asynkron/protoactor-go@v0.0.0-20240308120642-ef91a6abee75/actor/middleware/opentracing/receivermiddleware.go (about)

     1  package opentracing
     2  
     3  import (
     4  	"fmt"
     5  	"log/slog"
     6  
     7  	"github.com/asynkron/protoactor-go/actor"
     8  	"github.com/opentracing/opentracing-go"
     9  )
    10  
    11  func ReceiverMiddleware() actor.ReceiverMiddleware {
    12  	return func(next actor.ReceiverFunc) actor.ReceiverFunc {
    13  		return func(c actor.ReceiverContext, envelope *actor.MessageEnvelope) {
    14  			spanContext, err := opentracing.GlobalTracer().Extract(opentracing.TextMap, opentracing.TextMapReader(&messageHeaderReader{ReadOnlyMessageHeader: envelope.Header}))
    15  			if err == opentracing.ErrSpanContextNotFound {
    16  				c.Logger().Debug("INBOUND No spanContext found", slog.Any("self", c.Self()), slog.Any("error", err))
    17  				// next(c)
    18  			} else if err != nil {
    19  				c.Logger().Debug("INBOUND Error", slog.Any("self", c.Self()), slog.Any("error", err))
    20  				next(c, envelope)
    21  				return
    22  			}
    23  			var span opentracing.Span
    24  			switch envelope.Message.(type) {
    25  			case *actor.Started:
    26  				parentSpan := getAndClearParentSpan(c.Self())
    27  				if parentSpan != nil {
    28  					span = opentracing.StartSpan(fmt.Sprintf("%T/%T", c.Actor(), envelope.Message), opentracing.ChildOf(parentSpan.Context()))
    29  					c.Logger().Debug("INBOUND Found parent span", slog.Any("self", c.Self()), slog.Any("actor", c.Actor()), slog.Any("message", envelope.Message))
    30  				} else {
    31  					c.Logger().Debug("INBOUND No parent span", slog.Any("self", c.Self()), slog.Any("actor", c.Actor()), slog.Any("message", envelope.Message))
    32  				}
    33  			case *actor.Stopping:
    34  				var parentSpan opentracing.Span
    35  				if c.Parent() != nil {
    36  					parentSpan = getStoppingSpan(c.Parent())
    37  				}
    38  				if parentSpan != nil {
    39  					span = opentracing.StartSpan(fmt.Sprintf("%T/stopping", c.Actor()), opentracing.ChildOf(parentSpan.Context()))
    40  				} else {
    41  					span = opentracing.StartSpan(fmt.Sprintf("%T/stopping", c.Actor()))
    42  				}
    43  				setStoppingSpan(c.Self(), span)
    44  				span.SetTag("ActorPID", c.Self())
    45  				span.SetTag("ActorType", fmt.Sprintf("%T", c.Actor()))
    46  				span.SetTag("MessageType", fmt.Sprintf("%T", envelope.Message))
    47  				stoppingHandlingSpan := opentracing.StartSpan("stopping-handling", opentracing.ChildOf(span.Context()))
    48  				next(c, envelope)
    49  				stoppingHandlingSpan.Finish()
    50  				return
    51  			case *actor.Stopped:
    52  				span = getAndClearStoppingSpan(c.Self())
    53  				next(c, envelope)
    54  				if span != nil {
    55  					span.Finish()
    56  				}
    57  				return
    58  			}
    59  			if span == nil && spanContext == nil {
    60  				c.Logger().Debug("INBOUND No spanContext. Starting new span", slog.Any("self", c.Self()), slog.Any("actor", c.Actor()), slog.Any("message", envelope.Message))
    61  				span = opentracing.StartSpan(fmt.Sprintf("%T/%T", c.Actor(), envelope.Message))
    62  			}
    63  			if span == nil {
    64  				c.Logger().Debug("INBOUND Starting span from parent", slog.Any("self", c.Self()), slog.Any("actor", c.Actor()), slog.Any("message", envelope.Message))
    65  				span = opentracing.StartSpan(fmt.Sprintf("%T/%T", c.Actor(), envelope.Message), opentracing.ChildOf(spanContext))
    66  			}
    67  
    68  			setActiveSpan(c.Self(), span)
    69  			span.SetTag("ActorPID", c.Self())
    70  			span.SetTag("ActorType", fmt.Sprintf("%T", c.Actor()))
    71  			span.SetTag("MessageType", fmt.Sprintf("%T", envelope.Message))
    72  
    73  			defer func() {
    74  				c.Logger().Debug("INBOUND Finishing span", slog.Any("self", c.Self()), slog.Any("actor", c.Actor()), slog.Any("message", envelope.Message))
    75  				span.Finish()
    76  				clearActiveSpan(c.Self())
    77  			}()
    78  
    79  			next(c, envelope)
    80  		}
    81  	}
    82  }