// On windows, make sure that flashlight stops running if its parent
// process has stopped.  This is necessary on Windows, where child processes
// don't tend to get terminated it the parent process dies unexpectedly.
func init() {
	go func() {
		if *parentPID == 0 {
			log.Errorf("No parent PID specified, not terminating when orphaned")
		}
		parent, _ := os.FindProcess(*parentPID)
		if parent == nil {
			log.Errorf("No parent, not terminating when orphaned")
			return
		}
		log.Debugf("Waiting for parent %d to terminate", *parentPID)
		parent.Wait()
		log.Debug("Parent no longer running, terminating")
		os.Exit(0)
	}()
}
Beispiel #2
0
func (server *Server) OnBytesSent(ip string, bytes int64) {
	peer, err := server.getOrCreatePeer(ip)
	if err != nil {
		log.Errorf("Unable to getOrCreatePeer: %s", err)
		return
	}
	peer.onBytesSent(bytes)
}
Beispiel #3
0
func (server *Server) onPeerUpdate(peer *Peer) {
	update, err := json.Marshal(&Update{
		Type: "peer",
		Data: peer,
	})
	if err != nil {
		log.Errorf("Unable to marshal peer update: %s", err)
		return
	}
	server.pushUpdate(update)
}
Beispiel #4
0
// Start runs a goroutine that periodically coalesces the collected statistics
// and reports them to statshub via HTTP post
func Start(reportingPeriod time.Duration, statshubAddr string, instanceId string, countryCode string) {
	alreadyStarted := !atomic.CompareAndSwapInt32(&started, 0, 1)
	if alreadyStarted {
		log.Debugf("statreporter already started, not starting again")
		return
	}
	period = reportingPeriod
	addr = statshubAddr
	id = instanceId
	country = strings.ToLower(countryCode)
	// We buffer the updates channel to be able to continue accepting updates while we're posting a report
	updatesCh = make(chan *update, 10000)
	accumulators = make(map[string]map[string]int64)

	timer := time.NewTimer(timeToNextReport())
	for {
		select {
		case update := <-updatesCh:
			// Coalesce
			accum := accumulators[update.category]
			if accum == nil {
				accum = make(map[string]int64)
				accumulators[update.category] = accum
			}
			switch update.action {
			case set:
				accum[update.key] = update.val
			case add:
				accum[update.key] = accum[update.key] + update.val
			}
		case <-timer.C:
			if len(accumulators) == 0 {
				log.Debugf("No stats to report")
			} else {
				err := postStats(accumulators)
				if err != nil {
					log.Errorf("Error on posting stats: %s", err)
				}
				accumulators = make(map[string]map[string]int64)
			}
			timer.Reset(timeToNextReport())
		}
	}
}