Skip to content

Commit de4e4a0

Browse files
lzapachilleas-k
authored andcommitted
many: metrics option for stage durations
This commit introduces a new metrics option for the image building stages, allowing users to get more insights into the duration of each stage.
1 parent 3828d9c commit de4e4a0

File tree

4 files changed

+74
-0
lines changed

4 files changed

+74
-0
lines changed

cmd/image-builder/build.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ type buildOptions struct {
1717

1818
WriteManifest bool
1919
WriteBuildlog bool
20+
Metrics bool
2021
}
2122

2223
func buildImage(pbar progress.ProgressBar, res *imagefilter.Result, osbuildManifest []byte, opts *buildOptions) (string, error) {
@@ -38,6 +39,7 @@ func buildImage(pbar progress.ProgressBar, res *imagefilter.Result, osbuildManif
3839
osbuildOpts := &progress.OSBuildOptions{
3940
StoreDir: opts.StoreDir,
4041
OutputDir: opts.OutputDir,
42+
Metrics: opts.Metrics,
4143
}
4244
if opts.WriteBuildlog {
4345
if err := os.MkdirAll(opts.OutputDir, 0755); err != nil {

cmd/image-builder/main.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,10 @@ func cmdBuild(cmd *cobra.Command, args []string) error {
374374
if err != nil {
375375
return err
376376
}
377+
withMetrics, err := cmd.Flags().GetBool("with-metrics")
378+
if err != nil {
379+
return err
380+
}
377381
// XXX: check env here, i.e. if user is root and osbuild is installed
378382

379383
// Setup osbuild environment if running in a container
@@ -432,6 +436,7 @@ func cmdBuild(cmd *cobra.Command, args []string) error {
432436
StoreDir: cacheDir,
433437
WriteManifest: withManifest,
434438
WriteBuildlog: withBuildlog,
439+
Metrics: withMetrics,
435440
}
436441
pbar.SetPulseMsgf("Image building step")
437442
imagePath, err := buildImage(pbar, res, mf.Bytes(), buildOpts)
@@ -595,6 +600,7 @@ operating systems like Fedora, CentOS and RHEL with easy customizations support.
595600
// XXX: add "--verbose" here, similar to how bib is doing this
596601
// (see https://github.com/osbuild/bootc-image-builder/pull/790/commits/5cec7ffd8a526e2ca1e8ada0ea18f927695dfe43)
597602
buildCmd.Flags().String("progress", "auto", "type of progress bar to use (e.g. verbose,term)")
603+
buildCmd.Flags().Bool("with-metrics", false, `print timing information at the end of the build`)
598604
buildCmd.Flags().String("output-name", "", "set specific output basename")
599605
rootCmd.AddCommand(buildCmd)
600606
buildCmd.Flags().AddFlagSet(uploadCmd.Flags())

pkg/progress/command.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ type OSBuildOptions struct {
2525
BuildLog io.Writer
2626

2727
CacheMaxSize int64
28+
29+
Metrics bool
2830
}
2931

3032
// XXX: merge variant back into images/pkg/osbuild/osbuild-exec.go
@@ -154,6 +156,7 @@ func runOSBuildWithProgress(pb ProgressBar, manifest []byte, exports []string, o
154156
}()
155157

156158
var tracesMsgs []string
159+
oss := osbuildStageMetrics{}
157160
for {
158161
st, err := osbuildStatus.Status()
159162
if err != nil {
@@ -192,11 +195,21 @@ func runOSBuildWithProgress(pb ProgressBar, manifest []byte, exports []string, o
192195
tracesMsgs = append(tracesMsgs, st.Trace)
193196
fmt.Fprintln(buildLog, st.Trace)
194197
}
198+
199+
// store metrics if requested
200+
if opts.Metrics {
201+
oss.Add(st)
202+
}
195203
}
196204

197205
if err := cmd.Wait(); err != nil {
198206
return fmt.Errorf("error running osbuild: %w\nBuildLog:\n%s\nOutput:\n%s", err, strings.Join(tracesMsgs, "\n"), stdio.String())
199207
}
200208

209+
// append metrics to the end message
210+
if opts.Metrics {
211+
pb.Write(oss.Bytes())
212+
}
213+
201214
return nil
202215
}

pkg/progress/metrics.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package progress
2+
3+
import (
4+
"sort"
5+
"time"
6+
7+
"github.com/osbuild/images/pkg/osbuild"
8+
)
9+
10+
type osbuildStageMetrics struct {
11+
durations []measurement
12+
}
13+
14+
type measurement struct {
15+
Pipeline string
16+
Name string
17+
Duration time.Duration
18+
}
19+
20+
func (s *osbuildStageMetrics) Add(st *osbuild.Status) {
21+
if st.Duration > 1*time.Second && st.Message != "" {
22+
s.durations = append(s.durations, measurement{
23+
Pipeline: st.Pipeline,
24+
Name: st.Message,
25+
Duration: st.Duration,
26+
})
27+
}
28+
}
29+
30+
func (s *osbuildStageMetrics) String() string {
31+
if len(s.durations) == 0 {
32+
return ""
33+
}
34+
35+
// sort measurements by duration descending
36+
sort.Slice(s.durations, func(i, j int) bool {
37+
return s.durations[i].Duration > s.durations[j].Duration
38+
})
39+
40+
result := "Metrics:\n"
41+
for i, m := range s.durations {
42+
result += "\t" + m.Pipeline + ": " + m.Name + ": " + m.Duration.Truncate(time.Second).String() + "\n"
43+
if i >= 9 {
44+
break
45+
}
46+
}
47+
48+
return result
49+
}
50+
51+
func (s *osbuildStageMetrics) Bytes() []byte {
52+
return []byte(s.String())
53+
}

0 commit comments

Comments
 (0)