microservice1
is a simplified example of a microservice that responds to a browser (client).
microservice1
exposes 2 endpoints:
/products/001
that generates an error. The goal here is double:- check that the error returned to the client is REST friendly and contains enough info for the frontend to process the error.
- chech that the log contains enough information to be able to troubleshoot if necessary.
/todos
that is calling microservice2 which will call an external dummy API and return a TODO list. This will be used to test concurrency later on.
- Start microservices
> cd microservice1
> go run src/main.go
in another terminal
> cd microservice2
> go run src/main.go
- test the microservice1 endpoints in
test.rest
using the vscode REST client extension https://marketplace.visualstudio.com/items?itemName=humao.rest-client
If an error happens, the client should be able to provide an appropriate error message to the end user based on the payload received by this server without leaking any sensitive data or giving any information about the backend code structure or the underlying technology stack.
Error Logging should provide enough information to understand the origin of an error.
1 - An error must be created upon detection, in a controller, service, repository or http client 2 - An error should be only handled once, and this should happen in the controller 3 - Logging should only happens in the controller and should provide the path of the request that generated the error.
Any error will be encapsulated into a restErr
struct.
The restErr
has 2 purposes:
- Provide fields to create an standardized HTTP Error Response:
- the HTTTP Status,
- the title of the error
- a potential cause (like the name of a missing/invalid field). These fields are marshalled and presented to the client.
- Provide Logging information to a logger: these data may contain information sensitive information (db field names, db sytem name etc.) and therefore are not marshalled.
ErrPath
: contains something likeproductcontroller.GetProduct/productservice.GetProduct/productrepo.GetByID
to inform that an error has been triggered by theGetByID
function from the product repository, called by theGetProduct
function from the product service etc.ErrCode
andErrMessage
: the raw error code and message retrieved from MySQL, PostGres, an external API or another microservice.
type restErr struct {
// these fields are returned to the browser
ErrStatus int `json:"status"` // HTTP Status Code
ErrTitle string `json:"title"` // A string representation of the Status Code
ErrCause string `json:"cause,omitempty"` // The cause of the error, can be empty
// these fiedls are NOT returned to the browser and are only used for logging
ErrPath string `json:"-"` // The path of the error. Ex: "controller/controllerfunc/service/servicefunc/dbclient/dblientfunc"
ErrMessage string `json:"-"` // Raw error message returned by a DB, another Servive or whatever
ErrCode string `json:"-"` // Raw error code from the DB or another service
}
type RestErr interface {
Status() int // HTTP status code
Title() string // A string representation of the Status Code
Path() string // The path of the error. Ex: "controller/controllerfunc/service/servicefunc/dbclient/dblientfunc"
WrapPath(string) // Wrapper func to keep track of the path of the error
Code() string // Raw error code
Message() string // Raw error message not returned to the client
Error() string // string representation of a restErr
}