func TestCreateTaskBuckets(t *testing.T) { testutil.HandleTestingErr(db.ClearCollections(task.Collection), t, "couldnt reset host") Convey("With a starting time and a minute bucket size and inserting tasks with different start and finish", t, func() { now := time.Now() bucketSize := time.Duration(10) * time.Second // -20 -> 20 beforeStartHost := task.Task{Id: "beforeStartTask", StartTime: now.Add(time.Duration(-20) * time.Second), FinishTime: now.Add(time.Duration(20) * time.Second), Status: evergreen.TaskSucceeded} So(beforeStartHost.Insert(), ShouldBeNil) // 80 -> 120 afterEndHost := task.Task{Id: "afterStartTask", StartTime: now.Add(time.Duration(80) * time.Second), FinishTime: now.Add(time.Duration(120) * time.Second), Status: evergreen.TaskFailed} So(afterEndHost.Insert(), ShouldBeNil) // 20 -> 40: shouldnt be added h1 := task.Task{Id: "h1", StartTime: now.Add(time.Duration(20) * time.Second), FinishTime: now.Add(time.Duration(40) * time.Second), Status: evergreen.TaskUndispatched} So(h1.Insert(), ShouldBeNil) // 10 -> 80 h2 := task.Task{Id: "h2", StartTime: now.Add(time.Duration(10) * time.Second), FinishTime: now.Add(time.Duration(80) * time.Second), Status: evergreen.TaskSucceeded} So(h2.Insert(), ShouldBeNil) // 20 -> shouldnt be added neverEnding := task.Task{Id: "neverEnding", StartTime: now.Add(time.Duration(20) * time.Second), Status: evergreen.TaskSucceeded} So(neverEnding.Insert(), ShouldBeNil) // 5 -> 7 sameBucket := task.Task{Id: "sameBucket", StartTime: now.Add(time.Duration(5) * time.Second), FinishTime: now.Add(time.Duration(7) * time.Second), Status: evergreen.TaskFailed} So(sameBucket.Insert(), ShouldBeNil) // 5 -> 30 h4 := task.Task{Id: "h4", StartTime: now.Add(time.Duration(5) * time.Second), FinishTime: now.Add(time.Duration(30) * time.Second), Status: evergreen.TaskFailed} So(h4.Insert(), ShouldBeNil) endTime := now.Add(time.Duration(40) * time.Second) frameBounds := FrameBounds{ StartTime: now, EndTime: endTime, NumberBuckets: 4, BucketSize: bucketSize, } Convey("for four buckets of 10 seconds", func() { tasks, err := task.Find(task.ByTimeRun(now, endTime)) So(err, ShouldBeNil) So(len(tasks), ShouldEqual, 4) buckets, errors := CreateTaskBuckets(tasks, []task.Task{}, frameBounds) So(errors, ShouldBeEmpty) So(len(buckets), ShouldEqual, 4) So(int(buckets[0].TotalTime.Seconds()), ShouldEqual, 17) So(int(math.Ceil(buckets[1].TotalTime.Seconds())), ShouldEqual, 30) So(int(math.Ceil(buckets[2].TotalTime.Seconds())), ShouldEqual, 20) }) }) }
// CreateAllHostUtilizationBuckets aggregates each bucket by creating a time frame given the number of days back // and the granularity wanted (ie. days, minutes, seconds, hours) all in seconds. It returns a list of Host utilization // information for each bucket. func CreateAllHostUtilizationBuckets(daysBack, granularity int) ([]HostUtilizationBucket, error) { bounds := CalculateBounds(daysBack, granularity) // find non-static hosts dynamicHosts, err := host.Find(host.ByDynamicWithinTime(bounds.StartTime, bounds.EndTime)) if err != nil { return nil, err } // find static hosts staticHosts, err := host.Find(host.AllStatic) if err != nil { return nil, err } dynamicBuckets, _ := CreateHostBuckets(dynamicHosts, bounds) staticBuckets, _ := CreateHostBuckets(staticHosts, bounds) tasks, err := task.Find(task.ByTimeRun(bounds.StartTime, bounds.EndTime).WithFields(task.StartTimeKey, task.FinishTimeKey, task.HostIdKey)) if err != nil { return nil, err } oldTasks, err := task.FindOld(task.ByTimeRun(bounds.StartTime, bounds.EndTime)) if err != nil { return nil, err } taskBuckets, _ := CreateTaskBuckets(tasks, oldTasks, bounds) bucketData := []HostUtilizationBucket{} for i, staticBucket := range staticBuckets { b := HostUtilizationBucket{ StaticHost: staticBucket.TotalTime, DynamicHost: dynamicBuckets[i].TotalTime, Task: taskBuckets[i].TotalTime, StartTime: bounds.StartTime.Add(time.Duration(i) * bounds.BucketSize), EndTime: bounds.StartTime.Add(time.Duration(i+1) * bounds.BucketSize), } bucketData = append(bucketData, b) } return bucketData, nil }