You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by el...@apache.org on 2017/01/26 16:45:05 UTC

[1/4] incubator-trafficcontrol git commit: moved Deliveryservice structs and helper methods to DeliveryserviceData to resolve circular dependencies, fixed event logging for DS threasholds

Repository: incubator-trafficcontrol
Updated Branches:
  refs/heads/master 246e2e633 -> 41e653905


moved Deliveryservice structs and helper methods to DeliveryserviceData to resolve circular dependencies, fixed event logging for DS threasholds

(cherry picked from commit 954f292c17f0d29cd310e61d3ae80a7e673a5dc9)


Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/8f4329b5
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/8f4329b5
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/8f4329b5

Branch: refs/heads/master
Commit: 8f4329b5970ea908cc652e00d7430059e19fee3b
Parents: db38fad
Author: David Neuman <da...@gmail.com>
Authored: Wed Jan 25 13:43:31 2017 -0700
Committer: Jeff Elsloo <je...@cable.comcast.com>
Committed: Thu Jan 26 09:44:15 2017 -0700

----------------------------------------------------------------------
 .../traffic_monitor/deliveryservice/stat.go     | 243 ++-----------------
 .../traffic_monitor/deliveryservicedata/stat.go | 197 +++++++++++++++
 .../traffic_monitor/manager/datarequest.go      |   2 +-
 .../traffic_monitor/manager/stat.go             |   7 +-
 .../traffic_monitor/threadsafe/dsstats.go       |  10 +-
 .../traffic_monitor/threadsafe/lastkbpsstats.go |  11 +-
 .../traffic_monitor/threadsafe/polledcaches.go  |   4 +-
 7 files changed, 238 insertions(+), 236 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/8f4329b5/traffic_monitor/experimental/traffic_monitor/deliveryservice/stat.go
----------------------------------------------------------------------
diff --git a/traffic_monitor/experimental/traffic_monitor/deliveryservice/stat.go b/traffic_monitor/experimental/traffic_monitor/deliveryservice/stat.go
index 2b21969..90dbe71 100644
--- a/traffic_monitor/experimental/traffic_monitor/deliveryservice/stat.go
+++ b/traffic_monitor/experimental/traffic_monitor/deliveryservice/stat.go
@@ -21,8 +21,6 @@ package deliveryservice
 
 import (
 	"fmt"
-	"net/url"
-	"strconv"
 	"time"
 
 	"github.com/apache/incubator-trafficcontrol/traffic_monitor/experimental/common/log"
@@ -32,42 +30,13 @@ import (
 	"github.com/apache/incubator-trafficcontrol/traffic_monitor/experimental/traffic_monitor/enum"
 	"github.com/apache/incubator-trafficcontrol/traffic_monitor/experimental/traffic_monitor/health"
 	"github.com/apache/incubator-trafficcontrol/traffic_monitor/experimental/traffic_monitor/peer"
-	"github.com/apache/incubator-trafficcontrol/traffic_monitor/experimental/traffic_monitor/srvhttp"
 	todata "github.com/apache/incubator-trafficcontrol/traffic_monitor/experimental/traffic_monitor/trafficopsdata"
 	to "github.com/apache/incubator-trafficcontrol/traffic_ops/client"
 )
 
 // TODO remove 'ds' and 'stat' from names
 
-// Stats is the JSON-serialisable representation of delivery service Stats. It maps delivery service names to individual stat objects.
-type Stats struct {
-	DeliveryService map[enum.DeliveryServiceName]dsdata.Stat `json:"deliveryService"`
-	Time            time.Time                                `json:"-"`
-}
-
-// Copy performs a deep copy of this Stats object.
-func (s Stats) Copy() Stats {
-	b := NewStats()
-	for k, v := range s.DeliveryService {
-		b.DeliveryService[k] = v.Copy()
-	}
-	b.Time = s.Time
-	return b
-}
-
-// Get returns the stats for the given delivery service, and whether it exists.
-func (s Stats) Get(name enum.DeliveryServiceName) (dsdata.StatReadonly, bool) {
-	ds, ok := s.DeliveryService[name]
-	return ds, ok
-}
-
-// NewStats creates a new Stats object, initializing any pointer members.
-// TODO rename to just 'New'?
-func NewStats() Stats {
-	return Stats{DeliveryService: map[enum.DeliveryServiceName]dsdata.Stat{}}
-}
-
-func setStaticData(dsStats Stats, dsServers map[enum.DeliveryServiceName][]enum.CacheName) Stats {
+func setStaticData(dsStats dsdata.Stats, dsServers map[enum.DeliveryServiceName][]enum.CacheName) dsdata.Stats {
 	for ds, stat := range dsStats.DeliveryService {
 		stat.CommonStats.CachesConfiguredNum.Value = int64(len(dsServers[ds]))
 		dsStats.DeliveryService[ds] = stat // TODO consider changing dsStats.DeliveryService[ds] to a pointer so this kind of thing isn't necessary; possibly more performant, as well
@@ -75,7 +44,7 @@ func setStaticData(dsStats Stats, dsServers map[enum.DeliveryServiceName][]enum.
 	return dsStats
 }
 
-func addAvailableData(dsStats Stats, crStates peer.Crstates, serverCachegroups map[enum.CacheName]enum.CacheGroupName, serverDs map[enum.CacheName][]enum.DeliveryServiceName, serverTypes map[enum.CacheName]enum.CacheType, precomputed map[enum.CacheName]cache.PrecomputedData) (Stats, error) {
+func addAvailableData(dsStats dsdata.Stats, crStates peer.Crstates, serverCachegroups map[enum.CacheName]enum.CacheGroupName, serverDs map[enum.CacheName][]enum.DeliveryServiceName, serverTypes map[enum.CacheName]enum.CacheType, precomputed map[enum.CacheName]cache.PrecomputedData) (dsdata.Stats, error) {
 	for cache, available := range crStates.Caches {
 		cacheGroup, ok := serverCachegroups[cache]
 		if !ok {
@@ -152,105 +121,18 @@ func addAvailableData(dsStats Stats, crStates peer.Crstates, serverCachegroups m
 	return dsStats, nil
 }
 
-// LastStats includes the previously recieved stats for DeliveryServices and Caches, the stat itself, when it was received, and the stat value per second.
-type LastStats struct {
-	DeliveryServices map[enum.DeliveryServiceName]LastDSStat
-	Caches           map[enum.CacheName]LastStatsData
-}
-
-// NewLastStats returns a new LastStats object, initializing internal pointer values.
-func NewLastStats() LastStats {
-	return LastStats{DeliveryServices: map[enum.DeliveryServiceName]LastDSStat{}, Caches: map[enum.CacheName]LastStatsData{}}
-}
-
-// Copy performs a deep copy of this LastStats object.
-func (a LastStats) Copy() LastStats {
-	b := NewLastStats()
-	for k, v := range a.DeliveryServices {
-		b.DeliveryServices[k] = v.Copy()
-	}
-	for k, v := range a.Caches {
-		b.Caches[k] = v
-	}
-	return b
-}
-
-// LastDSStat maps and aggregates the last stats received for the given delivery service to caches, cache groups, types, and total.
-// TODO figure a way to associate this type with StatHTTP, with which its members correspond.
-type LastDSStat struct {
-	Caches      map[enum.CacheName]LastStatsData
-	CacheGroups map[enum.CacheGroupName]LastStatsData
-	Type        map[enum.CacheType]LastStatsData
-	Total       LastStatsData
-}
-
-// Copy performs a deep copy of this LastDSStat object.
-func (a LastDSStat) Copy() LastDSStat {
-	b := LastDSStat{
-		CacheGroups: map[enum.CacheGroupName]LastStatsData{},
-		Type:        map[enum.CacheType]LastStatsData{},
-		Caches:      map[enum.CacheName]LastStatsData{},
-		Total:       a.Total,
-	}
-	for k, v := range a.CacheGroups {
-		b.CacheGroups[k] = v
-	}
-	for k, v := range a.Type {
-		b.Type[k] = v
-	}
-	for k, v := range a.Caches {
-		b.Caches[k] = v
-	}
-	return b
-}
-
-func newLastDSStat() LastDSStat {
-	return LastDSStat{
-		CacheGroups: map[enum.CacheGroupName]LastStatsData{},
-		Type:        map[enum.CacheType]LastStatsData{},
-		Caches:      map[enum.CacheName]LastStatsData{},
-	}
-}
-
-// LastStatsData contains the last stats and per-second calculations for bytes and status codes received from a cache.
-type LastStatsData struct {
-	Bytes     LastStatData
-	Status2xx LastStatData
-	Status3xx LastStatData
-	Status4xx LastStatData
-	Status5xx LastStatData
-}
-
-// Sum returns the Sum() of each member data with the given LastStatsData corresponding members
-func (a LastStatsData) Sum(b LastStatsData) LastStatsData {
-	return LastStatsData{
-		Bytes:     a.Bytes.Sum(b.Bytes),
-		Status2xx: a.Status2xx.Sum(b.Status2xx),
-		Status3xx: a.Status3xx.Sum(b.Status3xx),
-		Status4xx: a.Status4xx.Sum(b.Status4xx),
-		Status5xx: a.Status5xx.Sum(b.Status5xx),
-	}
-}
-
-// LastStatData contains the value, time it was received, and per-second calculation since the previous stat, for a stat from a cache.
-type LastStatData struct {
-	PerSec float64
-	Stat   int64
-	Time   time.Time
-}
-
-// Sum adds the PerSec and Stat of the given data to this object. Time is meaningless for the summed object, and is thus set to 0.
-func (a LastStatData) Sum(b LastStatData) LastStatData {
-	return LastStatData{
-		PerSec: a.PerSec + b.PerSec,
-		Stat:   a.Stat + b.Stat,
+func newLastDSStat() dsdata.LastDSStat {
+	return dsdata.LastDSStat{
+		CacheGroups: map[enum.CacheGroupName]dsdata.LastStatsData{},
+		Type:        map[enum.CacheType]dsdata.LastStatsData{},
+		Caches:      map[enum.CacheName]dsdata.LastStatsData{},
 	}
 }
 
 // BytesPerKilobit is the number of bytes in a kilobit.
 const BytesPerKilobit = 125
 
-func addLastStat(lastData LastStatData, newStat int64, newStatTime time.Time) (LastStatData, error) {
+func addLastStat(lastData dsdata.LastStatData, newStat int64, newStatTime time.Time) (dsdata.LastStatData, error) {
 	if newStat == lastData.Stat {
 		return lastData, nil
 	}
@@ -272,7 +154,7 @@ func addLastStat(lastData LastStatData, newStat int64, newStatTime time.Time) (L
 	return lastData, nil
 }
 
-func addLastStats(lastData LastStatsData, newStats dsdata.StatCacheStats, newStatsTime time.Time) (LastStatsData, error) {
+func addLastStats(lastData dsdata.LastStatsData, newStats dsdata.StatCacheStats, newStatsTime time.Time) (dsdata.LastStatsData, error) {
 	errs := []error{nil, nil, nil, nil, nil}
 	lastData.Bytes, errs[0] = addLastStat(lastData.Bytes, newStats.OutBytes.Value, newStatsTime)
 	lastData.Status2xx, errs[1] = addLastStat(lastData.Status2xx, newStats.Status2xx.Value, newStatsTime)
@@ -282,7 +164,7 @@ func addLastStats(lastData LastStatsData, newStats dsdata.StatCacheStats, newSta
 	return lastData, util.JoinErrors(errs)
 }
 
-func addLastStatsToStatCacheStats(s dsdata.StatCacheStats, l LastStatsData) dsdata.StatCacheStats {
+func addLastStatsToStatCacheStats(s dsdata.StatCacheStats, l dsdata.LastStatsData) dsdata.StatCacheStats {
 	s.Kbps.Value = l.Bytes.PerSec / BytesPerKilobit
 	s.Tps2xx.Value = l.Status2xx.PerSec
 	s.Tps3xx.Value = l.Status3xx.PerSec
@@ -293,10 +175,10 @@ func addLastStatsToStatCacheStats(s dsdata.StatCacheStats, l LastStatsData) dsda
 }
 
 // addLastDSStatTotals takes a LastDSStat with only raw `Caches` data, and calculates and sets the `CacheGroups`, `Type`, and `Total` data, and returns the augmented structure.
-func addLastDSStatTotals(lastStat LastDSStat, cachesReporting map[enum.CacheName]bool, serverCachegroups map[enum.CacheName]enum.CacheGroupName, serverTypes map[enum.CacheName]enum.CacheType) LastDSStat {
-	cacheGroups := map[enum.CacheGroupName]LastStatsData{}
-	cacheTypes := map[enum.CacheType]LastStatsData{}
-	total := LastStatsData{}
+func addLastDSStatTotals(lastStat dsdata.LastDSStat, cachesReporting map[enum.CacheName]bool, serverCachegroups map[enum.CacheName]enum.CacheGroupName, serverTypes map[enum.CacheName]enum.CacheType) dsdata.LastDSStat {
+	cacheGroups := map[enum.CacheGroupName]dsdata.LastStatsData{}
+	cacheTypes := map[enum.CacheType]dsdata.LastStatsData{}
+	total := dsdata.LastStatsData{}
 	for cacheName, cacheStats := range lastStat.Caches {
 		if !cachesReporting[cacheName] {
 			continue
@@ -322,7 +204,7 @@ func addLastDSStatTotals(lastStat LastDSStat, cachesReporting map[enum.CacheName
 }
 
 // addDSPerSecStats calculates and adds the per-second delivery service stats to both the Stats and LastStats structures, and returns the augmented structures.
-func addDSPerSecStats(dsName enum.DeliveryServiceName, stat dsdata.Stat, lastStats LastStats, dsStats Stats, dsStatsTime time.Time, serverCachegroups map[enum.CacheName]enum.CacheGroupName, serverTypes map[enum.CacheName]enum.CacheType, mc to.TrafficMonitorConfigMap, events []health.Event) (Stats, LastStats, []health.Event) {
+func addDSPerSecStats(dsName enum.DeliveryServiceName, stat dsdata.Stat, lastStats dsdata.LastStats, dsStats dsdata.Stats, dsStatsTime time.Time, serverCachegroups map[enum.CacheName]enum.CacheGroupName, serverTypes map[enum.CacheName]enum.CacheType, mc to.TrafficMonitorConfigMap, events health.ThreadsafeEvents) (dsdata.Stats, dsdata.LastStats) {
 	err := error(nil)
 	lastStat, lastStatExists := lastStats.DeliveryServices[dsName]
 	if !lastStatExists {
@@ -354,11 +236,11 @@ func addDSPerSecStats(dsName enum.DeliveryServiceName, stat dsdata.Stat, lastSta
 		stat.CommonStats.IsAvailable.Value = false
 		stat.CommonStats.IsHealthy.Value = false
 		stat.CommonStats.ErrorStr.Value = errStr
-		events = append(events, health.Event{Time: time.Now(), Unix: time.Now().Unix(), Description: errStr, Name: dsName.String(), Hostname: dsName.String(), Type: "Delivery Service", Available: stat.CommonStats.IsAvailable.Value})
+		events.Add(health.Event{Time: time.Now(), Unix: time.Now().Unix(), Description: errStr, Name: dsName.String(), Hostname: dsName.String(), Type: "Delivery Service", Available: stat.CommonStats.IsAvailable.Value})
 	}
 
 	dsStats.DeliveryService[dsName] = stat
-	return dsStats, lastStats, events
+	return dsStats, lastStats
 }
 
 // latestBytes returns the most recent OutBytes from the given cache results, and the time of that result. It assumes zero results are not valid, but nonzero results with errors are valid.
@@ -370,7 +252,7 @@ func latestBytes(p cache.PrecomputedData) (int64, time.Time, error) {
 }
 
 // addCachePerSecStats calculates the cache per-second stats, adds them to LastStats, and returns the augmented object.
-func addCachePerSecStats(cacheName enum.CacheName, precomputed cache.PrecomputedData, lastStats LastStats) LastStats {
+func addCachePerSecStats(cacheName enum.CacheName, precomputed cache.PrecomputedData, lastStats dsdata.LastStats) dsdata.LastStats {
 	outBytes, outBytesTime, err := latestBytes(precomputed) // it's ok if `latestBytes` returns 0s with an error, `addLastStat` will refrain from setting it (unless the previous calculation was nonzero, in which case it will error appropriately).
 	if err != nil {
 		log.Warnf("while computing delivery service data for cache %v: %v\n", cacheName, err)
@@ -393,22 +275,21 @@ func addCachePerSecStats(cacheName enum.CacheName, precomputed cache.Precomputed
 // we set the (new - old) / lastChangedTime as the KBPS, and update the recorded LastChangedTime and LastChangedValue
 //
 // TODO handle ATS byte rolling (when the `out_bytes` overflows back to 0)
-func addPerSecStats(precomputed map[enum.CacheName]cache.PrecomputedData, dsStats Stats, lastStats LastStats, dsStatsTime time.Time, serverCachegroups map[enum.CacheName]enum.CacheGroupName, serverTypes map[enum.CacheName]enum.CacheType, mc to.TrafficMonitorConfigMap, events []health.Event) (Stats, LastStats, []health.Event) {
+func addPerSecStats(precomputed map[enum.CacheName]cache.PrecomputedData, dsStats dsdata.Stats, lastStats dsdata.LastStats, dsStatsTime time.Time, serverCachegroups map[enum.CacheName]enum.CacheGroupName, serverTypes map[enum.CacheName]enum.CacheType, mc to.TrafficMonitorConfigMap, events health.ThreadsafeEvents) (dsdata.Stats, dsdata.LastStats) {
 	for dsName, stat := range dsStats.DeliveryService {
-		dsStats, lastStats, events = addDSPerSecStats(dsName, stat, lastStats, dsStats, dsStatsTime, serverCachegroups, serverTypes, mc, events)
+		dsStats, lastStats = addDSPerSecStats(dsName, stat, lastStats, dsStats, dsStatsTime, serverCachegroups, serverTypes, mc, events)
 	}
 	for cacheName, precomputedData := range precomputed {
 		lastStats = addCachePerSecStats(cacheName, precomputedData, lastStats)
 	}
 
-	return dsStats, lastStats, events
+	return dsStats, lastStats
 }
 
 // CreateStats aggregates and creates statistics from given precomputed stat history. It returns the created stats, information about these stats necessary for the next calculation, and any error.
-func CreateStats(precomputed map[enum.CacheName]cache.PrecomputedData, toData todata.TOData, crStates peer.Crstates, lastStats LastStats, now time.Time, mc to.TrafficMonitorConfigMap) (Stats, LastStats, []health.Event, error) {
-	var events []health.Event
+func CreateStats(precomputed map[enum.CacheName]cache.PrecomputedData, toData todata.TOData, crStates peer.Crstates, lastStats dsdata.LastStats, now time.Time, mc to.TrafficMonitorConfigMap, events health.ThreadsafeEvents) (dsdata.Stats, dsdata.LastStats, error) {
 	start := time.Now()
-	dsStats := NewStats()
+	dsStats := dsdata.NewStats()
 	for deliveryService := range toData.DeliveryServiceServers {
 		if deliveryService == "" {
 			log.Errorf("EMPTY CreateStats deliveryService")
@@ -420,7 +301,7 @@ func CreateStats(precomputed map[enum.CacheName]cache.PrecomputedData, toData to
 	var err error
 	dsStats, err = addAvailableData(dsStats, crStates, toData.ServerCachegroups, toData.ServerDeliveryServices, toData.ServerTypes, precomputed) // TODO move after stat summarisation
 	if err != nil {
-		return dsStats, lastStats, events, fmt.Errorf("Error getting Cache availability data: %v", err)
+		return dsStats, lastStats, fmt.Errorf("Error getting Cache availability data: %v", err)
 	}
 
 	for server, precomputedData := range precomputed {
@@ -457,82 +338,10 @@ func CreateStats(precomputed map[enum.CacheName]cache.PrecomputedData, toData to
 		}
 	}
 
-	perSecStats, lastStats, events := addPerSecStats(precomputed, dsStats, lastStats, now, toData.ServerCachegroups, toData.ServerTypes, mc, events)
+	perSecStats, lastStats := addPerSecStats(precomputed, dsStats, lastStats, now, toData.ServerCachegroups, toData.ServerTypes, mc, events)
 	log.Infof("CreateStats took %v\n", time.Since(start))
 	perSecStats.Time = time.Now()
-	return perSecStats, lastStats, events, nil
-}
-
-func addStatCacheStats(s *dsdata.StatsOld, c dsdata.StatCacheStats, deliveryService enum.DeliveryServiceName, prefix string, t int64, filter dsdata.Filter) *dsdata.StatsOld {
-	add := func(name, val string) {
-		if filter.UseStat(name) {
-			// This is for compatibility with the Traffic Monitor 1.0 API.
-			// TODO abstract this? Or deprecate and remove it?
-			if name == "isAvailable" || name == "error-string" {
-				s.DeliveryService[deliveryService][dsdata.StatName("location."+prefix+name)] = []dsdata.StatOld{dsdata.StatOld{Time: t, Value: val}}
-			} else {
-				s.DeliveryService[deliveryService][dsdata.StatName(prefix+name)] = []dsdata.StatOld{dsdata.StatOld{Time: t, Value: val}}
-			}
-		}
-	}
-	add("out_bytes", strconv.Itoa(int(c.OutBytes.Value)))
-	add("isAvailable", fmt.Sprintf("%t", c.IsAvailable.Value))
-	add("status_5xx", strconv.Itoa(int(c.Status5xx.Value)))
-	add("status_4xx", strconv.Itoa(int(c.Status4xx.Value)))
-	add("status_3xx", strconv.Itoa(int(c.Status3xx.Value)))
-	add("status_2xx", strconv.Itoa(int(c.Status2xx.Value)))
-	add("in_bytes", strconv.Itoa(int(c.InBytes.Value)))
-	add("kbps", strconv.Itoa(int(c.Kbps.Value)))
-	add("tps_5xx", fmt.Sprintf("%f", c.Tps5xx.Value))
-	add("tps_4xx", fmt.Sprintf("%f", c.Tps4xx.Value))
-	add("tps_3xx", fmt.Sprintf("%f", c.Tps3xx.Value))
-	add("tps_2xx", fmt.Sprintf("%f", c.Tps2xx.Value))
-	add("error-string", c.ErrorString.Value)
-	add("tps_total", fmt.Sprintf("%f", c.TpsTotal.Value))
-	return s
-}
-
-func addCommonData(s *dsdata.StatsOld, c *dsdata.StatCommon, deliveryService enum.DeliveryServiceName, t int64, filter dsdata.Filter) *dsdata.StatsOld {
-	add := func(name string, val interface{}) {
-		if filter.UseStat(name) {
-			s.DeliveryService[deliveryService][dsdata.StatName(name)] = []dsdata.StatOld{dsdata.StatOld{Time: t, Value: val}}
-		}
-	}
-	add("caches-configured", fmt.Sprintf("%d", c.CachesConfiguredNum.Value))
-	add("caches-reporting", fmt.Sprintf("%d", len(c.CachesReporting)))
-	add("error-string", c.ErrorStr.Value)
-	add("status", c.StatusStr.Value)
-	add("isHealthy", fmt.Sprintf("%t", c.IsHealthy.Value))
-	add("isAvailable", fmt.Sprintf("%t", c.IsAvailable.Value))
-	add("caches-available", fmt.Sprintf("%d", c.CachesAvailableNum.Value))
-	add("disabledLocations", c.CachesDisabled)
-	return s
-}
-
-// JSON returns an object formatted as expected to be serialized to JSON and served.
-func (s Stats) JSON(filter dsdata.Filter, params url.Values) dsdata.StatsOld {
-	// TODO fix to be the time calculated, not the time requested
-	now := s.Time.UnixNano() / int64(time.Millisecond) // Traffic Monitor 1.0 API is 'ms since the epoch'
-	jsonObj := &dsdata.StatsOld{
-		CommonAPIData:   srvhttp.GetCommonAPIData(params, time.Now()),
-		DeliveryService: map[enum.DeliveryServiceName]map[dsdata.StatName][]dsdata.StatOld{},
-	}
-
-	for deliveryService, stat := range s.DeliveryService {
-		if !filter.UseDeliveryService(deliveryService) {
-			continue
-		}
-		jsonObj.DeliveryService[deliveryService] = map[dsdata.StatName][]dsdata.StatOld{}
-		jsonObj = addCommonData(jsonObj, &stat.CommonStats, deliveryService, now, filter)
-		for cacheGroup, cacheGroupStats := range stat.CacheGroups {
-			jsonObj = addStatCacheStats(jsonObj, cacheGroupStats, deliveryService, "location."+string(cacheGroup)+".", now, filter)
-		}
-		for cacheType, typeStats := range stat.Types {
-			jsonObj = addStatCacheStats(jsonObj, typeStats, deliveryService, "type."+cacheType.String()+".", now, filter)
-		}
-		jsonObj = addStatCacheStats(jsonObj, stat.TotalStats, deliveryService, "total.", now, filter)
-	}
-	return *jsonObj
+	return perSecStats, lastStats, nil
 }
 
 func getDsErrString(dsName enum.DeliveryServiceName, dsStats dsdata.StatCacheStats, monitorConfig to.TrafficMonitorConfigMap) string {

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/8f4329b5/traffic_monitor/experimental/traffic_monitor/deliveryservicedata/stat.go
----------------------------------------------------------------------
diff --git a/traffic_monitor/experimental/traffic_monitor/deliveryservicedata/stat.go b/traffic_monitor/experimental/traffic_monitor/deliveryservicedata/stat.go
index b5d54b1..b60a3d7 100644
--- a/traffic_monitor/experimental/traffic_monitor/deliveryservicedata/stat.go
+++ b/traffic_monitor/experimental/traffic_monitor/deliveryservicedata/stat.go
@@ -21,7 +21,9 @@ package deliveryservicedata // TODO rename?
 
 import (
 	"errors"
+	"fmt"
 	"net/url"
+	"strconv"
 	"time"
 
 	"github.com/apache/incubator-trafficcontrol/traffic_monitor/experimental/traffic_monitor/enum"
@@ -289,3 +291,198 @@ func (a Stat) Type(name enum.CacheType) (StatCacheStats, bool) {
 func (a Stat) Total() StatCacheStats {
 	return a.TotalStats
 }
+
+// Stats is the JSON-serialisable representation of delivery service Stats. It maps delivery service names to individual stat objects.
+type Stats struct {
+	DeliveryService map[enum.DeliveryServiceName]Stat `json:"deliveryService"`
+	Time            time.Time                         `json:"-"`
+}
+
+// Copy performs a deep copy of this Stats object.
+func (s Stats) Copy() Stats {
+	b := NewStats()
+	for k, v := range s.DeliveryService {
+		b.DeliveryService[k] = v.Copy()
+	}
+	b.Time = s.Time
+	return b
+}
+
+// Get returns the stats for the given delivery service, and whether it exists.
+func (s Stats) Get(name enum.DeliveryServiceName) (StatReadonly, bool) {
+	ds, ok := s.DeliveryService[name]
+	return ds, ok
+}
+
+// JSON returns an object formatted as expected to be serialized to JSON and served.
+func (s Stats) JSON(filter Filter, params url.Values) StatsOld {
+	// TODO fix to be the time calculated, not the time requested
+	now := s.Time.UnixNano() / int64(time.Millisecond) // Traffic Monitor 1.0 API is 'ms since the epoch'
+	jsonObj := &StatsOld{
+		CommonAPIData:   srvhttp.GetCommonAPIData(params, time.Now()),
+		DeliveryService: map[enum.DeliveryServiceName]map[StatName][]StatOld{},
+	}
+
+	for deliveryService, stat := range s.DeliveryService {
+		if !filter.UseDeliveryService(deliveryService) {
+			continue
+		}
+		jsonObj.DeliveryService[deliveryService] = map[StatName][]StatOld{}
+		jsonObj = addCommonData(jsonObj, &stat.CommonStats, deliveryService, now, filter)
+		for cacheGroup, cacheGroupStats := range stat.CacheGroups {
+			jsonObj = addStatCacheStats(jsonObj, cacheGroupStats, deliveryService, "location."+string(cacheGroup)+".", now, filter)
+		}
+		for cacheType, typeStats := range stat.Types {
+			jsonObj = addStatCacheStats(jsonObj, typeStats, deliveryService, "type."+cacheType.String()+".", now, filter)
+		}
+		jsonObj = addStatCacheStats(jsonObj, stat.TotalStats, deliveryService, "total.", now, filter)
+	}
+	return *jsonObj
+}
+
+// NewStats creates a new Stats object, initializing any pointer members.
+// TODO rename to just 'New'?
+func NewStats() Stats {
+	return Stats{DeliveryService: map[enum.DeliveryServiceName]Stat{}}
+}
+
+// LastStats includes the previously recieved stats for DeliveryServices and Caches, the stat itself, when it was received, and the stat value per second.
+type LastStats struct {
+	DeliveryServices map[enum.DeliveryServiceName]LastDSStat
+	Caches           map[enum.CacheName]LastStatsData
+}
+
+// NewLastStats returns a new LastStats object, initializing internal pointer values.
+func NewLastStats() LastStats {
+	return LastStats{DeliveryServices: map[enum.DeliveryServiceName]LastDSStat{}, Caches: map[enum.CacheName]LastStatsData{}}
+}
+
+// Copy performs a deep copy of this LastStats object.
+func (a LastStats) Copy() LastStats {
+	b := NewLastStats()
+	for k, v := range a.DeliveryServices {
+		b.DeliveryServices[k] = v.Copy()
+	}
+	for k, v := range a.Caches {
+		b.Caches[k] = v
+	}
+	return b
+}
+
+// LastDSStat maps and aggregates the last stats received for the given delivery service to caches, cache groups, types, and total.
+// TODO figure a way to associate this type with StatHTTP, with which its members correspond.
+type LastDSStat struct {
+	Caches      map[enum.CacheName]LastStatsData
+	CacheGroups map[enum.CacheGroupName]LastStatsData
+	Type        map[enum.CacheType]LastStatsData
+	Total       LastStatsData
+}
+
+// Copy performs a deep copy of this LastDSStat object.
+func (a LastDSStat) Copy() LastDSStat {
+	b := LastDSStat{
+		CacheGroups: map[enum.CacheGroupName]LastStatsData{},
+		Type:        map[enum.CacheType]LastStatsData{},
+		Caches:      map[enum.CacheName]LastStatsData{},
+		Total:       a.Total,
+	}
+	for k, v := range a.CacheGroups {
+		b.CacheGroups[k] = v
+	}
+	for k, v := range a.Type {
+		b.Type[k] = v
+	}
+	for k, v := range a.Caches {
+		b.Caches[k] = v
+	}
+	return b
+}
+
+func newLastDSStat() LastDSStat {
+	return LastDSStat{
+		CacheGroups: map[enum.CacheGroupName]LastStatsData{},
+		Type:        map[enum.CacheType]LastStatsData{},
+		Caches:      map[enum.CacheName]LastStatsData{},
+	}
+}
+
+// LastStatsData contains the last stats and per-second calculations for bytes and status codes received from a cache.
+type LastStatsData struct {
+	Bytes     LastStatData
+	Status2xx LastStatData
+	Status3xx LastStatData
+	Status4xx LastStatData
+	Status5xx LastStatData
+}
+
+// Sum returns the Sum() of each member data with the given LastStatsData corresponding members
+func (a LastStatsData) Sum(b LastStatsData) LastStatsData {
+	return LastStatsData{
+		Bytes:     a.Bytes.Sum(b.Bytes),
+		Status2xx: a.Status2xx.Sum(b.Status2xx),
+		Status3xx: a.Status3xx.Sum(b.Status3xx),
+		Status4xx: a.Status4xx.Sum(b.Status4xx),
+		Status5xx: a.Status5xx.Sum(b.Status5xx),
+	}
+}
+
+// LastStatData contains the value, time it was received, and per-second calculation since the previous stat, for a stat from a cache.
+type LastStatData struct {
+	PerSec float64
+	Stat   int64
+	Time   time.Time
+}
+
+// Sum adds the PerSec and Stat of the given data to this object. Time is meaningless for the summed object, and is thus set to 0.
+func (a LastStatData) Sum(b LastStatData) LastStatData {
+	return LastStatData{
+		PerSec: a.PerSec + b.PerSec,
+		Stat:   a.Stat + b.Stat,
+	}
+}
+
+func addCommonData(s *StatsOld, c *StatCommon, deliveryService enum.DeliveryServiceName, t int64, filter Filter) *StatsOld {
+	add := func(name string, val interface{}) {
+		if filter.UseStat(name) {
+			s.DeliveryService[deliveryService][StatName(name)] = []StatOld{StatOld{Time: t, Value: val}}
+		}
+	}
+	add("caches-configured", fmt.Sprintf("%d", c.CachesConfiguredNum.Value))
+	add("caches-reporting", fmt.Sprintf("%d", len(c.CachesReporting)))
+	add("error-string", c.ErrorStr.Value)
+	add("status", c.StatusStr.Value)
+	add("isHealthy", fmt.Sprintf("%t", c.IsHealthy.Value))
+	add("isAvailable", fmt.Sprintf("%t", c.IsAvailable.Value))
+	add("caches-available", fmt.Sprintf("%d", c.CachesAvailableNum.Value))
+	add("disabledLocations", c.CachesDisabled)
+	return s
+}
+
+func addStatCacheStats(s *StatsOld, c StatCacheStats, deliveryService enum.DeliveryServiceName, prefix string, t int64, filter Filter) *StatsOld {
+	add := func(name, val string) {
+		if filter.UseStat(name) {
+			// This is for compatibility with the Traffic Monitor 1.0 API.
+			// TODO abstract this? Or deprecate and remove it?
+			if name == "isAvailable" || name == "error-string" {
+				s.DeliveryService[deliveryService][StatName("location."+prefix+name)] = []StatOld{StatOld{Time: t, Value: val}}
+			} else {
+				s.DeliveryService[deliveryService][StatName(prefix+name)] = []StatOld{StatOld{Time: t, Value: val}}
+			}
+		}
+	}
+	add("out_bytes", strconv.Itoa(int(c.OutBytes.Value)))
+	add("isAvailable", fmt.Sprintf("%t", c.IsAvailable.Value))
+	add("status_5xx", strconv.Itoa(int(c.Status5xx.Value)))
+	add("status_4xx", strconv.Itoa(int(c.Status4xx.Value)))
+	add("status_3xx", strconv.Itoa(int(c.Status3xx.Value)))
+	add("status_2xx", strconv.Itoa(int(c.Status2xx.Value)))
+	add("in_bytes", strconv.Itoa(int(c.InBytes.Value)))
+	add("kbps", strconv.Itoa(int(c.Kbps.Value)))
+	add("tps_5xx", fmt.Sprintf("%f", c.Tps5xx.Value))
+	add("tps_4xx", fmt.Sprintf("%f", c.Tps4xx.Value))
+	add("tps_3xx", fmt.Sprintf("%f", c.Tps3xx.Value))
+	add("tps_2xx", fmt.Sprintf("%f", c.Tps2xx.Value))
+	add("error-string", c.ErrorString.Value)
+	add("tps_total", fmt.Sprintf("%f", c.TpsTotal.Value))
+	return s
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/8f4329b5/traffic_monitor/experimental/traffic_monitor/manager/datarequest.go
----------------------------------------------------------------------
diff --git a/traffic_monitor/experimental/traffic_monitor/manager/datarequest.go b/traffic_monitor/experimental/traffic_monitor/manager/datarequest.go
index 1c99eb3..4f1f83a 100644
--- a/traffic_monitor/experimental/traffic_monitor/manager/datarequest.go
+++ b/traffic_monitor/experimental/traffic_monitor/manager/datarequest.go
@@ -885,7 +885,7 @@ func createCacheStatuses(
 	healthHistory map[enum.CacheName][]cache.Result,
 	lastHealthDurations map[enum.CacheName]time.Duration,
 	cacheStates map[enum.CacheName]peer.IsAvailable,
-	lastStats ds.LastStats,
+	lastStats dsdata.LastStats,
 	localCacheStatusThreadsafe threadsafe.CacheAvailableStatus,
 	statMaxKbpses threadsafe.CacheKbpses,
 ) map[enum.CacheName]CacheStatus {

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/8f4329b5/traffic_monitor/experimental/traffic_monitor/manager/stat.go
----------------------------------------------------------------------
diff --git a/traffic_monitor/experimental/traffic_monitor/manager/stat.go b/traffic_monitor/experimental/traffic_monitor/manager/stat.go
index d98909f..50ce052 100644
--- a/traffic_monitor/experimental/traffic_monitor/manager/stat.go
+++ b/traffic_monitor/experimental/traffic_monitor/manager/stat.go
@@ -194,18 +194,13 @@ func processStatResults(
 	statResultHistoryThreadsafe.Set(statResultHistory)
 	statMaxKbpsesThreadsafe.Set(statMaxKbpses)
 
-	newDsStats, newLastStats, events, err := ds.CreateStats(precomputedData, toData, combinedStates, lastStats.Get().Copy(), time.Now(), mc)
+	newDsStats, newLastStats, err := ds.CreateStats(precomputedData, toData, combinedStates, lastStats.Get().Copy(), time.Now(), mc, events)
 	if err != nil {
 		errorCount.Inc()
 		log.Errorf("getting deliveryservice: %v\n", err)
 	} else {
 		dsStats.Set(newDsStats)
 		lastStats.Set(newLastStats)
-		if len(events) > 0 {
-			for _, event := range events {
-				te.Add(event)
-			}
-		}
 	}
 
 	health.CalcAvailability(results, "stat", statResultHistory, mc, toData, localCacheStatusThreadsafe, localStates, events)

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/8f4329b5/traffic_monitor/experimental/traffic_monitor/threadsafe/dsstats.go
----------------------------------------------------------------------
diff --git a/traffic_monitor/experimental/traffic_monitor/threadsafe/dsstats.go b/traffic_monitor/experimental/traffic_monitor/threadsafe/dsstats.go
index b8a7ffa..a13c01a 100644
--- a/traffic_monitor/experimental/traffic_monitor/threadsafe/dsstats.go
+++ b/traffic_monitor/experimental/traffic_monitor/threadsafe/dsstats.go
@@ -20,14 +20,14 @@ package threadsafe
  */
 
 import (
-	ds "github.com/apache/incubator-trafficcontrol/traffic_monitor/experimental/traffic_monitor/deliveryservice"
-	dsdata "github.com/apache/incubator-trafficcontrol/traffic_monitor/experimental/traffic_monitor/deliveryservicedata"
 	"sync"
+
+	dsdata "github.com/apache/incubator-trafficcontrol/traffic_monitor/experimental/traffic_monitor/deliveryservicedata"
 )
 
 // DSStats wraps a deliveryservice.Stats object to be safe for multiple reader goroutines and a single writer.
 type DSStats struct {
-	dsStats *ds.Stats
+	dsStats *dsdata.Stats
 	m       *sync.RWMutex
 }
 
@@ -38,7 +38,7 @@ type DSStatsReader interface {
 
 // NewDSStats returns a deliveryservice.Stats object wrapped to be safe for multiple readers and a single writer.
 func NewDSStats() DSStats {
-	s := ds.NewStats()
+	s := dsdata.NewStats()
 	return DSStats{m: &sync.RWMutex{}, dsStats: &s}
 }
 
@@ -50,7 +50,7 @@ func (o *DSStats) Get() dsdata.StatsReadonly {
 }
 
 // Set sets the internal Stats object. This MUST NOT be called by multiple goroutines.
-func (o *DSStats) Set(newDsStats ds.Stats) {
+func (o *DSStats) Set(newDsStats dsdata.Stats) {
 	o.m.Lock()
 	*o.dsStats = newDsStats
 	o.m.Unlock()

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/8f4329b5/traffic_monitor/experimental/traffic_monitor/threadsafe/lastkbpsstats.go
----------------------------------------------------------------------
diff --git a/traffic_monitor/experimental/traffic_monitor/threadsafe/lastkbpsstats.go b/traffic_monitor/experimental/traffic_monitor/threadsafe/lastkbpsstats.go
index 42c080d..610b8a9 100644
--- a/traffic_monitor/experimental/traffic_monitor/threadsafe/lastkbpsstats.go
+++ b/traffic_monitor/experimental/traffic_monitor/threadsafe/lastkbpsstats.go
@@ -20,31 +20,32 @@ package threadsafe
  */
 
 import (
-	ds "github.com/apache/incubator-trafficcontrol/traffic_monitor/experimental/traffic_monitor/deliveryservice"
 	"sync"
+
+	dsdata "github.com/apache/incubator-trafficcontrol/traffic_monitor/experimental/traffic_monitor/deliveryservicedata"
 )
 
 // LastStats wraps a deliveryservice.LastStats object to be safe for multiple readers and one writer.
 type LastStats struct {
-	stats *ds.LastStats
+	stats *dsdata.LastStats
 	m     *sync.RWMutex
 }
 
 // NewLastStats returns a wrapped a deliveryservice.LastStats object safe for multiple readers and one writer.
 func NewLastStats() LastStats {
-	s := ds.NewLastStats()
+	s := dsdata.NewLastStats()
 	return LastStats{m: &sync.RWMutex{}, stats: &s}
 }
 
 // Get returns the last KBPS stats object. Callers MUST NOT modify the object. It is not threadsafe for writing. If the object must be modified, callers must call LastStats.Copy() and modify the copy.
-func (o *LastStats) Get() ds.LastStats {
+func (o *LastStats) Get() dsdata.LastStats {
 	o.m.RLock()
 	defer o.m.RUnlock()
 	return *o.stats
 }
 
 // Set sets the internal LastStats object. This MUST NOT be called by multiple goroutines.
-func (o *LastStats) Set(s ds.LastStats) {
+func (o *LastStats) Set(s dsdata.LastStats) {
 	o.m.Lock()
 	*o.stats = s
 	o.m.Unlock()

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/8f4329b5/traffic_monitor/experimental/traffic_monitor/threadsafe/polledcaches.go
----------------------------------------------------------------------
diff --git a/traffic_monitor/experimental/traffic_monitor/threadsafe/polledcaches.go b/traffic_monitor/experimental/traffic_monitor/threadsafe/polledcaches.go
index 9276de4..ff987b7 100644
--- a/traffic_monitor/experimental/traffic_monitor/threadsafe/polledcaches.go
+++ b/traffic_monitor/experimental/traffic_monitor/threadsafe/polledcaches.go
@@ -24,7 +24,7 @@ import (
 
 	"github.com/apache/incubator-trafficcontrol/traffic_monitor/experimental/common/log"
 	"github.com/apache/incubator-trafficcontrol/traffic_monitor/experimental/traffic_monitor/cache"
-	ds "github.com/apache/incubator-trafficcontrol/traffic_monitor/experimental/traffic_monitor/deliveryservice"
+	dsdata "github.com/apache/incubator-trafficcontrol/traffic_monitor/experimental/traffic_monitor/deliveryservicedata"
 	"github.com/apache/incubator-trafficcontrol/traffic_monitor/experimental/traffic_monitor/enum"
 )
 
@@ -106,7 +106,7 @@ func copyCaches(a map[enum.CacheName]struct{}) map[enum.CacheName]struct{} {
 // SetPolled sets cache which have been polled. This is used to determine when the app has fully started up, and we can start serving. Serving Traffic Router with caches as 'down' which simply haven't been polled yet would be bad. Therefore, a cache is set as 'polled' if it has received different bandwidths from two different ATS ticks, OR if the cache is marked as down (and thus we won't get a bandwidth).
 // This is threadsafe for one writer, along with `Set`.
 // This is fast if there are no unpolled caches. Moreover, its speed is a function of the number of unpolled caches, not the number of caches total.
-func (t *UnpolledCaches) SetPolled(results []cache.Result, lastStats ds.LastStats) {
+func (t *UnpolledCaches) SetPolled(results []cache.Result, lastStats dsdata.LastStats) {
 	unpolledCaches := copyCaches(t.UnpolledCaches())
 	numUnpolledCaches := len(unpolledCaches)
 	if numUnpolledCaches == 0 {



[3/4] incubator-trafficcontrol git commit: cleaned up logging

Posted by el...@apache.org.
cleaned up logging

(cherry picked from commit b2d8e2dd5ea413f0aa130ec5ce2491ae658ada6c)


Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/3082e83e
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/3082e83e
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/3082e83e

Branch: refs/heads/master
Commit: 3082e83ef991ae0eedaf1d2f75cf53f835e7db54
Parents: 246e2e6
Author: David Neuman <da...@gmail.com>
Authored: Tue Jan 24 10:29:54 2017 -0700
Committer: Jeff Elsloo <je...@cable.comcast.com>
Committed: Thu Jan 26 09:44:15 2017 -0700

----------------------------------------------------------------------
 .../experimental/common/handler/handler.go      |  7 +++----
 .../experimental/common/poller/poller.go        | 10 ++++-----
 .../experimental/traffic_monitor/cache/cache.go | 16 +++++---------
 .../traffic_monitor/deliveryservice/stat.go     | 18 ++++++++--------
 .../traffic_monitor/manager/datarequest.go      | 22 ++++++++++----------
 .../traffic_monitor/manager/health.go           |  5 ++---
 .../traffic_monitor/manager/manager.go          |  1 -
 .../traffic_monitor/manager/monitorconfig.go    |  7 ++++++-
 .../traffic_monitor/manager/stat.go             | 12 ++---------
 .../traffic_monitor/threadsafe/polledcaches.go  |  4 ++--
 10 files changed, 45 insertions(+), 57 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/3082e83e/traffic_monitor/experimental/common/handler/handler.go
----------------------------------------------------------------------
diff --git a/traffic_monitor/experimental/common/handler/handler.go b/traffic_monitor/experimental/common/handler/handler.go
index 312553a..f83ef43 100644
--- a/traffic_monitor/experimental/common/handler/handler.go
+++ b/traffic_monitor/experimental/common/handler/handler.go
@@ -8,9 +8,9 @@ package handler
  * to you under the Apache License, Version 2.0 (the
  * "License"); you may not use this file except in compliance
  * with the License.  You may obtain a copy of the License at
- * 
+ *
  *   http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing,
  * software distributed under the License is distributed on an
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -19,7 +19,6 @@ package handler
  * under the License.
  */
 
-
 import (
 	"encoding/json"
 	"io"
@@ -61,7 +60,7 @@ func (handler OpsConfigFileHandler) Listen() {
 		err := json.Unmarshal(result.([]byte), &toc)
 
 		if err != nil {
-			log.Errorf("unmarshalling JSON: %s\n", err)
+			log.Errorf("Could not unmarshal Ops Config JSON: %s\n", err)
 		} else {
 			handler.OpsConfigChannel <- toc
 		}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/3082e83e/traffic_monitor/experimental/common/poller/poller.go
----------------------------------------------------------------------
diff --git a/traffic_monitor/experimental/common/poller/poller.go b/traffic_monitor/experimental/common/poller/poller.go
index 65288fc..67f6784 100644
--- a/traffic_monitor/experimental/common/poller/poller.go
+++ b/traffic_monitor/experimental/common/poller/poller.go
@@ -61,7 +61,7 @@ type HttpPollerConfig struct {
 	noSleep bool
 }
 
-// Creates and returns a new HttpPoller.
+// NewHTTP creates and returns a new HttpPoller.
 // If tick is false, HttpPoller.TickChan() will return nil. If noSleep is true, the poller will busywait instead of sleeping, and use a single goroutine which dispatches polls instead of a goroutine per poll.
 func NewHTTP(
 	interval time.Duration,
@@ -134,7 +134,7 @@ func (p MonitorConfigPoller) Poll() {
 				if err != nil {
 					log.Errorf("MonitorConfigPoller: %s\n %v\n", err, monitorConfig)
 				} else {
-					log.Infoln("MonitorConfigPoller: fetched monitorConfig")
+					log.Debugln("MonitorConfigPoller: fetched monitorConfig")
 					p.ConfigChannel <- *monitorConfig
 				}
 			} else {
@@ -156,10 +156,10 @@ type HTTPPollInfo struct {
 
 func (p HttpPoller) Poll() {
 	if p.Config.noSleep {
-		log.Infof("HttpPoller using InsomniacPoll\n")
+		log.Debugf("HttpPoller using InsomniacPoll\n")
 		p.InsomniacPoll()
 	} else {
-		log.Infof("HttpPoller using SleepPoll\n")
+		log.Debugf("HttpPoller using SleepPoll\n")
 		p.SleepPoll()
 	}
 }
@@ -213,7 +213,7 @@ func sleepPoller(interval time.Duration, id string, url string, fetcher fetcher.
 			realInterval := time.Now().Sub(lastTime)
 			if realInterval > interval+(time.Millisecond*100) {
 				instr.TimerFail.Inc()
-				log.Infof("Intended Duration: %v Actual Duration: %v\n", interval, realInterval)
+				log.Debugf("Intended Duration: %v Actual Duration: %v\n", interval, realInterval)
 			}
 			lastTime = time.Now()
 

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/3082e83e/traffic_monitor/experimental/traffic_monitor/cache/cache.go
----------------------------------------------------------------------
diff --git a/traffic_monitor/experimental/traffic_monitor/cache/cache.go b/traffic_monitor/experimental/traffic_monitor/cache/cache.go
index a0b6b60..98b996b 100644
--- a/traffic_monitor/experimental/traffic_monitor/cache/cache.go
+++ b/traffic_monitor/experimental/traffic_monitor/cache/cache.go
@@ -292,14 +292,14 @@ func (handler Handler) Handle(id string, r io.Reader, reqTime time.Duration, req
 	}
 
 	if reqErr != nil {
-		log.Errorf("%v handler given error '%v'\n", id, reqErr) // error here, in case the thing that called Handle didn't error
+		log.Warnf("%v handler given error '%v'\n", id, reqErr) // error here, in case the thing that called Handle didn't error
 		result.Error = reqErr
 		handler.resultChan <- result
 		return
 	}
 
 	if r == nil {
-		log.Errorf("%v handle reader nil\n", id)
+		log.Warnf("%v handle reader nil\n", id)
 		result.Error = fmt.Errorf("handler got nil reader")
 		handler.resultChan <- result
 		return
@@ -309,7 +309,7 @@ func (handler Handler) Handle(id string, r io.Reader, reqTime time.Duration, req
 	result.PrecomputedData.Time = result.Time
 
 	if decodeErr := json.NewDecoder(r).Decode(&result.Astats); decodeErr != nil {
-		log.Errorf("%s procnetdev decode error '%v'\n", id, decodeErr)
+		log.Warnf("%s procnetdev decode error '%v'\n", id, decodeErr)
 		result.Error = decodeErr
 		handler.resultChan <- result
 		return
@@ -323,8 +323,6 @@ func (handler Handler) Handle(id string, r io.Reader, reqTime time.Duration, req
 		log.Warnf("addkbps %s inf.speed empty\n", id)
 	}
 
-	log.Debugf("poll %v %v handle decode end\n", pollID, time.Now())
-
 	if reqErr != nil {
 		result.Error = reqErr
 		log.Errorf("addkbps handle %s error '%v'\n", id, reqErr)
@@ -333,13 +331,10 @@ func (handler Handler) Handle(id string, r io.Reader, reqTime time.Duration, req
 	}
 
 	if handler.Precompute() {
-		log.Debugf("poll %v %v handle precompute start\n", pollID, time.Now())
 		result = handler.precompute(result)
-		log.Debugf("poll %v %v handle precompute end\n", pollID, time.Now())
 	}
-	log.Debugf("poll %v %v handle write start\n", pollID, time.Now())
+
 	handler.resultChan <- result
-	log.Debugf("poll %v %v handle end\n", pollID, time.Now())
 }
 
 // outBytes takes the proc.net.dev string, and the interface name, and returns the bytes field
@@ -386,7 +381,7 @@ func (handler Handler) precompute(result Result) Result {
 		var err error
 		stats, err = processStat(result.ID, stats, todata, stat, value, result.Time)
 		if err != nil && err != dsdata.ErrNotProcessedStat {
-			log.Errorf("precomputing cache %v stat %v value %v error %v", result.ID, stat, value, err)
+			log.Infof("precomputing cache %v stat %v value %v error %v", result.ID, stat, value, err)
 			result.PrecomputedData.Errors = append(result.PrecomputedData.Errors, err)
 		}
 	}
@@ -506,7 +501,6 @@ func addCacheStat(stat *dsdata.StatCacheStats, name string, val interface{}) err
 		}
 		stat.OutBytes.Value += int64(v)
 	case "is_available":
-		log.Debugln("got is_available")
 		v, ok := val.(bool)
 		if !ok {
 			return fmt.Errorf("stat '%s' value expected bool actual '%v' type %T", name, val, val)

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/3082e83e/traffic_monitor/experimental/traffic_monitor/deliveryservice/stat.go
----------------------------------------------------------------------
diff --git a/traffic_monitor/experimental/traffic_monitor/deliveryservice/stat.go b/traffic_monitor/experimental/traffic_monitor/deliveryservice/stat.go
index b377a26..c1d8cba 100644
--- a/traffic_monitor/experimental/traffic_monitor/deliveryservice/stat.go
+++ b/traffic_monitor/experimental/traffic_monitor/deliveryservice/stat.go
@@ -78,29 +78,29 @@ func addAvailableData(dsStats Stats, crStates peer.Crstates, serverCachegroups m
 	for cache, available := range crStates.Caches {
 		cacheGroup, ok := serverCachegroups[cache]
 		if !ok {
-			log.Warnf("CreateStats not adding availability data for '%s': not found in Cachegroups\n", cache)
+			log.Infof("CreateStats not adding availability data for '%s': not found in Cachegroups\n", cache)
 			continue
 		}
 		deliveryServices, ok := serverDs[cache]
 		if !ok {
-			log.Warnf("CreateStats not adding availability data for '%s': not found in DeliveryServices\n", cache)
+			log.Infof("CreateStats not adding availability data for '%s': not found in DeliveryServices\n", cache)
 			continue
 		}
 		cacheType, ok := serverTypes[cache]
 		if !ok {
-			log.Warnf("CreateStats not adding availability data for '%s': not found in Server Types\n", cache)
+			log.Infof("CreateStats not adding availability data for '%s': not found in Server Types\n", cache)
 			continue
 		}
 
 		for _, deliveryService := range deliveryServices {
 			if deliveryService == "" {
-				log.Errorf("EMPTY addAvailableData DS") // various bugs in other functions can cause this - this will help identify and debug them.
+				log.Errorln("EMPTY addAvailableData DS") // various bugs in other functions can cause this - this will help identify and debug them.
 				continue
 			}
 
 			stat, ok := dsStats.DeliveryService[deliveryService]
 			if !ok {
-				log.Warnf("CreateStats not adding availability data for '%s': not found in Stats\n", cache)
+				log.Infof("CreateStats not adding availability data for '%s': not found in Stats\n", cache)
 				continue // TODO log warning? Error?
 			}
 
@@ -304,13 +304,13 @@ func addLastDSStatTotals(lastStat LastDSStat, cachesReporting map[enum.CacheName
 		if cacheGroup, ok := serverCachegroups[cacheName]; ok {
 			cacheGroups[cacheGroup] = cacheGroups[cacheGroup].Sum(cacheStats)
 		} else {
-			log.Errorf("while computing delivery service data, cache %v not in cachegroups\n", cacheName)
+			log.Warnf("while computing delivery service data, cache %v not in cachegroups\n", cacheName)
 		}
 
 		if cacheType, ok := serverTypes[cacheName]; ok {
 			cacheTypes[cacheType] = cacheTypes[cacheType].Sum(cacheStats)
 		} else {
-			log.Errorf("while computing delivery service data, cache %v not in types\n", cacheName)
+			log.Warnf("while computing delivery service data, cache %v not in types\n", cacheName)
 		}
 		total = total.Sum(cacheStats)
 	}
@@ -331,7 +331,7 @@ func addDSPerSecStats(dsName enum.DeliveryServiceName, stat dsdata.Stat, lastSta
 	for cacheName, cacheStats := range stat.Caches {
 		lastStat.Caches[cacheName], err = addLastStats(lastStat.Caches[cacheName], cacheStats, dsStatsTime)
 		if err != nil {
-			log.Errorf("%v adding kbps for cache %v: %v", dsName, cacheName, err)
+			log.Warnf("%v adding kbps for cache %v: %v", dsName, cacheName, err)
 			continue
 		}
 		cacheStats.Kbps.Value = lastStat.Caches[cacheName].Bytes.PerSec / BytesPerKilobit
@@ -376,7 +376,7 @@ func addCachePerSecStats(cacheName enum.CacheName, precomputed cache.Precomputed
 	lastStat := lastStats.Caches[cacheName] // if lastStats.Caches[cacheName] doesn't exist, it will be zero-constructed, and `addLastStat` will refrain from setting the PerSec for zero LastStats
 	lastStat.Bytes, err = addLastStat(lastStat.Bytes, outBytes, outBytesTime)
 	if err != nil {
-		log.Errorf("while computing delivery service data for cache %v: %v\n", cacheName, err)
+		log.Warnf("while computing delivery service data for cache %v: %v\n", cacheName, err)
 		return lastStats
 	}
 	lastStats.Caches[cacheName] = lastStat

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/3082e83e/traffic_monitor/experimental/traffic_monitor/manager/datarequest.go
----------------------------------------------------------------------
diff --git a/traffic_monitor/experimental/traffic_monitor/manager/datarequest.go b/traffic_monitor/experimental/traffic_monitor/manager/datarequest.go
index 7712154..1c99eb3 100644
--- a/traffic_monitor/experimental/traffic_monitor/manager/datarequest.go
+++ b/traffic_monitor/experimental/traffic_monitor/manager/datarequest.go
@@ -897,12 +897,12 @@ func createCacheStatuses(
 	for cacheName, cacheType := range cacheTypes {
 		infoHistory, ok := statInfoHistory[cacheName]
 		if !ok {
-			log.Warnf("createCacheStatuses stat info history missing cache %s\n", cacheName)
+			log.Infof("createCacheStatuses stat info history missing cache %s\n", cacheName)
 			continue
 		}
 
 		if len(infoHistory) < 1 {
-			log.Warnf("createCacheStatuses stat info history empty for cache %s\n", cacheName)
+			log.Infof("createCacheStatuses stat info history empty for cache %s\n", cacheName)
 			continue
 		}
 
@@ -912,32 +912,32 @@ func createCacheStatuses(
 
 		healthQueryTime, err := latestQueryTimeMS(cacheName, lastHealthDurations)
 		if err != nil {
-			log.Warnf("Error getting cache %v health query time: %v\n", cacheName, err)
+			log.Infof("Error getting cache %v health query time: %v\n", cacheName, err)
 		}
 
 		statTime, err := latestResultInfoTimeMS(cacheName, statInfoHistory)
 		if err != nil {
-			log.Warnf("Error getting cache %v stat result time: %v\n", cacheName, err)
+			log.Infof("Error getting cache %v stat result time: %v\n", cacheName, err)
 		}
 
 		healthTime, err := latestResultTimeMS(cacheName, healthHistory)
 		if err != nil {
-			log.Warnf("Error getting cache %v health result time: %v\n", cacheName, err)
+			log.Infof("Error getting cache %v health result time: %v\n", cacheName, err)
 		}
 
 		statSpan, err := infoResultSpanMS(cacheName, statInfoHistory)
 		if err != nil {
-			log.Warnf("Error getting cache %v stat span: %v\n", cacheName, err)
+			log.Infof("Error getting cache %v stat span: %v\n", cacheName, err)
 		}
 
 		healthSpan, err := resultSpanMS(cacheName, healthHistory)
 		if err != nil {
-			log.Warnf("Error getting cache %v health span: %v\n", cacheName, err)
+			log.Infof("Error getting cache %v health span: %v\n", cacheName, err)
 		}
 
 		var kbps *float64
 		if lastStat, ok := lastStats.Caches[cacheName]; !ok {
-			log.Warnf("cache not in last kbps cache %s\n", cacheName)
+			log.Infof("cache not in last kbps cache %s\n", cacheName)
 		} else {
 			kbpsVal := lastStat.Bytes.PerSec / float64(ds.BytesPerKilobit)
 			kbps = &kbpsVal
@@ -945,7 +945,7 @@ func createCacheStatuses(
 
 		var maxKbps *float64
 		if v, ok := maxKbpses[cacheName]; !ok {
-			log.Warnf("cache not in max kbps cache %s\n", cacheName)
+			log.Infof("cache not in max kbps cache %s\n", cacheName)
 		} else {
 			fv := float64(v)
 			maxKbps = &fv
@@ -954,7 +954,7 @@ func createCacheStatuses(
 		var connections *int64
 		connectionsVal, ok := conns[cacheName]
 		if !ok {
-			log.Warnf("cache not in connections %s\n", cacheName)
+			log.Infof("cache not in connections %s\n", cacheName)
 		} else {
 			connections = &connectionsVal
 		}
@@ -963,7 +963,7 @@ func createCacheStatuses(
 		var statusPoller *string
 		statusVal, ok := localCacheStatus[cacheName]
 		if !ok {
-			log.Warnf("cache not in statuses %s\n", cacheName)
+			log.Infof("cache not in statuses %s\n", cacheName)
 		} else {
 			statusString := statusVal.Status + " - "
 

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/3082e83e/traffic_monitor/experimental/traffic_monitor/manager/health.go
----------------------------------------------------------------------
diff --git a/traffic_monitor/experimental/traffic_monitor/manager/health.go b/traffic_monitor/experimental/traffic_monitor/manager/health.go
index e2657f8..a4465cf 100644
--- a/traffic_monitor/experimental/traffic_monitor/manager/health.go
+++ b/traffic_monitor/experimental/traffic_monitor/manager/health.go
@@ -159,7 +159,7 @@ func healthResultManagerListen(
 		for {
 			select {
 			case <-ticker.C:
-				log.Warnf("Health Result Manager flushing queued results\n")
+				log.Infof("Health Result Manager flushing queued results\n")
 				process(results)
 				break innerLoop
 			default:
@@ -207,7 +207,6 @@ func processHealthResult(
 	monitorConfigCopy := monitorConfig.Get()
 	healthHistoryCopy := healthHistory.Get().Copy()
 	for i, healthResult := range results {
-		log.Debugf("poll %v %v healthresultman start\n", healthResult.PollID, time.Now())
 		fetchCount.Inc()
 		var prevResult cache.Result
 		healthResultHistory := healthHistoryCopy[healthResult.ID]
@@ -222,7 +221,7 @@ func processHealthResult(
 
 		maxHistory := uint64(monitorConfigCopy.Profile[monitorConfigCopy.TrafficServer[string(healthResult.ID)].Profile].Parameters.HistoryCount)
 		if maxHistory < 1 {
-			log.Warnf("processHealthResult got history count %v for %v, setting to 1\n", maxHistory, healthResult.ID)
+			log.Infof("processHealthResult got history count %v for %v, setting to 1\n", maxHistory, healthResult.ID)
 			maxHistory = 1
 		}
 

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/3082e83e/traffic_monitor/experimental/traffic_monitor/manager/manager.go
----------------------------------------------------------------------
diff --git a/traffic_monitor/experimental/traffic_monitor/manager/manager.go b/traffic_monitor/experimental/traffic_monitor/manager/manager.go
index 974b3eb..c869365 100644
--- a/traffic_monitor/experimental/traffic_monitor/manager/manager.go
+++ b/traffic_monitor/experimental/traffic_monitor/manager/manager.go
@@ -34,7 +34,6 @@ import (
 	"github.com/apache/incubator-trafficcontrol/traffic_monitor/experimental/traffic_monitor/threadsafe"
 	todata "github.com/apache/incubator-trafficcontrol/traffic_monitor/experimental/traffic_monitor/trafficopsdata"
 	towrap "github.com/apache/incubator-trafficcontrol/traffic_monitor/experimental/traffic_monitor/trafficopswrapper"
-	//	to "github.com/apache/incubator-trafficcontrol/traffic_ops/client"
 	"github.com/davecheney/gmx"
 )
 

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/3082e83e/traffic_monitor/experimental/traffic_monitor/manager/monitorconfig.go
----------------------------------------------------------------------
diff --git a/traffic_monitor/experimental/traffic_monitor/manager/monitorconfig.go b/traffic_monitor/experimental/traffic_monitor/manager/monitorconfig.go
index f524a3c..76350d4 100644
--- a/traffic_monitor/experimental/traffic_monitor/manager/monitorconfig.go
+++ b/traffic_monitor/experimental/traffic_monitor/manager/monitorconfig.go
@@ -137,6 +137,8 @@ func trafficOpsHealthPollIntervalToDuration(t int) time.Duration {
 	return time.Duration(t) * time.Millisecond
 }
 
+var healthPollCount int
+
 // getPollIntervals reads the Traffic Ops Client monitorConfig structure, and parses and returns the health, peer, and stat poll intervals
 func getHealthPeerStatPollIntervals(monitorConfig to.TrafficMonitorConfigMap, cfg config.Config) (time.Duration, time.Duration, time.Duration, error) {
 	peerPollIntervalI, peerPollIntervalExists := monitorConfig.Config["peers.polling.interval"]
@@ -162,7 +164,10 @@ func getHealthPeerStatPollIntervals(monitorConfig to.TrafficMonitorConfigMap, cf
 	healthPollIntervalI, healthPollIntervalExists := monitorConfig.Config["heartbeat.polling.interval"]
 	healthPollIntervalInt, healthPollIntervalIsInt := healthPollIntervalI.(float64)
 	if !healthPollIntervalExists {
-		log.Warnf("Traffic Ops Monitor config missing 'heartbeat.polling.interval', using health for heartbeat.\n")
+		if healthPollCount == 0 { //only log this once
+			log.Warnln("Traffic Ops Monitor config missing 'heartbeat.polling.interval', using health for heartbeat.")
+			healthPollCount++
+		}
 		healthPollIntervalInt = statPollIntervalInt
 	} else if !healthPollIntervalIsInt {
 		log.Warnf("Traffic Ops Monitor config 'heartbeat.polling.interval' value '%v' type %T is not an integer, using health for heartbeat\n", statPollIntervalI, statPollIntervalI)

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/3082e83e/traffic_monitor/experimental/traffic_monitor/manager/stat.go
----------------------------------------------------------------------
diff --git a/traffic_monitor/experimental/traffic_monitor/manager/stat.go b/traffic_monitor/experimental/traffic_monitor/manager/stat.go
index 8e69bda..8d3404a 100644
--- a/traffic_monitor/experimental/traffic_monitor/manager/stat.go
+++ b/traffic_monitor/experimental/traffic_monitor/manager/stat.go
@@ -105,7 +105,7 @@ func StartStatHistoryManager(
 				case <-cachesChanged:
 					unpolledCaches.SetNewCaches(getNewCaches(localStates, monitorConfig))
 				case <-ticker.C:
-					log.Warnf("StatHistoryManager flushing queued results\n")
+					log.Infof("StatHistoryManager flushing queued results\n")
 					process(results)
 					break innerLoop
 				default:
@@ -162,7 +162,7 @@ func processStatResults(
 	for i, result := range results {
 		maxStats := uint64(mc.Profile[mc.TrafficServer[string(result.ID)].Profile].Parameters.HistoryCount)
 		if maxStats < 1 {
-			log.Warnf("processStatResults got history count %v for %v, setting to 1\n", maxStats, result.ID)
+			log.Infof("processStatResults got history count %v for %v, setting to 1\n", maxStats, result.ID)
 			maxStats = 1
 		}
 
@@ -194,16 +194,8 @@ func processStatResults(
 	statResultHistoryThreadsafe.Set(statResultHistory)
 	statMaxKbpsesThreadsafe.Set(statMaxKbpses)
 
-	for _, result := range results {
-		log.Debugf("poll %v %v CreateStats start\n", result.PollID, time.Now())
-	}
-
 	newDsStats, newLastStats, err := ds.CreateStats(precomputedData, toData, combinedStates, lastStats.Get().Copy(), time.Now(), mc)
 
-	for _, result := range results {
-		log.Debugf("poll %v %v CreateStats end\n", result.PollID, time.Now())
-	}
-
 	if err != nil {
 		errorCount.Inc()
 		log.Errorf("getting deliveryservice: %v\n", err)

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/3082e83e/traffic_monitor/experimental/traffic_monitor/threadsafe/polledcaches.go
----------------------------------------------------------------------
diff --git a/traffic_monitor/experimental/traffic_monitor/threadsafe/polledcaches.go b/traffic_monitor/experimental/traffic_monitor/threadsafe/polledcaches.go
index 978021f..9276de4 100644
--- a/traffic_monitor/experimental/traffic_monitor/threadsafe/polledcaches.go
+++ b/traffic_monitor/experimental/traffic_monitor/threadsafe/polledcaches.go
@@ -120,7 +120,7 @@ func (t *UnpolledCaches) SetPolled(results []cache.Result, lastStats ds.LastStat
 			}
 
 			if !result.Available || result.Error != nil {
-				log.Infof("polled %v\n", cache)
+				log.Debugf("polled %v\n", cache)
 				delete(unpolledCaches, cache)
 				break innerLoop
 			}
@@ -130,7 +130,7 @@ func (t *UnpolledCaches) SetPolled(results []cache.Result, lastStats ds.LastStat
 			continue
 		}
 		if lastStat.Bytes.PerSec != 0 {
-			log.Infof("polled %v\n", cache)
+			log.Debugf("polled %v\n", cache)
 			delete(unpolledCaches, cache)
 		}
 	}


[4/4] incubator-trafficcontrol git commit: This closes #232.

Posted by el...@apache.org.
This closes #232.


Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/41e65390
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/41e65390
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/41e65390

Branch: refs/heads/master
Commit: 41e65390544c334bda645ca696e2dc67122d5bac
Parents: 8f4329b
Author: Jeff Elsloo <je...@cable.comcast.com>
Authored: Thu Jan 26 09:44:52 2017 -0700
Committer: Jeff Elsloo <je...@cable.comcast.com>
Committed: Thu Jan 26 09:44:52 2017 -0700

----------------------------------------------------------------------

----------------------------------------------------------------------



[2/4] incubator-trafficcontrol git commit: add event logging for DS thresholds

Posted by el...@apache.org.
add event logging for DS thresholds

(cherry picked from commit ecfd60c768468a2ea6efe0143cd1d55d7ddbb440)


Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/db38fad6
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/db38fad6
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/db38fad6

Branch: refs/heads/master
Commit: db38fad68827defcd13f9330be025ca943635e2a
Parents: 3082e83
Author: David Neuman <da...@gmail.com>
Authored: Wed Jan 25 10:10:41 2017 -0700
Committer: Jeff Elsloo <je...@cable.comcast.com>
Committed: Thu Jan 26 09:44:15 2017 -0700

----------------------------------------------------------------------
 .../traffic_monitor/deliveryservice/stat.go     | 31 ++++++++++----------
 .../experimental/traffic_monitor/enum/enum.go   |  4 +++
 .../traffic_monitor/manager/stat.go             |  8 +++--
 3 files changed, 26 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/db38fad6/traffic_monitor/experimental/traffic_monitor/deliveryservice/stat.go
----------------------------------------------------------------------
diff --git a/traffic_monitor/experimental/traffic_monitor/deliveryservice/stat.go b/traffic_monitor/experimental/traffic_monitor/deliveryservice/stat.go
index c1d8cba..2b21969 100644
--- a/traffic_monitor/experimental/traffic_monitor/deliveryservice/stat.go
+++ b/traffic_monitor/experimental/traffic_monitor/deliveryservice/stat.go
@@ -30,6 +30,7 @@ import (
 	"github.com/apache/incubator-trafficcontrol/traffic_monitor/experimental/traffic_monitor/cache"
 	dsdata "github.com/apache/incubator-trafficcontrol/traffic_monitor/experimental/traffic_monitor/deliveryservicedata"
 	"github.com/apache/incubator-trafficcontrol/traffic_monitor/experimental/traffic_monitor/enum"
+	"github.com/apache/incubator-trafficcontrol/traffic_monitor/experimental/traffic_monitor/health"
 	"github.com/apache/incubator-trafficcontrol/traffic_monitor/experimental/traffic_monitor/peer"
 	"github.com/apache/incubator-trafficcontrol/traffic_monitor/experimental/traffic_monitor/srvhttp"
 	todata "github.com/apache/incubator-trafficcontrol/traffic_monitor/experimental/traffic_monitor/trafficopsdata"
@@ -321,7 +322,7 @@ func addLastDSStatTotals(lastStat LastDSStat, cachesReporting map[enum.CacheName
 }
 
 // addDSPerSecStats calculates and adds the per-second delivery service stats to both the Stats and LastStats structures, and returns the augmented structures.
-func addDSPerSecStats(dsName enum.DeliveryServiceName, stat dsdata.Stat, lastStats LastStats, dsStats Stats, dsStatsTime time.Time, serverCachegroups map[enum.CacheName]enum.CacheGroupName, serverTypes map[enum.CacheName]enum.CacheType, mc to.TrafficMonitorConfigMap) (Stats, LastStats) {
+func addDSPerSecStats(dsName enum.DeliveryServiceName, stat dsdata.Stat, lastStats LastStats, dsStats Stats, dsStatsTime time.Time, serverCachegroups map[enum.CacheName]enum.CacheGroupName, serverTypes map[enum.CacheName]enum.CacheType, mc to.TrafficMonitorConfigMap, events []health.Event) (Stats, LastStats, []health.Event) {
 	err := error(nil)
 	lastStat, lastStatExists := lastStats.DeliveryServices[dsName]
 	if !lastStatExists {
@@ -353,10 +354,11 @@ func addDSPerSecStats(dsName enum.DeliveryServiceName, stat dsdata.Stat, lastSta
 		stat.CommonStats.IsAvailable.Value = false
 		stat.CommonStats.IsHealthy.Value = false
 		stat.CommonStats.ErrorStr.Value = errStr
+		events = append(events, health.Event{Time: time.Now(), Unix: time.Now().Unix(), Description: errStr, Name: dsName.String(), Hostname: dsName.String(), Type: "Delivery Service", Available: stat.CommonStats.IsAvailable.Value})
 	}
 
 	dsStats.DeliveryService[dsName] = stat
-	return dsStats, lastStats
+	return dsStats, lastStats, events
 }
 
 // latestBytes returns the most recent OutBytes from the given cache results, and the time of that result. It assumes zero results are not valid, but nonzero results with errors are valid.
@@ -391,20 +393,20 @@ func addCachePerSecStats(cacheName enum.CacheName, precomputed cache.Precomputed
 // we set the (new - old) / lastChangedTime as the KBPS, and update the recorded LastChangedTime and LastChangedValue
 //
 // TODO handle ATS byte rolling (when the `out_bytes` overflows back to 0)
-func addPerSecStats(precomputed map[enum.CacheName]cache.PrecomputedData, dsStats Stats, lastStats LastStats, dsStatsTime time.Time, serverCachegroups map[enum.CacheName]enum.CacheGroupName, serverTypes map[enum.CacheName]enum.CacheType, mc to.TrafficMonitorConfigMap) (Stats, LastStats) {
+func addPerSecStats(precomputed map[enum.CacheName]cache.PrecomputedData, dsStats Stats, lastStats LastStats, dsStatsTime time.Time, serverCachegroups map[enum.CacheName]enum.CacheGroupName, serverTypes map[enum.CacheName]enum.CacheType, mc to.TrafficMonitorConfigMap, events []health.Event) (Stats, LastStats, []health.Event) {
 	for dsName, stat := range dsStats.DeliveryService {
-		dsStats, lastStats = addDSPerSecStats(dsName, stat, lastStats, dsStats, dsStatsTime, serverCachegroups, serverTypes, mc)
+		dsStats, lastStats, events = addDSPerSecStats(dsName, stat, lastStats, dsStats, dsStatsTime, serverCachegroups, serverTypes, mc, events)
 	}
 	for cacheName, precomputedData := range precomputed {
 		lastStats = addCachePerSecStats(cacheName, precomputedData, lastStats)
 	}
 
-	return dsStats, lastStats
+	return dsStats, lastStats, events
 }
 
 // CreateStats aggregates and creates statistics from given precomputed stat history. It returns the created stats, information about these stats necessary for the next calculation, and any error.
-func CreateStats(precomputed map[enum.CacheName]cache.PrecomputedData, toData todata.TOData, crStates peer.Crstates, lastStats LastStats, now time.Time, mc to.TrafficMonitorConfigMap) (Stats, LastStats, error) {
-
+func CreateStats(precomputed map[enum.CacheName]cache.PrecomputedData, toData todata.TOData, crStates peer.Crstates, lastStats LastStats, now time.Time, mc to.TrafficMonitorConfigMap) (Stats, LastStats, []health.Event, error) {
+	var events []health.Event
 	start := time.Now()
 	dsStats := NewStats()
 	for deliveryService := range toData.DeliveryServiceServers {
@@ -418,7 +420,7 @@ func CreateStats(precomputed map[enum.CacheName]cache.PrecomputedData, toData to
 	var err error
 	dsStats, err = addAvailableData(dsStats, crStates, toData.ServerCachegroups, toData.ServerDeliveryServices, toData.ServerTypes, precomputed) // TODO move after stat summarisation
 	if err != nil {
-		return dsStats, lastStats, fmt.Errorf("Error getting Cache availability data: %v", err)
+		return dsStats, lastStats, events, fmt.Errorf("Error getting Cache availability data: %v", err)
 	}
 
 	for server, precomputedData := range precomputed {
@@ -455,10 +457,10 @@ func CreateStats(precomputed map[enum.CacheName]cache.PrecomputedData, toData to
 		}
 	}
 
-	perSecStats, lastStats := addPerSecStats(precomputed, dsStats, lastStats, now, toData.ServerCachegroups, toData.ServerTypes, mc)
+	perSecStats, lastStats, events := addPerSecStats(precomputed, dsStats, lastStats, now, toData.ServerCachegroups, toData.ServerTypes, mc, events)
 	log.Infof("CreateStats took %v\n", time.Since(start))
 	perSecStats.Time = time.Now()
-	return perSecStats, lastStats, nil
+	return perSecStats, lastStats, events, nil
 }
 
 func addStatCacheStats(s *dsdata.StatsOld, c dsdata.StatCacheStats, deliveryService enum.DeliveryServiceName, prefix string, t int64, filter dsdata.Filter) *dsdata.StatsOld {
@@ -534,15 +536,14 @@ func (s Stats) JSON(filter dsdata.Filter, params url.Values) dsdata.StatsOld {
 }
 
 func getDsErrString(dsName enum.DeliveryServiceName, dsStats dsdata.StatCacheStats, monitorConfig to.TrafficMonitorConfigMap) string {
-	dsNameString := fmt.Sprintf("%s", dsName)
-	tpsThreshold := monitorConfig.DeliveryService[dsNameString].TotalTPSThreshold
+	tpsThreshold := monitorConfig.DeliveryService[dsName.String()].TotalTPSThreshold
 	if tpsThreshold > 0 && dsStats.TpsTotal.Value > float64(tpsThreshold) {
-		return fmt.Sprintf("TPSTotal too high (%v > %v)", dsStats.TpsTotal.Value, tpsThreshold)
+		return fmt.Sprintf("total.tps_total too high (%v > %v)", dsStats.TpsTotal.Value, tpsThreshold)
 	}
 
-	kbpsThreshold := monitorConfig.DeliveryService[dsNameString].TotalKbpsThreshold
+	kbpsThreshold := monitorConfig.DeliveryService[dsName.String()].TotalKbpsThreshold
 	if kbpsThreshold > 0 && dsStats.Kbps.Value > float64(kbpsThreshold) {
-		return fmt.Sprintf("TotalKbps too high (%v > %v)", dsStats.Kbps.Value, kbpsThreshold)
+		return fmt.Sprintf("total.kbps too high (%v > %v)", dsStats.Kbps.Value, kbpsThreshold)
 	}
 	return ""
 }

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/db38fad6/traffic_monitor/experimental/traffic_monitor/enum/enum.go
----------------------------------------------------------------------
diff --git a/traffic_monitor/experimental/traffic_monitor/enum/enum.go b/traffic_monitor/experimental/traffic_monitor/enum/enum.go
index 853236a..45546bd 100644
--- a/traffic_monitor/experimental/traffic_monitor/enum/enum.go
+++ b/traffic_monitor/experimental/traffic_monitor/enum/enum.go
@@ -64,6 +64,10 @@ func (t TrafficMonitorName) String() string {
 	return string(t)
 }
 
+func (d DeliveryServiceName) String() string {
+	return string(d)
+}
+
 // String returns a string representation of this cache type.
 func (t CacheType) String() string {
 	switch t {

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/db38fad6/traffic_monitor/experimental/traffic_monitor/manager/stat.go
----------------------------------------------------------------------
diff --git a/traffic_monitor/experimental/traffic_monitor/manager/stat.go b/traffic_monitor/experimental/traffic_monitor/manager/stat.go
index 8d3404a..d98909f 100644
--- a/traffic_monitor/experimental/traffic_monitor/manager/stat.go
+++ b/traffic_monitor/experimental/traffic_monitor/manager/stat.go
@@ -194,14 +194,18 @@ func processStatResults(
 	statResultHistoryThreadsafe.Set(statResultHistory)
 	statMaxKbpsesThreadsafe.Set(statMaxKbpses)
 
-	newDsStats, newLastStats, err := ds.CreateStats(precomputedData, toData, combinedStates, lastStats.Get().Copy(), time.Now(), mc)
-
+	newDsStats, newLastStats, events, err := ds.CreateStats(precomputedData, toData, combinedStates, lastStats.Get().Copy(), time.Now(), mc)
 	if err != nil {
 		errorCount.Inc()
 		log.Errorf("getting deliveryservice: %v\n", err)
 	} else {
 		dsStats.Set(newDsStats)
 		lastStats.Set(newLastStats)
+		if len(events) > 0 {
+			for _, event := range events {
+				te.Add(event)
+			}
+		}
 	}
 
 	health.CalcAvailability(results, "stat", statResultHistory, mc, toData, localCacheStatusThreadsafe, localStates, events)