# README
for what
Middleware for reading or generating correlation IDs for each incoming request.
Correlation IDs can then be added to your logs, making it simple to retrieve all logs generated from a single HTTP request.
The middleware checks for the x-request-id
header by default, but can be set to any key,like x-correlation-id
Contributing
We welcome community contributions to this project.
Please read Contributor Guide for more information on how to get started.
depends
in go mod project
# before above global settings
# test version info
$ git ls-remote -q https://github.com/bar-counter/gin-correlation-id.git
# test depends see full version
$ go list -mod readonly -v -m -versions github.com/bar-counter/gin-correlation-id
# or use last version add go.mod by script
$ echo "go mod edit -require=$(go list -mod=readonly -m -versions github.com/bar-counter/gin-correlation-id | awk '{print $1 "@" $NF}')"
$ echo "go mod vendor"
evn
- minimum go version: go 1.18
- change
go 1.18
,^1.18
,1.18.10
to new go version
libs
Feature
- id creation support
- uuid v4 by https://github.com/gofrs/uuid
- snowflake https://github.com/bwmarrin/snowflake
- shortuuid by https://github.com/lithammer/shortuuid
- change CorrelationID Header key at each support
- CORS cross-origin resource sharing
- more perfect test case coverage
- more perfect benchmark case
Performance
- Performance log see PerformanceLog.md
platform | arch | method | times | ns/op | B/op | allocs/op | cpu |
---|---|---|---|---|---|---|---|
linux | amd64 | Benchmark_gin_correlation_id_uuidv4-2 | 167029 | 7124 ns/op | 2320 B/op | 32 allocs/op | Intel(R) Xeon(R) CPU E5-2673 v4 @ 2.30GHz |
linux | amd64 | BenchmarkParallel_gin_correlation_id_uuidv4-2 | 218067 | 5572 ns/op | 2320 B/op | 32 allocs/op | Intel(R) Xeon(R) CPU E5-2673 v4 @ 2.30GHz |
linux | amd64 | BenchmarkParallel_gin_correlation_id_snowflake-2 | 260205 | 4920 ns/op | 2256 B/op | 31 allocs/op | Intel(R) Xeon(R) CPU E5-2673 v4 @ 2.30GHz |
linux | amd64 | Benchmark_gin_correlation_id_snowflake-2 | 199422 | 5922 ns/op | 2256 B/op | 31 allocs/op | Intel(R) Xeon(R) CPU E5-2673 v4 @ 2.30GHz |
linux | amd64 | BenchmarkGinIdShortUuid-2 | 73371 | 15670 ns/op | 4891 B/op | 128 allocs/op | Intel(R) Xeon(R) CPU E5-2673 v4 @ 2.30GHz |
linux | amd64 | BenchmarkParallelGinIdShortUuid-2 | 103296 | 10477 ns/op | 4891 B/op | 128 allocs/op | Intel(R) Xeon(R) CPU E5-2673 v4 @ 2.30GHz |
windows | amd64 | Benchmark_gin_correlation_id_uuidv4-2 | 215640 | 5563 ns/op | 2344 B/op | 33 allocs/op | Intel(R) Xeon(R) Platinum 8272CL CPU @ 2.60GHz |
windows | amd64 | BenchmarkParallel_gin_correlation_id_uuidv4-2 | 291274 | 3558 ns/op | 2344 B/op | 33 allocs/op | Intel(R) Xeon(R) Platinum 8272CL CPU @ 2.60GHz |
windows | amd64 | Benchmark_gin_correlation_id_snowflake-2 | 228192 | 5059 ns/op | 2256 B/op | 31 allocs/op | Intel(R) Xeon(R) Platinum 8272CL CPU @ 2.60GHz |
windows | amd64 | BenchmarkParallel_gin_correlation_id_snowflake-2 | 347394 | 3327 ns/op | 2256 B/op | 31 allocs/op | Intel(R) Xeon(R) Platinum 8272CL CPU @ 2.60GHz |
windows | amd64 | BenchmarkGinIdShortUuid-2 | 95556 | 12331 ns/op | 4915 B/op | 129 allocs/op | Intel(R) Xeon(R) Platinum 8272CL CPU @ 2.60GHz |
windows | amd64 | BenchmarkParallelGinIdShortUuid-2 | 153523 | 8331 ns/op | 4915 B/op | 129 allocs/op | Intel(R) Xeon(R) Platinum 8272CL CPU @ 2.60GHz |
darwin | arm64 | Benchmark_gin_correlation_id_uuidv4-2 | 440373 | 2712 ns/op | 2321 B/op | 32 allocs/op | apple silicon M1 Max core 10 |
darwin | arm64 | BenchmarkParallel_gin_correlation_id_uuidv4-10 | 513122 | 2296 ns/op | 2324 B/op | 32 allocs/op | apple silicon M1 Max core 10 |
darwin | arm64 | Benchmark_gin_correlation_id_snowflake-2 | 570752 | 2095 ns/op | 2257 B/op | 31 allocs/op | apple silicon M1 Max core 10 |
darwin | arm64 | BenchmarkParallel_gin_correlation_id_snowflake-10 | 557127 | 2213 ns/op | 2260 B/op | 31 allocs/op | apple silicon M1 Max core 10 |
darwin | arm64 | BenchmarkGinIdShortUuid-2 | 202786 | 5920 ns/op | 4893 B/op | 128 allocs/op | apple silicon M1 Max core 10 |
darwin | arm64 | BenchmarkParallelGinIdShortUuid-10 | 330234 | 3614 ns/op | 4898 B/op | 128 allocs/op | apple silicon M1 Max core 10 |
ns/op
is the average time per operation, lower latency better performanceB/op
is the number of bytes allocated per operation, memory allocation means getting more memory from the operating system, less occupied betterallocs/op
is the number of allocations per operation, memory allocation means getting more memory from the operating system, less occupied better
usage
- see full api usage at unit test case
- gin_correlation_id_uuidv4
- gin_correlation_id_snowflake
- gin_correlation_id_shortuuid
go 1.18
,^1.18
,1.18.10
to new go version for dev
sample uuid-v4
package main
import (
"github.com/bar-counter/gin-correlation-id/gin_correlation_id_uuidv4"
"github.com/gin-gonic/gin"
"net/http"
"log"
"fmt"
)
func ginPingRouter() *gin.Engine {
router := gin.New()
// add Middleware
router.Use(gin_correlation_id_uuidv4.Middleware())
router.GET("/ping", func(c *gin.Context) {
c.String(http.StatusOK, "pong as correlation ID: %s", gin_correlation_id_uuidv4.GetCorrelationID(c))
})
return router
}
func main() {
// Create the Gin engine.
g := ginPingRouter()
serverPort := "49002"
log.Printf("=> now server access as: http://127.0.0.1:%s", serverPort)
err := http.ListenAndServe(fmt.Sprintf(":%v", serverPort), g)
if err != nil {
fmt.Printf("run gin server err %v\n", err)
return
}
}
integrationTest
- run server then test as curl
$ curl -v http://127.0.0.1:49002/ping
* Trying 127.0.0.1:49002...
* Connected to 127.0.0.1 (127.0.0.1) port 49002 (#0)
> GET /ping HTTP/1.1
> Host: 127.0.0.1:49002
> User-Agent: curl/7.80.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Access-Control-Expose-Headers: x-request-id
< Content-Type: text/plain; charset=utf-8
< X-Request-Id: 0b737fda-5439-487b-9f81-a7824b88532e
< Date: Sun, 18 Jun 2023 04:20:27 GMT
< Content-Length: 60
<
* Connection #0 to host 127.0.0.1 left intact
pong as correlation ID: 0b737fda-5439-487b-9f81-a7824b88532e
response header
hasX-Request-Id
key ascorrelation ID
- can get
correlation ID
as
// use uuid v4
gin_correlation_id_uuidv4.GetCorrelationID(*gin.Context)
// use snowflake
gin_correlation_id_snowflake.GetCorrelationID(*gin.Context)
// use shortuuid
gin_correlation_id_shortuuid.GetCorrelationID(*gin.Context)
CORS
If you are using cross-origin resource sharing (CORS)
e.g. you are making requests to an API from a frontend JavaScript code served from a different origin, you have to ensure two things:
- permit correlation ID header in the incoming requests' HTTP headers so the value can be reused by the middleware,
- add the correlation ID header to the allowlist in responses' HTTP headers so it can be accessed by the browser.
have to include the Access-Control-Allow-Origin
and Access-Control-Expose-Headers
- use this lib will add
Access-Control-Expose-Headers
auto by middleware - so only add
Access-Control-Allow-Origin
like use this lib https://github.com/gin-contrib/cors
dev
# It needs to be executed after the first use or update of dependencies.
$ make init dep
- test code
$ make test testBenchmark
add main.go file and run
# run at env dev use cmd/main.go
$ make dev
- ci to fast check
# check style at local
$ make style
# run ci at local
$ make ci
docker
# then test build as test/Dockerfile
$ make dockerTestRestartLatest
# clean test build
$ make dockerTestPruneLatest
# more info see
$ make helpDocker
# Packages
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author