func splitPayload(p pb.ClientStatsPayload, maxEntriesPerPayload int) []clientStatsPayload {
	if len(p.Stats) == 0 {
		return nil
	}
	// 1. Get how many payloads we need, based on the total number of entries.
	nbEntries := 0
	for _, b := range p.Stats {
		nbEntries += len(b.Stats)
	}
	if maxEntriesPerPayload <= 0 || nbEntries < maxEntriesPerPayload {
		// nothing to do, break early
		return []clientStatsPayload{{ClientStatsPayload: p, nbEntries: nbEntries}}
	}
	nbPayloads := nbEntries / maxEntriesPerPayload
	if nbEntries%maxEntriesPerPayload != 0 {
		nbPayloads++
	}

	// 2. Initialize a slice of nbPayloads indexes maps, mapping a time window (stat +
	//    duration) to a stats payload.
	payloads := make([]clientStatsPayload, nbPayloads)
	for i := 0; i < nbPayloads; i++ {
		payloads[i] = clientStatsPayload{
			bucketIndexes: make(map[timeWindow]int, 1),
			ClientStatsPayload: pb.ClientStatsPayload{
				Hostname:         p.Hostname,
				Env:              p.Env,
				Version:          p.Version,
				Service:          p.Service,
				Lang:             p.Lang,
				TracerVersion:    p.TracerVersion,
				RuntimeID:        p.RuntimeID,
				Sequence:         p.Sequence,
				AgentAggregation: p.AgentAggregation,
				Stats:            make([]pb.ClientStatsBucket, 0, maxEntriesPerPayload),
			},
		}
	}
	// 3. Iterate over all entries of each stats. Add the entry to one of
	//    the payloads, in a round robin fashion. Use the bucketIndexes map to
	//    ensure that we have one ClientStatsBucket per timeWindow for each ClientStatsPayload.
	i := 0
	for _, b := range p.Stats {
		tw := timeWindow{b.Start, b.Duration}
		for _, g := range b.Stats {
			j := i % nbPayloads
			bi, ok := payloads[j].bucketIndexes[tw]
			if !ok {
				bi = len(payloads[j].Stats)
				payloads[j].bucketIndexes[tw] = bi
				payloads[j].Stats = append(payloads[j].Stats, pb.ClientStatsBucket{Start: tw.start, Duration: tw.duration})
			}
			// here, we can just append the group, because there are no duplicate groups in the original stats payloads sent to the writer.
			payloads[j].Stats[bi].Stats = append(payloads[j].Stats[bi].Stats, g)
			payloads[j].nbEntries++
			i++
		}
	}
	return payloads
}
// splitPayload splits a stats payload to ensure that each stats payload has less than maxEntriesPerPayload entries.
splitPayload splits a stats payload to ensure that each stats payload has less than maxEntriesPerPayload entries.
// splitPayload splits a stats payload to ensure that each stats payload has less than maxEntriesPerPayload entries .
func splitPayload(p pb.ClientStatsPayload, maxEntriesPerPayload int) []clientStatsPayload {
	if len(p.Stats) == 0 {
		return nil
	}
	nbEntries := 0
	for _, b := range p.Stats {
		nbEntries += len(b.Stats)
	}
	if maxEntriesPerPayload <= 0 || nbEntries < maxEntriesPerPayload {
		return []clientStatsPayload{{ClientStatsPayload: p, nbEntries: nbEntries}}
	}
	nbPayloads := nbEntries / maxEntriesPerPayload
	if nbEntries%maxEntriesPerPayload != 0 {
		nbPayloads++
	}
	payloads := make([]clientStatsPayload, nbPayloads)
	for i := 0; i < nbPayloads; i++ {
		payloads[i] = clientStatsPayload{
			bucketIndexes: make(map[timeWindow]int, 1),
			ClientStatsPayload: pb.ClientStatsPayload{
				Hostname:         p.Hostname,
				Env:              p.Env,
				Version:          p.Version,
				Service:          p.Service,
				Lang:             p.Lang,
				TracerVersion:    p.TracerVersion,
				RuntimeID:        p.RuntimeID,
				Sequence:         p.Sequence,
				AgentAggregation: p.AgentAggregation,
				Stats:            make([]pb.ClientStatsBucket, 0, maxEntriesPerPayload),
			},
		}
	}
	i := 0
	for _, b := range p.Stats {
		tw := timeWindow{b.Start, b.Duration}
		for _, g := range b.Stats {
			j := i % nbPayloads
			bi, ok := payloads[j].bucketIndexes[tw]
			if !ok {
				bi = len(payloads[j].Stats)
				payloads[j].bucketIndexes[tw] = bi
				payloads[j].Stats = append(payloads[j].Stats, pb.ClientStatsBucket{Start: tw.start, Duration: tw.duration})
			}
			payloads[j].Stats[bi].Stats = append(payloads[j].Stats[bi].Stats, g)
			payloads[j].nbEntries++
			i++
		}
	}
	return payloads
}
func splitPayload ( p pb . ClientStatsPayload , maxEntriesPerPayload int ) [ ] clientStatsPayload { if len ( p . Stats ) == 0 { return nil } nbEntries := 0 for _ , b := range p . Stats { nbEntries += len ( b . Stats ) } if maxEntriesPerPayload <= 0 || nbEntries < maxEntriesPerPayload { return [ ] clientStatsPayload { { ClientStatsPayload : p , nbEntries : nbEntries } } } nbPayloads := nbEntries / maxEntriesPerPayload if nbEntries % maxEntriesPerPayload != 0 { nbPayloads ++ } payloads := make ( [ ] clientStatsPayload , nbPayloads ) for i := 0 ; i < nbPayloads ; i ++ { payloads [ i ] = clientStatsPayload { bucketIndexes : make ( map [ timeWindow ] int , 1 ) , ClientStatsPayload : pb . ClientStatsPayload { Hostname : p . Hostname , Env : p . Env , Version : p . Version , Service : p . Service , Lang : p . Lang , TracerVersion : p . TracerVersion , RuntimeID : p . RuntimeID , Sequence : p . Sequence , AgentAggregation : p . AgentAggregation , Stats : make ( [ ] pb . ClientStatsBucket , 0 , maxEntriesPerPayload ) , } , } } i := 0 for _ , b := range p . Stats { tw := timeWindow { b . Start , b . Duration } for _ , g := range b . Stats { j := i % nbPayloads bi , ok := payloads [ j ] . bucketIndexes [ tw ] if ! ok { bi = len ( payloads [ j ] . Stats ) payloads [ j ] . bucketIndexes [ tw ] = bi payloads [ j ] . Stats = append ( payloads [ j ] . Stats , pb . ClientStatsBucket { Start : tw . start , Duration : tw . duration } ) } payloads [ j ] . Stats [ bi ] . Stats = append ( payloads [ j ] . Stats [ bi ] . Stats , g ) payloads [ j ] . nbEntries ++ i ++ } } return payloads }
splitPayload splits a stats payload to ensure that each stats payload has less than maxEntriesPerPayload entries.
splitPayload splits a stats payload to ensure that each stats payload has less than maxEntriesPerPayload entries .
// 1. Get how many payloads we need, based on the total number of entries. // nothing to do, break early // 2. Initialize a slice of nbPayloads indexes maps, mapping a time window (stat + //    duration) to a stats payload. // 3. Iterate over all entries of each stats. Add the entry to one of //    the payloads, in a round robin fashion. Use the bucketIndexes map to //    ensure that we have one ClientStatsBucket per timeWindow for each ClientStatsPayload. // here, we can just append the group, because there are no duplicate groups in the original stats payloads sent to the writer.