mirror of
https://github.com/openshift/image-registry.git
synced 2026-02-05 09:45:55 +01:00
metrics: report filesystem errors
to help customers detect and solve errors, we specifically report metrics on a few filesystem specific errors. we have seen customers configure the registry with a read-only filesystem without noticing until it's too late. more specifically, when using the registry only as a pull-through cache, a read-only filesystem will be imperceptible to clients unless the upstream registry experiences an outage, then it'll be too late to fix the cache. the file too large (EFBIG) and device out of space (ENOSPC) errors were added just in case. there have not been (so far) reports of customers silently running into this errors on their PVCs.
This commit is contained in:
@@ -1,13 +1,33 @@
|
||||
package metrics
|
||||
|
||||
import storagedriver "github.com/distribution/distribution/v3/registry/storage/driver"
|
||||
import (
|
||||
"errors"
|
||||
"io/fs"
|
||||
"syscall"
|
||||
|
||||
storagedriver "github.com/distribution/distribution/v3/registry/storage/driver"
|
||||
)
|
||||
|
||||
const (
|
||||
errCodeUnsupportedMethod = "UNSUPPORTED_METHOD"
|
||||
errCodePathNotFound = "PATH_NOT_FOUND"
|
||||
errCodeInvalidPath = "INVALID_PATH"
|
||||
errCodeInvalidOffset = "INVALID_OFFSET"
|
||||
errCodeReadOnlyFS = "READ_ONLY_FILESYSTEM"
|
||||
errCodeFileTooLarge = "FILE_TOO_LARGE"
|
||||
errCodeDeviceOutOfSpace = "DEVICE_OUT_OF_SPACE"
|
||||
errCodeUnknown = "UNKNOWN"
|
||||
|
||||
// errnoEFBIG represents a file too large error.
|
||||
// See `man errno` for more.
|
||||
errnoEFBIG = 27
|
||||
// errnoENOSPC represents a device out of space error.
|
||||
// See `man errno` for more.
|
||||
errnoENOSPC = 28
|
||||
// errnoEROFS represents the syscall error number returned when an attempt
|
||||
// to write to a read-only filesystem was made.
|
||||
// See `man errno` for more.
|
||||
errnoEROFS = 30
|
||||
)
|
||||
|
||||
func storageErrorCode(err error) string {
|
||||
@@ -20,7 +40,38 @@ func storageErrorCode(err error) string {
|
||||
return errCodeInvalidPath
|
||||
case storagedriver.InvalidOffsetError:
|
||||
return errCodeInvalidOffset
|
||||
case storagedriver.Error:
|
||||
var perr *fs.PathError
|
||||
if !errors.As(actual.Enclosed, &perr) {
|
||||
return errCodeUnknown
|
||||
}
|
||||
unwrapped := perr.Unwrap()
|
||||
if unwrapped == nil {
|
||||
return errCodeUnknown
|
||||
}
|
||||
errno, ok := unwrapped.(syscall.Errno)
|
||||
if !ok {
|
||||
return errCodeUnknown
|
||||
}
|
||||
return syscallErrnoToErrorCode(errno)
|
||||
|
||||
}
|
||||
|
||||
return errCodeUnknown
|
||||
}
|
||||
|
||||
// syscallErrnoToErrorCode transforms the errno in an unwrapped fs.PathErr into
|
||||
// a storage error code used to report metrics.
|
||||
//
|
||||
// if the given errno is not known to us, return errCodeUnknown.
|
||||
func syscallErrnoToErrorCode(errno syscall.Errno) string {
|
||||
switch errno {
|
||||
case errnoEROFS:
|
||||
return errCodeReadOnlyFS
|
||||
case errnoEFBIG:
|
||||
return errCodeFileTooLarge
|
||||
case errnoENOSPC:
|
||||
return errCodeDeviceOutOfSpace
|
||||
}
|
||||
return errCodeUnknown
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user