当前位置:网站首页>Gin framework: implementing distributed log tracing
Gin framework: implementing distributed log tracing
2022-06-24 01:29:00 【Trespass 】
Introduce
Through a complete example , Based on Gin Implementing distributed log tracing in framework .
What is? API Log tracking ?
One API Requests span multiple microservices , We hope to pass a unique ID Retrieve the log of the whole link .
We will use rk-boot To start up Gin Microservices of the framework .
Please visit the following address for a complete tutorial :
install
go get github.com/rookie-ninja/rk-boot go get github.com/rookie-ninja/rk-gin
Quick start
We will create /v1/greeter API To verify , At the same time open logging, meta and tracing Middleware to achieve the purpose .
1. establish bootA.yaml & serverA.go
ServerA monitor 1949 port , And send a request to ServerB.
We go through rkginctx.InjectSpanToNewContext() Method to Tracing Information is injected into Context in , Send to ServerB.
---
gin:
- name: greeter # Required
port: 1949 # Required
enabled: true # Required
interceptors:
loggingZap:
enabled: true # Optional, enable logging interceptor
meta:
enabled: true # Optional, enable meta interceptor
tracingTelemetry:
enabled: true # Optional, enable tracing interceptor// Copyright (c) 2021 rookie-ninja
//
// Use of this source code is governed by an Apache-style
// license that can be found in the LICENSE file.
package main
import (
"context"
"github.com/gin-gonic/gin"
"github.com/rookie-ninja/rk-boot"
"github.com/rookie-ninja/rk-gin/boot"
"github.com/rookie-ninja/rk-gin/interceptor/context"
"net/http"
)
// Application entrance.
func main() {
// Create a new boot instance.
boot := rkboot.NewBoot(rkboot.WithBootConfigPath("bootA.yaml"))
// Register handler
boot.GetEntry("greeter").(*rkgin.GinEntry).Router.GET("/v1/greeter", GreeterA)
// Bootstrap
boot.Bootstrap(context.Background())
// Wait for shutdown sig
boot.WaitForShutdownSig(context.Background())
}
// GreeterA will add trace info into context and call serverB
func GreeterA(ctx *gin.Context) {
// Call serverB at 2008
req, _ := http.NewRequest(http.MethodGet, "http://localhost:2008/v1/greeter", nil)
// Inject current trace information into context
rkginctx.InjectSpanToHttpRequest(ctx, req)
// Call server
http.DefaultClient.Do(req)
// Respond to request
ctx.String(http.StatusOK, "Hello from serverA!")
}2. establish bootB.yaml & serverB.go
ServerB monitor 2008 port .
---
gin:
- name: greeter # Required
port: 2008 # Required
enabled: true # Required
interceptors:
loggingZap:
enabled: true # Optional, enable logging interceptor
meta:
enabled: true # Optional, enable meta interceptor
tracingTelemetry:
enabled: true # Optional, enable tracing interceptor// Copyright (c) 2021 rookie-ninja
//
// Use of this source code is governed by an Apache-style
// license that can be found in the LICENSE file.
package main
import (
"context"
"github.com/gin-gonic/gin"
"github.com/rookie-ninja/rk-boot"
"github.com/rookie-ninja/rk-gin/boot"
"net/http"
)
// Application entrance.
func main() {
// Create a new boot instance.
boot := rkboot.NewBoot(rkboot.WithBootConfigPath("bootB.yaml"))
// Register handler
boot.GetEntry("greeter").(*rkgin.GinEntry).Router.GET("/v1/greeter", GreeterB)
// Bootstrap
boot.Bootstrap(context.Background())
// Wait for shutdown sig
boot.WaitForShutdownSig(context.Background())
}
// GreeterB receive request from serverA and respond.
func GreeterB(ctx *gin.Context) {
ctx.String(http.StatusOK, "Hello from serverB!")
}3. Folder structure
. ├── bootA.yaml ├── bootB.yaml ├── go.mod ├── go.sum ├── serverA.go └── serverB.go 0 directories, 6 files
4. start-up ServerA & ServerB
$ go run serverA.go $ go run serverB.go
5. Go to ServerA Send a request
$ curl localhost:1949/v1/greeter Hello from serverA!
6. Verify the log
In the logs of the two services , There will be the same traceId, Different requestId.
We can go through grep traceId To track RPC.
- ServerA
------------------------------------------------------------------------
endTime=2021-11-18T01:29:56.698997+08:00
...
ids={"eventId":"f5878390-1a5a-4bb9-8b39-bf4261864c0f","requestId":"f5878390-1a5a-4bb9-8b39-bf4261864c0f","traceId":"b2d70ab9f8207ef4a9f0c3fb1be5c22c"}
...
operation=/v1/greeter
resCode=200
eventStatus=Ended
EOE- ServerB
------------------------------------------------------------------------
endTime=2021-11-18T01:29:56.698606+08:00
...
ids={"eventId":"273c97d2-e11a-46f5-a044-bb9c0cf64540","requestId":"273c97d2-e11a-46f5-a044-bb9c0cf64540","traceId":"b2d70ab9f8207ef4a9f0c3fb1be5c22c"}
...
operation=/v1/greeter
resCode=200
eventStatus=Ended
EOEConcept
When we don't use, for example jaeger When calling the chain service , We hope to track the data in the distributed system through logs RPC request .
rk-boot The middleware will pass openTelemetry Library to write... To the log traceId To track RPC.
When the logging middleware is started , Original data middleware , When calling the chain middleware , The middleware will write the following three types into the log ID.
EventId
When the logging middleware is started ,EventId It will generate automatically .
---
gin:
- name: greeter # Required
port: 1949 # Required
enabled: true # Required
interceptors:
loggingZap:
enabled: true------------------------------------------------------------------------
...
ids={"eventId":"cd617f0c-2d93-45e1-bef0-95c89972530d"}
...RequestId
When the log middleware and the original data middleware are started ,RequestId and EventId It will generate automatically , And these two ID Will be consistent .
---
gin:
- name: greeter # Required
port: 1949 # Required
enabled: true # Required
interceptors:
loggingZap:
enabled: true
meta:
enabled: true------------------------------------------------------------------------
...
ids={"eventId":"8226ba9b-424e-4e19-ba63-d37ca69028b3","requestId":"8226ba9b-424e-4e19-ba63-d37ca69028b3"}
...Even if the user overwrites RequestId,EventId Will be consistent .
rkginctx.AddHeaderToClient(ctx, rkginctx.RequestIdKey, "overridden-request-id")
------------------------------------------------------------------------
...
ids={"eventId":"overridden-request-id","requestId":"overridden-request-id"}
...TraceId
When the call chain middleware is started ,traceId It will generate automatically .
---
gin:
- name: greeter # Required
port: 1949 # Required
enabled: true # Required
interceptors:
loggingZap:
enabled: true
meta:
enabled: true
tracingTelemetry:
enabled: true------------------------------------------------------------------------
...
ids={"eventId":"dd19cf9a-c7be-486c-b29d-7af777a78ebe","requestId":"dd19cf9a-c7be-486c-b29d-7af777a78ebe","traceId":"316a7b475ff500a76bfcd6147036951c"}
...边栏推荐
- [solution] how to realize AI automatic recognition of high altitude parabolic behavior?
- Local cache selection (guava/caffeine/ohc) and performance comparison
- Why traifik ingress?
- AES encryption analysis of CNKI academic translation
- Echo framework: implementing timeout Middleware
- Application analysis of video edge computing gateway easynvr in video overall monitoring solution
- Map data types in golang
- Theoretical analysis of countermeasure training: adaptive step size fast countermeasure training
- How to view kubernetes API traffic by grabbing packets
- Coordinate system "slang" in GIS world
猜你喜欢
![[flutter] comment utiliser les paquets et plug - ins flutter](/img/a6/e494dcdb2d3830b6d6c24d0ee05af2.png)
[flutter] comment utiliser les paquets et plug - ins flutter
![2022 postgraduate entrance examination experience sharing [preliminary examination, school selection, re examination, adjustment, school recruitment and social recruitment]](/img/05/e204f526e2f3e90ed9a7ad0361a72e.png)
2022 postgraduate entrance examination experience sharing [preliminary examination, school selection, re examination, adjustment, school recruitment and social recruitment]

Everything I see is the category of my precise positioning! Open source of a new method for saliency map visualization

JS input / output statements, variables

Installation and use of winscp and putty

Use recursion to form a multi-level directory tree structure, with possibly the most detailed notes of the whole network.

Zhongshanshan: engineers after being blasted will take off | ONEFLOW u

跨域和JSONP

Shardingsphere-proxy-5.0.0 implementation of capacity range partition (V)

985 Android programmers won the oral offer of Alibaba P6 in 40 days. After the successful interview, they sorted out these interview ideas
随机推荐
Ctfhub miscellaneous --icmp
Network security meets new regulations again, UK and US warn apt hacker attacks November 18 global network security hotspots
[technology planting grass] talk about the system design and architecture of large-scale shopping platform
Why traifik ingress?
Graduation project - thesis writing notes [design topic type, thesis writing details, design materials]
The Mars rescue plan has been released. The year of the tiger is limited to dolls waiting for you!
Golang gets the start timestamp and end timestamp of a past or future week or month
[OSG] OSG development (04) - create multiple scene views
Technology sharing | Clickhouse cluster's way of expanding replicas under sharding
How to build high quality and high brand websites what should be paid attention to in the construction of enterprise websites
How to make a fixed asset identification card
. Net core cross platform development bbs forum (connotation source code + complete operation video)
What is the suffix of the domain name for trademark registration? What are the differences between trademarks and domain names?
What is memory out of order access?
Esp8266 OTA remote and wireless upgrade
Cloud computing "keeping the promise"
Local cache selection (guava/caffeine/ohc) and performance comparison
Longest substring without duplicate characters
Real time preview of RTSP video based on webrtc
ShardingSphere-proxy-5.0.0容量范围分片的实现(五)