func (s *Server) ListenAndServe() { var err error s.getAuth() s.typesdb, err = collectd.TypesDBFile(s.typesdbpath) if err != nil { log.Error("CollectdServer: TypesDB: ", err) return } addr, err := net.ResolveUDPAddr("udp4", s.listenAddress) if err != nil { log.Error("CollectdServer: ResolveUDPAddr: ", err) return } if s.listenAddress != "" { s.conn, err = net.ListenUDP("udp", addr) if err != nil { log.Error("CollectdServer: Listen: ", err) return } } defer s.conn.Close() s.HandleSocket(s.conn) }
func ListenAndServe(s *Server, iface string) error { if iface == "" { // Make sure we have an address return errors.New("bind address required") } else if s.Database == "" { // Make sure they have a database return errors.New("database was not specified in config") } addr, err := net.ResolveUDPAddr("udp", iface) if err != nil { return fmt.Errorf("unable to resolve UDP address: %v", err) } s.typesdb, err = gollectd.TypesDBFile(s.typesdbpath) if err != nil { return fmt.Errorf("unable to parse typesDBFile: %v", err) } conn, err := net.ListenUDP("udp", addr) if err != nil { return fmt.Errorf("unable to listen on UDP: %v", err) } s.conn = conn s.wg.Add(1) go s.serve(conn) return nil }
// Open starts the service. func (s *Service) Open() error { s.Logger.Printf("Starting collectd service") if s.Config.BindAddress == "" { return fmt.Errorf("bind address is blank") } else if s.Config.Database == "" { return fmt.Errorf("database name is blank") } else if s.PointsWriter == nil { return fmt.Errorf("PointsWriter is nil") } if err := s.MetaStore.WaitForLeader(leaderWaitTimeout); err != nil { s.Logger.Printf("Failed to detect a cluster leader: %s", err.Error()) return err } if _, err := s.MetaStore.CreateDatabaseIfNotExists(s.Config.Database); err != nil { s.Logger.Printf("Failed to ensure target database %s exists: %s", s.Config.Database, err.Error()) return err } if s.typesdb == nil { // Open collectd types. typesdb, err := gollectd.TypesDBFile(s.Config.TypesDB) if err != nil { return fmt.Errorf("Open(): %s", err) } s.typesdb = typesdb } // Resolve our address. addr, err := net.ResolveUDPAddr("udp", s.Config.BindAddress) if err != nil { return fmt.Errorf("unable to resolve UDP address: %s", err) } s.addr = addr // Start listening ln, err := net.ListenUDP("udp", addr) if err != nil { return fmt.Errorf("unable to listen on UDP: %s", err) } s.ln = ln s.Logger.Println("Listening on UDP: ", ln.LocalAddr().String()) // Start the points batcher. s.batcher = tsdb.NewPointBatcher(s.Config.BatchSize, time.Duration(s.Config.BatchDuration)) s.batcher.Start() // Create channel and wait group for signalling goroutines to stop. s.stop = make(chan struct{}) s.wg.Add(2) // Start goroutines that process collectd packets. go s.serve() go s.writePoints() return nil }
// Listen takes collectd network packets and breaks them into individual samples. func Listen(config ListenConfig, c chan collectd.Packet) { // Initialise the error counts errorCounts.Add("fetch.receive", 0) laddr, err := net.ResolveUDPAddr("udp", config.Bind) if err != nil { log.Fatalln("[fatal] Listen: failed to resolve address", err) } conn, err := net.ListenUDP("udp", laddr) if err != nil { log.Fatalln("[fatal] Listen: failed to listen", err) } types, err := collectd.TypesDBFile(config.Typesdb) if err != nil { log.Fatalln("[fatal] Listen: failed to parse types.db", err) } for { // 1452 is collectd 5's default buffer size. See: // https://collectd.org/wiki/index.php/Binary_protocol buf := make([]byte, 1452) n, err := conn.Read(buf[:]) if err != nil { log.Println("[error] Listen: Failed to receive packet", err) errorCounts.Add("fetch.receive", 1) continue } listenCounts.Add("raw", 1) packets, err := collectd.Packets(buf[0:n], types) for _, p := range *packets { listenCounts.Add("decoded", 1) c <- p } } }
// Listen for collectd network packets, parse , and send them over a channel func Listen(addr string, c chan collectd.Packet, typesdb string) { laddr, err := net.ResolveUDPAddr("udp", addr) if err != nil { log.Fatalln("fatal: failed to resolve address", err) } conn, err := net.ListenUDP("udp", laddr) if err != nil { log.Fatalln("fatal: failed to listen", err) } types, err := collectd.TypesDBFile(typesdb) if err != nil { log.Fatalln("fatal: failed to parse types.db", err) } for { // 1452 is collectd 5's default buffer size. See: // https://collectd.org/wiki/index.php/Binary_protocol buf := make([]byte, 1452) n, err := conn.Read(buf[:]) if err != nil { log.Println("error: Failed to receive packet", err) continue } packets, err := collectd.Packets(buf[0:n], types) if err != nil { log.Println("error: Failed to receive packet", err) continue } for _, p := range *packets { c <- p } } }
func main() { typesPath := flag.String("typesdb", "", "Path to types.db") flag.Parse() if *typesPath == "" { flag.Usage() os.Exit(1) } types, err := collectd.TypesDBFile(*typesPath) if err != nil { fmt.Printf("%s\n", err) os.Exit(1) } for k, pv := range types { fmt.Printf("%s:\n", k) for _, v := range pv { fmt.Printf("\t%+v\n", *v) } } }
// Open starts the service. func (s *Service) Open() error { s.Logger.Printf("Starting collectd service") // Configure expvar monitoring. It's OK to do this even if the service fails to open and // should be done before any data could arrive for the service. key := strings.Join([]string{"collectd", s.Config.BindAddress}, ":") tags := map[string]string{"bind": s.Config.BindAddress} s.statMap = influxdb.NewStatistics(key, "collectd", tags) if s.Config.BindAddress == "" { return fmt.Errorf("bind address is blank") } else if s.Config.Database == "" { return fmt.Errorf("database name is blank") } else if s.PointsWriter == nil { return fmt.Errorf("PointsWriter is nil") } if err := s.MetaStore.WaitForLeader(leaderWaitTimeout); err != nil { s.Logger.Printf("Failed to detect a cluster leader: %s", err.Error()) return err } if _, err := s.MetaStore.CreateDatabaseIfNotExists(s.Config.Database); err != nil { s.Logger.Printf("Failed to ensure target database %s exists: %s", s.Config.Database, err.Error()) return err } if s.typesdb == nil { // Open collectd types. typesdb, err := gollectd.TypesDBFile(s.Config.TypesDB) if err != nil { return fmt.Errorf("Open(): %s", err) } s.typesdb = typesdb } // Resolve our address. addr, err := net.ResolveUDPAddr("udp", s.Config.BindAddress) if err != nil { return fmt.Errorf("unable to resolve UDP address: %s", err) } s.addr = addr // Start listening ln, err := net.ListenUDP("udp", addr) if err != nil { return fmt.Errorf("unable to listen on UDP: %s", err) } s.ln = ln s.Logger.Println("Listening on UDP: ", ln.LocalAddr().String()) // Start the points batcher. s.batcher = tsdb.NewPointBatcher(s.Config.BatchSize, s.Config.BatchPending, time.Duration(s.Config.BatchDuration)) s.batcher.Start() // Create channel and wait group for signalling goroutines to stop. s.stop = make(chan struct{}) s.wg.Add(2) // Start goroutines that process collectd packets. go s.serve() go s.writePoints() return nil }
// Open starts the service. func (s *Service) Open() error { s.mu.Lock() defer s.mu.Unlock() if !s.closed() { return nil // Already open. } s.done = make(chan struct{}) s.Logger.Printf("Starting collectd service") if s.Config.BindAddress == "" { return fmt.Errorf("bind address is blank") } else if s.Config.Database == "" { return fmt.Errorf("database name is blank") } else if s.PointsWriter == nil { return fmt.Errorf("PointsWriter is nil") } if s.typesdb == nil { // Open collectd types. if stat, err := os.Stat(s.Config.TypesDB); err != nil { return fmt.Errorf("Stat(): %s", err) } else if stat.IsDir() { alltypesdb := make(gollectd.Types) var readdir func(path string) readdir = func(path string) { files, err := ioutil.ReadDir(path) if err != nil { s.Logger.Printf("Unable to read directory %s: %s\n", path, err) return } for _, f := range files { fullpath := filepath.Join(path, f.Name()) if f.IsDir() { readdir(fullpath) continue } s.Logger.Printf("Loading %s\n", fullpath) types, err := gollectd.TypesDBFile(fullpath) if err != nil { s.Logger.Printf("Unable to parse collectd types file: %s\n", f.Name()) continue } for k, t := range types { a, ok := alltypesdb[k] if ok { alltypesdb[k] = t } else { alltypesdb[k] = append(a, t...) } } } } readdir(s.Config.TypesDB) s.typesdb = alltypesdb } else { s.Logger.Printf("Loading %s\n", s.Config.TypesDB) typesdb, err := gollectd.TypesDBFile(s.Config.TypesDB) if err != nil { return fmt.Errorf("Open(): %s", err) } s.typesdb = typesdb } } // Resolve our address. addr, err := net.ResolveUDPAddr("udp", s.Config.BindAddress) if err != nil { return fmt.Errorf("unable to resolve UDP address: %s", err) } s.addr = addr // Start listening conn, err := net.ListenUDP("udp", addr) if err != nil { return fmt.Errorf("unable to listen on UDP: %s", err) } if s.Config.ReadBuffer != 0 { err = conn.SetReadBuffer(s.Config.ReadBuffer) if err != nil { return fmt.Errorf("unable to set UDP read buffer to %d: %s", s.Config.ReadBuffer, err) } } s.conn = conn s.Logger.Println("Listening on UDP: ", conn.LocalAddr().String()) // Start the points batcher. s.batcher = tsdb.NewPointBatcher(s.Config.BatchSize, s.Config.BatchPending, time.Duration(s.Config.BatchDuration)) s.batcher.Start() // Create waitgroup for signalling goroutines to stop and start goroutines // that process collectd packets. s.wg.Add(2) go func() { defer s.wg.Done(); s.serve() }() go func() { defer s.wg.Done(); s.writePoints() }() return nil }