Get kind from runtime.Object. Unify metric names (#91041)

* Normalize name labels

* Access kind

* Read kind from the runtime object instead from the options object

* use kind from object on create
This commit is contained in:
Leonor Oliveira 2024-07-29 08:58:48 +01:00 committed by GitHub
parent a7679b5f8d
commit 6a1e835f12
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 189 additions and 79 deletions

View File

@ -37,17 +37,18 @@ func (d *DualWriterMode1) Mode() DualWriterMode {
// Create overrides the behavior of the generic DualWriter and writes only to LegacyStorage.
func (d *DualWriterMode1) Create(ctx context.Context, original runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) {
var method = "create"
log := d.Log.WithValues("kind", options.Kind, "method", method)
var kind = original.GetObjectKind().GroupVersionKind().Kind
log := d.Log.WithValues("method", method, "kind", kind)
ctx = klog.NewContext(ctx, log)
startLegacy := time.Now()
created, err := d.Legacy.Create(ctx, original, createValidation, options)
if err != nil {
log.Error(err, "unable to create object in legacy storage")
d.recordLegacyDuration(true, mode1Str, options.Kind, method, startLegacy)
d.recordLegacyDuration(true, mode1Str, kind, method, startLegacy)
return created, err
}
d.recordLegacyDuration(false, mode1Str, options.Kind, method, startLegacy)
d.recordLegacyDuration(false, mode1Str, kind, method, startLegacy)
createdCopy := created.DeepCopyObject()
@ -61,7 +62,7 @@ func (d *DualWriterMode1) Create(ctx context.Context, original runtime.Object, c
startStorage := time.Now()
storageObj, errObjectSt := d.Storage.Create(ctx, createdCopy, createValidation, options)
d.recordStorageDuration(errObjectSt != nil, mode1Str, options.Kind, method, startStorage)
d.recordStorageDuration(errObjectSt != nil, mode1Str, kind, method, startStorage)
if err != nil {
cancel()
}
@ -78,7 +79,7 @@ func (d *DualWriterMode1) Create(ctx context.Context, original runtime.Object, c
// Get overrides the behavior of the generic DualWriter and reads only from LegacyStorage.
func (d *DualWriterMode1) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
var method = "get"
log := d.Log.WithValues("kind", options.Kind, "method", method, "name", name)
log := d.Log.WithValues("method", method, "name", name)
ctx = klog.NewContext(ctx, log)
startLegacy := time.Now()
@ -86,14 +87,19 @@ func (d *DualWriterMode1) Get(ctx context.Context, name string, options *metav1.
if errLegacy != nil {
log.Error(errLegacy, "unable to get object in legacy storage")
}
d.recordLegacyDuration(errLegacy != nil, mode1Str, options.Kind, method, startLegacy)
var kind string
if res != nil {
kind = res.GetObjectKind().GroupVersionKind().Kind
}
d.recordLegacyDuration(errLegacy != nil, mode1Str, kind, method, startLegacy)
go func(res runtime.Object) {
startStorage := time.Now()
ctx, cancel := context.WithTimeoutCause(ctx, time.Second*10, errors.New("storage get timeout"))
defer cancel()
storageObj, err := d.Storage.Get(ctx, name, options)
d.recordStorageDuration(err != nil, mode1Str, options.Kind, method, startStorage)
d.recordStorageDuration(err != nil, mode1Str, kind, method, startStorage)
if err != nil {
log.Error(err, "unable to get object in storage")
cancel()
@ -112,7 +118,7 @@ func (d *DualWriterMode1) Get(ctx context.Context, name string, options *metav1.
// List overrides the behavior of the generic DualWriter and reads only from LegacyStorage.
func (d *DualWriterMode1) List(ctx context.Context, options *metainternalversion.ListOptions) (runtime.Object, error) {
var method = "list"
log := d.Log.WithValues("kind", options.Kind, "resourceVersion", options.ResourceVersion, "kind", options.Kind, "method", method)
log := d.Log.WithValues("resourceVersion", options.ResourceVersion, "method", method)
ctx = klog.NewContext(ctx, log)
startLegacy := time.Now()
@ -120,14 +126,18 @@ func (d *DualWriterMode1) List(ctx context.Context, options *metainternalversion
if errLegacy != nil {
log.Error(errLegacy, "unable to list object in legacy storage")
}
d.recordLegacyDuration(errLegacy != nil, mode1Str, options.Kind, method, startLegacy)
var kind string
if res != nil {
kind = res.GetObjectKind().GroupVersionKind().Kind
}
d.recordLegacyDuration(errLegacy != nil, mode1Str, kind, method, startLegacy)
go func(res runtime.Object) {
startStorage := time.Now()
ctx, cancel := context.WithTimeoutCause(ctx, time.Second*10, errors.New("storage list timeout"))
defer cancel()
storageObj, err := d.Storage.List(ctx, options)
d.recordStorageDuration(err != nil, mode1Str, options.Kind, method, startStorage)
d.recordStorageDuration(err != nil, mode1Str, kind, method, startStorage)
if err != nil {
cancel()
}
@ -143,14 +153,18 @@ func (d *DualWriterMode1) List(ctx context.Context, options *metainternalversion
func (d *DualWriterMode1) Delete(ctx context.Context, name string, deleteValidation rest.ValidateObjectFunc, options *metav1.DeleteOptions) (runtime.Object, bool, error) {
var method = "delete"
log := d.Log.WithValues("name", name, "kind", options.Kind, "method", method, "name", name)
log := d.Log.WithValues("name", name, "method", method, "name", name)
ctx = klog.NewContext(ctx, d.Log)
startLegacy := time.Now()
res, async, err := d.Legacy.Delete(ctx, name, deleteValidation, options)
var kind string
if res != nil {
kind = res.GetObjectKind().GroupVersionKind().Kind
}
if err != nil {
log.Error(err, "unable to delete object in legacy storage")
d.recordLegacyDuration(true, mode1Str, options.Kind, method, startLegacy)
d.recordLegacyDuration(true, mode1Str, kind, method, startLegacy)
return res, async, err
}
d.recordLegacyDuration(false, mode1Str, name, method, startLegacy)
@ -160,7 +174,7 @@ func (d *DualWriterMode1) Delete(ctx context.Context, name string, deleteValidat
ctx, cancel := context.WithTimeoutCause(ctx, time.Second*10, errors.New("storage delete timeout"))
defer cancel()
storageObj, _, err := d.Storage.Delete(ctx, name, deleteValidation, options)
d.recordStorageDuration(err != nil, mode1Str, options.Kind, method, startStorage)
d.recordStorageDuration(err != nil, mode1Str, kind, method, startStorage)
if err != nil {
cancel()
}
@ -177,24 +191,28 @@ func (d *DualWriterMode1) Delete(ctx context.Context, name string, deleteValidat
// DeleteCollection overrides the behavior of the generic DualWriter and deletes only from LegacyStorage.
func (d *DualWriterMode1) DeleteCollection(ctx context.Context, deleteValidation rest.ValidateObjectFunc, options *metav1.DeleteOptions, listOptions *metainternalversion.ListOptions) (runtime.Object, error) {
var method = "delete-collection"
log := d.Log.WithValues("kind", options.Kind, "resourceVersion", listOptions.ResourceVersion, "method", method)
log := d.Log.WithValues("resourceVersion", listOptions.ResourceVersion, "method", method)
ctx = klog.NewContext(ctx, log)
var kind string
startLegacy := time.Now()
res, err := d.Legacy.DeleteCollection(ctx, deleteValidation, options, listOptions)
if res != nil {
kind = res.GetObjectKind().GroupVersionKind().Kind
}
if err != nil {
log.Error(err, "unable to delete collection in legacy storage")
d.recordLegacyDuration(true, mode1Str, options.Kind, method, startLegacy)
d.recordLegacyDuration(true, mode1Str, kind, method, startLegacy)
return res, err
}
d.recordLegacyDuration(false, mode1Str, options.Kind, method, startLegacy)
d.recordLegacyDuration(false, mode1Str, kind, method, startLegacy)
go func(res runtime.Object) {
startStorage := time.Now()
ctx, cancel := context.WithTimeoutCause(ctx, time.Second*10, errors.New("storage deletecollection timeout"))
defer cancel()
storageObj, err := d.Storage.DeleteCollection(ctx, deleteValidation, options, listOptions)
d.recordStorageDuration(err != nil, mode1Str, options.Kind, method, startStorage)
d.recordStorageDuration(err != nil, mode1Str, kind, method, startStorage)
if err != nil {
cancel()
}
@ -210,17 +228,21 @@ func (d *DualWriterMode1) DeleteCollection(ctx context.Context, deleteValidation
func (d *DualWriterMode1) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool, options *metav1.UpdateOptions) (runtime.Object, bool, error) {
var method = "update"
log := d.Log.WithValues("name", name, "kind", options.Kind, "method", method, "name", name)
log := d.Log.WithValues("name", name, "method", method, "name", name)
ctx = klog.NewContext(ctx, log)
var kind string
startLegacy := time.Now()
res, async, err := d.Legacy.Update(ctx, name, objInfo, createValidation, updateValidation, forceAllowCreate, options)
if res != nil {
kind = res.GetObjectKind().GroupVersionKind().Kind
}
if err != nil {
log.Error(err, "unable to update in legacy storage")
d.recordLegacyDuration(true, mode1Str, options.Kind, method, startLegacy)
d.recordLegacyDuration(true, mode1Str, kind, method, startLegacy)
return res, async, err
}
d.recordLegacyDuration(false, mode1Str, options.Kind, method, startLegacy)
d.recordLegacyDuration(false, mode1Str, kind, method, startLegacy)
go func(res runtime.Object) {
ctx, cancel := context.WithTimeoutCause(ctx, time.Second*10, errors.New("storage update timeout"))
@ -256,7 +278,7 @@ func (d *DualWriterMode1) Update(ctx context.Context, name string, objInfo rest.
startStorage := time.Now()
defer cancel()
storageObj, _, errObjectSt := d.Storage.Update(ctx, name, objInfo, createValidation, updateValidation, forceAllowCreate, options)
d.recordStorageDuration(errObjectSt != nil, mode1Str, options.Kind, method, startStorage)
d.recordStorageDuration(errObjectSt != nil, mode1Str, kind, method, startStorage)
if err != nil {
cancel()
}

View File

@ -40,17 +40,18 @@ func (d *DualWriterMode2) Mode() DualWriterMode {
// Create overrides the behavior of the generic DualWriter and writes to LegacyStorage and Storage.
func (d *DualWriterMode2) Create(ctx context.Context, original runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) {
var method = "create"
log := d.Log.WithValues("kind", options.Kind, "method", method)
var kind = original.GetObjectKind().GroupVersionKind().Kind
log := d.Log.WithValues("method", method, "kind", kind)
ctx = klog.NewContext(ctx, log)
startLegacy := time.Now()
created, err := d.Legacy.Create(ctx, original, createValidation, options)
if err != nil {
log.Error(err, "unable to create object in legacy storage")
d.recordLegacyDuration(true, mode2Str, options.Kind, method, startLegacy)
d.recordLegacyDuration(true, mode2Str, kind, method, startLegacy)
return created, err
}
d.recordLegacyDuration(false, mode2Str, options.Kind, method, startLegacy)
d.recordLegacyDuration(false, mode2Str, kind, method, startLegacy)
if err := enrichLegacyObject(original, created); err != nil {
return created, err
@ -60,10 +61,10 @@ func (d *DualWriterMode2) Create(ctx context.Context, original runtime.Object, c
rsp, err := d.Storage.Create(ctx, created, createValidation, options)
if err != nil {
log.WithValues("name").Error(err, "unable to create object in storage")
d.recordStorageDuration(true, mode2Str, options.Kind, method, startStorage)
d.recordStorageDuration(true, mode2Str, kind, method, startStorage)
return rsp, err
}
d.recordStorageDuration(false, mode2Str, options.Kind, method, startStorage)
d.recordStorageDuration(false, mode2Str, kind, method, startStorage)
areEqual := Compare(rsp, created)
d.recordOutcome(mode2Str, getName(rsp), areEqual, method)
@ -76,12 +77,17 @@ func (d *DualWriterMode2) Create(ctx context.Context, original runtime.Object, c
// It retrieves an object from Storage if possible, and if not it falls back to LegacyStorage.
func (d *DualWriterMode2) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
var method = "get"
log := d.Log.WithValues("name", name, "resourceVersion", options.ResourceVersion, "kind", options.Kind, "method", method)
log := d.Log.WithValues("name", name, "resourceVersion", options.ResourceVersion, "method", method)
ctx = klog.NewContext(ctx, log)
startStorage := time.Now()
objStorage, err := d.Storage.Get(ctx, name, options)
d.recordStorageDuration(err != nil, mode2Str, options.Kind, method, startStorage)
var kind string
if objStorage != nil {
kind = objStorage.GetObjectKind().GroupVersionKind().Kind
}
d.recordStorageDuration(err != nil, mode2Str, kind, method, startStorage)
if err != nil {
// if it errors because it's not found, we try to fetch it from the legacy storage
if !apierrors.IsNotFound(err) {
@ -95,10 +101,10 @@ func (d *DualWriterMode2) Get(ctx context.Context, name string, options *metav1.
objLegacy, err := d.Legacy.Get(ctx, name, options)
if err != nil {
log.Error(err, "unable to fetch object from legacy")
d.recordLegacyDuration(true, mode2Str, options.Kind, method, startLegacy)
d.recordLegacyDuration(true, mode2Str, kind, method, startLegacy)
return objLegacy, err
}
d.recordLegacyDuration(false, mode2Str, options.Kind, method, startLegacy)
d.recordLegacyDuration(false, mode2Str, kind, method, startLegacy)
areEqual := Compare(objStorage, objLegacy)
d.recordOutcome(mode2Str, name, areEqual, method)
@ -117,17 +123,21 @@ func (d *DualWriterMode2) Get(ctx context.Context, name string, options *metav1.
// It returns Storage entries if possible and falls back to LegacyStorage entries if not.
func (d *DualWriterMode2) List(ctx context.Context, options *metainternalversion.ListOptions) (runtime.Object, error) {
var method = "list"
log := d.Log.WithValues("kind", options.Kind, "resourceVersion", options.ResourceVersion, "kind", options.Kind, "method", method)
log := d.Log.WithValues("resourceVersion", options.ResourceVersion, "method", method)
ctx = klog.NewContext(ctx, log)
startLegacy := time.Now()
ll, err := d.Legacy.List(ctx, options)
var kind string
if ll != nil {
kind = ll.GetObjectKind().GroupVersionKind().Kind
}
if err != nil {
log.Error(err, "unable to list objects from legacy storage")
d.recordLegacyDuration(true, mode2Str, options.Kind, method, startLegacy)
d.recordLegacyDuration(true, mode2Str, kind, method, startLegacy)
return ll, err
}
d.recordLegacyDuration(false, mode2Str, options.Kind, method, startLegacy)
d.recordLegacyDuration(false, mode2Str, kind, method, startLegacy)
legacyList, err := meta.ExtractList(ll)
if err != nil {
@ -150,10 +160,10 @@ func (d *DualWriterMode2) List(ctx context.Context, options *metainternalversion
sl, err := d.Storage.List(ctx, &optionsStorage)
if err != nil {
log.Error(err, "unable to list objects from storage")
d.recordStorageDuration(true, mode2Str, options.Kind, method, startStorage)
d.recordStorageDuration(true, mode2Str, kind, method, startStorage)
return sl, err
}
d.recordStorageDuration(false, mode2Str, options.Kind, method, startStorage)
d.recordStorageDuration(false, mode2Str, kind, method, startStorage)
storageList, err := meta.ExtractList(sl)
if err != nil {
@ -192,17 +202,21 @@ func (d *DualWriterMode2) List(ctx context.Context, options *metainternalversion
// DeleteCollection overrides the behavior of the generic DualWriter and deletes from both LegacyStorage and Storage.
func (d *DualWriterMode2) DeleteCollection(ctx context.Context, deleteValidation rest.ValidateObjectFunc, options *metav1.DeleteOptions, listOptions *metainternalversion.ListOptions) (runtime.Object, error) {
var method = "delete-collection"
log := d.Log.WithValues("kind", options.Kind, "resourceVersion", listOptions.ResourceVersion, "method", method)
log := d.Log.WithValues("resourceVersion", listOptions.ResourceVersion, "method", method)
ctx = klog.NewContext(ctx, log)
var kind string
startLegacy := time.Now()
deleted, err := d.Legacy.DeleteCollection(ctx, deleteValidation, options, listOptions)
if deleted != nil {
kind = deleted.GetObjectKind().GroupVersionKind().Kind
}
if err != nil {
log.WithValues("deleted", deleted).Error(err, "failed to delete collection successfully from legacy storage")
d.recordLegacyDuration(true, mode2Str, options.Kind, method, startLegacy)
d.recordLegacyDuration(true, mode2Str, kind, method, startLegacy)
return deleted, err
}
d.recordLegacyDuration(false, mode2Str, options.Kind, method, startLegacy)
d.recordLegacyDuration(false, mode2Str, kind, method, startLegacy)
legacyList, err := meta.ExtractList(deleted)
if err != nil {
@ -223,10 +237,10 @@ func (d *DualWriterMode2) DeleteCollection(ctx context.Context, deleteValidation
res, err := d.Storage.DeleteCollection(ctx, deleteValidation, options, &optionsStorage)
if err != nil {
log.WithValues("deleted", res).Error(err, "failed to delete collection successfully from Storage")
d.recordStorageDuration(true, mode2Str, options.Kind, method, startStorage)
d.recordStorageDuration(true, mode2Str, kind, method, startStorage)
return res, err
}
d.recordStorageDuration(false, mode2Str, options.Kind, method, startStorage)
d.recordStorageDuration(false, mode2Str, kind, method, startStorage)
areEqual := Compare(res, deleted)
d.recordOutcome(mode2Str, getName(res), areEqual, method)
@ -239,30 +253,35 @@ func (d *DualWriterMode2) DeleteCollection(ctx context.Context, deleteValidation
func (d *DualWriterMode2) Delete(ctx context.Context, name string, deleteValidation rest.ValidateObjectFunc, options *metav1.DeleteOptions) (runtime.Object, bool, error) {
var method = "delete"
log := d.Log.WithValues("name", name, "kind", options.Kind, "method", method)
log := d.Log.WithValues("name", name, "method", method)
ctx = klog.NewContext(ctx, log)
var kind string
startLegacy := time.Now()
deletedLS, async, err := d.Legacy.Delete(ctx, name, deleteValidation, options)
if deletedLS != nil {
kind = deletedLS.GetObjectKind().GroupVersionKind().Kind
}
if err != nil {
if !apierrors.IsNotFound(err) {
log.WithValues("objectList", deletedLS).Error(err, "could not delete from legacy store")
d.recordLegacyDuration(true, mode2Str, options.Kind, method, startLegacy)
d.recordLegacyDuration(true, mode2Str, kind, method, startLegacy)
return deletedLS, async, err
}
}
d.recordLegacyDuration(false, mode2Str, options.Kind, method, startLegacy)
d.recordLegacyDuration(false, mode2Str, kind, method, startLegacy)
startStorage := time.Now()
deletedS, _, err := d.Storage.Delete(ctx, name, deleteValidation, options)
if err != nil {
if !apierrors.IsNotFound(err) {
log.WithValues("objectList", deletedS).Error(err, "could not delete from duplicate storage")
d.recordStorageDuration(true, mode2Str, options.Kind, method, startStorage)
d.recordStorageDuration(true, mode2Str, kind, method, startStorage)
}
return deletedS, async, err
}
d.recordStorageDuration(false, mode2Str, options.Kind, method, startStorage)
d.recordStorageDuration(false, mode2Str, kind, method, startStorage)
areEqual := Compare(deletedS, deletedLS)
d.recordOutcome(mode2Str, name, areEqual, method)
@ -276,11 +295,15 @@ func (d *DualWriterMode2) Delete(ctx context.Context, name string, deleteValidat
// Update overrides the generic behavior of the Storage and writes first to the legacy storage and then to storage.
func (d *DualWriterMode2) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool, options *metav1.UpdateOptions) (runtime.Object, bool, error) {
var method = "update"
log := d.Log.WithValues("name", name, "kind", options.Kind, "method", method)
log := d.Log.WithValues("name", name, "method", method)
ctx = klog.NewContext(ctx, log)
var kind string
// get foundObj and (updated) object so they can be stored in legacy store
foundObj, err := d.Storage.Get(ctx, name, &metav1.GetOptions{})
if foundObj != nil {
kind = foundObj.GetObjectKind().GroupVersionKind().Kind
}
if err != nil {
if !apierrors.IsNotFound(err) {
log.WithValues("object", foundObj).Error(err, "could not get object to update")
@ -291,6 +314,9 @@ func (d *DualWriterMode2) Update(ctx context.Context, name string, objInfo rest.
// obj can be populated in case it's found or empty in case it's not found
updated, err := objInfo.UpdatedObject(ctx, foundObj)
if updated != nil {
kind = updated.GetObjectKind().GroupVersionKind().Kind
}
if err != nil {
log.WithValues("object", updated).Error(err, "could not update or create object")
return nil, false, err
@ -300,10 +326,10 @@ func (d *DualWriterMode2) Update(ctx context.Context, name string, objInfo rest.
obj, created, err := d.Legacy.Update(ctx, name, &updateWrapper{upstream: objInfo, updated: updated}, createValidation, updateValidation, forceAllowCreate, options)
if err != nil {
log.WithValues("object", obj).Error(err, "could not update in legacy storage")
d.recordLegacyDuration(true, mode2Str, options.Kind, "update", startLegacy)
d.recordLegacyDuration(true, mode2Str, kind, "update", startLegacy)
return obj, created, err
}
d.recordLegacyDuration(false, mode2Str, options.Kind, "update", startLegacy)
d.recordLegacyDuration(false, mode2Str, kind, "update", startLegacy)
// if the object is found, create a new updateWrapper with the object found
if foundObj != nil {
@ -322,7 +348,7 @@ func (d *DualWriterMode2) Update(ctx context.Context, name string, objInfo rest.
res, created, err := d.Storage.Update(ctx, name, objInfo, createValidation, updateValidation, forceAllowCreate, options)
if err != nil {
log.WithValues("object", res).Error(err, "could not update in storage")
d.recordStorageDuration(true, mode2Str, options.Kind, "update", startStorage)
d.recordStorageDuration(true, mode2Str, kind, "update", startStorage)
return res, created, err
}

View File

@ -35,17 +35,18 @@ const mode3Str = "3"
// Create overrides the behavior of the generic DualWriter and writes to LegacyStorage and Storage.
func (d *DualWriterMode3) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) {
var method = "create"
log := d.Log.WithValues("kind", options.Kind, "method", method)
var kind = obj.GetObjectKind().GroupVersionKind().Kind
log := d.Log.WithValues("kind", kind, "method", method)
ctx = klog.NewContext(ctx, log)
startStorage := time.Now()
created, err := d.Storage.Create(ctx, obj, createValidation, options)
if err != nil {
log.Error(err, "unable to create object in storage")
d.recordLegacyDuration(true, mode3Str, options.Kind, method, startStorage)
d.recordLegacyDuration(true, mode3Str, kind, method, startStorage)
return created, err
}
d.recordStorageDuration(false, mode3Str, options.Kind, method, startStorage)
d.recordStorageDuration(false, mode3Str, kind, method, startStorage)
go func() {
ctx, cancel := context.WithTimeoutCause(ctx, time.Second*10, errors.New("legacy create timeout"))
@ -53,7 +54,7 @@ func (d *DualWriterMode3) Create(ctx context.Context, obj runtime.Object, create
startLegacy := time.Now()
_, errObjectSt := d.Legacy.Create(ctx, obj, createValidation, options)
d.recordLegacyDuration(errObjectSt != nil, mode3Str, options.Kind, method, startLegacy)
d.recordLegacyDuration(errObjectSt != nil, mode3Str, kind, method, startLegacy)
}()
return created, err
@ -62,7 +63,7 @@ func (d *DualWriterMode3) Create(ctx context.Context, obj runtime.Object, create
// Get overrides the behavior of the generic DualWriter and retrieves an object from Storage.
func (d *DualWriterMode3) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
var method = "get"
log := d.Log.WithValues("kind", options.Kind, "name", name, "method", method)
log := d.Log.WithValues("name", name, "method", method)
ctx = klog.NewContext(ctx, log)
startStorage := time.Now()
@ -70,7 +71,12 @@ func (d *DualWriterMode3) Get(ctx context.Context, name string, options *metav1.
if err != nil {
log.Error(err, "unable to get object in storage")
}
d.recordStorageDuration(err != nil, mode3Str, options.Kind, method, startStorage)
var kind string
if res != nil {
kind = res.GetObjectKind().GroupVersionKind().Kind
}
d.recordStorageDuration(err != nil, mode3Str, kind, method, startStorage)
return res, err
}
@ -78,7 +84,7 @@ func (d *DualWriterMode3) Get(ctx context.Context, name string, options *metav1.
// List overrides the behavior of the generic DualWriter and reads only from Unified Store.
func (d *DualWriterMode3) List(ctx context.Context, options *metainternalversion.ListOptions) (runtime.Object, error) {
var method = "list"
log := d.Log.WithValues("kind", options.Kind, "resourceVersion", options.ResourceVersion, "method", method)
log := d.Log.WithValues("resourceVersion", options.ResourceVersion, "method", method)
ctx = klog.NewContext(ctx, log)
startStorage := time.Now()
@ -86,21 +92,29 @@ func (d *DualWriterMode3) List(ctx context.Context, options *metainternalversion
if err != nil {
log.Error(err, "unable to list object in storage")
}
d.recordStorageDuration(err != nil, mode3Str, options.Kind, method, startStorage)
var kind string
if res != nil {
kind = res.GetObjectKind().GroupVersionKind().Kind
}
d.recordStorageDuration(err != nil, mode3Str, kind, method, startStorage)
return res, err
}
func (d *DualWriterMode3) Delete(ctx context.Context, name string, deleteValidation rest.ValidateObjectFunc, options *metav1.DeleteOptions) (runtime.Object, bool, error) {
var method = "delete"
log := d.Log.WithValues("name", name, "kind", options.Kind, "method", method)
log := d.Log.WithValues("name", name, "method", method)
ctx = klog.NewContext(ctx, d.Log)
var kind string
startStorage := time.Now()
res, async, err := d.Storage.Delete(ctx, name, deleteValidation, options)
if res != nil {
kind = res.GetObjectKind().GroupVersionKind().Kind
}
if err != nil {
log.Error(err, "unable to delete object in storage")
d.recordStorageDuration(true, mode3Str, options.Kind, method, startStorage)
d.recordStorageDuration(true, mode3Str, kind, method, startStorage)
return res, async, err
}
d.recordStorageDuration(false, mode3Str, name, method, startStorage)
@ -110,7 +124,7 @@ func (d *DualWriterMode3) Delete(ctx context.Context, name string, deleteValidat
ctx, cancel := context.WithTimeoutCause(ctx, time.Second*10, errors.New("legacy delete timeout"))
defer cancel()
_, _, err := d.Legacy.Delete(ctx, name, deleteValidation, options)
d.recordLegacyDuration(err != nil, mode3Str, options.Kind, method, startLegacy)
d.recordLegacyDuration(err != nil, mode3Str, kind, method, startLegacy)
}()
return res, async, err
@ -119,17 +133,21 @@ func (d *DualWriterMode3) Delete(ctx context.Context, name string, deleteValidat
// Update overrides the behavior of the generic DualWriter and writes first to Storage and then to LegacyStorage.
func (d *DualWriterMode3) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool, options *metav1.UpdateOptions) (runtime.Object, bool, error) {
var method = "update"
log := d.Log.WithValues("name", name, "kind", options.Kind, "method", method)
log := d.Log.WithValues("name", name, "method", method)
ctx = klog.NewContext(ctx, log)
var kind string
startStorage := time.Now()
res, async, err := d.Storage.Update(ctx, name, objInfo, createValidation, updateValidation, forceAllowCreate, options)
if res != nil {
kind = res.GetObjectKind().GroupVersionKind().Kind
}
if err != nil {
log.Error(err, "unable to update in storage")
d.recordLegacyDuration(true, mode3Str, options.Kind, method, startStorage)
d.recordLegacyDuration(true, mode3Str, kind, method, startStorage)
return res, async, err
}
d.recordStorageDuration(false, mode3Str, options.Kind, method, startStorage)
d.recordStorageDuration(false, mode3Str, kind, method, startStorage)
go func() {
ctx, cancel := context.WithTimeoutCause(ctx, time.Second*10, errors.New("legacy update timeout"))
@ -137,7 +155,7 @@ func (d *DualWriterMode3) Update(ctx context.Context, name string, objInfo rest.
startLegacy := time.Now()
defer cancel()
_, _, errObjectSt := d.Legacy.Update(ctx, name, objInfo, createValidation, updateValidation, forceAllowCreate, options)
d.recordLegacyDuration(errObjectSt != nil, mode3Str, options.Kind, method, startLegacy)
d.recordLegacyDuration(errObjectSt != nil, mode3Str, kind, method, startLegacy)
}()
return res, async, err
@ -146,24 +164,28 @@ func (d *DualWriterMode3) Update(ctx context.Context, name string, objInfo rest.
// DeleteCollection overrides the behavior of the generic DualWriter and deletes from both LegacyStorage and Storage.
func (d *DualWriterMode3) DeleteCollection(ctx context.Context, deleteValidation rest.ValidateObjectFunc, options *metav1.DeleteOptions, listOptions *metainternalversion.ListOptions) (runtime.Object, error) {
var method = "delete-collection"
log := d.Log.WithValues("kind", options.Kind, "resourceVersion", listOptions.ResourceVersion, "method", method)
log := d.Log.WithValues("resourceVersion", listOptions.ResourceVersion, "method", method)
ctx = klog.NewContext(ctx, log)
var kind string
startStorage := time.Now()
res, err := d.Storage.DeleteCollection(ctx, deleteValidation, options, listOptions)
if res != nil {
kind = res.GetObjectKind().GroupVersionKind().Kind
}
if err != nil {
log.Error(err, "unable to delete collection in storage")
d.recordStorageDuration(true, mode3Str, options.Kind, method, startStorage)
d.recordStorageDuration(true, mode3Str, kind, method, startStorage)
return res, err
}
d.recordStorageDuration(false, mode3Str, options.Kind, method, startStorage)
d.recordStorageDuration(false, mode3Str, kind, method, startStorage)
go func() {
startLegacy := time.Now()
ctx, cancel := context.WithTimeoutCause(ctx, time.Second*10, errors.New("legacy deletecollection timeout"))
defer cancel()
_, err := d.Legacy.DeleteCollection(ctx, deleteValidation, options, listOptions)
d.recordStorageDuration(err != nil, mode3Str, options.Kind, method, startLegacy)
d.recordStorageDuration(err != nil, mode3Str, kind, method, startLegacy)
}()
return res, err

View File

@ -2,6 +2,7 @@ package rest
import (
"context"
"time"
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -35,77 +36,116 @@ func (d *DualWriterMode4) Mode() DualWriterMode {
// Create overrides the behavior of the generic DualWriter and writes only to Storage.
func (d *DualWriterMode4) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) {
var method = "create"
log := d.Log.WithValues("kind", options.Kind, "method", method)
var kind = obj.GetObjectKind().GroupVersionKind().Kind
log := d.Log.WithValues("method", method, "kind", kind)
ctx = klog.NewContext(ctx, log)
startStorage := time.Now()
res, err := d.Storage.Create(ctx, obj, createValidation, options)
if err != nil {
log.Error(err, "unable to create object in storage")
}
d.recordStorageDuration(err != nil, mode4Str, kind, method, startStorage)
return res, err
}
// Get overrides the behavior of the generic DualWriter and retrieves an object from Storage.
func (d *DualWriterMode4) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
var method = "get"
log := d.Log.WithValues("kind", options.Kind, "method", method)
log := d.Log.WithValues("method", method)
ctx = klog.NewContext(ctx, log)
startStorage := time.Now()
res, err := d.Storage.Get(ctx, name, options)
if err != nil {
log.Error(err, "unable to create object in storage")
}
var kind string
if res != nil {
kind = res.GetObjectKind().GroupVersionKind().Kind
}
d.recordStorageDuration(err != nil, mode4Str, kind, method, startStorage)
return res, err
}
func (d *DualWriterMode4) Delete(ctx context.Context, name string, deleteValidation rest.ValidateObjectFunc, options *metav1.DeleteOptions) (runtime.Object, bool, error) {
var method = "delete"
log := d.Log.WithValues("name", name, "kind", options.Kind, "method", method)
log := d.Log.WithValues("name", name, "method", method)
ctx = klog.NewContext(ctx, log)
var kind string
startStorage := time.Now()
res, async, err := d.Storage.Delete(ctx, name, deleteValidation, options)
if err != nil {
log.Error(err, "unable to delete object in storage")
}
if res != nil {
kind = res.GetObjectKind().GroupVersionKind().Kind
}
d.recordStorageDuration(err != nil, mode4Str, kind, method, startStorage)
return res, async, err
}
// DeleteCollection overrides the behavior of the generic DualWriter and deletes only from Storage.
func (d *DualWriterMode4) DeleteCollection(ctx context.Context, deleteValidation rest.ValidateObjectFunc, options *metav1.DeleteOptions, listOptions *metainternalversion.ListOptions) (runtime.Object, error) {
var method = "delete-collection"
log := d.Log.WithValues("kind", options.Kind, "resourceVersion", listOptions.ResourceVersion, "method", method, "mode", mode4Str)
log := d.Log.WithValues("resourceVersion", listOptions.ResourceVersion, "method", method, "mode", mode4Str)
ctx = klog.NewContext(ctx, log)
var kind string
startStorage := time.Now()
res, err := d.Storage.DeleteCollection(ctx, deleteValidation, options, listOptions)
if err != nil {
log.Error(err, "unable to delete collection in storage")
}
if res != nil {
kind = res.GetObjectKind().GroupVersionKind().Kind
}
d.recordStorageDuration(err != nil, mode4Str, kind, method, startStorage)
return res, err
}
// Update overrides the generic behavior of the Storage and writes only to US.
func (d *DualWriterMode4) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool, options *metav1.UpdateOptions) (runtime.Object, bool, error) {
var method = "update"
log := d.Log.WithValues("name", name, "kind", options.Kind, "method", method)
log := d.Log.WithValues("name", name, "method", method)
ctx = klog.NewContext(ctx, log)
var kind string
startStorage := time.Now()
res, async, err := d.Storage.Update(ctx, name, objInfo, createValidation, updateValidation, forceAllowCreate, options)
if err != nil {
log.Error(err, "unable to update object in storage")
}
if res != nil {
kind = res.GetObjectKind().GroupVersionKind().Kind
}
d.recordStorageDuration(err != nil, mode4Str, kind, method, startStorage)
return res, async, err
}
func (d *DualWriterMode4) List(ctx context.Context, options *metainternalversion.ListOptions) (runtime.Object, error) {
var method = "list"
log := d.Log.WithValues("kind", options.Kind, "resourceVersion", options.ResourceVersion, "kind", options.Kind, "method", method)
log := d.Log.WithValues("resourceVersion", options.ResourceVersion, "method", method)
ctx = klog.NewContext(ctx, log)
startStorage := time.Now()
res, err := d.Storage.List(ctx, options)
if err != nil {
log.Error(err, "unable to list objects in storage")
}
var kind string
if res != nil {
kind = res.GetObjectKind().GroupVersionKind().Kind
}
d.recordStorageDuration(err != nil, mode4Str, kind, method, startStorage)
return res, err
}
//TODO: uncomment when storage watch is implemented
// func (d *DualWriterMode4) Watch(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) {
// var method = "watch"
// d.Log.WithValues("kind", options.Kind, "method", method, "mode", mode4Str).Info("starting to watch")
// d.Log.WithValues("kind", kind, "method", method, "mode", mode4Str).Info("starting to watch")
// return d.Storage.Watch(ctx, options)
// }

View File

@ -51,14 +51,14 @@ func (m *dualWriterMetrics) init(reg prometheus.Registerer) {
}
}
func (m *dualWriterMetrics) recordLegacyDuration(isError bool, mode string, name string, method string, startFrom time.Time) {
func (m *dualWriterMetrics) recordLegacyDuration(isError bool, mode string, kind string, method string, startFrom time.Time) {
duration := time.Since(startFrom).Seconds()
m.legacy.WithLabelValues(strconv.FormatBool(isError), mode, name, method).Observe(duration)
m.legacy.WithLabelValues(strconv.FormatBool(isError), mode, kind, method).Observe(duration)
}
func (m *dualWriterMetrics) recordStorageDuration(isError bool, mode string, name string, method string, startFrom time.Time) {
func (m *dualWriterMetrics) recordStorageDuration(isError bool, mode string, kind string, method string, startFrom time.Time) {
duration := time.Since(startFrom).Seconds()
m.storage.WithLabelValues(strconv.FormatBool(isError), mode, name, method).Observe(duration)
m.storage.WithLabelValues(strconv.FormatBool(isError), mode, kind, method).Observe(duration)
}
func (m *dualWriterMetrics) recordOutcome(mode string, name string, areEqual bool, method string) {