github.com/newrelic/newrelic-client-go@v1.1.0/pkg/events/events.go (about)

     1  package events
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"errors"
     7  	"fmt"
     8  	"strings"
     9  	"time"
    10  
    11  	"github.com/newrelic/newrelic-client-go/internal/http"
    12  	"github.com/newrelic/newrelic-client-go/pkg/config"
    13  	"github.com/newrelic/newrelic-client-go/pkg/logging"
    14  )
    15  
    16  const (
    17  	DefaultBatchWorkers = 1
    18  	DefaultBatchSize    = 900
    19  	DefaultBatchTimeout = 60 * time.Second
    20  )
    21  
    22  // Events is used to send custom events to NRDB.
    23  type Events struct {
    24  	client http.Client
    25  	config config.Config
    26  	logger logging.Logger
    27  
    28  	// For queue based event handling
    29  	accountID  int
    30  	eventQueue chan []byte
    31  	eventTimer *time.Timer
    32  	flushQueue []chan bool
    33  
    34  	// These have defaults
    35  	batchWorkers int
    36  	batchSize    int
    37  	batchTimeout time.Duration
    38  }
    39  
    40  // New is used to create a new Events client instance.
    41  func New(cfg config.Config) Events {
    42  	cfg.Compression = config.Compression.Gzip
    43  
    44  	client := http.NewClient(cfg)
    45  	if cfg.InsightsInsertKey != "" {
    46  		client.SetAuthStrategy(&http.InsightsInsertKeyAuthorizer{})
    47  	} else {
    48  		client.SetAuthStrategy(&http.LicenseKeyAuthorizer{})
    49  	}
    50  
    51  	pkg := Events{
    52  		client:       client,
    53  		config:       cfg,
    54  		logger:       cfg.GetLogger(),
    55  		batchWorkers: DefaultBatchWorkers,
    56  		batchSize:    DefaultBatchSize,
    57  		batchTimeout: DefaultBatchTimeout,
    58  	}
    59  
    60  	return pkg
    61  }
    62  
    63  // CreateEvent reports a custom event to New Relic.
    64  func (e *Events) CreateEvent(accountID int, event interface{}) error {
    65  	return e.CreateEventWithContext(context.Background(), accountID, event)
    66  }
    67  
    68  // CreateEventWithContext reports a custom event to New Relic.
    69  func (e *Events) CreateEventWithContext(ctx context.Context, accountID int, event interface{}) error {
    70  	jsonData, err := e.marshalEvent(event)
    71  	if err != nil {
    72  		return err
    73  	}
    74  	if jsonData == nil {
    75  		return errors.New("events: CreateEvent marhal returned nil data")
    76  	}
    77  
    78  	resp := &createEventResponse{}
    79  
    80  	_, err = e.client.PostWithContext(ctx, e.config.Region().InsightsURL(accountID), nil, *jsonData, resp)
    81  	if err != nil {
    82  		return err
    83  	}
    84  
    85  	if !resp.Success {
    86  		return errors.New("failed creating custom event")
    87  	}
    88  
    89  	return nil
    90  }
    91  
    92  // marshalEvent converts the event interface into a JSON []byte
    93  func (e *Events) marshalEvent(event interface{}) (*[]byte, error) {
    94  	var jsonData []byte
    95  
    96  	switch event := event.(type) {
    97  	case []byte:
    98  		jsonData = event
    99  	case string:
   100  		jsonData = []byte(event)
   101  	default:
   102  		var err error
   103  		jsonData, err = json.Marshal(event)
   104  		if err != nil {
   105  			return nil, fmt.Errorf("error marshaling event data: %s", err.Error())
   106  		}
   107  	}
   108  
   109  	if !strings.Contains(string(jsonData), "eventType") {
   110  		return nil, fmt.Errorf("event data must contain eventType field. %s", jsonData)
   111  	}
   112  
   113  	return &jsonData, nil
   114  }
   115  
   116  type createEventResponse struct {
   117  	Success bool   `json:"success"`
   118  	UUID    string `json:"uuid"`
   119  }