package analytics import ( "net/http" "time" "github.com/segmentio/backo-go" "github.com/xtgo/uuid" ) // Instances of this type carry the different configuration options that may // be set when instantiating a client. // // Each field's zero-value is either meaningful or interpreted as using the // default value defined by the library. type Config struct { // The endpoint to which the client connect and send their messages, set to // `DefaultEndpoint` by default. Endpoint string // The flushing interval of the client. Messages will be sent when they've // been queued up to the maximum batch size or when the flushing interval // timer triggers. Interval time.Duration // The HTTP transport used by the client, this allows an application to // redefine how requests are being sent at the HTTP level (for example, // to change the connection pooling policy). // If none is specified the client uses `http.DefaultTransport`. Transport http.RoundTripper // The logger used by the client to output info or error messages when that // are generated by background operations. // If none is specified the client uses a standard logger that outputs to // `os.Stderr`. Logger Logger // The callback object that will be used by the client to notify the // application when messages sends to the backend API succeeded or failed. Callback Callback // The maximum number of messages that will be sent in one API call. // Messages will be sent when they've been queued up to the maximum batch // size or when the flushing interval timer triggers. // Note that the API will still enforce a 500KB limit on each HTTP request // which is independent from the number of embedded messages. BatchSize int // When set to true the client will send more frequent and detailed messages // to its logger. Verbose bool // The default context set on each message sent by the client. DefaultContext *Context // The retry policy used by the client to resend requests that have failed. // The function is called with how many times the operation has been retried // and is expected to return how long the client should wait before trying // again. // If not set the client will fallback to use a default retry policy. RetryAfter func(int) time.Duration // A function called by the client to generate unique message identifiers. // The client uses a UUID generator if none is provided. // This field is not exported and only exposed internally to let unit tests // mock the id generation. uid func() string // A function called by the client to get the current time, `time.Now` is // used by default. // This field is not exported and only exposed internally to let unit tests // mock the current time. now func() time.Time // The maximum number of goroutines that will be spawned by a client to send // requests to the backend API. // This field is not exported and only exposed internally to let unit tests // mock the current time. maxConcurrentRequests int } // This constant sets the default endpoint to which client instances send // messages if none was explictly set. const DefaultEndpoint = "https://api.segment.io" // This constant sets the default flush interval used by client instances if // none was explicitly set. const DefaultInterval = 5 * time.Second // This constant sets the default batch size used by client instances if none // was explicitly set. const DefaultBatchSize = 250 // Verifies that fields that don't have zero-values are set to valid values, // returns an error describing the problem if a field was invalid. func (c *Config) validate() error { if c.Interval < 0 { return ConfigError{ Reason: "negative time intervals are not supported", Field: "Interval", Value: c.Interval, } } if c.BatchSize < 0 { return ConfigError{ Reason: "negative batch sizes are not supported", Field: "BatchSize", Value: c.BatchSize, } } return nil } // Given a config object as argument the function will set all zero-values to // their defaults and return the modified object. func makeConfig(c Config) Config { if len(c.Endpoint) == 0 { c.Endpoint = DefaultEndpoint } if c.Interval == 0 { c.Interval = DefaultInterval } if c.Transport == nil { c.Transport = http.DefaultTransport } if c.Logger == nil { c.Logger = newDefaultLogger() } if c.BatchSize == 0 { c.BatchSize = DefaultBatchSize } if c.DefaultContext == nil { c.DefaultContext = &Context{} } if c.RetryAfter == nil { c.RetryAfter = backo.DefaultBacko().Duration } if c.uid == nil { c.uid = uid } if c.now == nil { c.now = time.Now } if c.maxConcurrentRequests == 0 { c.maxConcurrentRequests = 1000 } // We always overwrite the 'library' field of the default context set on the // client because we want this information to be accurate. c.DefaultContext.Library = LibraryInfo{ Name: "analytics-go", Version: Version, } return c } // This function returns a string representation of a UUID, it's the default // function used for generating unique IDs. func uid() string { return uuid.NewRandom().String() }