diff --git a/daemon/containerd/image_delete.go b/daemon/containerd/image_delete.go index 96d55ac6326b8..81654c15ea658 100644 --- a/daemon/containerd/image_delete.go +++ b/daemon/containerd/image_delete.go @@ -55,7 +55,14 @@ import ( // conflict will not be reported. // // TODO(thaJeztah): image delete should send prometheus counters; see https://github.com/moby/moby/issues/45268 -func (i *ImageService) ImageDelete(ctx context.Context, imageRef string, force, prune bool) ([]imagetypes.DeleteResponse, error) { +func (i *ImageService) ImageDelete(ctx context.Context, imageRef string, force, prune bool) (response []imagetypes.DeleteResponse, retErr error) { + start := time.Now() + defer func() { + if retErr == nil { + dimages.ImageActions.WithValues("delete").UpdateSince(start) + } + }() + var c conflictType if !force { c |= conflictSoft diff --git a/daemon/containerd/image_history.go b/daemon/containerd/image_history.go index e20710c3c641a..f3a0de99f5ffa 100644 --- a/daemon/containerd/image_history.go +++ b/daemon/containerd/image_history.go @@ -2,12 +2,14 @@ package containerd import ( "context" + "time" containerdimages "github.com/containerd/containerd/images" "github.com/containerd/containerd/platforms" "github.com/containerd/log" "github.com/distribution/reference" imagetype "github.com/docker/docker/api/types/image" + dimages "github.com/docker/docker/daemon/images" "github.com/opencontainers/go-digest" "github.com/opencontainers/image-spec/identity" "github.com/pkg/errors" @@ -16,6 +18,7 @@ import ( // ImageHistory returns a slice of HistoryResponseItem structures for the // specified image name by walking the image lineage. func (i *ImageService) ImageHistory(ctx context.Context, name string) ([]*imagetype.HistoryResponseItem, error) { + start := time.Now() img, err := i.resolveImage(ctx, name) if err != nil { return nil, err @@ -113,6 +116,7 @@ func (i *ImageService) ImageHistory(ctx context.Context, name string) ([]*imaget } } + dimages.ImageActions.WithValues("history").UpdateSince(start) return history, nil } diff --git a/daemon/containerd/image_pull.go b/daemon/containerd/image_pull.go index fbb71b4766809..82ed8a7084e19 100644 --- a/daemon/containerd/image_pull.go +++ b/daemon/containerd/image_pull.go @@ -6,6 +6,7 @@ import ( "io" "os" "strings" + "time" "github.com/containerd/containerd" cerrdefs "github.com/containerd/containerd/errdefs" @@ -17,6 +18,7 @@ import ( "github.com/distribution/reference" "github.com/docker/docker/api/types/events" registrytypes "github.com/docker/docker/api/types/registry" + dimages "github.com/docker/docker/daemon/images" "github.com/docker/docker/distribution" "github.com/docker/docker/errdefs" "github.com/docker/docker/internal/compatcontext" @@ -29,7 +31,13 @@ import ( // PullImage initiates a pull operation. baseRef is the image to pull. // If reference is not tagged, all tags are pulled. -func (i *ImageService) PullImage(ctx context.Context, baseRef reference.Named, platform *ocispec.Platform, metaHeaders map[string][]string, authConfig *registrytypes.AuthConfig, outStream io.Writer) error { +func (i *ImageService) PullImage(ctx context.Context, baseRef reference.Named, platform *ocispec.Platform, metaHeaders map[string][]string, authConfig *registrytypes.AuthConfig, outStream io.Writer) (retErr error) { + start := time.Now() + defer func() { + if retErr == nil { + dimages.ImageActions.WithValues("pull").UpdateSince(start) + } + }() out := streamformatter.NewJSONProgressOutput(outStream, false) if !reference.IsNameOnly(baseRef) { diff --git a/daemon/containerd/image_push.go b/daemon/containerd/image_push.go index b8bb0234441ac..150e3c61c58b2 100644 --- a/daemon/containerd/image_push.go +++ b/daemon/containerd/image_push.go @@ -6,6 +6,7 @@ import ( "io" "strings" "sync" + "time" "github.com/containerd/containerd/content" cerrdefs "github.com/containerd/containerd/errdefs" @@ -19,6 +20,7 @@ import ( "github.com/distribution/reference" "github.com/docker/docker/api/types/events" "github.com/docker/docker/api/types/registry" + dimages "github.com/docker/docker/daemon/images" "github.com/docker/docker/errdefs" "github.com/docker/docker/internal/compatcontext" "github.com/docker/docker/pkg/progress" @@ -40,6 +42,12 @@ import ( // to perform cross-repo mounts of the shared content when pushing to a different // repository on the same registry. func (i *ImageService) PushImage(ctx context.Context, sourceRef reference.Named, metaHeaders map[string][]string, authConfig *registry.AuthConfig, outStream io.Writer) (retErr error) { + start := time.Now() + defer func() { + if retErr == nil { + dimages.ImageActions.WithValues("push").UpdateSince(start) + } + }() out := streamformatter.NewJSONProgressOutput(outStream, false) progress.Messagef(out, "", "The push refers to repository [%s]", sourceRef.Name()) diff --git a/daemon/images/image_delete.go b/daemon/images/image_delete.go index 073683460c13b..7e70dfac229ec 100644 --- a/daemon/images/image_delete.go +++ b/daemon/images/image_delete.go @@ -173,7 +173,7 @@ func (i *ImageService) ImageDelete(ctx context.Context, imageRef string, force, return nil, err } - imageActions.WithValues("delete").UpdateSince(start) + ImageActions.WithValues("delete").UpdateSince(start) return records, nil } diff --git a/daemon/images/image_history.go b/daemon/images/image_history.go index 9f5286ae5e136..1617f8be62906 100644 --- a/daemon/images/image_history.go +++ b/daemon/images/image_history.go @@ -76,6 +76,6 @@ func (i *ImageService) ImageHistory(ctx context.Context, name string) ([]*image. break } } - imageActions.WithValues("history").UpdateSince(start) + ImageActions.WithValues("history").UpdateSince(start) return history, nil } diff --git a/daemon/images/image_pull.go b/daemon/images/image_pull.go index b938466411a06..23c3b43c971db 100644 --- a/daemon/images/image_pull.go +++ b/daemon/images/image_pull.go @@ -26,7 +26,7 @@ func (i *ImageService) PullImage(ctx context.Context, ref reference.Named, platf start := time.Now() err := i.pullImageWithReference(ctx, ref, platform, metaHeaders, authConfig, outStream) - imageActions.WithValues("pull").UpdateSince(start) + ImageActions.WithValues("pull").UpdateSince(start) if err != nil { return err } diff --git a/daemon/images/image_push.go b/daemon/images/image_push.go index 9e33d68785bc7..30a4cb9ba3159 100644 --- a/daemon/images/image_push.go +++ b/daemon/images/image_push.go @@ -48,6 +48,6 @@ func (i *ImageService) PushImage(ctx context.Context, ref reference.Named, metaH err := distribution.Push(ctx, ref, imagePushConfig) close(progressChan) <-writesDone - imageActions.WithValues("push").UpdateSince(start) + ImageActions.WithValues("push").UpdateSince(start) return err } diff --git a/daemon/images/locals.go b/daemon/images/metrics.go similarity index 56% rename from daemon/images/locals.go rename to daemon/images/metrics.go index 77416aa4886d9..1b1056462ce7c 100644 --- a/daemon/images/locals.go +++ b/daemon/images/metrics.go @@ -4,11 +4,14 @@ import ( metrics "github.com/docker/go-metrics" ) -var imageActions metrics.LabeledTimer +// ImagesActions measures the time it takes to process some image actions. +// Exported for use in the containerd-backed image store and it is not intended +// for external consumption. Do not use! +var ImageActions metrics.LabeledTimer func init() { ns := metrics.NewNamespace("engine", "daemon", nil) - imageActions = ns.NewLabeledTimer("image_actions", "The number of seconds it takes to process each image action", "action") + ImageActions = ns.NewLabeledTimer("image_actions", "The number of seconds it takes to process each image action", "action") // TODO: is it OK to register a namespace with the same name? Or does this // need to be exported from somewhere? metrics.Register(ns)