package graphite import ( "fmt" "strings" "github.com/influxdata/influxdb/models" ) const ( // DefaultBindAddress is the default binding interface if none is specified. DefaultBindAddress = ":2003" // DefaultDatabase is the default database if none is specified. DefaultDatabase = "graphite" // DefaultProtocol is the default IP protocol used by the Graphite input. DefaultProtocol = "tcp" // DefaultSeparator is the default join character to use when joining multiple // measurment parts in a template. DefaultSeparator = "." // DefaultUDPReadBuffer is the default buffer size for the UDP listener. // Sets the size of the operating system's receive buffer associated with // the UDP traffic. Keep in mind that the OS must be able // to handle the number set here or the UDP listener will error and exit. // // DefaultReadBuffer = 0 means to use the OS default, which is usually too // small for high UDP performance. // // Increasing OS buffer limits: // Linux: sudo sysctl -w net.core.rmem_max= // BSD/Darwin: sudo sysctl -w kern.ipc.maxsockbuf= DefaultUdpReadBuffer = 0 ) // Config represents the configuration for Graphite endpoints. type Config struct { BindAddress string Protocol string UdpReadBuffer int Separator string Tags []string Templates []string } // WithDefaults takes the given config and returns a new config with any required // default values set. func (c *Config) WithDefaults() *Config { d := *c if d.BindAddress == "" { d.BindAddress = DefaultBindAddress } if d.Protocol == "" { d.Protocol = DefaultProtocol } if d.Separator == "" { d.Separator = DefaultSeparator } if d.UdpReadBuffer == 0 { d.UdpReadBuffer = DefaultUdpReadBuffer } return &d } // DefaultTags returns the config's tags. func (c *Config) DefaultTags() models.Tags { tags := models.Tags{} for _, t := range c.Tags { parts := strings.Split(t, "=") tags[parts[0]] = parts[1] } return tags } // Validate validates the config's templates and tags. func (c *Config) Validate() error { if err := c.validateTemplates(); err != nil { return err } if err := c.validateTags(); err != nil { return err } return nil } func (c *Config) validateTemplates() error { // map to keep track of filters we see filters := map[string]struct{}{} for i, t := range c.Templates { parts := strings.Fields(t) // Ensure template string is non-empty if len(parts) == 0 { return fmt.Errorf("missing template at position: %d", i) } if len(parts) == 1 && parts[0] == "" { return fmt.Errorf("missing template at position: %d", i) } if len(parts) > 3 { return fmt.Errorf("invalid template format: '%s'", t) } template := t filter := "" tags := "" if len(parts) >= 2 { // We could have