Add rusage-logfile flag to optionally send rusage to a file
Currently the rusage is reported to stdout and rather cumbersome to parse. The new flag rusage-logfile can be used to specify a file to which the log will be written instead. Signed-off-by: Dan Čermák <dcermak@suse.com>
This commit is contained in:
parent
4fa566ead2
commit
a6b3b6f672
|
@ -334,6 +334,7 @@ func budCmd(c *cobra.Command, inputArgs []string, iopts budOptions) error {
|
||||||
Isolation: isolation,
|
Isolation: isolation,
|
||||||
Labels: iopts.Label,
|
Labels: iopts.Label,
|
||||||
Layers: layers,
|
Layers: layers,
|
||||||
|
LogRusage: iopts.LogRusage,
|
||||||
Manifest: iopts.Manifest,
|
Manifest: iopts.Manifest,
|
||||||
MaxPullPushRetries: maxPullPushRetries,
|
MaxPullPushRetries: maxPullPushRetries,
|
||||||
NamespaceOptions: namespaceOptions,
|
NamespaceOptions: namespaceOptions,
|
||||||
|
@ -349,6 +350,7 @@ func budCmd(c *cobra.Command, inputArgs []string, iopts budOptions) error {
|
||||||
ReportWriter: reporter,
|
ReportWriter: reporter,
|
||||||
Runtime: iopts.Runtime,
|
Runtime: iopts.Runtime,
|
||||||
RuntimeArgs: runtimeFlags,
|
RuntimeArgs: runtimeFlags,
|
||||||
|
RusageLogFile: iopts.RusageLogFile,
|
||||||
SignBy: iopts.SignBy,
|
SignBy: iopts.SignBy,
|
||||||
SignaturePolicyPath: iopts.SignaturePolicy,
|
SignaturePolicyPath: iopts.SignaturePolicy,
|
||||||
Squash: iopts.Squash,
|
Squash: iopts.Squash,
|
||||||
|
@ -357,7 +359,6 @@ func budCmd(c *cobra.Command, inputArgs []string, iopts budOptions) error {
|
||||||
TransientMounts: iopts.Volumes,
|
TransientMounts: iopts.Volumes,
|
||||||
OciDecryptConfig: decConfig,
|
OciDecryptConfig: decConfig,
|
||||||
Jobs: &iopts.Jobs,
|
Jobs: &iopts.Jobs,
|
||||||
LogRusage: iopts.LogRusage,
|
|
||||||
}
|
}
|
||||||
if iopts.IgnoreFile != "" {
|
if iopts.IgnoreFile != "" {
|
||||||
excludes, err := parseDockerignore(iopts.IgnoreFile)
|
excludes, err := parseDockerignore(iopts.IgnoreFile)
|
||||||
|
|
|
@ -217,6 +217,8 @@ type BuildOptions struct {
|
||||||
Jobs *int
|
Jobs *int
|
||||||
// LogRusage logs resource usage for each step.
|
// LogRusage logs resource usage for each step.
|
||||||
LogRusage bool
|
LogRusage bool
|
||||||
|
// File to which the Rusage logs will be saved to instead of stdout
|
||||||
|
RusageLogFile string
|
||||||
// Excludes is a list of excludes to be used instead of the .dockerignore file.
|
// Excludes is a list of excludes to be used instead of the .dockerignore file.
|
||||||
Excludes []string
|
Excludes []string
|
||||||
// From is the image name to use to replace the value specified in the first
|
// From is the image name to use to replace the value specified in the first
|
||||||
|
|
|
@ -116,6 +116,7 @@ type Executor struct {
|
||||||
stagesSemaphore *semaphore.Weighted
|
stagesSemaphore *semaphore.Weighted
|
||||||
jobs int
|
jobs int
|
||||||
logRusage bool
|
logRusage bool
|
||||||
|
rusageLogFile *os.File
|
||||||
imageInfoLock sync.Mutex
|
imageInfoLock sync.Mutex
|
||||||
imageInfoCache map[string]imageTypeAndHistoryAndDiffIDs
|
imageInfoCache map[string]imageTypeAndHistoryAndDiffIDs
|
||||||
fromOverride string
|
fromOverride string
|
||||||
|
@ -183,6 +184,18 @@ func NewExecutor(logger *logrus.Logger, store storage.Store, options define.Buil
|
||||||
writer = ioutil.Discard
|
writer = ioutil.Discard
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var rusageLogFile *os.File
|
||||||
|
if options.LogRusage && !options.Quiet {
|
||||||
|
if options.RusageLogFile == "" {
|
||||||
|
rusageLogFile = os.Stdout
|
||||||
|
} else {
|
||||||
|
rusageLogFile, err = os.OpenFile(options.RusageLogFile, os.O_TRUNC|os.O_CREATE|os.O_WRONLY, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
exec := Executor{
|
exec := Executor{
|
||||||
logger: logger,
|
logger: logger,
|
||||||
stages: make(map[string]*StageExecutor),
|
stages: make(map[string]*StageExecutor),
|
||||||
|
@ -241,6 +254,7 @@ func NewExecutor(logger *logrus.Logger, store storage.Store, options define.Buil
|
||||||
terminatedStage: make(map[string]struct{}),
|
terminatedStage: make(map[string]struct{}),
|
||||||
jobs: jobs,
|
jobs: jobs,
|
||||||
logRusage: options.LogRusage,
|
logRusage: options.LogRusage,
|
||||||
|
rusageLogFile: rusageLogFile,
|
||||||
imageInfoCache: make(map[string]imageTypeAndHistoryAndDiffIDs),
|
imageInfoCache: make(map[string]imageTypeAndHistoryAndDiffIDs),
|
||||||
fromOverride: options.From,
|
fromOverride: options.From,
|
||||||
manifest: options.Manifest,
|
manifest: options.Manifest,
|
||||||
|
@ -530,6 +544,12 @@ func (b *Executor) Build(ctx context.Context, stages imagebuilder.Stages) (image
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cleanupImages = nil
|
cleanupImages = nil
|
||||||
|
|
||||||
|
if b.rusageLogFile != nil && b.rusageLogFile != os.Stdout {
|
||||||
|
// we deliberately ignore the error here, as this
|
||||||
|
// function can be called multiple times
|
||||||
|
b.rusageLogFile.Close()
|
||||||
|
}
|
||||||
return lastErr
|
return lastErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -704,8 +704,8 @@ func (s *StageExecutor) Execute(ctx context.Context, base string) (imgID string,
|
||||||
fmt.Fprintf(s.executor.out, "error gathering resource usage information: %v\n", err)
|
fmt.Fprintf(s.executor.out, "error gathering resource usage information: %v\n", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !s.executor.quiet && s.executor.logRusage {
|
if s.executor.rusageLogFile != nil {
|
||||||
fmt.Fprintf(s.executor.out, "%s\n", rusage.FormatDiff(usage.Subtract(resourceUsage)))
|
fmt.Fprintf(s.executor.rusageLogFile, "%s\n", rusage.FormatDiff(usage.Subtract(resourceUsage)))
|
||||||
}
|
}
|
||||||
resourceUsage = usage
|
resourceUsage = usage
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,6 +84,7 @@ type BudResults struct {
|
||||||
TLSVerify bool
|
TLSVerify bool
|
||||||
Jobs int
|
Jobs int
|
||||||
LogRusage bool
|
LogRusage bool
|
||||||
|
RusageLogFile string
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromAndBugResults represents the results for common flags
|
// FromAndBugResults represents the results for common flags
|
||||||
|
@ -199,6 +200,10 @@ func GetBudFlags(flags *BudResults) pflag.FlagSet {
|
||||||
if err := fs.MarkHidden("log-rusage"); err != nil {
|
if err := fs.MarkHidden("log-rusage"); err != nil {
|
||||||
panic(fmt.Sprintf("error marking the log-rusage flag as hidden: %v", err))
|
panic(fmt.Sprintf("error marking the log-rusage flag as hidden: %v", err))
|
||||||
}
|
}
|
||||||
|
fs.StringVar(&flags.RusageLogFile, "rusage-logfile", "", "destination file to which rusage should be logged to instead of stdout (= the default).")
|
||||||
|
if err := fs.MarkHidden("rusage-logfile"); err != nil {
|
||||||
|
panic(fmt.Sprintf("error marking the rusage-logfile flag as hidden: %v", err))
|
||||||
|
}
|
||||||
fs.StringVar(&flags.Manifest, "manifest", "", "add the image to the specified manifest list. Creates manifest if it does not exist")
|
fs.StringVar(&flags.Manifest, "manifest", "", "add the image to the specified manifest list. Creates manifest if it does not exist")
|
||||||
fs.BoolVar(&flags.NoCache, "no-cache", false, "Do not use existing cached images for the container build. Build from the start with a new set of cached layers.")
|
fs.BoolVar(&flags.NoCache, "no-cache", false, "Do not use existing cached images for the container build. Build from the start with a new set of cached layers.")
|
||||||
fs.String("os", runtime.GOOS, "set the OS to the provided value instead of the current operating system of the host")
|
fs.String("os", runtime.GOOS, "set the OS to the provided value instead of the current operating system of the host")
|
||||||
|
|
|
@ -2423,6 +2423,19 @@ EOM
|
||||||
expect_output --substring ".*\(system\).*\(user\).*\(elapsed\).*input.*output"
|
expect_output --substring ".*\(system\).*\(user\).*\(elapsed\).*input.*output"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "bud with-rusage-logfile" {
|
||||||
|
_prefetch alpine
|
||||||
|
run_buildah bud --log-rusage --rusage-logfile "foo.log" --layers --pull=false --format docker --signature-policy ${TESTSDIR}/policy.json ${TESTSDIR}/bud/shell
|
||||||
|
# the logfile should exist
|
||||||
|
if [ ! -e "foo.log" ]; then die "foo.log not present!"; fi
|
||||||
|
# expect that foo.log only contains lines that were formatted using pkg/rusage.FormatDiff()
|
||||||
|
formatted_lines=$(grep ".*\(system\).*\(user\).*\(elapsed\).*input.*output" foo.log | wc -l)
|
||||||
|
line_count=$(cat foo.log | wc -l)
|
||||||
|
if [[ "$formatted_lines" -ne "$line_count" ]]; then
|
||||||
|
die "Got ${formatted_lines} lines formatted with pkg/rusage.FormatDiff() but foo.log has ${line_count} lines"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
@test "bud-caching-from-scratch" {
|
@test "bud-caching-from-scratch" {
|
||||||
_prefetch alpine
|
_prefetch alpine
|
||||||
# run the build once
|
# run the build once
|
||||||
|
|
Loading…
Reference in New Issue