You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@trafficcontrol.apache.org by GitBox <gi...@apache.org> on 2018/11/19 15:33:57 UTC

[GitHub] dneuman64 closed pull request #3000: Traffic Monitor fix unnecessary structs

dneuman64 closed pull request #3000: Traffic Monitor fix unnecessary structs
URL: https://github.com/apache/trafficcontrol/pull/3000
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/traffic_monitor/cache/astats.go b/traffic_monitor/cache/astats.go
index fb5645465..1d47a0988 100644
--- a/traffic_monitor/cache/astats.go
+++ b/traffic_monitor/cache/astats.go
@@ -49,3 +49,12 @@ func Unmarshal(body []byte) (Astats, error) {
 	err := json.Unmarshal(body, &aStats)
 	return aStats, err
 }
+
+type AStat struct {
+	InBytes   uint64
+	OutBytes  uint64
+	Status2xx uint64
+	Status3xx uint64
+	Status4xx uint64
+	Status5xx uint64
+}
diff --git a/traffic_monitor/cache/astats_test.go b/traffic_monitor/cache/astats_test.go
index b3c1860d2..ed8869161 100644
--- a/traffic_monitor/cache/astats_test.go
+++ b/traffic_monitor/cache/astats_test.go
@@ -22,7 +22,12 @@ package cache
 import (
 	"fmt"
 	"io/ioutil"
+	"math/rand"
+	"strconv"
 	"testing"
+
+	"github.com/apache/trafficcontrol/lib/go-tc"
+	"github.com/apache/trafficcontrol/traffic_monitor/todata"
 )
 
 func TestAstats(t *testing.T) {
@@ -39,3 +44,96 @@ func TestAstats(t *testing.T) {
 	}
 	fmt.Printf("Found %v key/val pairs in ats\n", len(aStats.Ats))
 }
+
+func getMockTODataDSNameDirectMatches() map[tc.DeliveryServiceName]string {
+	return map[tc.DeliveryServiceName]string{
+		"ds0": "ds0.example.invalid",
+		"ds1": "ds1.example.invalid",
+	}
+}
+
+// ds, ok := toData.DeliveryServiceRegexes.DeliveryService(domain, subdomain, subsubdomain)
+func getMockTOData(dsNameFQDNs map[tc.DeliveryServiceName]string) todata.TOData {
+	tod := todata.New()
+	for dsName, dsDirectMatch := range dsNameFQDNs {
+		tod.DeliveryServiceRegexes.DirectMatches[dsDirectMatch] = dsName
+	}
+	return *tod
+}
+
+func getMockRawStats(cacheName string, dsNameFQDNs map[tc.DeliveryServiceName]string) map[string]interface{} {
+	st := map[string]interface{}{}
+	for _, dsFQDN := range dsNameFQDNs {
+		st["plugin.remap_stats."+dsFQDN+".in_bytes"] = float64(rand.Uint64())
+		st["plugin.remap_stats."+dsFQDN+".out_bytes"] = float64(rand.Uint64())
+		st["plugin.remap_stats."+dsFQDN+".status_2xx"] = float64(rand.Uint64())
+		st["plugin.remap_stats."+dsFQDN+".status_3xx"] = float64(rand.Uint64())
+		st["plugin.remap_stats."+dsFQDN+".status_4xx"] = float64(rand.Uint64())
+		st["plugin.remap_stats."+dsFQDN+".status_5xx"] = float64(rand.Uint64())
+	}
+	return st
+}
+
+func getMockSystem(infSpeed int, outBytes int) AstatsSystem {
+	infName := randStr()
+	return AstatsSystem{
+		InfName:           infName,
+		InfSpeed:          9876554433210,
+		ProcNetDev:        infName + ":12234567 8901234    1    2    3     4          5   12345 " + strconv.Itoa(outBytes) + " 923412341234    6    7    8     9       10          11",
+		ProcLoadavg:       "1.2 2.34 5.67 1/876 1234",
+		ConfigLoadRequest: rand.Int(),
+		LastReloadRequest: rand.Int(),
+		ConfigReloads:     rand.Int(),
+		LastReload:        rand.Int(),
+		AstatsLoad:        rand.Int(),
+		NotAvailable:      randBool(),
+	}
+
+}
+
+func TestAstatsPrecompute(t *testing.T) {
+	dsNameFQDNs := getMockTODataDSNameDirectMatches()
+	toData := getMockTOData(dsNameFQDNs)
+	cacheName := "cache0"
+	rawStats := getMockRawStats(cacheName, dsNameFQDNs)
+	outBytes := 987655443321
+	infSpeedMbps := 9876554433210
+	system := getMockSystem(infSpeedMbps, outBytes)
+
+	prc := astatsPrecompute(tc.CacheName(cacheName), toData, rawStats, system)
+
+	if len(prc.Errors) != 0 {
+		t.Fatalf("astatsPrecompute Errors expected 0, actual: %+v\n", prc.Errors)
+	}
+	if prc.OutBytes != int64(outBytes) {
+		t.Fatalf("astatsPrecompute OutBytes expected 987655443321, actual: %+v\n", prc.OutBytes)
+	}
+	if prc.MaxKbps != int64(infSpeedMbps*1000) {
+		t.Fatalf("astatsPrecompute MaxKbps expected 9876554433210000, actual: %+v\n", prc.MaxKbps)
+	}
+
+	for dsName, dsFQDN := range dsNameFQDNs {
+		dsStat, ok := prc.DeliveryServiceStats[dsName]
+		if !ok {
+			t.Fatalf("astatsPrecompute DeliveryServiceStats expected %+v, actual: missing\n", dsName)
+		}
+		if statName := "plugin.remap_stats." + dsFQDN + ".in_bytes"; dsStat.InBytes != uint64(rawStats[statName].(float64)) {
+			t.Fatalf("astatsPrecompute DeliveryServiceStats[%+v].InBytes expected %+v, actual: %+v\n", dsName, uint64(rawStats[statName].(float64)), dsStat.InBytes)
+		}
+		if statName := "plugin.remap_stats." + dsFQDN + ".out_bytes"; dsStat.OutBytes != uint64(rawStats[statName].(float64)) {
+			t.Fatalf("astatsPrecompute DeliveryServiceStats[%+v].OutBytes expected %+v, actual: %+v\n", dsName, uint64(rawStats[statName].(float64)), dsStat.OutBytes)
+		}
+		if statName := "plugin.remap_stats." + dsFQDN + ".status_2xx"; dsStat.Status2xx != uint64(rawStats[statName].(float64)) {
+			t.Fatalf("astatsPrecompute DeliveryServiceStats[%+v].Status2xx expected %+v, actual: %+v\n", dsName, uint64(rawStats[statName].(float64)), dsStat.Status2xx)
+		}
+		if statName := "plugin.remap_stats." + dsFQDN + ".status_3xx"; dsStat.Status3xx != uint64(rawStats[statName].(float64)) {
+			t.Fatalf("astatsPrecompute DeliveryServiceStats[%+v].Status3xx expected %+v, actual: %+v\n", dsName, uint64(rawStats[statName].(float64)), dsStat.Status3xx)
+		}
+		if statName := "plugin.remap_stats." + dsFQDN + ".status_4xx"; dsStat.Status4xx != uint64(rawStats[statName].(float64)) {
+			t.Fatalf("astatsPrecompute DeliveryServiceStats[%+v].Status4xx expected %+v, actual: %+v\n", dsName, uint64(rawStats[statName].(float64)), dsStat.Status4xx)
+		}
+		if statName := "plugin.remap_stats." + dsFQDN + ".status_5xx"; dsStat.Status5xx != uint64(rawStats[statName].(float64)) {
+			t.Fatalf("astatsPrecompute DeliveryServiceStats[%+v].Status5xx expected %+v, actual: %+v\n", dsName, uint64(rawStats[statName].(float64)), dsStat.Status5xx)
+		}
+	}
+}
diff --git a/traffic_monitor/cache/cache.go b/traffic_monitor/cache/cache.go
index 282523035..6e4f8c6f9 100644
--- a/traffic_monitor/cache/cache.go
+++ b/traffic_monitor/cache/cache.go
@@ -28,7 +28,6 @@ import (
 
 	"github.com/apache/trafficcontrol/lib/go-log"
 	"github.com/apache/trafficcontrol/lib/go-tc"
-	"github.com/apache/trafficcontrol/traffic_monitor/dsdata"
 	"github.com/apache/trafficcontrol/traffic_monitor/srvhttp"
 	"github.com/apache/trafficcontrol/traffic_monitor/todata"
 )
@@ -60,7 +59,7 @@ func (handler Handler) Precompute() bool {
 
 // PrecomputedData represents data parsed and pre-computed from the Result.
 type PrecomputedData struct {
-	DeliveryServiceStats map[tc.DeliveryServiceName]dsdata.Stat
+	DeliveryServiceStats map[tc.DeliveryServiceName]*AStat
 	OutBytes             int64
 	MaxKbps              int64
 	Errors               []error
diff --git a/traffic_monitor/cache/data_test.go b/traffic_monitor/cache/data_test.go
index 6e3cac798..794e4efcb 100644
--- a/traffic_monitor/cache/data_test.go
+++ b/traffic_monitor/cache/data_test.go
@@ -172,11 +172,22 @@ func randDsStat() dsdata.Stat {
 	}
 }
 
-func randDsStats() map[tc.DeliveryServiceName]dsdata.Stat {
+func randAStat() *AStat {
+	return &AStat{
+		InBytes:   rand.Uint64(),
+		OutBytes:  rand.Uint64(),
+		Status2xx: rand.Uint64(),
+		Status3xx: rand.Uint64(),
+		Status4xx: rand.Uint64(),
+		Status5xx: rand.Uint64(),
+	}
+}
+
+func randDsStats() map[tc.DeliveryServiceName]*AStat {
 	num := 5
-	a := map[tc.DeliveryServiceName]dsdata.Stat{}
+	a := map[tc.DeliveryServiceName]*AStat{}
 	for i := 0; i < num; i++ {
-		a[tc.DeliveryServiceName(randStr())] = randDsStat()
+		a[tc.DeliveryServiceName(randStr())] = randAStat()
 	}
 	return a
 }
diff --git a/traffic_monitor/cache/stats_type_astats.go b/traffic_monitor/cache/stats_type_astats.go
index 11a1917f0..29419d1f0 100644
--- a/traffic_monitor/cache/stats_type_astats.go
+++ b/traffic_monitor/cache/stats_type_astats.go
@@ -57,7 +57,8 @@ func astatsParse(cache tc.CacheName, rdr io.Reader) (error, map[string]interface
 }
 
 func astatsPrecompute(cache tc.CacheName, toData todata.TOData, rawStats map[string]interface{}, system AstatsSystem) PrecomputedData {
-	stats := map[tc.DeliveryServiceName]dsdata.Stat{}
+	stats := map[tc.DeliveryServiceName]*AStat{}
+
 	precomputed := PrecomputedData{}
 	var err error
 	if precomputed.OutBytes, err = astatsOutBytes(system.ProcNetDev, system.InfName); err != nil {
@@ -69,7 +70,6 @@ func astatsPrecompute(cache tc.CacheName, toData todata.TOData, rawStats map[str
 	precomputed.MaxKbps = int64(system.InfSpeed) * kbpsInMbps
 
 	for stat, value := range rawStats {
-		var err error
 		stats, err = astatsProcessStat(cache, stats, toData, stat, value)
 		if err != nil && err != dsdata.ErrNotProcessedStat {
 			log.Infof("precomputing cache %v stat %v value %v error %v", cache, stat, value, err)
@@ -104,7 +104,7 @@ func astatsOutBytes(procNetDev, iface string) (int64, error) {
 }
 
 // astatsProcessStat and its subsidiary functions act as a State Machine, flowing the stat thru states for each "." component of the stat name
-func astatsProcessStat(server tc.CacheName, stats map[tc.DeliveryServiceName]dsdata.Stat, toData todata.TOData, stat string, value interface{}) (map[tc.DeliveryServiceName]dsdata.Stat, error) {
+func astatsProcessStat(server tc.CacheName, stats map[tc.DeliveryServiceName]*AStat, toData todata.TOData, stat string, value interface{}) (map[tc.DeliveryServiceName]*AStat, error) {
 	parts := strings.Split(stat, ".")
 	if len(parts) < 1 {
 		return stats, fmt.Errorf("stat has no initial part")
@@ -122,7 +122,7 @@ func astatsProcessStat(server tc.CacheName, stats map[tc.DeliveryServiceName]dsd
 	}
 }
 
-func astatsProcessStatPlugin(server tc.CacheName, stats map[tc.DeliveryServiceName]dsdata.Stat, toData todata.TOData, stat string, statParts []string, value interface{}) (map[tc.DeliveryServiceName]dsdata.Stat, error) {
+func astatsProcessStatPlugin(server tc.CacheName, stats map[tc.DeliveryServiceName]*AStat, toData todata.TOData, stat string, statParts []string, value interface{}) (map[tc.DeliveryServiceName]*AStat, error) {
 	if len(statParts) < 1 {
 		return stats, fmt.Errorf("stat has no plugin part")
 	}
@@ -134,7 +134,7 @@ func astatsProcessStatPlugin(server tc.CacheName, stats map[tc.DeliveryServiceNa
 	}
 }
 
-func astatsProcessStatPluginRemapStats(server tc.CacheName, stats map[tc.DeliveryServiceName]dsdata.Stat, toData todata.TOData, stat string, statParts []string, value interface{}) (map[tc.DeliveryServiceName]dsdata.Stat, error) {
+func astatsProcessStatPluginRemapStats(server tc.CacheName, stats map[tc.DeliveryServiceName]*AStat, toData todata.TOData, stat string, statParts []string, value interface{}) (map[tc.DeliveryServiceName]*AStat, error) {
 	if len(statParts) < 3 {
 		return stats, fmt.Errorf("stat has no remap_stats deliveryservice and name parts")
 	}
@@ -158,116 +158,57 @@ func astatsProcessStatPluginRemapStats(server tc.CacheName, stats map[tc.Deliver
 
 	dsStat, ok := stats[ds]
 	if !ok {
-		newStat := dsdata.NewStat()
-		dsStat = *newStat
+		dsStat = &AStat{}
+		stats[ds] = dsStat
 	}
 
-	if err := astatsAddCacheStat(&dsStat.TotalStats, statName, value); err != nil {
+	if err := astatsAddCacheStat(dsStat, statName, value); err != nil {
 		return stats, err
 	}
-
-	cachegroup, ok := toData.ServerCachegroups[server]
-	if !ok {
-		return stats, fmt.Errorf("server missing from TOData.ServerCachegroups")
-	}
-	dsStat.CacheGroups[cachegroup] = dsStat.TotalStats
-
-	cacheType, ok := toData.ServerTypes[server]
-	if !ok {
-		return stats, fmt.Errorf("server missing from TOData.ServerTypes")
-	}
-	dsStat.Types[cacheType] = dsStat.TotalStats
-
-	dsStat.Caches[server] = dsStat.TotalStats
-
-	stats[ds] = dsStat
+	stats[ds] = dsStat // TODO verify unnecessary, remove
 	return stats, nil
 }
 
 // addCacheStat adds the given stat to the existing stat. Note this adds, it doesn't overwrite. Numbers are summed, strings are concatenated.
 // TODO make this less duplicate code somehow.
-func astatsAddCacheStat(stat *dsdata.StatCacheStats, name string, val interface{}) error {
+func astatsAddCacheStat(stat *AStat, name string, val interface{}) error {
 	switch name {
 	case "status_2xx":
 		v, ok := val.(float64)
 		if !ok {
 			return fmt.Errorf("stat '%s' value expected int actual '%v' type %T", name, val, val)
 		}
-		stat.Status2xx.Value += int64(v)
+		stat.Status2xx += uint64(v)
 	case "status_3xx":
 		v, ok := val.(float64)
 		if !ok {
 			return fmt.Errorf("stat '%s' value expected int actual '%v' type %T", name, val, val)
 		}
-		stat.Status3xx.Value += int64(v)
+		stat.Status3xx += uint64(v)
 	case "status_4xx":
 		v, ok := val.(float64)
 		if !ok {
 			return fmt.Errorf("stat '%s' value expected int actual '%v' type %T", name, val, val)
 		}
-		stat.Status4xx.Value += int64(v)
+		stat.Status4xx += uint64(v)
 	case "status_5xx":
 		v, ok := val.(float64)
 		if !ok {
 			return fmt.Errorf("stat '%s' value expected int actual '%v' type %T", name, val, val)
 		}
-		stat.Status5xx.Value += int64(v)
+		stat.Status5xx += uint64(v)
 	case "out_bytes":
 		v, ok := val.(float64)
 		if !ok {
 			return fmt.Errorf("stat '%s' value expected int actual '%v' type %T", name, val, val)
 		}
-		stat.OutBytes.Value += int64(v)
-	case "is_available":
-		v, ok := val.(bool)
-		if !ok {
-			return fmt.Errorf("stat '%s' value expected bool actual '%v' type %T", name, val, val)
-		}
-		if v {
-			stat.IsAvailable.Value = true
-		}
+		stat.OutBytes += uint64(v)
 	case "in_bytes":
 		v, ok := val.(float64)
 		if !ok {
 			return fmt.Errorf("stat '%s' value expected int actual '%v' type %T", name, val, val)
 		}
-		stat.InBytes.Value += v
-	case "tps_2xx":
-		v, ok := val.(int64)
-		if !ok {
-			return fmt.Errorf("stat '%s' value expected int actual '%v' type %T", name, val, val)
-		}
-		stat.Tps2xx.Value += float64(v)
-	case "tps_3xx":
-		v, ok := val.(int64)
-		if !ok {
-			return fmt.Errorf("stat '%s' value expected int actual '%v' type %T", name, val, val)
-		}
-		stat.Tps3xx.Value += float64(v)
-	case "tps_4xx":
-		v, ok := val.(int64)
-		if !ok {
-			return fmt.Errorf("stat '%s' value expected int actual '%v' type %T", name, val, val)
-		}
-		stat.Tps4xx.Value += float64(v)
-	case "tps_5xx":
-		v, ok := val.(int64)
-		if !ok {
-			return fmt.Errorf("stat '%s' value expected int actual '%v' type %T", name, val, val)
-		}
-		stat.Tps5xx.Value += float64(v)
-	case "error_string":
-		v, ok := val.(string)
-		if !ok {
-			return fmt.Errorf("stat '%s' value expected string actual '%v' type %T", name, val, val)
-		}
-		stat.ErrorString.Value += v + ", "
-	case "tps_total":
-		v, ok := val.(float64)
-		if !ok {
-			return fmt.Errorf("stat '%s' value expected int actual '%v' type %T", name, val, val)
-		}
-		stat.TpsTotal.Value += v
+		stat.InBytes += uint64(v)
 	case "status_unknown":
 		return dsdata.ErrNotProcessedStat
 	default:
diff --git a/traffic_monitor/cache/stats_type_astats_dsnames.go b/traffic_monitor/cache/stats_type_astats_dsnames.go
index 772aacc8e..204af6c40 100644
--- a/traffic_monitor/cache/stats_type_astats_dsnames.go
+++ b/traffic_monitor/cache/stats_type_astats_dsnames.go
@@ -38,7 +38,7 @@ func init() {
 }
 
 func astatsdsnamesPrecompute(cache tc.CacheName, toData todata.TOData, rawStats map[string]interface{}, system AstatsSystem) PrecomputedData {
-	stats := map[tc.DeliveryServiceName]dsdata.Stat{}
+	stats := map[tc.DeliveryServiceName]*AStat{}
 	precomputed := PrecomputedData{}
 	var err error
 	if precomputed.OutBytes, err = astatsdsnamesOutBytes(system.ProcNetDev, system.InfName); err != nil {
@@ -62,7 +62,7 @@ func astatsdsnamesPrecompute(cache tc.CacheName, toData todata.TOData, rawStats
 }
 
 // astatsdsnamesProcessStat and its subsidiary functions act as a State Machine, flowing the stat thru states for each "." component of the stat name
-func astatsdsnamesProcessStat(server tc.CacheName, stats map[tc.DeliveryServiceName]dsdata.Stat, toData todata.TOData, stat string, value interface{}) (map[tc.DeliveryServiceName]dsdata.Stat, error) {
+func astatsdsnamesProcessStat(server tc.CacheName, stats map[tc.DeliveryServiceName]*AStat, toData todata.TOData, stat string, value interface{}) (map[tc.DeliveryServiceName]*AStat, error) {
 	parts := strings.Split(stat, ".")
 	if len(parts) < 1 {
 		return stats, fmt.Errorf("stat has no initial part")
@@ -80,7 +80,7 @@ func astatsdsnamesProcessStat(server tc.CacheName, stats map[tc.DeliveryServiceN
 	}
 }
 
-func astatsdsnamesProcessStatPlugin(server tc.CacheName, stats map[tc.DeliveryServiceName]dsdata.Stat, toData todata.TOData, stat string, statParts []string, value interface{}) (map[tc.DeliveryServiceName]dsdata.Stat, error) {
+func astatsdsnamesProcessStatPlugin(server tc.CacheName, stats map[tc.DeliveryServiceName]*AStat, toData todata.TOData, stat string, statParts []string, value interface{}) (map[tc.DeliveryServiceName]*AStat, error) {
 	if len(statParts) < 1 {
 		return stats, fmt.Errorf("stat has no plugin part")
 	}
@@ -92,7 +92,7 @@ func astatsdsnamesProcessStatPlugin(server tc.CacheName, stats map[tc.DeliverySe
 	}
 }
 
-func astatsdsnamesProcessStatPluginRemapStats(server tc.CacheName, stats map[tc.DeliveryServiceName]dsdata.Stat, toData todata.TOData, stat string, statParts []string, value interface{}) (map[tc.DeliveryServiceName]dsdata.Stat, error) {
+func astatsdsnamesProcessStatPluginRemapStats(server tc.CacheName, stats map[tc.DeliveryServiceName]*AStat, toData todata.TOData, stat string, statParts []string, value interface{}) (map[tc.DeliveryServiceName]*AStat, error) {
 	if len(statParts) < 3 {
 		return stats, fmt.Errorf("stat has no remap_stats deliveryservice and name parts")
 	}
@@ -106,28 +106,14 @@ func astatsdsnamesProcessStatPluginRemapStats(server tc.CacheName, stats map[tc.
 
 	dsStat, ok := stats[ds]
 	if !ok {
-		newStat := dsdata.NewStat()
-		dsStat = *newStat
+		dsStat = &AStat{}
+		stats[ds] = dsStat
 	}
 
-	if err := astatsdstypesAddCacheStat(&dsStat.TotalStats, statName, value); err != nil {
+	if err := astatsdstypesAddCacheStat(dsStat, statName, value); err != nil {
 		return stats, err
 	}
 
-	cachegroup, ok := toData.ServerCachegroups[server]
-	if !ok {
-		return stats, fmt.Errorf("server missing from TOData.ServerCachegroups")
-	}
-	dsStat.CacheGroups[cachegroup] = dsStat.TotalStats
-
-	cacheType, ok := toData.ServerTypes[server]
-	if !ok {
-		return stats, fmt.Errorf("server missing from TOData.ServerTypes")
-	}
-	dsStat.Types[cacheType] = dsStat.TotalStats
-
-	dsStat.Caches[server] = dsStat.TotalStats
-
 	stats[ds] = dsStat
 	return stats, nil
 }
@@ -157,7 +143,7 @@ func astatsdsnamesOutBytes(procNetDev, iface string) (int64, error) {
 }
 
 // astatsdstypesAddCacheStat adds the given stat to the existing stat. Note this adds, it doesn't overwrite. Numbers are summed, strings are concatenated.
-func astatsdstypesAddCacheStat(stat *dsdata.StatCacheStats, name string, val interface{}) error {
+func astatsdstypesAddCacheStat(stat *AStat, name string, val interface{}) error {
 	// TODO make this less duplicate code somehow.
 	// NOTE this is superficially duplicated from astatsAddCacheStat, but they are conceptually different, because the `astats` format changing should not necessarily affect the `astats-dstypes` format. The MUST be kept separate, and code between them MUST NOT be de-duplicated.
 	switch name {
@@ -166,81 +152,37 @@ func astatsdstypesAddCacheStat(stat *dsdata.StatCacheStats, name string, val int
 		if !ok {
 			return fmt.Errorf("stat '%s' value expected int actual '%v' type %T", name, val, val)
 		}
-		stat.Status2xx.Value += int64(v)
+		stat.Status2xx += uint64(v)
 	case "status_3xx":
 		v, ok := val.(float64)
 		if !ok {
 			return fmt.Errorf("stat '%s' value expected int actual '%v' type %T", name, val, val)
 		}
-		stat.Status3xx.Value += int64(v)
+		stat.Status3xx += uint64(v)
 	case "status_4xx":
 		v, ok := val.(float64)
 		if !ok {
 			return fmt.Errorf("stat '%s' value expected int actual '%v' type %T", name, val, val)
 		}
-		stat.Status4xx.Value += int64(v)
+		stat.Status4xx += uint64(v)
 	case "status_5xx":
 		v, ok := val.(float64)
 		if !ok {
 			return fmt.Errorf("stat '%s' value expected int actual '%v' type %T", name, val, val)
 		}
-		stat.Status5xx.Value += int64(v)
+		stat.Status5xx += uint64(v)
 	case "out_bytes":
 		v, ok := val.(float64)
 		if !ok {
 			return fmt.Errorf("stat '%s' value expected int actual '%v' type %T", name, val, val)
 		}
-		stat.OutBytes.Value += int64(v)
-	case "is_available":
-		v, ok := val.(bool)
-		if !ok {
-			return fmt.Errorf("stat '%s' value expected bool actual '%v' type %T", name, val, val)
-		}
-		if v {
-			stat.IsAvailable.Value = true
-		}
+		stat.OutBytes += uint64(v)
 	case "in_bytes":
 		v, ok := val.(float64)
 		if !ok {
 			return fmt.Errorf("stat '%s' value expected int actual '%v' type %T", name, val, val)
 		}
-		stat.InBytes.Value += v
-	case "tps_2xx":
-		v, ok := val.(int64)
-		if !ok {
-			return fmt.Errorf("stat '%s' value expected int actual '%v' type %T", name, val, val)
-		}
-		stat.Tps2xx.Value += float64(v)
-	case "tps_3xx":
-		v, ok := val.(int64)
-		if !ok {
-			return fmt.Errorf("stat '%s' value expected int actual '%v' type %T", name, val, val)
-		}
-		stat.Tps3xx.Value += float64(v)
-	case "tps_4xx":
-		v, ok := val.(int64)
-		if !ok {
-			return fmt.Errorf("stat '%s' value expected int actual '%v' type %T", name, val, val)
-		}
-		stat.Tps4xx.Value += float64(v)
-	case "tps_5xx":
-		v, ok := val.(int64)
-		if !ok {
-			return fmt.Errorf("stat '%s' value expected int actual '%v' type %T", name, val, val)
-		}
-		stat.Tps5xx.Value += float64(v)
-	case "error_string":
-		v, ok := val.(string)
-		if !ok {
-			return fmt.Errorf("stat '%s' value expected string actual '%v' type %T", name, val, val)
-		}
-		stat.ErrorString.Value += v + ", "
-	case "tps_total":
-		v, ok := val.(float64)
-		if !ok {
-			return fmt.Errorf("stat '%s' value expected int actual '%v' type %T", name, val, val)
-		}
-		stat.TpsTotal.Value += v
+		stat.InBytes += uint64(v)
 	case "status_unknown":
 		return dsdata.ErrNotProcessedStat
 	default:
diff --git a/traffic_monitor/cache/stats_type_noop.go b/traffic_monitor/cache/stats_type_noop.go
index 9610ed7b4..87f2283e8 100644
--- a/traffic_monitor/cache/stats_type_noop.go
+++ b/traffic_monitor/cache/stats_type_noop.go
@@ -25,7 +25,6 @@ import (
 	"io"
 
 	"github.com/apache/trafficcontrol/lib/go-tc"
-	"github.com/apache/trafficcontrol/traffic_monitor/dsdata"
 	"github.com/apache/trafficcontrol/traffic_monitor/todata"
 )
 
@@ -46,5 +45,5 @@ func noopParse(cache tc.CacheName, r io.Reader) (error, map[string]interface{},
 }
 
 func noopPrecompute(cache tc.CacheName, toData todata.TOData, rawStats map[string]interface{}, system AstatsSystem) PrecomputedData {
-	return PrecomputedData{DeliveryServiceStats: map[tc.DeliveryServiceName]dsdata.Stat{}}
+	return PrecomputedData{DeliveryServiceStats: map[tc.DeliveryServiceName]*AStat{}}
 }
diff --git a/traffic_monitor/ds/stat.go b/traffic_monitor/ds/stat.go
index 202834499..1f0f9e13d 100644
--- a/traffic_monitor/ds/stat.go
+++ b/traffic_monitor/ds/stat.go
@@ -375,16 +375,16 @@ func CreateStats(precomputed map[tc.CacheName]cache.PrecomputedData, toData toda
 			}
 
 			if _, ok := dsStats.DeliveryService[ds]; !ok {
-				dsStats.DeliveryService[ds] = resultStat
-				continue
+				// TODO use sync pool?
+				dsStats.DeliveryService[ds] = *(dsdata.NewStat())
 			}
 			httpDsStat := dsStats.DeliveryService[ds]
-			httpDsStat.TotalStats = httpDsStat.TotalStats.Sum(resultStat.TotalStats)
-			httpDsStat.CacheGroups[cachegroup] = httpDsStat.CacheGroups[cachegroup].Sum(resultStat.CacheGroups[cachegroup])
-			httpDsStat.Types[serverType] = httpDsStat.Types[serverType].Sum(resultStat.Types[serverType])
-			httpDsStat.Caches[server] = httpDsStat.Caches[server].Sum(resultStat.Caches[server])
+			httpDsStat.TotalStats = SumDSAstats(httpDsStat.TotalStats, resultStat)
+			httpDsStat.CacheGroups[cachegroup] = SumDSAstats(httpDsStat.CacheGroups[cachegroup], resultStat)
+			httpDsStat.Types[serverType] = SumDSAstats(httpDsStat.Types[serverType], resultStat)
+			httpDsStat.Caches[server] = SumDSAstats(httpDsStat.Caches[server], resultStat)
 			httpDsStat.CommonStats = dsStats.DeliveryService[ds].CommonStats
-			dsStats.DeliveryService[ds] = httpDsStat // TODO determine if necessary
+			dsStats.DeliveryService[ds] = httpDsStat // TODO determine if necessary? Change to pointers, so it isn't?
 		}
 	}
 
@@ -403,3 +403,14 @@ func getDSErr(dsName tc.DeliveryServiceName, dsStats dsdata.StatCacheStats, moni
 	}
 	return nil
 }
+
+func SumDSAstats(ds dsdata.StatCacheStats, cacheStat *cache.AStat) dsdata.StatCacheStats {
+	// TODO change to pointer? Change everything in dsdata to pointers?
+	ds.OutBytes.Value += int64(cacheStat.OutBytes)
+	ds.InBytes.Value += float64(cacheStat.InBytes)
+	ds.Status2xx.Value += int64(cacheStat.Status2xx)
+	ds.Status3xx.Value += int64(cacheStat.Status3xx)
+	ds.Status4xx.Value += int64(cacheStat.Status4xx)
+	ds.Status5xx.Value += int64(cacheStat.Status5xx)
+	return ds
+}


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services