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

     1  package metrics
     2  
     3  import (
     4  	"time"
     5  
     6  	"github.com/ThreeDotsLabs/watermill/message"
     7  	"go.opencensus.io/stats"
     8  	"go.opencensus.io/tag"
     9  )
    10  
    11  var (
    12  	publisherLabelKeys = []string{
    13  		labelKeyHandlerName,
    14  		labelKeyPublisherName,
    15  		labelSuccess,
    16  	}
    17  )
    18  
    19  type PublisherDecorator struct {
    20  	pub           message.Publisher
    21  	publisherName string
    22  }
    23  
    24  func (p *PublisherDecorator) Publish(topic string, messages ...*message.Message) (err error) {
    25  	if len(messages) == 0 {
    26  		return p.pub.Publish(topic)
    27  	}
    28  
    29  	// TODO: take ctx not only from first msg. Might require changing the signature of Publish, which is planned anyway.
    30  	ctx := messages[0].Context()
    31  	labels := labelsFromCtx(ctx, publisherLabelKeys...)
    32  	if labels[labelKeyPublisherName] == "" {
    33  		labels[labelKeyPublisherName] = p.publisherName
    34  	}
    35  	if labels[labelKeyHandlerName] == "" {
    36  		labels[labelKeyHandlerName] = labelValueNoHandler
    37  	}
    38  
    39  	tags := []tag.Mutator{
    40  		tag.Upsert(PublisherName, labels[labelKeyPublisherName]),
    41  		tag.Upsert(HandlerName, labels[labelKeyHandlerName]),
    42  	}
    43  	start := time.Now()
    44  
    45  	defer func() {
    46  		if publishAlreadyObserved(ctx) {
    47  			// decorator idempotency when applied decorator multiple times
    48  			return
    49  		}
    50  
    51  		if err != nil {
    52  			tags = append(tags, tag.Upsert(Success, "false"))
    53  		} else {
    54  			tags = append(tags, tag.Upsert(Success, "true"))
    55  		}
    56  
    57  		_ = stats.RecordWithTags(ctx, tags, PublisherPublishTime.M(time.Since(start).Seconds()))
    58  	}()
    59  
    60  	for _, msg := range messages {
    61  		msg.SetContext(setPublishObservedToCtx(msg.Context()))
    62  	}
    63  
    64  	return p.pub.Publish(topic, messages...)
    65  }
    66  
    67  func (p *PublisherDecorator) Close() error {
    68  	return p.pub.Close()
    69  }
    70  
    71  // DecoratePublisher decorates a publisher with instrumentation.
    72  func DecoratePublisher(pub message.Publisher) (message.Publisher, error) {
    73  	return &PublisherDecorator{
    74  		pub:           pub,
    75  		publisherName: StructName(pub),
    76  	}, nil
    77  }