// Run runs a new HTTP service at the given addr, making data requests to the given c. // Run may be called repeatedly, and each time, will shut down any existing service first. // Run is NOT threadsafe, and MUST NOT be called concurrently by multiple goroutines. func (s Server) Run(c chan<- DataRequest, addr string) error { // TODO make an object, which itself is not threadsafe, but which encapsulates all data so multiple // objects can be created and Run. if s.stoppableListener != nil { log.Infof("Stopping Web Server\n") s.stoppableListener.Stop() s.stoppableListenerWaitGroup.Wait() } log.Infof("Starting Web Server\n") var err error var originalListener net.Listener if originalListener, err = net.Listen("tcp", addr); err != nil { return err } if s.stoppableListener, err = stoppableListener.New(originalListener); err != nil { return err } s.mgrReqChan = c sm := http.NewServeMux() err = s.registerEndpoints(sm) if err != nil { return err } server := &http.Server{ Addr: addr, Handler: sm, ReadTimeout: 10 * time.Second, WriteTimeout: 10 * time.Second, MaxHeaderBytes: 1 << 20, } s.stoppableListenerWaitGroup = sync.WaitGroup{} s.stoppableListenerWaitGroup.Add(1) go func() { defer s.stoppableListenerWaitGroup.Done() server.Serve(s.stoppableListener) }() log.Infof("Web server listening on %s", addr) return nil }
func CreateStats(statHistory map[enum.CacheName][]cache.Result, toData todata.TOData, crStates peer.Crstates, lastKbpsStats StatsLastKbps, now time.Time) (Stats, StatsLastKbps, error) { start := time.Now() dsStats := NewStats() for deliveryService, _ := range toData.DeliveryServiceServers { if deliveryService == "" { log.Errorf("EMPTY CreateStats deliveryService") continue } dsStats.DeliveryService[enum.DeliveryServiceName(deliveryService)] = *dsdata.NewStat() } dsStats = setStaticData(dsStats, toData.DeliveryServiceServers) var err error dsStats, err = addAvailableData(dsStats, crStates, toData.ServerCachegroups, toData.ServerDeliveryServices, toData.ServerTypes, statHistory) // TODO move after stat summarisation if err != nil { return dsStats, lastKbpsStats, fmt.Errorf("Error getting Cache availability data: %v", err) } for server, history := range statHistory { if len(history) < 1 { continue // TODO warn? } cachegroup, ok := toData.ServerCachegroups[server] if !ok { log.Warnf("server %s has no cachegroup, skipping\n", server) continue } serverType, ok := toData.ServerTypes[enum.CacheName(server)] if !ok { log.Warnf("server %s not in CRConfig, skipping\n", server) continue } result := history[len(history)-1] // TODO check result.PrecomputedData.Errors for ds, resultStat := range result.PrecomputedData.DeliveryServiceStats { if ds == "" { log.Errorf("EMPTY precomputed delivery service") continue } if _, ok := dsStats.DeliveryService[ds]; !ok { dsStats.DeliveryService[ds] = resultStat continue } httpDsStat := dsStats.DeliveryService[ds] httpDsStat.Total = httpDsStat.Total.Sum(resultStat.Total) httpDsStat.CacheGroups[cachegroup] = httpDsStat.CacheGroups[cachegroup].Sum(resultStat.CacheGroups[cachegroup]) httpDsStat.Type[serverType] = httpDsStat.Type[serverType].Sum(resultStat.Type[serverType]) dsStats.DeliveryService[ds] = httpDsStat // TODO determine if necessary } } kbpsStats, kbpsStatsLastKbps, kbpsErr := addKbps(statHistory, dsStats, lastKbpsStats, now) log.Infof("CreateStats took %v\n", time.Since(start)) return kbpsStats, kbpsStatsLastKbps, kbpsErr }
func processHealthResult(cacheHealthChan <-chan cache.Result, toData todata.TODataThreadsafe, localStates peer.CRStatesThreadsafe, lastHealthDurations DurationMapThreadsafe, statHistory StatHistoryThreadsafe, monitorConfig TrafficMonitorConfigMapThreadsafe, peerStates peer.CRStatesPeersThreadsafe, combinedStates peer.CRStatesThreadsafe, fetchCount UintThreadsafe, errorCount UintThreadsafe, events EventsThreadsafe, localCacheStatus CacheAvailableStatusThreadsafe, lastHealthEndTimes map[enum.CacheName]time.Time, healthHistory map[enum.CacheName][]cache.Result, results []cache.Result) { if len(results) == 0 { return } toDataCopy := toData.Get() // create a copy, so the same data used for all processing of this cache health result monitorConfigCopy := monitorConfig.Get() // copy now, so all calculations are on the same data for _, healthResult := range results { log.Debugf("poll %v %v healthresultman start\n", healthResult.PollID, time.Now()) fetchCount.Inc() var prevResult cache.Result healthResultHistory := healthHistory[enum.CacheName(healthResult.Id)] // healthResultHistory := healthHistory.Get(enum.CacheName(healthResult.Id)) if len(healthResultHistory) != 0 { prevResult = healthResultHistory[len(healthResultHistory)-1] } health.GetVitals(&healthResult, &prevResult, &monitorConfigCopy) // healthHistory.Set(enum.CacheName(healthResult.Id), pruneHistory(append(healthHistory.Get(enum.CacheName(healthResult.Id)), healthResult), defaultMaxHistory)) healthHistory[enum.CacheName(healthResult.Id)] = pruneHistory(append(healthHistory[enum.CacheName(healthResult.Id)], healthResult), defaultMaxHistory) isAvailable, whyAvailable := health.EvalCache(healthResult, &monitorConfigCopy) if localStates.Get().Caches[healthResult.Id].IsAvailable != isAvailable { log.Infof("Changing state for %s was: %t now: %t because %s errors: %v", healthResult.Id, prevResult.Available, isAvailable, whyAvailable, healthResult.Errors) events.Add(Event{Time: time.Now().Unix(), Description: whyAvailable, Name: healthResult.Id, Hostname: healthResult.Id, Type: toDataCopy.ServerTypes[enum.CacheName(healthResult.Id)].String(), Available: isAvailable}) } localCacheStatus.Set(enum.CacheName(healthResult.Id), CacheAvailableStatus{Available: isAvailable, Status: monitorConfigCopy.TrafficServer[healthResult.Id].Status}) // TODO move within localStates localStates.SetCache(healthResult.Id, peer.IsAvailable{IsAvailable: isAvailable}) log.Debugf("poll %v %v calculateDeliveryServiceState start\n", healthResult.PollID, time.Now()) calculateDeliveryServiceState(toDataCopy.DeliveryServiceServers, localStates) log.Debugf("poll %v %v calculateDeliveryServiceState end\n", healthResult.PollID, time.Now()) } // TODO determine if we should combineCrStates() here for _, healthResult := range results { if lastHealthStart, ok := lastHealthEndTimes[enum.CacheName(healthResult.Id)]; ok { d := time.Since(lastHealthStart) lastHealthDurations.Set(enum.CacheName(healthResult.Id), d) } lastHealthEndTimes[enum.CacheName(healthResult.Id)] = time.Now() log.Debugf("poll %v %v finish\n", healthResult.PollID, time.Now()) healthResult.PollFinished <- healthResult.PollID } }