docs/static/v0.7/project/contributing/contributing-error/index.html
Meshery pervasively uses MeshKit as a golang and infrastructure management-specific library in all of its components. MeshKit helps populate error messages with a uniform and useful set of informative attributes.
To help with creating error codes, MeshKit contains a tool that analyzes, verifies and updates error codes in Meshery source code trees. It extracts error details into a file that can be used for publishing all error code references on the Meshery error codes reference page. The objective to create this was to avoid centralized handling of error codes and automating everything
In order to create a Meshery error object, you will need to create a custom wrapper object for the native golang error. This can be done from the MeshKit Error package.
This tool will create a couple of files, one of them is designed to be used to generate the error reference on the Meshery Documentation website. The file errorutil_analyze_summary.json contains a summary of the analysis, notably lists of duplicates etc.
make error analyzes your code and returns any warnings to be aware of.Use the errors.New() function to create a new instance of the error object and pass situation-specific attributes as function arguments. These attributes are:
`errors.New(ErrExampleCode, errors.Alert, []string{"<short-description>"}, []string{"<long-description>"}, []string{"<probable-cause>"}, []string{"<suggested remediation>"})`
In this example we are creating an Error for being unable to marshal JSON
`var (
// Error code
ErrMarshalCode= "replace_me"
//Static errors (for example)
ErrExample = errors.New(ErrExampleCode, errors.Alert, []string{"<short-description>"}, []string{"<long-description>"}, []string{"<probable-cause>"}, []string{"<suggested remediation>"})
)
// Dynamic errors
//Error Name
func ErrMarshal(err error, obj string) error {
return errors.New(ErrMarshalCode, errors.Alert, []string{"Unable to marshal the : ", obj}, []string{err.Error()}, []string{}, []string{})
}`
Old
`bd, err := json.Marshal(providers)
if err != nil {
http.Error(w, "unable to marshal the providers", http.StatusInternalServerError)
return
}`
New
`bd, err := json.Marshal(providers)
if err != nil {
obj := "provider"
http.Error(w, ErrMarshal(err, obj).Error(), http.StatusInternalServerError)
return
}`
There already exists an interface for logger in MeshKit.
To enforce the use of meshkit errors, meshkit logger was designed such that it only works with meshkit errors. If a non-meshkit error is logged through the logger, it would panic and kill the process. See: meshkit#119 for more insight.
`type Logger struct {
log logger.Handler
}`
`logrus.Debugf("meshLocationURL: %s", meshLocationURL)`
`l.log.Debug("meshLocationURL: ", meshLocationURL)`
`logrus.Errorf("error marshaling data: %v.", err)`
`l.log.Error(ErrMarshal(err, obj))`
`package main
import (
"fmt"
"os"
meshkitErrors "github.com/layer5io/meshkit/errors"
"github.com/layer5io/meshkit/logger"
"github.com/sirupsen/logrus"
"github.com/spf13/viper"
)
var (
// CI will replace `test_code` with new error code
ErrOpeningFileCode = "test_code"
)
func main() {
logLevel := viper.GetInt("LOG_LEVEL")
if viper.GetBool("DEBUG") {
logLevel = int(logrus.DebugLevel)
}
log, err := logger.New("test", logger.Options{
Format: logger.SyslogLogFormat,
LogLevel: logLevel,
})
if err != nil {
fmt.Println(err)
os.Exit(1)
}
// logging meshkit error
err = openFileWithMeshkitError("some.txt")
if err != nil {
log.Error(err)
}
// OUTPUT
// ERRO[2021-11-10T17:31:28+05:30] open some.txt: no such file or directory
// app=test code=1001 probable-cause="empty string passed as argument .file with this name doesn't exist"
// severity=2 short-description="unable to open file" suggested-remediation="pass a non-empty string as
// filename .create file before opening it"
// logging non meshkit error
err = openFile("some.txt")
if err != nil {
log.Error(err)
}
// OUTPUT
// ERRO[2024-07-01T19:09:09+05:30] open some.txt: no such file or directory
// app=test code= probable-cause= severity=0 short-description= suggested-remediation=
}
// this returns a non meshkit error
func openFile(name string) error {
_, err := os.Open(name)
return err
}
// this returns a meshkit error
func openFileWithMeshkitError(name string) error {
_, err := os.Open(name)
return ErrOpeningFile(err)
}
func ErrOpeningFile(err error) error {
return meshkitErrors.New(ErrOpeningFileCode, meshkitErrors.Alert, []string{"unable to open file"},
[]string{err.Error()},
[]string{"empty string passed as argument ", "file with this name doesn't exist"},
[]string{"pass a non-empty string as filename ", "create file before opening it"})
}`