func NewTimeSlotAggregator(clock common.TimeSource, logger bark.Logger) *TimeslotAggregator {
	aggr := new(TimeslotAggregator)
	aggr.clock = clock
	aggr.logger = logger
	aggr.stopCh = make(chan struct{})
	aggr.sigCh = make(chan struct{})
	aggr.dataCh = make(chan *metricData, dataChannelSize)
	return aggr
}
NewTimeSlotAggregator creates and returns an instance of
MetricsAggregator that aggregates data at fixed interval
timeslots. Internally, the TimeSlotAggregator maintains
a circular buffer of timeslots, where each timeslot is
typically, a minute. The size of the buffer determines
the history that's stored by the aggregator. Incoming
data is always added to the current timeslot whereas readers
always start reading from the timeslot preceding the current
one (and go back). This allows lockless access to the hashmaps
that hold the aggregated metric data.

MetricGroups:
Metrics reported to the aggregator are composed of a
timesamp, metricName, metricValue and a groupTag. A group
tag allows for aggregation of same metric at different
levels. For example, when a store reports an extent metric
nExtentsActive, this metric can be aggregated by many levels,
i.e. storeHostUUID, extentUUID, dstUUID. This problem is
solved by the group tag.

Inside a TimeSlot:
Each timeslot internally maintains a single hashmap that's
indexed by a key representing a specific metric. Since the
same metric can be used by multiple metric groups, the
indexed string is a combination of groupTag and metricName.

SigChannel:
As mentioned before, timeslots are only advanced when there is
incoming data. So, when there is no incoming data for a while,
the data in the current time slot will not be consumed by readers.
To overcome this problem, we have a signchannel that will force
advancement of timeslot when the input stream is idle.
package load
import (
	"strings"
	"sync"
	"sync/atomic"
	"time"
	"github.com/uber-common/bark"
	"github.com/uber/cherami-server/common"
)
type (
	metricData struct {
		hostID string
		groupTag string
		metricName MetricName
		metricValue int64
		timestamp int64
	}
	timeslotData struct {
		n   int64  
		sum int64  
	}
	timeslot struct {
		beginTime int64                     
		data      map[string]*timeslotData  
	}
	TimeslotAggregator struct {
		currIdx   int64  
		started   int64
		timeslots [historySize]timeslot  
		dataCh    chan *metricData       
		sigCh     chan struct{}          
		stopCh    chan struct{}
		stopWG    sync.WaitGroup
		clock     common.TimeSource
		logger    bark.Logger
	}
)
const historySize = 10  
const maxClockSkew = int64(time.Second * 5)
const aggregationPeriod = int64(time.Minute)  
const dataChannelSize = 256                   