@@ -2,6 +2,7 @@ package remoteimage
2
2
3
3
import (
4
4
"context"
5
+ "fmt"
5
6
"time"
6
7
7
8
"github.com/containerd/containerd/reference/docker"
@@ -14,7 +15,7 @@ import (
14
15
15
16
type Puller interface {
16
17
Pull (context.Context ) error
17
- ImageSize (context.Context ) int
18
+ ImageSize (context.Context ) ( int , error )
18
19
}
19
20
20
21
func NewPuller (imageSvc cri.ImageServiceClient , image docker.Named ,
@@ -34,48 +35,76 @@ type puller struct {
34
35
35
36
// Returns the compressed size of the image that was pulled in bytes
36
37
// see https://github.com/containerd/containerd/issues/9261
37
- func (p puller ) ImageSize (ctx context.Context ) int {
38
+ func (p puller ) ImageSize (ctx context.Context ) (size int , err error ) {
39
+ defer func () {
40
+ if err != nil {
41
+ klog .Errorf (err .Error ())
42
+ metrics .OperationErrorsCount .WithLabelValues ("size-error" ).Inc ()
43
+ }
44
+ }()
38
45
imageSpec := & cri.ImageSpec {Image : p .image .String ()}
39
- imageStatusResponse , _ := p .imageSvc .ImageStatus (ctx , & cri.ImageStatusRequest {
46
+ if imageStatusResponse , err := p .imageSvc .ImageStatus (ctx , & cri.ImageStatusRequest {
40
47
Image : imageSpec ,
41
- })
42
- return int (imageStatusResponse .Image .Size_ )
48
+ }); err != nil {
49
+ size = 0
50
+ err = fmt .Errorf ("remoteimage.ImageSize(): call returned an error: %s" , err .Error ())
51
+ return size , err
52
+ } else if imageStatusResponse == nil {
53
+ size = 0
54
+ err = fmt .Errorf ("remoteimage.ImageSize(): imageStatusResponse is nil" )
55
+ return size , err
56
+ } else if imageStatusResponse .Image == nil {
57
+ size = 0
58
+ err = fmt .Errorf ("remoteimage.ImageSize(): imageStatusResponse.Image is nil" )
59
+ return size , err
60
+ } else {
61
+ size = imageStatusResponse .Image .Size ()
62
+ err = nil
63
+ return size , err
64
+ }
43
65
}
44
66
45
67
func (p puller ) Pull (ctx context.Context ) (err error ) {
46
68
startTime := time .Now ()
47
69
defer func () { // must capture final value of "err"
48
70
elapsed := time .Since (startTime ).Seconds ()
71
+ // pull time metrics and logs
72
+ klog .Infof ("remoteimage.Pull(): pulled %s in %d milliseconds" , p .image .String (), int (1000 * elapsed ))
49
73
metrics .ImagePullTimeHist .WithLabelValues (metrics .BoolToString (err != nil )).Observe (elapsed )
50
74
metrics .ImagePullTime .WithLabelValues (p .image .String (), metrics .BoolToString (err != nil )).Set (elapsed )
51
75
if err != nil {
52
76
metrics .OperationErrorsCount .WithLabelValues ("pull-error" ).Inc ()
53
- } else {
54
- go func () {
55
- size := p .ImageSize (ctx )
56
- metrics .ImagePullSizeBytes .WithLabelValues (p .image .String ()).Set (float64 (size ))
57
- }()
58
77
}
59
78
go func () {
60
- //TODO: this is a hack to ensure data is cleared in a reasonable timeframe and does not build up.
61
- // pushgateway may remove the need for this. https://prometheus.io/docs/practices/pushing/
79
+ //TODO: this is a hack to ensure data is cleared in a reasonable time frame (after scrape) and does not build up.
62
80
time .Sleep (1 * time .Minute )
63
81
metrics .ImagePullTime .DeleteLabelValues (p .image .String (), metrics .BoolToString (err != nil ))
64
- if err == nil {
65
- metrics .ImagePullSizeBytes .DeleteLabelValues (p .image .String ())
66
- }
67
82
}()
83
+ // pull size metrics and logs
84
+ if err == nil { // only size if pull was successful
85
+ if size , err2 := p .ImageSize (ctx ); err2 != nil {
86
+ // log entries and error counts emitted inside ImageSize() method
87
+ } else { // success
88
+ klog .Infof ("remoteimage.Pull(): pulled %s with size of %d bytes" , p .image .String (), size )
89
+ metrics .ImagePullSizeBytes .WithLabelValues (p .image .String ()).Set (float64 (size ))
90
+ go func () {
91
+ //TODO: this is a hack to ensure data is cleared in a reasonable time frame (after scrape) and does not build up.
92
+ time .Sleep (1 * time .Minute )
93
+ metrics .ImagePullSizeBytes .DeleteLabelValues (p .image .String ())
94
+ }()
95
+ }
96
+ }
68
97
}()
69
98
repo := p .image .Name ()
70
99
imageSpec := & cri.ImageSpec {Image : p .image .String ()}
71
100
creds , withCredentials := p .keyring .Lookup (repo )
72
- klog .V (2 ).Infof ("remoteimage.Pull(): len(creds)=%d, withCreds=%t" , len (creds ), withCredentials )
101
+ // klog.V(2).Infof("remoteimage.Pull(): len(creds)=%d, withCreds=%t", len(creds), withCredentials)
73
102
if ! withCredentials {
74
103
_ , err = p .imageSvc .PullImage (ctx , & cri.PullImageRequest {
75
104
Image : imageSpec ,
76
105
})
77
106
78
- klog .V (2 ).Infof ("remoteimage.Pull(no creds): completed with err=%v" , err )
107
+ klog .V (2 ).Infof ("remoteimage.Pull(no creds): pulling %s completed with err=%v" , p . image . String () , err )
79
108
return
80
109
}
81
110
@@ -96,7 +125,7 @@ func (p puller) Pull(ctx context.Context) (err error) {
96
125
})
97
126
98
127
if err == nil {
99
- klog .V (2 ).Info ("remoteimage.Pull(with creds): completed with err==nil" )
128
+ klog .V (2 ).Info ("remoteimage.Pull(with creds): pulling %s completed with err==nil" , p . image . String () )
100
129
return
101
130
}
102
131
0 commit comments