예제 #1
0
파일: pixel.go 프로젝트: tgres/tgres
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))
		}
	}

}
예제 #2
0
파일: services.go 프로젝트: tgres/tgres
// 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)
		}
	}
}
예제 #3
0
파일: services.go 프로젝트: tgres/tgres
// 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)
		}
	}
}
예제 #4
0
파일: services.go 프로젝트: tgres/tgres
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())
		}
	}
}
예제 #5
0
파일: pixel.go 프로젝트: tgres/tgres
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)
			}
		}

	}
}
예제 #6
0
파일: daemon.go 프로젝트: tgres/tgres
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...")
	}
}
예제 #7
0
파일: daemon.go 프로젝트: tgres/tgres
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)
	}
}