// 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) }() }
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) }
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) }
// 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()) } } }