1// +build !dockerless 2 3/* 4Copyright 2015 The Kubernetes Authors. 5 6Licensed under the Apache License, Version 2.0 (the "License"); 7you may not use this file except in compliance with the License. 8You may obtain a copy of the License at 9 10 http://www.apache.org/licenses/LICENSE-2.0 11 12Unless required by applicable law or agreed to in writing, software 13distributed under the License is distributed on an "AS IS" BASIS, 14WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15See the License for the specific language governing permissions and 16limitations under the License. 17*/ 18 19package libdocker 20 21import ( 22 "time" 23 24 dockertypes "github.com/docker/docker/api/types" 25 dockercontainer "github.com/docker/docker/api/types/container" 26 dockerimagetypes "github.com/docker/docker/api/types/image" 27 28 "k8s.io/kubernetes/pkg/kubelet/dockershim/metrics" 29) 30 31// instrumentedInterface wraps the Interface and records the operations 32// and errors metrics. 33type instrumentedInterface struct { 34 client Interface 35} 36 37// NewInstrumentedInterface creates an instrumented Interface from an existing Interface. 38func NewInstrumentedInterface(dockerClient Interface) Interface { 39 return instrumentedInterface{ 40 client: dockerClient, 41 } 42} 43 44// recordOperation records the duration of the operation. 45func recordOperation(operation string, start time.Time) { 46 metrics.DockerOperations.WithLabelValues(operation).Inc() 47 metrics.DockerOperationsLatency.WithLabelValues(operation).Observe(metrics.SinceInSeconds(start)) 48} 49 50// recordError records error for metric if an error occurred. 51func recordError(operation string, err error) { 52 if err != nil { 53 if _, ok := err.(operationTimeout); ok { 54 metrics.DockerOperationsTimeout.WithLabelValues(operation).Inc() 55 } 56 // Docker operation timeout error is also a docker error, so we don't add else here. 57 metrics.DockerOperationsErrors.WithLabelValues(operation).Inc() 58 } 59} 60 61func (in instrumentedInterface) ListContainers(options dockertypes.ContainerListOptions) ([]dockertypes.Container, error) { 62 const operation = "list_containers" 63 defer recordOperation(operation, time.Now()) 64 65 out, err := in.client.ListContainers(options) 66 recordError(operation, err) 67 return out, err 68} 69 70func (in instrumentedInterface) InspectContainer(id string) (*dockertypes.ContainerJSON, error) { 71 const operation = "inspect_container" 72 defer recordOperation(operation, time.Now()) 73 74 out, err := in.client.InspectContainer(id) 75 recordError(operation, err) 76 return out, err 77} 78 79func (in instrumentedInterface) InspectContainerWithSize(id string) (*dockertypes.ContainerJSON, error) { 80 const operation = "inspect_container_withsize" 81 defer recordOperation(operation, time.Now()) 82 83 out, err := in.client.InspectContainerWithSize(id) 84 recordError(operation, err) 85 return out, err 86} 87 88func (in instrumentedInterface) CreateContainer(opts dockertypes.ContainerCreateConfig) (*dockercontainer.ContainerCreateCreatedBody, error) { 89 const operation = "create_container" 90 defer recordOperation(operation, time.Now()) 91 92 out, err := in.client.CreateContainer(opts) 93 recordError(operation, err) 94 return out, err 95} 96 97func (in instrumentedInterface) StartContainer(id string) error { 98 const operation = "start_container" 99 defer recordOperation(operation, time.Now()) 100 101 err := in.client.StartContainer(id) 102 recordError(operation, err) 103 return err 104} 105 106func (in instrumentedInterface) StopContainer(id string, timeout time.Duration) error { 107 const operation = "stop_container" 108 defer recordOperation(operation, time.Now()) 109 110 err := in.client.StopContainer(id, timeout) 111 recordError(operation, err) 112 return err 113} 114 115func (in instrumentedInterface) RemoveContainer(id string, opts dockertypes.ContainerRemoveOptions) error { 116 const operation = "remove_container" 117 defer recordOperation(operation, time.Now()) 118 119 err := in.client.RemoveContainer(id, opts) 120 recordError(operation, err) 121 return err 122} 123 124func (in instrumentedInterface) UpdateContainerResources(id string, updateConfig dockercontainer.UpdateConfig) error { 125 const operation = "update_container" 126 defer recordOperation(operation, time.Now()) 127 128 err := in.client.UpdateContainerResources(id, updateConfig) 129 recordError(operation, err) 130 return err 131} 132 133func (in instrumentedInterface) InspectImageByRef(image string) (*dockertypes.ImageInspect, error) { 134 const operation = "inspect_image" 135 defer recordOperation(operation, time.Now()) 136 137 out, err := in.client.InspectImageByRef(image) 138 recordError(operation, err) 139 return out, err 140} 141 142func (in instrumentedInterface) InspectImageByID(image string) (*dockertypes.ImageInspect, error) { 143 const operation = "inspect_image" 144 defer recordOperation(operation, time.Now()) 145 146 out, err := in.client.InspectImageByID(image) 147 recordError(operation, err) 148 return out, err 149} 150 151func (in instrumentedInterface) ListImages(opts dockertypes.ImageListOptions) ([]dockertypes.ImageSummary, error) { 152 const operation = "list_images" 153 defer recordOperation(operation, time.Now()) 154 155 out, err := in.client.ListImages(opts) 156 recordError(operation, err) 157 return out, err 158} 159 160func (in instrumentedInterface) PullImage(imageID string, auth dockertypes.AuthConfig, opts dockertypes.ImagePullOptions) error { 161 const operation = "pull_image" 162 defer recordOperation(operation, time.Now()) 163 err := in.client.PullImage(imageID, auth, opts) 164 recordError(operation, err) 165 return err 166} 167 168func (in instrumentedInterface) RemoveImage(image string, opts dockertypes.ImageRemoveOptions) ([]dockertypes.ImageDeleteResponseItem, error) { 169 const operation = "remove_image" 170 defer recordOperation(operation, time.Now()) 171 172 imageDelete, err := in.client.RemoveImage(image, opts) 173 recordError(operation, err) 174 return imageDelete, err 175} 176 177func (in instrumentedInterface) Logs(id string, opts dockertypes.ContainerLogsOptions, sopts StreamOptions) error { 178 const operation = "logs" 179 defer recordOperation(operation, time.Now()) 180 181 err := in.client.Logs(id, opts, sopts) 182 recordError(operation, err) 183 return err 184} 185 186func (in instrumentedInterface) Version() (*dockertypes.Version, error) { 187 const operation = "version" 188 defer recordOperation(operation, time.Now()) 189 190 out, err := in.client.Version() 191 recordError(operation, err) 192 return out, err 193} 194 195func (in instrumentedInterface) Info() (*dockertypes.Info, error) { 196 const operation = "info" 197 defer recordOperation(operation, time.Now()) 198 199 out, err := in.client.Info() 200 recordError(operation, err) 201 return out, err 202} 203 204func (in instrumentedInterface) CreateExec(id string, opts dockertypes.ExecConfig) (*dockertypes.IDResponse, error) { 205 const operation = "create_exec" 206 defer recordOperation(operation, time.Now()) 207 208 out, err := in.client.CreateExec(id, opts) 209 recordError(operation, err) 210 return out, err 211} 212 213func (in instrumentedInterface) StartExec(startExec string, opts dockertypes.ExecStartCheck, sopts StreamOptions) error { 214 const operation = "start_exec" 215 defer recordOperation(operation, time.Now()) 216 217 err := in.client.StartExec(startExec, opts, sopts) 218 recordError(operation, err) 219 return err 220} 221 222func (in instrumentedInterface) InspectExec(id string) (*dockertypes.ContainerExecInspect, error) { 223 const operation = "inspect_exec" 224 defer recordOperation(operation, time.Now()) 225 226 out, err := in.client.InspectExec(id) 227 recordError(operation, err) 228 return out, err 229} 230 231func (in instrumentedInterface) AttachToContainer(id string, opts dockertypes.ContainerAttachOptions, sopts StreamOptions) error { 232 const operation = "attach" 233 defer recordOperation(operation, time.Now()) 234 235 err := in.client.AttachToContainer(id, opts, sopts) 236 recordError(operation, err) 237 return err 238} 239 240func (in instrumentedInterface) ImageHistory(id string) ([]dockerimagetypes.HistoryResponseItem, error) { 241 const operation = "image_history" 242 defer recordOperation(operation, time.Now()) 243 244 out, err := in.client.ImageHistory(id) 245 recordError(operation, err) 246 return out, err 247} 248 249func (in instrumentedInterface) ResizeExecTTY(id string, height, width uint) error { 250 const operation = "resize_exec" 251 defer recordOperation(operation, time.Now()) 252 253 err := in.client.ResizeExecTTY(id, height, width) 254 recordError(operation, err) 255 return err 256} 257 258func (in instrumentedInterface) ResizeContainerTTY(id string, height, width uint) error { 259 const operation = "resize_container" 260 defer recordOperation(operation, time.Now()) 261 262 err := in.client.ResizeContainerTTY(id, height, width) 263 recordError(operation, err) 264 return err 265} 266 267func (in instrumentedInterface) GetContainerStats(id string) (*dockertypes.StatsJSON, error) { 268 const operation = "stats" 269 defer recordOperation(operation, time.Now()) 270 271 out, err := in.client.GetContainerStats(id) 272 recordError(operation, err) 273 return out, err 274} 275