github.com/vseinstrumentiru/lego@v1.0.2/internal/lego/transport/event/metrics/subscriber.go (about)

     1  package metrics
     2  
     3  import (
     4  	"emperror.dev/errors"
     5  	"github.com/ThreeDotsLabs/watermill/message"
     6  	"go.opencensus.io/stats"
     7  	"go.opencensus.io/tag"
     8  )
     9  
    10  var (
    11  	subscriberLabelKeys = []string{
    12  		labelKeyHandlerName,
    13  		labelKeySubscriberName,
    14  	}
    15  )
    16  
    17  type SubscriberDecorator struct {
    18  	message.Subscriber
    19  	subscriberName string
    20  }
    21  
    22  func (s *SubscriberDecorator) recordMetrics(msg *message.Message) {
    23  	if msg == nil {
    24  		return
    25  	}
    26  
    27  	ctx := msg.Context()
    28  	labels := labelsFromCtx(ctx, subscriberLabelKeys...)
    29  
    30  	if labels[labelKeySubscriberName] == "" {
    31  		labels[labelKeySubscriberName] = s.subscriberName
    32  	}
    33  	if labels[labelKeyHandlerName] == "" {
    34  		labels[labelKeyHandlerName] = labelValueNoHandler
    35  	}
    36  
    37  	tags := []tag.Mutator{
    38  		tag.Upsert(SubscriberName, labels[labelKeySubscriberName]),
    39  		tag.Upsert(HandlerName, labels[labelKeyHandlerName]),
    40  	}
    41  
    42  	go func() {
    43  		if subscribeAlreadyObserved(ctx) {
    44  			// decorator idempotency when applied decorator multiple times
    45  			return
    46  		}
    47  
    48  		select {
    49  		case <-msg.Acked():
    50  			tags = append(tags, tag.Upsert(Acked, "acked"))
    51  		case <-msg.Nacked():
    52  			tags = append(tags, tag.Upsert(Acked, "nacked"))
    53  		}
    54  
    55  		_ = stats.RecordWithTags(ctx, tags, SubscriberReceivedMessage.M(1))
    56  	}()
    57  
    58  	msg.SetContext(setSubscribeObservedToCtx(msg.Context()))
    59  }
    60  
    61  // DecorateSubscriber decorates a publisher with instrumentation.
    62  func DecorateSubscriber(sub message.Subscriber) (message.Subscriber, error) {
    63  	d := &SubscriberDecorator{
    64  		subscriberName: StructName(sub),
    65  	}
    66  
    67  	var err error
    68  	d.Subscriber, err = message.MessageTransformSubscriberDecorator(d.recordMetrics)(sub)
    69  	if err != nil {
    70  		return nil, errors.Wrap(err, "could not decorate subscriber with metrics decorator")
    71  	}
    72  
    73  	return d, nil
    74  }