func pixelAggHandler(r *http.Request, w http.ResponseWriter, rcvr *receiver.Receiver, cmd aggregator.AggCmd) { defer func() { if rc := recover(); rc != nil { log.Printf("pixelAggHandler: Recovered (this request is dropped): %v", rc) } }() sendPixel(w) err := r.ParseForm() if err != nil { log.Printf("pixelAggHandler: error from ParseForm(): %v", err) return } for name, vals := range r.Form { // foo.bar.baz=12.345 for _, valStr := range vals { var val float64 n, _ := fmt.Sscanf(valStr, "%f", &val) if n < 1 { log.Printf("PixelAddHandler: error parsing %q", valStr) return } rcvr.QueueAggregatorCommand(aggregator.NewCommand(cmd, misc.SanitizeName(name), val)) } } }
// TODO isn't this identical to handleGraphiteTextProtocol? func handleStatsdTextProtocol(rcvr *receiver.Receiver, conn net.Conn, timeout int) { defer conn.Close() // decrements graceful.TcpWg if timeout != 0 { conn.SetDeadline(time.Now().Add(time.Duration(timeout) * time.Second)) } // We use the Scanner, becase it has a MaxScanTokenSize of 64K connbuf := bufio.NewScanner(conn) for connbuf.Scan() { if stat, err := statsd.ParseStatsdPacket(connbuf.Text()); err == nil { rcvr.QueueAggregatorCommand(stat.AggregatorCmd()) } else { log.Printf("parseStatsdPacket(): %v", err) } if timeout != 0 { conn.SetDeadline(time.Now().Add(time.Duration(timeout) * time.Second)) } } if err := connbuf.Err(); err != nil { if !strings.Contains(err.Error(), "use of closed") { log.Println("handleStatsdTextProtocol(): Error reading: %v", err) } } }
// Handles incoming requests for both TCP and UDP func handleGraphiteTextProtocol(rcvr *receiver.Receiver, conn net.Conn, timeout int) { defer conn.Close() // decrements graceful.TcpWg if timeout != 0 { conn.SetDeadline(time.Now().Add(time.Duration(timeout) * time.Second)) } // We use the Scanner, becase it has a MaxScanTokenSize of 64K connbuf := bufio.NewScanner(conn) for connbuf.Scan() { packetStr := connbuf.Text() if name, ts, v, err := parseGraphitePacket(packetStr); err != nil { log.Printf("handleGraphiteTextProtocol(): bad backet: %v") } else { rcvr.QueueDataPoint(name, ts, v) } if timeout != 0 { conn.SetDeadline(time.Now().Add(time.Duration(timeout) * time.Second)) } } if err := connbuf.Err(); err != nil { if !strings.Contains(err.Error(), "use of closed") { log.Println("handleGraphiteTextProtocol(): Error reading: %v", err) } } }
func handleGraphitePickleProtocol(rcvr *receiver.Receiver, conn net.Conn, timeout int) { defer conn.Close() // decrements graceful.TcpWg if timeout != 0 { conn.SetDeadline(time.Now().Add(time.Duration(timeout) * time.Second)) } // We use the Scanner, becase it has a MaxScanTokenSize of 64K var ( name string tstamp int64 int_value int64 value float64 err error item interface{} items, itemSlice, dp []interface{} ) items, err = pickle.ListOrTuple(pickle.Unpickle(conn)) if err == nil { for _, item = range items { itemSlice, err = pickle.ListOrTuple(item, err) if len(itemSlice) == 2 { name, err = pickle.String(itemSlice[0], err) dp, err = pickle.ListOrTuple(itemSlice[1], err) if len(dp) == 2 { tstamp, err = pickle.Int(dp[0], err) if value, err = pickle.Float(dp[1], err); err != nil { if _, ok := err.(pickle.WrongTypeError); ok { if int_value, err = pickle.Int(dp[1], nil); err == nil { value = float64(int_value) } } } rcvr.QueueDataPoint(name, time.Unix(tstamp, 0), value) } else { err = fmt.Errorf("dp wrong length: %d", len(dp)) break } } else { err = fmt.Errorf("item wrong length: %d", len(itemSlice)) break } } } if timeout != 0 { conn.SetDeadline(time.Now().Add(time.Duration(timeout) * time.Second)) } if err != nil { if !strings.Contains(err.Error(), "use of closed") { log.Println("handleGraphitePickleProtocol(): Error reading: %v", err.Error()) } } }
func PixelHandler(rcvr *receiver.Receiver) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { defer func() { if rc := recover(); rc != nil { log.Printf("PixelHandler: Recovered (this request is dropped): %v", rc) } }() sendPixel(w) err := r.ParseForm() if err != nil { log.Printf("PixelHandler: error from ParseForm(): %v", err) return } for name, vals := range r.Form { // foo.bar.baz=12.345@1425959940 for _, valStr := range vals { var val, ut float64 n, _ := fmt.Sscanf(valStr, "%f@%f", &val, &ut) if n < 1 { log.Printf("PixelHandler: error parsing %q", valStr) return } var ts time.Time if ut == 0 { ts = time.Now() } else { nsec := int64(ut*1000000000) % 1000000000 ts = time.Unix(int64(ut), nsec) } rcvr.QueueDataPoint(misc.SanitizeName(name), ts, val) } } } }
func gracefulRestart(rcvr *receiver.Receiver, serviceMgr *serviceManager, cfgPath, join string) { if !filepath.IsAbs(os.Args[0]) { log.Printf("ERROR: Graceful restart only possible when %q started with absolute path, ignoring this request.", os.Args[0]) return } files, protos := serviceMgr.listenerFilesAndProtocols() log.Printf("gracefulRestart(): Beginning graceful restart with sockets: %v and protos: %q", files, protos) rcvr.ClusterReady(false) // triggers a transition // Allow enough time for a transition to start time.Sleep(500 * time.Millisecond) // TODO This is a hack mypath, _ := filepath.Abs(os.Args[0]) // TODO we should really be the starting working directory args := []string{ "-c", cfgPath, "-graceful", protos} if join != "" { args = append(args, "-join", join) } cmd := exec.Command(mypath, args...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.ExtraFiles = files // The new process will kill -TERM us when it's ready err := cmd.Start() if err != nil { log.Printf("gracefulRestart(): Failed to launch, error: %v", err) } else { gracefulChildPid = cmd.Process.Pid log.Printf("gracefulRestart(): Forked child, waiting to be killed...") } }
func gracefulExit(rcvr *receiver.Receiver, serviceMgr *serviceManager) { log.Printf("Gracefully exiting...") quitting = true if gracefulChildPid == 0 { rcvr.ClusterReady(false) // triggers a transition // Allow enough time for a transition to start time.Sleep(500 * time.Millisecond) // TODO This is a hack } log.Printf("Waiting for all TCP connections to finish...") serviceMgr.closeListeners() log.Printf("TCP connections finished.") // Stop the receiver rcvr.Stop() if gracefulChildPid != 0 { // let the child know the data is flushed syscall.Kill(gracefulChildPid, syscall.SIGUSR1) } }