Skip to content

Commit

Permalink
Introduce CSV report output
Browse files Browse the repository at this point in the history
Refactor report functions to use an `io.Writer` instead of a filename.

Add CSV report output function with a test case.

Add flags to support HTML and CSV based reports.
  • Loading branch information
HeavyWombat committed Nov 26, 2020
1 parent 59de9e7 commit e09a987
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 9 deletions.
31 changes: 30 additions & 1 deletion internal/cmd/buildrun-series.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ limitations under the License.
package cmd

import (
"bytes"
"io"
"io/ioutil"
"os"

"github.com/gonvenience/bunt"
"github.com/homeport/build-load/internal/load"
"github.com/spf13/cobra"
Expand All @@ -28,6 +33,9 @@ var buildRunSeriesCmdSettings struct {
buildTestsIncrement int
namingCfg load.NamingConfig
buildCfg load.BuildConfig

htmlOutput string
csvOutput string
}

var buildRunSeriesCmd = &cobra.Command{
Expand All @@ -51,7 +59,25 @@ var buildRunSeriesCmd = &cobra.Command{
return err
}

return load.CreateChartJS("report.html", results)
var store = func(filename string, f func(w io.Writer) error) error {
var buf bytes.Buffer
f(&buf)
return ioutil.WriteFile(filename, buf.Bytes(), os.FileMode(0644))
}

if len(buildRunSeriesCmdSettings.htmlOutput) > 0 {
store(buildRunSeriesCmdSettings.htmlOutput, func(w io.Writer) error {
return load.CreateChartJS(results, w)
})
}

if len(buildRunSeriesCmdSettings.csvOutput) > 0 {
store(buildRunSeriesCmdSettings.csvOutput, func(w io.Writer) error {
return load.CreateBuildRunResultSetCSV(results, w)
})
}

return nil
},
}

Expand All @@ -65,6 +91,9 @@ func init() {
buildRunSeriesCmd.Flags().IntVar(&buildRunSeriesCmdSettings.buildTestsMax, "build-tests-max", 100, "highest number of parallel builds to test")
buildRunSeriesCmd.Flags().IntVar(&buildRunSeriesCmdSettings.buildTestsIncrement, "build-tests-increment", 5, "increment for spinning up the number of parallel tests")

buildRunSeriesCmd.Flags().StringVar(&buildRunSeriesCmdSettings.htmlOutput, "html", "", "filename of the HTML report")
buildRunSeriesCmd.Flags().StringVar(&buildRunSeriesCmdSettings.csvOutput, "csv", "", "filename of the CSV report")

applyNamingFlags(buildRunSeriesCmd, &buildRunSeriesCmdSettings.namingCfg)
applyBuildRunSettingsFlags(buildRunSeriesCmd, &buildRunSeriesCmdSettings.buildCfg)
}
11 changes: 3 additions & 8 deletions internal/load/reports_chartjs.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ package load
import (
"fmt"
"html/template"
"os"
"io"
)

// CreateChartJS creates a page with ChartsJS to render the provided results
func CreateChartJS(filename string, data []BuildRunResultSet) error {
func CreateChartJS(data []BuildRunResultSet, w io.Writer) error {
const reportTemplate = `<!DOCTYPE html>
<html>
Expand Down Expand Up @@ -135,17 +135,12 @@ func CreateChartJS(filename string, data []BuildRunResultSet) error {
datasets[3].Data = append(datasets[3].Data, buildRunResultSet.Median.ValueOf(BuildRunRampUpDuration).Seconds())
}

output, err := os.Create(filename)
if err != nil {
return err
}

type inputs struct {
Labels []string
Datasets []dataset
}

return tmpl.Execute(output, inputs{
return tmpl.Execute(w, inputs{
Labels: labels,
Datasets: datasets,
})
Expand Down
56 changes: 56 additions & 0 deletions internal/load/reports_csv.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
Copyright © 2020 The Homeport Team
Licensed 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 KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package load

import (
"fmt"
"io"
"strconv"

"github.com/gonvenience/neat"
)

// CreateBuildRunResultSetCSV creates a comma separated values (CSV) content based on the buildrun result sets
func CreateBuildRunResultSetCSV(data []BuildRunResultSet, w io.Writer) error {
var table = [][]string{}
for i, buildRunResultSet := range data {
// add header based on first set entry
if i == 0 {
var row = []string{"number of results"}
for _, value := range buildRunResultSet.Median {
row = append(row, value.Description)
}

table = append(table, row)
}

var row = []string{strconv.Itoa(buildRunResultSet.NumberOfResults)}
for _, value := range buildRunResultSet.Median {
row = append(row, strconv.Itoa(int(value.Value.Milliseconds())))
}

table = append(table, row)
}

out, err := neat.Table(table, neat.CustomSeparator(", "))
if err != nil {
return err
}

_, err = fmt.Fprint(w, out)
return err
}
68 changes: 68 additions & 0 deletions internal/load/reports_csv_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
Copyright © 2020 The Homeport Team
Licensed 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 KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package load_test

import (
"bytes"
"time"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"

. "github.com/homeport/build-load/internal/load"
)

var _ = Describe("create CSV reports", func() {
var mockBuildRunResults = func(n int) []BuildRunResult {
var result = make([]BuildRunResult, n)
for i := 0; i < n; i++ {
result[i] = BuildRunResult{
Value{TotalBuildRunTime, time.Duration(i+1) * 1 * time.Second},
Value{BuildRunRampUpDuration, time.Duration(i+1) * 10 * time.Second},
Value{TaskRunRampUpDuration, time.Duration(i+1) * 100 * time.Second},
Value{PodRampUpDuration, time.Duration(i+1) * 1000 * time.Second},
Value{InternalProcessingTime, time.Duration(i+1) * 10000 * time.Second},
}
}

return result
}

Context("having a buildrun result set", func() {
It("should create a CSV file based on the content in the buildrun result set", func() {
var buildRunResultSets = []BuildRunResultSet{
CalculateBuildRunResultSet(mockBuildRunResults(5)),
CalculateBuildRunResultSet(mockBuildRunResults(10)),
CalculateBuildRunResultSet(mockBuildRunResults(15)),
CalculateBuildRunResultSet(mockBuildRunResults(20)),
CalculateBuildRunResultSet(mockBuildRunResults(25)),
}

var buf bytes.Buffer
err := CreateBuildRunResultSetCSV(buildRunResultSets, &buf)
Expect(err).ToNot(HaveOccurred())

Expect(buf.String()).To(Equal(`number of results, total time between buildrun creation until finish, time between buildrun creation and taskrun creation, time between taskrun creation and tekton pod creation, time between tekton pod creation and first container start, remaining internal processing time
5 , 3000 , 30000 , 300000 , 3000000 , 30000000
10 , 5500 , 55000 , 550000 , 5500000 , 55000000
15 , 8000 , 80000 , 800000 , 8000000 , 80000000
20 , 10500 , 105000 , 1050000 , 10500000 , 105000000
25 , 13000 , 130000 , 1300000 , 13000000 , 130000000
`))
})
})
})

0 comments on commit e09a987

Please sign in to comment.