Golang Development Utilities
Utilities for golang developments on Conflux blockchain, especially for backend service.
Module |
Description |
Alert |
Send notification message to dingtalk. |
API |
REST API utilities based on gin. |
Config |
Initialize all modules. |
DLock |
Utilities for distributed lock. |
Health |
Utilities for health management. |
HTTP |
Provides common used middlewares. |
Log |
Based on logrus and integrated with Alert. |
Metrics |
To monitor system runtime. |
Rate Limit |
Utilities to limit request rate. |
Store |
Provides utilities to initialize database. |
Viper |
To fix some issues of original viper. |
Alert
Before sending any message to dingtalk, client should initialize dingtalk robot when setup program.
Initialize programmatically:
alert.InitDingTalk(config *DingTalkConfig, tags []string)
alert.SendDingTalkTextMessage(level, brief, detail string)
Or, initialize from configuration file, which is recommended:
alert.MustInitFromViper()
Moreover, alert could be integrated with log module, so as to send messages to dingtalk when warning
or error
logs occurred.
API
This module provides common HTTP responses along with standard errors in JSON format.
Uniform JSON message in HTTP response body:
type BusinessError struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data"`
}
Code
0 indicates success, and Data
is an object indicates the return value of REST API. Code
with non-zero value indicates any error occurred, please refer to the Message
and Data
fields for more details. There are some pre-defined errors as below:
- 1: Invalid parameter, see
Data
for detailed error.
- 2: Internal server error, see
Data
for detailed error.
- 3: Too many requests, see
Data
for detailed error.
To distinguish backend service error and gateway error, we only use 200
and 600
as HTTP response status code:
- 200: success, or known business error, e.g. entity not found.
- 600: unexpected system error, e.g. database error, io error.
We recommend to initialize REST API from configuration file. Client only requires to provide a factory to setup controllers.
// Setup controllers.
factory := func(router *gin.Engine) {
router.GET("url", api.Wrap(controller))
}
// Start REST API server in a separate goroutine.
go api.MustServeFromViper(factory)
Config
Initialize all modules at the entry point of program, including viper, log, metrics and alert.
config.MustInit(viperEnvPrefix string)
The viperEnvPrefix
is used to overwrite configurations from environment. E.g. if the viperEnvPrefix
is FOO
, then client could set environment as below to overwrite config alert.dingTalk.secret
:
FOO_ALERT_DINGTALK_SECRET='dsafsadf'
You could follow the example config.yaml
under config folder to setup your own configuration file. Generally, you could only overwrite configurations if the default value not suitable.
Distributed Lock
Utilities to achieve high availability.
Health
Provides utilities for error tolerant health monitoring to avoid massive duplicated alerts.
Generally, system shall not report failure if auto resolved in a short time. However, system should report failure if not solved in a short time, and periodically remind failure if unrecovered for a long time.
- Counter: manage health status based on the number of continous failures.
- TimedCounter: manage health status based on duration since the first failure.
HTTP
Provides utilities to hook middlewares to HTTP handler, e.g. remote address, API key and rate limit.
Log
We recommend to initialize log module from configuration file, and allow to send dingtalk messages when warning
or error
messages occurred.
Metrics
We recommend to initialize metrics module from configuration file. Client could also configure influxdb to report metrics periodically. See MetricsConfig
for more details.
Rate Limit
Provides basic rate limit algorithms, including fixed window, token bucket, along with utilities for HTTP middleware.
Note, rate limit middleware depends on the HTTP middleware RealIP
.
Store
We recommend to initialize store module from configuration file.
config := mysql.MustNewConfigFromViper()
db := config.MustOpenOrCreate(tables ...interface{})
Viper
Fixes issues when unmarshal configurations from environment. A simple way to load configuration from file is as below:
viper.MustUnmarshalKey(key string, valPtr interface{}, resolver ...ValueResolver)
// E.g. load `foo` config from file.
var config FooConfig
viper.MustUnmarshalKey("foo", &config)