Skip to content
Commits on Source (15)
# [3.39.0](https://gitlab.com/gitlab-org/container-registry/compare/v3.38.0-gitlab...v3.39.0-gitlab) (2022-04-13)
### Bug Fixes
* properly initialize multierror during imports ([3e33781](https://gitlab.com/gitlab-org/container-registry/commit/3e33781a7443a8093bd4069fe8ecaab0b260b6ed))
### Features
* add histogram for counting imported layers per manifest ([7fea14a](https://gitlab.com/gitlab-org/container-registry/commit/7fea14a53021987e4004d514abe6c2f9e340aae4))
* add histogram metric to monitor the number of imported tags ([4eeab85](https://gitlab.com/gitlab-org/container-registry/commit/4eeab85a1a56a30dc68fa06789709f1f28c9d397))
* add histograms for blob transfer durations and byte sizes ([dc959bb](https://gitlab.com/gitlab-org/container-registry/commit/dc959bbd1bd5134db9afd973fecc6ef7250237be))
# [3.38.0](https://gitlab.com/gitlab-org/container-registry/compare/v3.37.1-gitlab...v3.38.0-gitlab) (2022-04-07)
......
......@@ -15,7 +15,7 @@ require (
github.com/dnaeon/go-vcr v1.0.1 // indirect
github.com/docker/go-metrics v0.0.1
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7
github.com/getsentry/sentry-go v0.11.0
github.com/getsentry/sentry-go v0.13.0
github.com/go-redis/redis/v8 v8.11.3
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/mock v1.6.0
......@@ -47,8 +47,6 @@ require (
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac
google.golang.org/api v0.58.0
google.golang.org/genproto v0.0.0-20211011165927-a5fb3255271e // indirect
......
......@@ -194,11 +194,14 @@ github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWo
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc=
github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
github.com/getsentry/sentry-go v0.11.0 h1:qro8uttJGvNAMr5CLcFI9CHR0aDzXl0Vs3Pmw/oTPg8=
github.com/getsentry/sentry-go v0.11.0/go.mod h1:KBQIxiZAetw62Cj8Ri964vAEWVdgfaUCn30Q3bCvANo=
github.com/getsentry/sentry-go v0.13.0 h1:20dgTiUSfxRB/EhMPtxcL9ZEbM1ZdR+W/7f7NWD+xWo=
github.com/getsentry/sentry-go v0.13.0/go.mod h1:EOsfu5ZdvKPfeHYV6pTVQnsjfp30+XA7//UooKNumH0=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
......@@ -213,6 +216,10 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8=
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
github.com/go-redis/redis/v8 v8.11.3 h1:GCjoYp8c+yQTJfc0n69iwSiHjvuAdruxl7elnZCxgt8=
github.com/go-redis/redis/v8 v8.11.3/go.mod h1:xNJ9xDG09FsIPwh3bWdk+0oDWHbtF9rPN0F/oD9XeKc=
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
......@@ -235,6 +242,8 @@ github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRx
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU=
github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
......@@ -473,7 +482,9 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g=
github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y=
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
......@@ -494,12 +505,15 @@ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaO
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-oci8 v0.1.1/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.12 h1:Y41i/hVW3Pgwr8gV+J23B9YEY0zxjptBuCWEaxmAOow=
......@@ -689,6 +703,7 @@ github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKn
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
......@@ -753,6 +768,7 @@ golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
......@@ -847,6 +863,7 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
......@@ -953,6 +970,7 @@ golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac h1:oN6lz7iLW/YC7un8pq+9bOLyXrprv2+DKfkJY+2LJJw=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
......@@ -971,6 +989,7 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs=
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
......
......@@ -15,6 +15,7 @@ import (
v2 "github.com/docker/distribution/registry/api/v2"
"github.com/docker/distribution/registry/datastore/models"
"github.com/docker/distribution/registry/internal/migration"
"github.com/docker/distribution/registry/internal/migration/metrics"
"github.com/docker/distribution/registry/storage/driver"
"github.com/opencontainers/go-digest"
v1 "github.com/opencontainers/image-spec/specs-go/v1"
......@@ -165,7 +166,7 @@ func (imp *Importer) importLayer(ctx context.Context, dbRepo *models.Repository,
return fmt.Errorf("linking layer blob to repository: %w", err)
}
if err := imp.transferBlob(ctx, dbLayer.Digest); err != nil {
if err := imp.transferBlob(ctx, dbLayer.Digest, dbLayer.Size, metrics.BlobTypeLayer); err != nil {
return err
}
......@@ -174,6 +175,8 @@ func (imp *Importer) importLayer(ctx context.Context, dbRepo *models.Repository,
func (imp *Importer) importLayers(ctx context.Context, dbRepo *models.Repository, fsRepo distribution.Repository, dbManifest *models.Manifest, fsLayers []distribution.Descriptor) error {
total := len(fsLayers)
metrics.LayerCount(total)
for i, fsLayer := range fsLayers {
l := log.GetLogger(log.WithContext(ctx)).WithFields(log.Fields{
"repository": dbRepo.Path,
......@@ -204,7 +207,7 @@ func (imp *Importer) importLayers(ctx context.Context, dbRepo *models.Repository
return nil
}
func (imp *Importer) transferBlob(ctx context.Context, d digest.Digest) error {
func (imp *Importer) transferBlob(ctx context.Context, d digest.Digest, size int64, t metrics.BlobType) error {
if imp.dryRun || imp.blobTransferService == nil {
return nil
}
......@@ -218,11 +221,13 @@ func (imp *Importer) transferBlob(ctx context.Context, d digest.Digest) error {
noop = true
}
end := time.Since(start).Seconds()
duration := time.Since(start).Seconds()
metrics.BlobTransfer(duration, float64(size), t)
log.GetLogger(log.WithContext(ctx)).WithFields(log.Fields{
"noop": noop,
"digest": d,
"duration_s": end,
"duration_s": duration,
"blob_type": t.String(),
}).Info("blob transfer complete")
return nil
......@@ -260,7 +265,7 @@ func (imp *Importer) importManifestV2(ctx context.Context, fsRepo distribution.R
return nil, err
}
if err = imp.transferBlob(ctx, m.Config().Digest); err != nil {
if err = imp.transferBlob(ctx, m.Config().Digest, m.Config().Size, metrics.BlobTypeConfig); err != nil {
return nil, err
}
......@@ -448,6 +453,7 @@ func (imp *Importer) importTags(ctx context.Context, fsRepo distribution.Reposit
}
total := len(fsTags)
metrics.TagCount(metrics.ImportTypeFinal, total)
semaphore := make(chan struct{}, imp.tagConcurrency)
tagResChan := make(chan *tagLookupResponse)
......@@ -598,6 +604,7 @@ func (imp *Importer) preImportTaggedManifests(ctx context.Context, fsRepo distri
}
total := len(fsTags)
metrics.TagCount(metrics.ImportTypePre, total)
for i, fsTag := range fsTags {
l := log.GetLogger(log.WithContext(ctx)).WithFields(log.Fields{"repository": dbRepo.Path, "tag_name": fsTag, "count": i + 1, "total": total})
......@@ -760,7 +767,7 @@ func (imp *Importer) ImportAll(ctx context.Context) error {
// Even if we found the blob in the database, try to transfer in case it's
// not present in blob storage on the transfer side.
if err = imp.transferBlob(ctx, desc.Digest); err != nil {
if err = imp.transferBlob(ctx, desc.Digest, desc.Size, metrics.BlobTypeUnknown); err != nil {
return err
}
......
......@@ -614,27 +614,24 @@ func TestGitlabAPI_RepositoryImport_ImportInProgress(t *testing.T) {
}
func TestGitlabAPI_RepositoryImport_Put_PreImportFailed(t *testing.T) {
// FIXME
t.Skip("Skipped, see https://gitlab.com/gitlab-org/container-registry/-/issues/633")
rootDir := t.TempDir()
migrationDir := filepath.Join(rootDir, "/new")
repoPath := "notags/repo"
repoPath := "old/repo"
tagName := "import-tag"
mockedImportNotifSrv := newMockImportNotification(t, repoPath)
env := newTestEnv(t,
withFSDriver(rootDir),
withMigrationEnabled,
withMigrationTestSlowImport(-1),
withMigrationRootDirectory(migrationDir),
withImportNotification(mockImportNotificationServer(t, mockedImportNotifSrv)))
t.Cleanup(env.Shutdown)
env.requireDB(t)
// Push up a image to the old side of the registry, but do not push any tags,
// the pre import will start without error, but the actual pre import will fail.
seedRandomSchema2Manifest(t, env, repoPath, putByDigest, writeToFilesystemOnly)
seedRandomSchema2Manifest(t, env, repoPath, putByTag(tagName), writeToFilesystemOnly)
repoRef, err := reference.WithName(repoPath)
require.NoError(t, err)
......@@ -653,7 +650,7 @@ func TestGitlabAPI_RepositoryImport_Put_PreImportFailed(t *testing.T) {
mockedImportNotifSrv.waitForImportNotification(
t, repoPath, string(migration.RepositoryStatusPreImportFailed),
"pre importing tagged manifests: reading tags: unknown repository name=notags/repo", 2*time.Second,
"negative testing delay", 2*time.Second,
)
importURL, err := env.builder.BuildGitlabV1RepositoryImportURL(repoRef, url.Values{"import_type": []string{"final"}})
......@@ -683,32 +680,10 @@ func TestGitlabAPI_RepositoryImport_Put_PreImportFailed(t *testing.T) {
// an error that could be misleading.
mockedImportNotifSrv.waitForImportNotification(
t, repoPath, string(migration.RepositoryStatusPreImportFailed),
"pre importing tagged manifests: reading tags: unknown repository name=notags/repo", 2*time.Second,
"negative testing delay", 2*time.Second,
)
req, err = http.NewRequest(http.MethodGet, importURL, nil)
require.NoError(t, err)
resp, err = http.DefaultClient.Do(req)
require.NoError(t, err)
defer resp.Body.Close()
require.Equal(t, http.StatusOK, resp.StatusCode)
b, err := io.ReadAll(resp.Body)
require.NoError(t, err)
var s handlers.RepositoryImportStatus
err = json.Unmarshal(b, &s)
require.NoError(t, err)
expectedStatus := handlers.RepositoryImportStatus{
Name: repositoryName(repoPath),
Path: repoPath,
Status: migration.RepositoryStatusPreImportFailed,
}
require.Equal(t, expectedStatus, s)
assertImportStatus(t, importURL, repoPath, migration.RepositoryStatusPreImportFailed, "negative testing delay")
}
func TestGitlabAPI_RepositoryImport_Put_RepositoryNotPresentOnOldSide(t *testing.T) {
......
......@@ -187,7 +187,7 @@ func (ih *importHandler) StartRepositoryImport(w http.ResponseWriter, r *http.Re
dbRepo.MigrationError = sql.NullString{}
}
dbRepo, err = ih.createOrUpdateRepo(ih.Context, dbRepo)
dbRepo, err = ih.createOrUpdateRepo(dbRepo)
if err != nil {
err = errcode.FromUnknownError(err)
ih.Errors = append(ih.Errors, err)
......@@ -203,6 +203,8 @@ func (ih *importHandler) StartRepositoryImport(w http.ResponseWriter, r *http.Re
// See: https://gitlab.com/gitlab-org/container-registry/-/issues/617a
migrationDriver, err := migrationDriver(ih.App.Config)
if err != nil {
// try to update status from `(pre_)import_in_progress` to `(pre_)import_failed` before heading out
ih.updateRepoWithError(ih.Context, dbRepo, err, &multierror.Error{})
err = errcode.FromUnknownError(err)
ih.Errors = append(ih.Errors, err)
......@@ -212,6 +214,8 @@ func (ih *importHandler) StartRepositoryImport(w http.ResponseWriter, r *http.Re
bts, err := storage.NewBlobTransferService(ih.App.driver, migrationDriver)
if err != nil {
// try to update status from `(pre_)import_in_progress` to `(pre_)import_failed` before heading out
ih.updateRepoWithError(ih.Context, dbRepo, err, &multierror.Error{})
err = errcode.FromUnknownError(err)
ih.Errors = append(ih.Errors, err)
......@@ -251,7 +255,7 @@ func (ih *importHandler) StartRepositoryImport(w http.ResponseWriter, r *http.Re
err = ih.runImport(importCtx, importer, dbRepo)
if err != nil {
l.WithError(err).Error("importing repository")
l.WithError(err).Error("repository import failed")
errortracking.Capture(err, errortracking.WithContext(importCtx), errortracking.WithRequest(r))
}
report(true, err)
......@@ -322,7 +326,7 @@ func (ih *importHandler) shouldImport(dbRepo *models.Repository) (bool, error) {
return true, nil
}
func (ih *importHandler) createOrUpdateRepo(ctx context.Context, dbRepo *models.Repository) (*models.Repository, error) {
func (ih *importHandler) createOrUpdateRepo(dbRepo *models.Repository) (*models.Repository, error) {
var status migration.RepositoryStatus
if ih.preImport {
status = migration.RepositoryStatusPreImportInProgress
......@@ -347,7 +351,7 @@ func (ih *importHandler) createOrUpdateRepo(ctx context.Context, dbRepo *models.
}
func (ih *importHandler) runImport(ctx context.Context, importer *datastore.Importer, dbRepo *models.Repository) error {
var multiErrs *multierror.Error
multiErrs := &multierror.Error{}
if ih.preImport {
if err := importer.PreImport(ctx, dbRepo.Path); err != nil {
......
package metrics
import (
"github.com/docker/distribution/metrics"
"github.com/prometheus/client_golang/prometheus"
)
var (
tagCountHist *prometheus.HistogramVec
layerCountHist prometheus.Histogram
blobTransferDurationHist *prometheus.HistogramVec
blobTransferSizeHist *prometheus.HistogramVec
)
const (
subsystem = "migration"
importTypeLabel = "import_type"
blobTypeLabel = "blob_type"
tagCountName = "tag_counts"
tagCountDesc = "A histogram of tag counts per repository (pre)import."
layerCountName = "layer_counts"
layerCountDesc = "A histogram of layer counts per (pre)imported manifest."
blobTransferDurationName = "blob_transfer_duration_seconds"
blobTransferDurationDesc = "A histogram of latencies for blob transfers."
blobTransferSizeName = "blob_transfer_size_bytes"
blobTransferSizeDesc = "A histogram of byte sizes for blob transfers."
)
func init() {
tagCountHist = prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Namespace: metrics.NamespacePrefix,
Subsystem: subsystem,
Name: tagCountName,
Help: tagCountDesc,
Buckets: []float64{0, 1, 2, 5, 10, 25, 50, 100, 250, 500, 1000, 2000, 5000, 10000, 15000, 20000, 50000, 100000},
},
[]string{importTypeLabel},
)
layerCountHist = prometheus.NewHistogram(
prometheus.HistogramOpts{
Namespace: metrics.NamespacePrefix,
Subsystem: subsystem,
Name: layerCountName,
Help: layerCountDesc,
Buckets: []float64{1, 2, 5, 10, 25, 50, 100, 200},
},
)
blobTransferDurationHist = prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Namespace: metrics.NamespacePrefix,
Subsystem: subsystem,
Name: blobTransferDurationName,
Help: blobTransferDurationDesc,
Buckets: prometheus.DefBuckets,
},
[]string{blobTypeLabel},
)
blobTransferSizeHist = prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Namespace: metrics.NamespacePrefix,
Subsystem: subsystem,
Name: blobTransferSizeName,
Help: blobTransferSizeDesc,
Buckets: []float64{
512 * 1024, // 512KiB
1024 * 1024, // 1MiB
1024 * 1024 * 64, // 64MiB
1024 * 1024 * 128, // 128MiB
1024 * 1024 * 256, // 256MiB
1024 * 1024 * 512, // 512MiB
1024 * 1024 * 1024, // 1GiB
1024 * 1024 * 1024 * 2, // 2GiB
1024 * 1024 * 1024 * 3, // 3GiB
1024 * 1024 * 1024 * 4, // 4GiB
1024 * 1024 * 1024 * 5, // 5GiB
1024 * 1024 * 1024 * 6, // 6GiB
1024 * 1024 * 1024 * 7, // 7GiB
1024 * 1024 * 1024 * 8, // 8GiB
1024 * 1024 * 1024 * 9, // 9GiB
1024 * 1024 * 1024 * 10, // 10GiB
1024 * 1024 * 1024 * 20, // 20GiB
1024 * 1024 * 1024 * 30, // 30GiB
1024 * 1024 * 1024 * 40, // 40GiB
1024 * 1024 * 1024 * 50, // 50GiB
},
},
[]string{blobTypeLabel},
)
prometheus.MustRegister(tagCountHist)
prometheus.MustRegister(layerCountHist)
prometheus.MustRegister(blobTransferDurationHist)
prometheus.MustRegister(blobTransferSizeHist)
}
type importType string
const (
ImportTypePre importType = "pre"
ImportTypeFinal importType = "final"
)
func (t importType) String() string {
return string(t)
}
func TagCount(t importType, count int) {
tagCountHist.WithLabelValues(t.String()).Observe(float64(count))
}
func LayerCount(count int) {
layerCountHist.Observe(float64(count))
}
type BlobType string
const (
BlobTypeConfig BlobType = "config"
BlobTypeLayer BlobType = "layer"
BlobTypeUnknown BlobType = "unknown"
)
func (t BlobType) String() string {
return string(t)
}
func BlobTransfer(duration float64, size float64, t BlobType) {
blobTransferDurationHist.WithLabelValues(t.String()).Observe(duration)
blobTransferSizeHist.WithLabelValues(t.String()).Observe(size)
}
package metrics
import (
"bytes"
"fmt"
"testing"
"github.com/docker/distribution/metrics"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/testutil"
"github.com/stretchr/testify/require"
)
func TestTagCount(t *testing.T) {
TagCount(ImportTypePre, 10)
TagCount(ImportTypeFinal, 9)
var expected bytes.Buffer
expected.WriteString(`
# HELP registry_migration_tag_counts A histogram of tag counts per repository (pre)import.
# TYPE registry_migration_tag_counts histogram
registry_migration_tag_counts_bucket{import_type="final",le="0"} 0
registry_migration_tag_counts_bucket{import_type="final",le="1"} 0
registry_migration_tag_counts_bucket{import_type="final",le="2"} 0
registry_migration_tag_counts_bucket{import_type="final",le="5"} 0
registry_migration_tag_counts_bucket{import_type="final",le="10"} 1
registry_migration_tag_counts_bucket{import_type="final",le="25"} 1
registry_migration_tag_counts_bucket{import_type="final",le="50"} 1
registry_migration_tag_counts_bucket{import_type="final",le="100"} 1
registry_migration_tag_counts_bucket{import_type="final",le="250"} 1
registry_migration_tag_counts_bucket{import_type="final",le="500"} 1
registry_migration_tag_counts_bucket{import_type="final",le="1000"} 1
registry_migration_tag_counts_bucket{import_type="final",le="2000"} 1
registry_migration_tag_counts_bucket{import_type="final",le="5000"} 1
registry_migration_tag_counts_bucket{import_type="final",le="10000"} 1
registry_migration_tag_counts_bucket{import_type="final",le="15000"} 1
registry_migration_tag_counts_bucket{import_type="final",le="20000"} 1
registry_migration_tag_counts_bucket{import_type="final",le="50000"} 1
registry_migration_tag_counts_bucket{import_type="final",le="100000"} 1
registry_migration_tag_counts_bucket{import_type="final",le="+Inf"} 1
registry_migration_tag_counts_sum{import_type="final"} 9
registry_migration_tag_counts_count{import_type="final"} 1
registry_migration_tag_counts_bucket{import_type="pre",le="0"} 0
registry_migration_tag_counts_bucket{import_type="pre",le="1"} 0
registry_migration_tag_counts_bucket{import_type="pre",le="2"} 0
registry_migration_tag_counts_bucket{import_type="pre",le="5"} 0
registry_migration_tag_counts_bucket{import_type="pre",le="10"} 1
registry_migration_tag_counts_bucket{import_type="pre",le="25"} 1
registry_migration_tag_counts_bucket{import_type="pre",le="50"} 1
registry_migration_tag_counts_bucket{import_type="pre",le="100"} 1
registry_migration_tag_counts_bucket{import_type="pre",le="250"} 1
registry_migration_tag_counts_bucket{import_type="pre",le="500"} 1
registry_migration_tag_counts_bucket{import_type="pre",le="1000"} 1
registry_migration_tag_counts_bucket{import_type="pre",le="2000"} 1
registry_migration_tag_counts_bucket{import_type="pre",le="5000"} 1
registry_migration_tag_counts_bucket{import_type="pre",le="10000"} 1
registry_migration_tag_counts_bucket{import_type="pre",le="15000"} 1
registry_migration_tag_counts_bucket{import_type="pre",le="20000"} 1
registry_migration_tag_counts_bucket{import_type="pre",le="50000"} 1
registry_migration_tag_counts_bucket{import_type="pre",le="100000"} 1
registry_migration_tag_counts_bucket{import_type="pre",le="+Inf"} 1
registry_migration_tag_counts_sum{import_type="pre"} 10
registry_migration_tag_counts_count{import_type="pre"} 1
`)
CountsFullName := fmt.Sprintf("%s_%s_%s", metrics.NamespacePrefix, subsystem, tagCountName)
err := testutil.GatherAndCompare(prometheus.DefaultGatherer, &expected, CountsFullName)
require.NoError(t, err)
}
func TestLayerCount(t *testing.T) {
LayerCount(1)
LayerCount(100)
var expected bytes.Buffer
expected.WriteString(`
# HELP registry_migration_layer_counts A histogram of layer counts per (pre)imported manifest.
# TYPE registry_migration_layer_counts histogram
registry_migration_layer_counts_bucket{le="1"} 1
registry_migration_layer_counts_bucket{le="2"} 1
registry_migration_layer_counts_bucket{le="5"} 1
registry_migration_layer_counts_bucket{le="10"} 1
registry_migration_layer_counts_bucket{le="25"} 1
registry_migration_layer_counts_bucket{le="50"} 1
registry_migration_layer_counts_bucket{le="100"} 2
registry_migration_layer_counts_bucket{le="200"} 2
registry_migration_layer_counts_bucket{le="+Inf"} 2
registry_migration_layer_counts_sum 101
registry_migration_layer_counts_count 2
`)
CountFullName := fmt.Sprintf("%s_%s_%s", metrics.NamespacePrefix, subsystem, layerCountName)
err := testutil.GatherAndCompare(prometheus.DefaultGatherer, &expected, CountFullName)
require.NoError(t, err)
}
func TestBlobTransfer(t *testing.T) {
BlobTransfer(.1, 34234123, BlobTypeLayer)
BlobTransfer(0.25, 7754, BlobTypeConfig)
BlobTransfer(0.4, 5351258, BlobTypeUnknown)
var expected bytes.Buffer
expected.WriteString(`
# HELP registry_migration_blob_transfer_duration_seconds A histogram of latencies for blob transfers.
# TYPE registry_migration_blob_transfer_duration_seconds histogram
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="config",le="0.005"} 0
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="config",le="0.01"} 0
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="config",le="0.025"} 0
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="config",le="0.05"} 0
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="config",le="0.1"} 0
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="config",le="0.25"} 1
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="config",le="0.5"} 1
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="config",le="1"} 1
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="config",le="2.5"} 1
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="config",le="5"} 1
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="config",le="10"} 1
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="config",le="+Inf"} 1
registry_migration_blob_transfer_duration_seconds_sum{blob_type="config"} 0.25
registry_migration_blob_transfer_duration_seconds_count{blob_type="config"} 1
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="layer",le="0.005"} 0
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="layer",le="0.01"} 0
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="layer",le="0.025"} 0
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="layer",le="0.05"} 0
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="layer",le="0.1"} 1
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="layer",le="0.25"} 1
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="layer",le="0.5"} 1
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="layer",le="1"} 1
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="layer",le="2.5"} 1
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="layer",le="5"} 1
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="layer",le="10"} 1
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="layer",le="+Inf"} 1
registry_migration_blob_transfer_duration_seconds_sum{blob_type="layer"} 0.1
registry_migration_blob_transfer_duration_seconds_count{blob_type="layer"} 1
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="unknown",le="0.005"} 0
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="unknown",le="0.01"} 0
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="unknown",le="0.025"} 0
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="unknown",le="0.05"} 0
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="unknown",le="0.1"} 0
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="unknown",le="0.25"} 0
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="unknown",le="0.5"} 1
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="unknown",le="1"} 1
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="unknown",le="2.5"} 1
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="unknown",le="5"} 1
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="unknown",le="10"} 1
registry_migration_blob_transfer_duration_seconds_bucket{blob_type="unknown",le="+Inf"} 1
registry_migration_blob_transfer_duration_seconds_sum{blob_type="unknown"} 0.4
registry_migration_blob_transfer_duration_seconds_count{blob_type="unknown"} 1
# HELP registry_migration_blob_transfer_size_bytes A histogram of byte sizes for blob transfers.
# TYPE registry_migration_blob_transfer_size_bytes histogram
registry_migration_blob_transfer_size_bytes_bucket{blob_type="config",le="524288"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="config",le="1.048576e+06"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="config",le="6.7108864e+07"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="config",le="1.34217728e+08"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="config",le="2.68435456e+08"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="config",le="5.36870912e+08"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="config",le="1.073741824e+09"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="config",le="2.147483648e+09"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="config",le="3.221225472e+09"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="config",le="4.294967296e+09"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="config",le="5.36870912e+09"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="config",le="6.442450944e+09"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="config",le="7.516192768e+09"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="config",le="8.589934592e+09"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="config",le="9.663676416e+09"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="config",le="1.073741824e+10"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="config",le="2.147483648e+10"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="config",le="3.221225472e+10"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="config",le="4.294967296e+10"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="config",le="5.36870912e+10"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="config",le="+Inf"} 1
registry_migration_blob_transfer_size_bytes_sum{blob_type="config"} 7754
registry_migration_blob_transfer_size_bytes_count{blob_type="config"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="layer",le="524288"} 0
registry_migration_blob_transfer_size_bytes_bucket{blob_type="layer",le="1.048576e+06"} 0
registry_migration_blob_transfer_size_bytes_bucket{blob_type="layer",le="6.7108864e+07"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="layer",le="1.34217728e+08"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="layer",le="2.68435456e+08"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="layer",le="5.36870912e+08"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="layer",le="1.073741824e+09"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="layer",le="2.147483648e+09"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="layer",le="3.221225472e+09"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="layer",le="4.294967296e+09"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="layer",le="5.36870912e+09"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="layer",le="6.442450944e+09"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="layer",le="7.516192768e+09"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="layer",le="8.589934592e+09"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="layer",le="9.663676416e+09"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="layer",le="1.073741824e+10"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="layer",le="2.147483648e+10"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="layer",le="3.221225472e+10"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="layer",le="4.294967296e+10"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="layer",le="5.36870912e+10"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="layer",le="+Inf"} 1
registry_migration_blob_transfer_size_bytes_sum{blob_type="layer"} 3.4234123e+07
registry_migration_blob_transfer_size_bytes_count{blob_type="layer"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="unknown",le="524288"} 0
registry_migration_blob_transfer_size_bytes_bucket{blob_type="unknown",le="1.048576e+06"} 0
registry_migration_blob_transfer_size_bytes_bucket{blob_type="unknown",le="6.7108864e+07"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="unknown",le="1.34217728e+08"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="unknown",le="2.68435456e+08"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="unknown",le="5.36870912e+08"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="unknown",le="1.073741824e+09"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="unknown",le="2.147483648e+09"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="unknown",le="3.221225472e+09"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="unknown",le="4.294967296e+09"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="unknown",le="5.36870912e+09"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="unknown",le="6.442450944e+09"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="unknown",le="7.516192768e+09"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="unknown",le="8.589934592e+09"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="unknown",le="9.663676416e+09"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="unknown",le="1.073741824e+10"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="unknown",le="2.147483648e+10"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="unknown",le="3.221225472e+10"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="unknown",le="4.294967296e+10"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="unknown",le="5.36870912e+10"} 1
registry_migration_blob_transfer_size_bytes_bucket{blob_type="unknown",le="+Inf"} 1
registry_migration_blob_transfer_size_bytes_sum{blob_type="unknown"} 5.351258e+06
registry_migration_blob_transfer_size_bytes_count{blob_type="unknown"} 1
`)
durationFullName := fmt.Sprintf("%s_%s_%s", metrics.NamespacePrefix, subsystem, blobTransferDurationName)
sizeFullName := fmt.Sprintf("%s_%s_%s", metrics.NamespacePrefix, subsystem, blobTransferSizeName)
err := testutil.GatherAndCompare(prometheus.DefaultGatherer, &expected, durationFullName, sizeFullName)
require.NoError(t, err)
}