Skywalking-go自動監(jiān)控增強使用探究
1.使用Skywalking-go
使用Skywalking-go,我們可以基于Golang build提供的-toolexec參數(shù),實現(xiàn)了編譯期劫持,達到在對代碼幾乎無侵入的情況下,實現(xiàn)埋點。
Skywalking對大量的框架(比如: gin)提供了支持, 然后這種支持僅限于增加了tracing信息。我們知道完整的監(jiān)控往往離不開3個重要部分Metrics、Tracing、Logging。那些需要埋點的位置,往往這3種信息都是需要的,是否可以修改Skywalking-go,來達到代碼增強的過程同時添加Metrics、Tracing、Logging呢?答案是肯定的。
代碼參考
1)改動后的Skywalking-go
vearne/skywalking-go
注意: 如果讀者有自己改動的計劃,建議好好閱讀官方文檔,并參考萌叔的改動代碼
git diff f9929c6c9275b12f70ec2368544244f27a92f768
2) 測試項目
vearne/sw-test
2.解決問題
2.1 Tracing
tracing保持不變
2.2 Logging
Skywalking默認提供了對zap
、logrus
的劫持,因此可以直接在插件對應(yīng)的攔截器中增加對應(yīng)的日志即可
intercepter.go
package gin import ( "fmt" "github.com/gin-gonic/gin" // 需要增加的import "github.com/apache/skywalking-go/plugins/core/log" "github.com/apache/skywalking-go/plugins/core/operator" "github.com/apache/skywalking-go/plugins/core/prom" "github.com/apache/skywalking-go/plugins/core/tracing" ) type HTTPInterceptor struct { } ... func (h *HTTPInterceptor) AfterInvoke(invocation operator.Invocation, result ...interface{}) error { ... // add logging log.Infof("url:%v", context.Request.URL.Path) ... return nil }
經(jīng)過上訴改動以后,插件攔截器新增的日志,也會輸出到和業(yè)務(wù)日志相同的位置
2024-01-08 13:51:24 | info | url:/ping | {"SW_CTX": "[sw-test,e6966b62ade911eeb5565626e1cdcfe1@10.2.130.14,N/A,N/A,-1]"} 2024-01-08 13:51:24 | info | sw-test/main.go:76 | ping | {"setRes": 0, "SW_CTX": "[sw-test,e6966b62ade911eeb5565626e1cdcfe1@10.2.130.14,e6964894ade911eeb5565626e1cdcfe1.98.39164466848770001,e6964894ade911eeb5565626e1cdcfe1.98.39164466848770002,0]"}
可以看出每條日志都被添加了tracing信息,這有助于我們把tracing和對應(yīng)的日志關(guān)聯(lián)起來
zap
日志增強的示例
func New(core zapcore.Core, options ...Option) (skywalking_result_0 *Logger) { defer skywalking_enhance_automaticLoggerBindgo_uber_org_zap_New(&core,&options,&skywalking_result_0); /* 這個defer函數(shù)把返回的新創(chuàng)建的logger對象skywalking_result_0,保存在一個全局變量中 "New", "NewNop", "NewProduction", "NewDevelopment", "NewExample"也做了類似動作 */ if core == nil { return NewNop() } log := &Logger{ core: core, errorOutput: zapcore.Lock(os.Stderr), addStack: zapcore.FatalLevel + 1, clock: zapcore.DefaultClock, } return log.WithOptions(options...) }
2.2 Metrics
Skywalking-go也有提供的Metrics,但它的實現(xiàn)比較弱,另外萌叔的項目幾乎都使用的是Prometheus + Grafana,因此我們需要在插件中加入Prometheus的Metrics.
注意: 以下只敘述概要,完整代碼見vearne/skywalking-go
1) PromOperator
首先需要修改Operator的全局定義
common.go
type Operator interface { Tracing() interface{} // to TracingOperator Logger() interface{} // to LogOperator Tools() interface{} // to ToolsOperator DebugStack() []byte // Getting the stack of the current goroutine, for getting details when plugin broken. Entity() interface{} // Get the entity of the service Metrics() interface{} // to MetricsOperator LogReporter() interface{} // to LogReporter // 增加PromMetrics PromMetrics() interface{} // to PromOperator }
PromOperator
的接口定義位于 prom.go
PromOperator
的接口實現(xiàn)為PromWrapper
, 位于prometheus.go
2)在plugin中(此處為gin) 使用Metrics的示例
intercepter.go
import ( "fmt" "github.com/gin-gonic/gin" "github.com/apache/skywalking-go/plugins/core/log" "github.com/apache/skywalking-go/plugins/core/operator" // 需要增加的import "github.com/apache/skywalking-go/plugins/core/prom" "github.com/apache/skywalking-go/plugins/core/tracing" ) type HTTPInterceptor struct { } ... func (h *HTTPInterceptor) AfterInvoke(invocation operator.Invocation, result ...interface{}) error { // add metrics httpReqTotal := prom.GetOrNewCounterVec( "gin_requests_total", "Total number of gin HTTP requests made", []string{"method", "path", "status"}, ) httpReqTotal.With(map[string]string{ "method": context.Request.Method, "path": context.Request.URL.Path, "status": fmt.Sprintf("%d", context.Writer.Status()), }).(prom.Counter).Inc() return nil }
3)劫持 promhttp.Handler()
一般我們對prometheus的使用方式如下:
import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" "log" "net/http" ) var cpuTemp prometheus.Gauge func main() { cpuTemp = prometheus.NewGauge(prometheus.GaugeOpts{ Name: "cpu_temperature_celsius", Help: "Current temperature of the CPU.", }) prometheus.MustRegister(cpuTemp) http.Handle("/metrics", promhttp.Handler()) log.Fatal(http.ListenAndServe(":9090", nil)) }
prometheus.MustRegister()
會把監(jiān)控指標(biāo)cpuTemp注冊到prometheus.DefaultRegister
上,為了使得插件中DefaultRegister和業(yè)務(wù)應(yīng)用中使用Register
是同一個,需要為Prometheus開發(fā)一個代碼增強插件,劫持promhttp.Handler()
plugins/prometheus
import ( "github.com/apache/skywalking-go/plugins/core/log" "github.com/apache/skywalking-go/plugins/core/operator" "github.com/apache/skywalking-go/plugins/core/prom" "github.com/prometheus/client_golang/prometheus" ) type RegistryInterceptor struct { } func (h *RegistryInterceptor) BeforeInvoke(invocation operator.Invocation) error { return nil } func (h *RegistryInterceptor) AfterInvoke(invocation operator.Invocation, result ...interface{}) error { log.Infof("-----register prometheus------, %p\n", prometheus.DefaultRegisterer) prom.SetRegistry(prometheus.DefaultRegisterer) return nil }
3. 業(yè)務(wù)應(yīng)用
main.go
package main import ( "context" // 必須引入依賴包 _ "github.com/apache/skywalking-go" "github.com/gin-gonic/gin" "github.com/go-resty/resty/v2" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/redis/go-redis/v9" zlog "github.com/vearne/zaplog" "go.uber.org/zap" "golang.org/x/sync/errgroup" "net/http" ) var rdb *redis.Client func main() { zlog.InitLogger("/tmp/aa.log", "debug") // 添加Prometheus的相關(guān)監(jiān)控 // /metrics go func() { r := gin.Default() /* promhttp.Handler()調(diào)用后 prometheus.DefaultRegister會被注入到全局變量中 */ r.GET("/metrics", gin.WrapH(promhttp.Handler())) r.Run(":9090") }() //prometheus.NewRegistry() rdb = redis.NewClient(&redis.Options{ Addr: "localhost:6379", }) r := gin.Default() r.GET("/hello", func(c *gin.Context) { ... }) r.GET("/hello2", func(c *gin.Context) { ... }) r.GET("/ping", func(c *gin.Context) { ... }) r.Run(":8000") }
注意: go.mod中 需要用replace引入萌叔改動后的Skywalking-go
replace github.com/apache/skywalking-go => github.com/vearne/skywalking-go v0.3.0-1 require ( github.com/apache/skywalking-go v0.3.0-1 ... )
結(jié)果:監(jiān)控指標(biāo)使用正常
總結(jié)
Skywalking不僅僅可以用來增加tracing信息,它應(yīng)該被視為一個非常強大的代碼增強工具,具有很大的潛力。
以上就是Skywalking-go自動監(jiān)控增強使用探究的詳細內(nèi)容,更多關(guān)于go Skywalking自動監(jiān)控的資料請關(guān)注腳本之家其它相關(guān)文章!
- golang調(diào)試bug及性能監(jiān)控方式實踐總結(jié)
- golang?pprof?監(jiān)控goroutine?thread統(tǒng)計原理詳解
- golang?pprof監(jiān)控memory?block?mutex統(tǒng)計原理分析
- golang?pprof監(jiān)控memory?block?mutex使用指南
- golang?pprof?監(jiān)控系列?go?trace統(tǒng)計原理與使用解析
- prometheus?client_go為應(yīng)用程序自定義監(jiān)控指標(biāo)
- web項目中g(shù)olang性能監(jiān)控解析
- Go語言metrics應(yīng)用監(jiān)控指標(biāo)基本使用說明
相關(guān)文章
golang結(jié)合mysql設(shè)置最大連接數(shù)和最大空閑連接數(shù)
本文介紹golang?中連接MySQL時,如何設(shè)置最大連接數(shù)和最大空閑連接數(shù),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-02-02go語言數(shù)據(jù)結(jié)構(gòu)之前綴樹Trie
這篇文章主要介紹了go語言數(shù)據(jù)結(jié)構(gòu)之前綴樹Trie,文章圍繞主題展開詳細內(nèi)容介紹,具有一定得參考價值,需要的小伙伴可以參考一下2022-05-05