github.com/blend/go-sdk@v1.20240719.1/datadog/collector.go (about)

     1  /*
     2  
     3  Copyright (c) 2024 - Present. Blend Labs, Inc. All rights reserved
     4  Use of this source code is governed by a MIT license that can be found in the LICENSE file.
     5  
     6  */
     7  
     8  package datadog
     9  
    10  import (
    11  	"strings"
    12  	"time"
    13  
    14  	dogstatsd "github.com/DataDog/datadog-go/v5/statsd"
    15  
    16  	"github.com/blend/go-sdk/stats"
    17  	"github.com/blend/go-sdk/timeutil"
    18  )
    19  
    20  // Assert that the datadog collector implements stats.Collector and stats.EventCollector.
    21  var (
    22  	_ stats.Collector      = (*Collector)(nil)
    23  	_ stats.EventCollector = (*Collector)(nil)
    24  )
    25  
    26  // New returns a new stats collector from a config.
    27  func New(cfg Config, opts ...dogstatsd.Option) (*Collector, error) {
    28  	var client *dogstatsd.Client
    29  	var err error
    30  	if cfg.BufferedOrDefault() {
    31  		opts = append(opts, dogstatsd.WithMaxMessagesPerPayload(cfg.BufferDepthOrDefault()))
    32  	}
    33  
    34  	if len(cfg.Namespace) > 0 {
    35  		opts = append(opts, dogstatsd.WithNamespace(strings.ToLower(cfg.Namespace)+"."))
    36  	}
    37  
    38  	client, err = dogstatsd.New(cfg.GetAddress(), opts...)
    39  	if err != nil {
    40  		return nil, err
    41  	}
    42  
    43  	collector := &Collector{
    44  		client:      client,
    45  		defaultTags: cfg.DefaultTags,
    46  	}
    47  	return collector, nil
    48  }
    49  
    50  // MustNew returns a new stats collector from a config, but panics on error.
    51  func MustNew(cfg Config) *Collector {
    52  	collector, err := New(cfg)
    53  	if err != nil {
    54  		panic(err)
    55  	}
    56  	return collector
    57  }
    58  
    59  // Collector is a class that wraps the statsd collector we're using.
    60  type Collector struct {
    61  	client      *dogstatsd.Client
    62  	defaultTags []string
    63  }
    64  
    65  // AddDefaultTag adds a new default tag.
    66  func (dc *Collector) AddDefaultTag(name, value string) {
    67  	dc.defaultTags = append(dc.defaultTags, stats.Tag(name, value))
    68  }
    69  
    70  // AddDefaultTags adds new default tags.
    71  func (dc *Collector) AddDefaultTags(tags ...string) {
    72  	dc.defaultTags = append(dc.defaultTags, tags...)
    73  }
    74  
    75  // DefaultTags returns the default tags for the collector.
    76  func (dc *Collector) DefaultTags() []string {
    77  	return dc.defaultTags
    78  }
    79  
    80  // Count increments a counter by a value.
    81  func (dc *Collector) Count(name string, value int64, tags ...string) error {
    82  	return dc.client.Count(name, value, dc.tagsWithDefaults(tags...), 1.0)
    83  }
    84  
    85  // Increment increments a counter by 1.
    86  func (dc *Collector) Increment(name string, tags ...string) error {
    87  	return dc.client.Count(name, 1, dc.tagsWithDefaults(tags...), 1.0)
    88  }
    89  
    90  // Gauge sets a gauge value.
    91  func (dc *Collector) Gauge(name string, value float64, tags ...string) error {
    92  	return dc.client.Gauge(name, value, dc.tagsWithDefaults(tags...), 1.0)
    93  }
    94  
    95  // Histogram sets a gauge value that statistics are computed on the agent.
    96  func (dc *Collector) Histogram(name string, value float64, tags ...string) error {
    97  	return dc.client.Histogram(name, value, dc.tagsWithDefaults(tags...), 1.0)
    98  }
    99  
   100  // Distribution sets a gauge value that statistics are computed on the server.
   101  func (dc *Collector) Distribution(name string, value float64, tags ...string) error {
   102  	return dc.client.Distribution(name, value, dc.tagsWithDefaults(tags...), 1.0)
   103  }
   104  
   105  // TimeInMilliseconds sets a timing value.
   106  func (dc *Collector) TimeInMilliseconds(name string, value time.Duration, tags ...string) error {
   107  	return dc.client.TimeInMilliseconds(name, timeutil.Milliseconds(value), dc.tagsWithDefaults(tags...), 1.0)
   108  }
   109  
   110  // Flush forces a flush of all the queued statsd payloads.
   111  func (dc *Collector) Flush() error {
   112  	if dc.client == nil {
   113  		return nil
   114  	}
   115  	return dc.client.Flush()
   116  }
   117  
   118  // Close closes the statsd client.
   119  func (dc *Collector) Close() error {
   120  	if dc.client == nil {
   121  		return nil
   122  	}
   123  	return dc.client.Close()
   124  }
   125  
   126  // SimpleEvent sends an event w/ title and text
   127  func (dc *Collector) SimpleEvent(title, text string) error {
   128  	return dc.client.SimpleEvent(title, text)
   129  }
   130  
   131  // SendEvent sends any *dogstatsd.Event
   132  func (dc *Collector) SendEvent(event stats.Event) error {
   133  	return dc.client.Event(ConvertEvent(event))
   134  }
   135  
   136  // CreateEvent makes a new Event with the collectors default tags.
   137  func (dc *Collector) CreateEvent(title, text string, tags ...string) stats.Event {
   138  	return stats.Event{
   139  		Title: title,
   140  		Text:  text,
   141  		Tags:  dc.tagsWithDefaults(tags...),
   142  	}
   143  }
   144  
   145  // helpers
   146  func (dc *Collector) tagsWithDefaults(tags ...string) []string {
   147  	return append(dc.defaultTags, tags...)
   148  }
   149  
   150  // ConvertEvent converts a stats event to a statsd (datadog) event.
   151  func ConvertEvent(e stats.Event) *dogstatsd.Event {
   152  	return &dogstatsd.Event{
   153  		Title:          e.Title,
   154  		Text:           e.Text,
   155  		Timestamp:      e.Timestamp,
   156  		Hostname:       e.Hostname,
   157  		AggregationKey: e.AggregationKey,
   158  		Priority:       dogstatsd.EventPriority(e.Priority),
   159  		SourceTypeName: e.SourceTypeName,
   160  		AlertType:      dogstatsd.EventAlertType(e.AlertType),
   161  		Tags:           e.Tags,
   162  	}
   163  }