You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by li...@apache.org on 2023/07/11 05:08:04 UTC

[skywalking-go] branch main updated: Support log report to the backend (#68)

This is an automated email from the ASF dual-hosted git repository.

liuhan pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-go.git


The following commit(s) were added to refs/heads/main by this push:
     new 512efb2  Support log report to the backend (#68)
512efb2 is described below

commit 512efb2f1347f36e66cb827266c77e73ae70773d
Author: mrproliu <74...@qq.com>
AuthorDate: Tue Jul 11 05:07:59 2023 +0000

    Support log report to the backend (#68)
---
 .github/workflows/plugin-tests.yaml                |   2 +
 CHANGES.md                                         |   5 +
 go.work                                            |   2 +
 plugins/core/logreport.go                          |  87 +++++++++
 plugins/core/operator/common.go                    |  13 +-
 plugins/core/operator/logger.go                    |   4 +
 plugins/core/reporter/api.go                       |   2 +
 plugins/core/reporter/grpc/grpc.go                 |  46 +++++
 plugins/core/span_default.go                       |  11 ++
 plugins/core/span_noop.go                          |   8 +
 plugins/core/test_base.go                          |   7 +
 plugins/core/tracer.go                             |   6 +
 plugins/go-redisv9/go.mod                          |   5 +-
 plugins/go-redisv9/go.sum                          |  15 --
 plugins/gorm/go.mod                                |   2 +-
 plugins/gorm/go.sum                                |   2 +-
 plugins/runtimemetrics/instrument.go               |   2 +-
 test/plugins/scenarios/logrus/bin/startup.sh       |  24 +++
 test/plugins/scenarios/logrus/config/excepted.yml  |  67 +++++++
 test/plugins/scenarios/logrus/go.mod               |   8 +
 test/plugins/scenarios/logrus/go.sum               |  11 ++
 test/plugins/scenarios/logrus/main.go              |  67 +++++++
 test/plugins/scenarios/logrus/plugin.yml           |  30 ++++
 test/plugins/scenarios/zap/bin/startup.sh          |  24 +++
 test/plugins/scenarios/zap/config/excepted.yml     |  67 +++++++
 test/plugins/scenarios/zap/go.mod                  |   3 +
 test/plugins/scenarios/zap/go.sum                  |   0
 test/plugins/scenarios/zap/main.go                 |  66 +++++++
 test/plugins/scenarios/zap/plugin.yml              |  34 ++++
 tools/go-agent/config/agent.default.yaml           |   5 +
 tools/go-agent/config/loader.go                    |  30 +++-
 tools/go-agent/instrument/consts/operator.go       |  20 +--
 tools/go-agent/instrument/consts/tls.go            |   4 +-
 tools/go-agent/instrument/logger/context.go        |  70 +++++++-
 tools/go-agent/instrument/logger/context_test.go   |  17 +-
 tools/go-agent/instrument/logger/frameworks/api.go |  33 +++-
 .../instrument/logger/frameworks/logrus.go         |  11 +-
 .../instrument/logger/frameworks/logrus_adapt.go   |   4 +-
 .../instrument/logger/frameworks/logrus_format.go  |  26 ++-
 .../logger/frameworks/templates/init.tmpl          |  36 +++-
 tools/go-agent/instrument/logger/frameworks/zap.go | 194 +++++++++++++--------
 .../instrument/logger/frameworks/zap_core.go       |  61 +++++++
 .../frameworks/{zap_adapt.go => zap_root.go}       |  28 ++-
 tools/go-agent/instrument/logger/instrument.go     |  92 +++++++---
 tools/go-agent/instrument/plugins/rewrite/var.go   |   2 +-
 45 files changed, 1073 insertions(+), 180 deletions(-)

diff --git a/.github/workflows/plugin-tests.yaml b/.github/workflows/plugin-tests.yaml
index 21b57c3..714d805 100644
--- a/.github/workflows/plugin-tests.yaml
+++ b/.github/workflows/plugin-tests.yaml
@@ -79,6 +79,8 @@ jobs:
           - microv4
           - mongo
           - mysql
+          - zap
+          - logrus
           - plugin_exclusion
           - runtime_metrics
     steps:
diff --git a/CHANGES.md b/CHANGES.md
index e02b0fc..4dd0f75 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -8,12 +8,17 @@ Release Notes.
 * Enhance the plugin rewrite ability to support `switch` and `if/else` in the plugin codes.
 * Support inject the skywalking-go into project through agent.
 * Support add configuration for plugin.
+* Support metrics report API for plugin.
+* Support report Golang runtime metrics.
+* Support log reporter.
 
 #### Plugins
 * Support [go-redis](https://github.com/redis/go-redis) v9 redis client framework.
 * Support collecting [Native HTTP](https://pkg.go.dev/net/http) URI parameter on server side.
 * Support [Mongo](https://github.com/mongodb/mongo-go-driver) database client framework.
 * Support [Native SQL](https://pkg.go.dev/net/http) database client framework with [MySQL Driver](github.com/go-sql-driver/mysql).
+* Support [Logrus](https://github.com/sirupsen/logrus) log report to the backend.
+* Support [Zap](https://github.com/uber-go/zap) log report to the backend.
 
 #### Documentation
 
diff --git a/go.work b/go.work
index 0e4fc6e..a2d1d46 100644
--- a/go.work
+++ b/go.work
@@ -33,6 +33,8 @@ use (
 	./test/plugins/scenarios/microv4
 	./test/plugins/scenarios/mongo
 	./test/plugins/scenarios/mysql
+	./test/plugins/scenarios/logrus
+	./test/plugins/scenarios/zap
 
 	./test/plugins/scenarios/plugin_exclusion
 	./test/plugins/scenarios/runtime_metrics
diff --git a/plugins/core/logreport.go b/plugins/core/logreport.go
new file mode 100644
index 0000000..361b462
--- /dev/null
+++ b/plugins/core/logreport.go
@@ -0,0 +1,87 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package core
+
+import (
+	"time"
+
+	commonv3 "skywalking.apache.org/repo/goapi/collect/common/v3"
+	logv3 "skywalking.apache.org/repo/goapi/collect/logging/v3"
+)
+
+func (t *Tracer) LogReporter() interface{} {
+	return t
+}
+
+type logTracingContext interface {
+	GetServiceName() string
+	GetInstanceName() string
+	GetTraceID() string
+	GetTraceSegmentID() string
+	GetSpanID() int32
+	GetEndPointName() string
+}
+
+func (t *Tracer) ReportLog(ctx, timeObj interface{}, level, msg string, labels map[string]string) {
+	tracingContext, ok := ctx.(logTracingContext)
+	if !ok || tracingContext == nil {
+		return
+	}
+	entity := t.ServiceEntity
+	if entity == nil {
+		return
+	}
+	timeData := timeObj.(time.Time)
+
+	tags := &logv3.LogTags{
+		Data: []*commonv3.KeyStringValuePair{
+			{
+				Key:   "LEVEL",
+				Value: level,
+			},
+		},
+	}
+	for k, v := range labels {
+		tags.Data = append(tags.Data, &commonv3.KeyStringValuePair{
+			Key:   k,
+			Value: v,
+		})
+	}
+
+	logData := &logv3.LogData{
+		Timestamp:       Millisecond(timeData),
+		Service:         tracingContext.GetServiceName(),
+		ServiceInstance: tracingContext.GetInstanceName(),
+		Endpoint:        tracingContext.GetEndPointName(),
+		Body: &logv3.LogDataBody{
+			Type: "TEXT",
+			Content: &logv3.LogDataBody_Text{
+				Text: &logv3.TextLog{Text: msg},
+			},
+		},
+		TraceContext: &logv3.TraceContext{
+			TraceId:        tracingContext.GetTraceID(),
+			TraceSegmentId: tracingContext.GetTraceSegmentID(),
+			SpanId:         tracingContext.GetSpanID(),
+		},
+		Tags:  tags,
+		Layer: "GENERAL",
+	}
+
+	t.Reporter.SendLog(logData)
+}
diff --git a/plugins/core/operator/common.go b/plugins/core/operator/common.go
index 55260bb..dbe7684 100644
--- a/plugins/core/operator/common.go
+++ b/plugins/core/operator/common.go
@@ -23,12 +23,13 @@ var MetricsAppender = func(interface{}) {}
 var MetricsCollectAppender = func(func()) {}
 
 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
+	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
 }
 
 type Entity interface {
diff --git a/plugins/core/operator/logger.go b/plugins/core/operator/logger.go
index 53358e8..b7b0aef 100644
--- a/plugins/core/operator/logger.go
+++ b/plugins/core/operator/logger.go
@@ -27,3 +27,7 @@ type LogOperator interface {
 	Error(args ...interface{})
 	Errorf(format string, args ...interface{})
 }
+
+type LogReporter interface {
+	ReportLog(ctx, time interface{}, level, msg string, labels map[string]string)
+}
diff --git a/plugins/core/reporter/api.go b/plugins/core/reporter/api.go
index ce3b30a..02f9585 100644
--- a/plugins/core/reporter/api.go
+++ b/plugins/core/reporter/api.go
@@ -20,6 +20,7 @@ package reporter
 import (
 	commonv3 "skywalking.apache.org/repo/goapi/collect/common/v3"
 	agentv3 "skywalking.apache.org/repo/goapi/collect/language/agent/v3"
+	logv3 "skywalking.apache.org/repo/goapi/collect/logging/v3"
 )
 
 // Tag are supported by sky-walking engine.
@@ -108,6 +109,7 @@ type Reporter interface {
 	Boot(entity *Entity, cdsWatchers []AgentConfigChangeWatcher)
 	SendTracing(spans []ReportedSpan)
 	SendMetrics(metrics []ReportedMeter)
+	SendLog(log *logv3.LogData)
 	ConnectionStatus() ConnectionStatus
 	Close()
 }
diff --git a/plugins/core/reporter/grpc/grpc.go b/plugins/core/reporter/grpc/grpc.go
index 8013f67..cc30c76 100644
--- a/plugins/core/reporter/grpc/grpc.go
+++ b/plugins/core/reporter/grpc/grpc.go
@@ -30,6 +30,7 @@ import (
 
 	configuration "skywalking.apache.org/repo/goapi/collect/agent/configuration/v3"
 	agentv3 "skywalking.apache.org/repo/goapi/collect/language/agent/v3"
+	logv3 "skywalking.apache.org/repo/goapi/collect/logging/v3"
 	managementv3 "skywalking.apache.org/repo/goapi/collect/management/v3"
 
 	"github.com/apache/skywalking-go/plugins/core/operator"
@@ -48,6 +49,7 @@ func NewGRPCReporter(logger operator.LogOperator, serverAddr string, opts ...Rep
 		logger:           logger,
 		tracingSendCh:    make(chan *agentv3.SegmentObject, maxSendQueueSize),
 		metricsSendCh:    make(chan []*agentv3.MeterData, maxSendQueueSize),
+		logSendCh:        make(chan *logv3.LogData, maxSendQueueSize),
 		checkInterval:    defaultCheckInterval,
 		cdsInterval:      defaultCDSInterval, // cds default on
 		connectionStatus: reporter.ConnectionStatusConnected,
@@ -71,6 +73,7 @@ func NewGRPCReporter(logger operator.LogOperator, serverAddr string, opts ...Rep
 	r.conn = conn
 	r.traceClient = agentv3.NewTraceSegmentReportServiceClient(r.conn)
 	r.metricsClient = agentv3.NewMeterReportServiceClient(r.conn)
+	r.logClient = logv3.NewLogReportServiceClient(r.conn)
 	r.managementClient = managementv3.NewManagementServiceClient(r.conn)
 	if r.cdsInterval > 0 {
 		r.cdsClient = configuration.NewConfigurationDiscoveryServiceClient(r.conn)
@@ -84,9 +87,11 @@ type gRPCReporter struct {
 	logger           operator.LogOperator
 	tracingSendCh    chan *agentv3.SegmentObject
 	metricsSendCh    chan []*agentv3.MeterData
+	logSendCh        chan *logv3.LogData
 	conn             *grpc.ClientConn
 	traceClient      agentv3.TraceSegmentReportServiceClient
 	metricsClient    agentv3.MeterReportServiceClient
+	logClient        logv3.LogReportServiceClient
 	managementClient managementv3.ManagementServiceClient
 	checkInterval    time.Duration
 	cdsInterval      time.Duration
@@ -236,6 +241,19 @@ func (r *gRPCReporter) SendMetrics(metrics []reporter.ReportedMeter) {
 	}
 }
 
+func (r *gRPCReporter) SendLog(log *logv3.LogData) {
+	defer func() {
+		if err := recover(); err != nil {
+			r.logger.Errorf("reporter log err %v", err)
+		}
+	}()
+	select {
+	case r.logSendCh <- log:
+	default:
+		r.logger.Errorf("reach max logger send buffer")
+	}
+}
+
 func (r *gRPCReporter) convertLabels(labels map[string]string) []*agentv3.Label {
 	if len(labels) == 0 {
 		return nil
@@ -320,6 +338,27 @@ func (r *gRPCReporter) initSendPipeline() {
 			break
 		}
 	}()
+	go func() {
+	StreamLoop:
+		for {
+			stream, err := r.logClient.Collect(metadata.NewOutgoingContext(context.Background(), r.md))
+			if err != nil {
+				r.logger.Errorf("open stream error %v", err)
+				time.Sleep(5 * time.Second)
+				continue StreamLoop
+			}
+			for s := range r.logSendCh {
+				err = stream.Send(s)
+				if err != nil {
+					r.logger.Errorf("send log error %v", err)
+					r.closeLogStream(stream)
+					continue StreamLoop
+				}
+			}
+			r.closeLogStream(stream)
+			break
+		}
+	}()
 }
 
 func (r *gRPCReporter) initCDS(cdsWatchers []reporter.AgentConfigChangeWatcher) {
@@ -372,6 +411,13 @@ func (r *gRPCReporter) closeMetricsStream(stream agentv3.MeterReportService_Coll
 	}
 }
 
+func (r *gRPCReporter) closeLogStream(stream logv3.LogReportService_CollectClient) {
+	_, err := stream.CloseAndRecv()
+	if err != nil && err != io.EOF {
+		r.logger.Errorf("send closing error %v", err)
+	}
+}
+
 func (r *gRPCReporter) reportInstanceProperties() (err error) {
 	_, err = r.managementClient.ReportInstanceProperties(metadata.NewOutgoingContext(context.Background(), r.md), &managementv3.InstanceProperties{
 		Service:         r.entity.ServiceName,
diff --git a/plugins/core/span_default.go b/plugins/core/span_default.go
index 9f38401..0e53a17 100644
--- a/plugins/core/span_default.go
+++ b/plugins/core/span_default.go
@@ -191,3 +191,14 @@ func (ds *DefaultSpan) AsyncFinish() {
 	}
 	ds.AsyncModeFinished = true
 }
+
+func (ds *DefaultSpan) GetEndPointName() string {
+	if ds.SpanType == SpanTypeEntry {
+		return ds.OperationName
+	}
+	return ""
+}
+
+func (ds *DefaultSpan) GetParentSpan() interface{} {
+	return ds.Parent
+}
diff --git a/plugins/core/span_noop.go b/plugins/core/span_noop.go
index 4c40fbd..85cff00 100644
--- a/plugins/core/span_noop.go
+++ b/plugins/core/span_noop.go
@@ -99,3 +99,11 @@ func (n *NoopSpan) PrepareAsync() {
 
 func (n *NoopSpan) AsyncFinish() {
 }
+
+func (n *NoopSpan) GetEndPointName() string {
+	return ""
+}
+
+func (n *NoopSpan) GetParentSpan() interface{} {
+	return nil
+}
diff --git a/plugins/core/test_base.go b/plugins/core/test_base.go
index 148aaf1..5fa2ae3 100644
--- a/plugins/core/test_base.go
+++ b/plugins/core/test_base.go
@@ -22,6 +22,8 @@ import (
 
 	"github.com/apache/skywalking-go/plugins/core/operator"
 	"github.com/apache/skywalking-go/plugins/core/reporter"
+
+	logv3 "skywalking.apache.org/repo/goapi/collect/logging/v3"
 )
 
 var tlsData interface{}
@@ -66,6 +68,7 @@ func GetReportedSpans() []reporter.ReportedSpan {
 type StoreReporter struct {
 	Spans   []reporter.ReportedSpan
 	Metrics []reporter.ReportedMeter
+	Logs    []*logv3.LogData
 }
 
 func NewStoreReporter() *StoreReporter {
@@ -83,6 +86,10 @@ func (r *StoreReporter) SendMetrics(metrics []reporter.ReportedMeter) {
 	r.Metrics = append(r.Metrics, metrics...)
 }
 
+func (r *StoreReporter) SendLog(log *logv3.LogData) {
+	r.Logs = append(r.Logs, log)
+}
+
 func (r *StoreReporter) ConnectionStatus() reporter.ConnectionStatus {
 	return ReportConnectionStatus
 }
diff --git a/plugins/core/tracer.go b/plugins/core/tracer.go
index df0ef68..eedd3b2 100644
--- a/plugins/core/tracer.go
+++ b/plugins/core/tracer.go
@@ -26,6 +26,8 @@ import (
 
 	"github.com/apache/skywalking-go/plugins/core/operator"
 	"github.com/apache/skywalking-go/plugins/core/reporter"
+
+	logv3 "skywalking.apache.org/repo/goapi/collect/logging/v3"
 )
 
 // nolint
@@ -135,6 +137,10 @@ func (e *emptyReporter) SendTracing(spans []reporter.ReportedSpan) {
 func (e *emptyReporter) SendMetrics(metrics []reporter.ReportedMeter) {
 }
 
+// nolint
+func (e *emptyReporter) SendLog(log *logv3.LogData) {
+}
+
 func (e *emptyReporter) ConnectionStatus() reporter.ConnectionStatus {
 	return reporter.ConnectionStatusDisconnect
 }
diff --git a/plugins/go-redisv9/go.mod b/plugins/go-redisv9/go.mod
index 6260bf4..51b7dd1 100644
--- a/plugins/go-redisv9/go.mod
+++ b/plugins/go-redisv9/go.mod
@@ -2,12 +2,9 @@ module github.com/apache/skywalking-go/plugins/go-redisv9
 
 go 1.18
 
-require (
-	github.com/redis/go-redis/v9 v9.0.5
-)
+require github.com/redis/go-redis/v9 v9.0.5
 
 require (
 	github.com/cespare/xxhash/v2 v2.2.0 // indirect
-	github.com/dave/dst v0.27.2 // indirect
 	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
 )
diff --git a/plugins/go-redisv9/go.sum b/plugins/go-redisv9/go.sum
index b269a6f..51a6329 100644
--- a/plugins/go-redisv9/go.sum
+++ b/plugins/go-redisv9/go.sum
@@ -1,23 +1,8 @@
-github.com/apache/skywalking-go/plugins/core v0.0.0-20230531133153-0c54f7fe6e62 h1:geTGEa3GDXLbgAjJnzHliEVsL9rShyJMPI4oXdTuS+4=
-github.com/apache/skywalking-go/plugins/core v0.0.0-20230531133153-0c54f7fe6e62/go.mod h1:P0tAFNAYJUNsiTlFQgxmCcRcu+7Y0MP8GBZfSI449CM=
 github.com/bsm/ginkgo/v2 v2.7.0 h1:ItPMPH90RbmZJt5GtkcNvIRuGEdwlBItdNVoyzaNQao=
-github.com/bsm/ginkgo/v2 v2.7.0/go.mod h1:AiKlXPm7ItEHNc/2+OkrNG4E0ITzojb9/xWzvQ9XZ9w=
 github.com/bsm/gomega v1.26.0 h1:LhQm+AFcgV2M0WyKroMASzAzCAJVpAxQXv4SaI9a69Y=
-github.com/bsm/gomega v1.26.0/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
 github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
 github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
-github.com/dave/dst v0.27.2 h1:4Y5VFTkhGLC1oddtNwuxxe36pnyLxMFXT51FOzH8Ekc=
-github.com/dave/dst v0.27.2/go.mod h1:jHh6EOibnHgcUW3WjKHisiooEkYwqpHLBSX1iOBhEyc=
-github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
 github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
-github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
-github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 h1:EaDatTxkdHG+U3Bk4EUr+DZ7fOGwTfezUiUJMaIcaho=
-github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5/go.mod h1:fyalQWdtzDBECAQFBJuQe5bzQ02jGd5Qcbgb97Flm7U=
 github.com/redis/go-redis/v9 v9.0.5 h1:CuQcn5HIEeK7BgElubPP8CGtE0KakrnbBSTLjathl5o=
 github.com/redis/go-redis/v9 v9.0.5/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk=
-github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
-golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
-golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
-golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
-gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
diff --git a/plugins/gorm/go.mod b/plugins/gorm/go.mod
index 504358b..ee80d26 100644
--- a/plugins/gorm/go.mod
+++ b/plugins/gorm/go.mod
@@ -3,7 +3,7 @@ module github.com/apache/skywalking-go/plugins/gorm
 go 1.18
 
 require (
-	github.com/go-sql-driver/mysql v1.7.0
+	github.com/go-sql-driver/mysql v1.7.1
 	github.com/stretchr/testify v1.8.2
 	gorm.io/driver/mysql v1.5.1
 	gorm.io/gorm v1.25.1
diff --git a/plugins/gorm/go.sum b/plugins/gorm/go.sum
index 0fbbbcf..7a90168 100644
--- a/plugins/gorm/go.sum
+++ b/plugins/gorm/go.sum
@@ -1,5 +1,5 @@
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
-github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
+github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
 github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
 github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
 github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
diff --git a/plugins/runtimemetrics/instrument.go b/plugins/runtimemetrics/instrument.go
index cadf05a..082cada 100644
--- a/plugins/runtimemetrics/instrument.go
+++ b/plugins/runtimemetrics/instrument.go
@@ -35,7 +35,7 @@ func NewInstrument() *Instrument {
 }
 
 func (r *Instrument) Name() string {
-	return "runtime-metrics"
+	return "runtimemetrics"
 }
 
 func (r *Instrument) BasePackage() string {
diff --git a/test/plugins/scenarios/logrus/bin/startup.sh b/test/plugins/scenarios/logrus/bin/startup.sh
new file mode 100755
index 0000000..14e3ffa
--- /dev/null
+++ b/test/plugins/scenarios/logrus/bin/startup.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+home="$(cd "$(dirname $0)"; pwd)"
+go build ${GO_BUILD_OPTS} -o logrus
+
+export SW_AGENT_LOG_REPORTER_LABEL_KEYS=module
+
+./logrus
\ No newline at end of file
diff --git a/test/plugins/scenarios/logrus/config/excepted.yml b/test/plugins/scenarios/logrus/config/excepted.yml
new file mode 100644
index 0000000..983c4aa
--- /dev/null
+++ b/test/plugins/scenarios/logrus/config/excepted.yml
@@ -0,0 +1,67 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+segmentItems: []
+meterItems: []
+logItems:
+  - serviceName: logrus
+    logSize: ge 3
+    logs:
+      - timestamp: nq 0
+        endpoint: ''
+        body:
+          type: TEXT
+          content: { text: 'fetch dynamic configuration error rpc error: code = Unimplemented
+              desc = Method not found: skywalking.v3.ConfigurationDiscoveryService/fetchConfigurations' }
+        traceContext: { traceId: N/A, traceSegmentId: N/A, spanId: -1 }
+        tags:
+          data:
+            - { key: LEVEL, value: error }
+        layer: GENERAL
+      - timestamp: nq 0
+        endpoint: GET:/provider
+        body:
+          type: TEXT
+          content:
+            text: providerHandler
+        traceContext:
+          traceId: not null
+          traceSegmentId: not null
+          spanId: 0
+        tags:
+          data:
+            - key: LEVEL
+              value: info
+            - key: module
+              value: test-service
+        layer: GENERAL
+      - timestamp: nq 0
+        endpoint: GET:/consumer
+        body:
+          type: TEXT
+          content:
+            text: consumerHandler
+        traceContext:
+          traceId: not null
+          traceSegmentId: not null
+          spanId: 0
+        tags:
+          data:
+            - key: LEVEL
+              value: info
+            - key: module
+              value: test-service
+        layer: GENERAL
diff --git a/test/plugins/scenarios/logrus/go.mod b/test/plugins/scenarios/logrus/go.mod
new file mode 100644
index 0000000..82a3a0f
--- /dev/null
+++ b/test/plugins/scenarios/logrus/go.mod
@@ -0,0 +1,8 @@
+module test/plugins/scenarios/logrus
+
+go 1.18
+
+require (
+	github.com/sirupsen/logrus v1.9.3 // indirect
+	golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
+)
diff --git a/test/plugins/scenarios/logrus/go.sum b/test/plugins/scenarios/logrus/go.sum
new file mode 100644
index 0000000..2cbdecd
--- /dev/null
+++ b/test/plugins/scenarios/logrus/go.sum
@@ -0,0 +1,11 @@
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
+github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/test/plugins/scenarios/logrus/main.go b/test/plugins/scenarios/logrus/main.go
new file mode 100644
index 0000000..fd43394
--- /dev/null
+++ b/test/plugins/scenarios/logrus/main.go
@@ -0,0 +1,67 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package main
+
+import (
+	"io"
+	"net/http"
+
+	"github.com/sirupsen/logrus"
+
+	_ "github.com/apache/skywalking-go"
+)
+
+var (
+	log = logrus.WithField("module", "test-service")
+)
+
+func providerHandler(w http.ResponseWriter, r *http.Request) {
+	log.Infof("providerHandler")
+	_, _ = w.Write([]byte("success"))
+}
+
+func consumerHandler(w http.ResponseWriter, r *http.Request) {
+	resp, err := http.Get("http://localhost:8080/provider?test=1")
+	if err != nil {
+		log.Printf("request provider error: %v", err)
+		w.WriteHeader(http.StatusInternalServerError)
+		return
+	}
+	defer resp.Body.Close()
+	body, err := io.ReadAll(resp.Body)
+	if err != nil {
+		log.Print(err)
+		w.WriteHeader(http.StatusInternalServerError)
+		return
+	}
+	log.Infof("consumerHandler")
+	_, _ = w.Write(body)
+}
+
+func main() {
+	logrus.SetFormatter(&logrus.JSONFormatter{})
+
+	http.HandleFunc("/provider", providerHandler)
+	http.HandleFunc("/consumer", consumerHandler)
+
+	http.HandleFunc("/health", func(writer http.ResponseWriter, request *http.Request) {
+		writer.WriteHeader(http.StatusOK)
+	})
+
+	_ = http.ListenAndServe(":8080", nil)
+}
diff --git a/test/plugins/scenarios/logrus/plugin.yml b/test/plugins/scenarios/logrus/plugin.yml
new file mode 100644
index 0000000..eb2cd80
--- /dev/null
+++ b/test/plugins/scenarios/logrus/plugin.yml
@@ -0,0 +1,30 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+entry-service: http://${HTTP_HOST}:${HTTP_PORT}/consumer
+health-checker: http://${HTTP_HOST}:${HTTP_PORT}/health
+start-script: ./bin/startup.sh
+framework: github.com/sirupsen/logrus
+export-port: 8080
+support-version:
+  - go: 1.18
+    framework:
+      - v1.8.2
+      - v1.8.3
+      - v1.9.0
+      - v1.9.1
+      - v1.9.2
+      - v1.9.3
diff --git a/test/plugins/scenarios/zap/bin/startup.sh b/test/plugins/scenarios/zap/bin/startup.sh
new file mode 100755
index 0000000..3ae8704
--- /dev/null
+++ b/test/plugins/scenarios/zap/bin/startup.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+home="$(cd "$(dirname $0)"; pwd)"
+go build ${GO_BUILD_OPTS} -o zap
+
+export SW_AGENT_LOG_REPORTER_LABEL_KEYS=module
+
+./zap
\ No newline at end of file
diff --git a/test/plugins/scenarios/zap/config/excepted.yml b/test/plugins/scenarios/zap/config/excepted.yml
new file mode 100644
index 0000000..0b927f9
--- /dev/null
+++ b/test/plugins/scenarios/zap/config/excepted.yml
@@ -0,0 +1,67 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+segmentItems: []
+meterItems: []
+logItems:
+  - serviceName: zap
+    logSize: ge 3
+    logs:
+      - timestamp: nq 0
+        endpoint: ''
+        body:
+          type: TEXT
+          content: { text: 'fetch dynamic configuration error rpc error: code = Unimplemented
+              desc = Method not found: skywalking.v3.ConfigurationDiscoveryService/fetchConfigurations' }
+        traceContext: { traceId: N/A, traceSegmentId: N/A, spanId: -1 }
+        tags:
+          data:
+            - { key: LEVEL, value: error }
+        layer: GENERAL
+      - timestamp: nq 0
+        endpoint: GET:/provider
+        body:
+          type: TEXT
+          content:
+            text: providerHandler
+        traceContext:
+          traceId: not null
+          traceSegmentId: not null
+          spanId: 0
+        tags:
+          data:
+            - key: LEVEL
+              value: info
+            - key: module
+              value: test-service-provider
+        layer: GENERAL
+      - timestamp: nq 0
+        endpoint: GET:/consumer
+        body:
+          type: TEXT
+          content:
+            text: consumerHandler
+        traceContext:
+          traceId: not null
+          traceSegmentId: not null
+          spanId: 0
+        tags:
+          data:
+            - key: LEVEL
+              value: info
+            - key: module
+              value: test-service-consumer
+        layer: GENERAL
diff --git a/test/plugins/scenarios/zap/go.mod b/test/plugins/scenarios/zap/go.mod
new file mode 100644
index 0000000..02bec57
--- /dev/null
+++ b/test/plugins/scenarios/zap/go.mod
@@ -0,0 +1,3 @@
+module test/plugins/scenarios/zap
+
+go 1.18
diff --git a/test/plugins/scenarios/zap/go.sum b/test/plugins/scenarios/zap/go.sum
new file mode 100644
index 0000000..e69de29
diff --git a/test/plugins/scenarios/zap/main.go b/test/plugins/scenarios/zap/main.go
new file mode 100644
index 0000000..9ed157f
--- /dev/null
+++ b/test/plugins/scenarios/zap/main.go
@@ -0,0 +1,66 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package main
+
+import (
+	"io"
+	"net/http"
+
+	"go.uber.org/zap"
+
+	_ "github.com/apache/skywalking-go"
+)
+
+var (
+	logger, _ = zap.NewProduction()
+	log       = logger.Sugar()
+)
+
+func providerHandler(w http.ResponseWriter, r *http.Request) {
+	log.With("module", "test-service-provider").Info("providerHandler")
+	_, _ = w.Write([]byte("success"))
+}
+
+func consumerHandler(w http.ResponseWriter, r *http.Request) {
+	resp, err := http.Get("http://localhost:8080/provider?test=1")
+	if err != nil {
+		log.Warnf("request provider, error: %v", err)
+		w.WriteHeader(http.StatusInternalServerError)
+		return
+	}
+	defer resp.Body.Close()
+	body, err := io.ReadAll(resp.Body)
+	if err != nil {
+		log.Warn(err)
+		w.WriteHeader(http.StatusInternalServerError)
+		return
+	}
+	log.With("module", "test-service-consumer").Info("consumerHandler")
+	_, _ = w.Write(body)
+}
+
+func main() {
+	http.HandleFunc("/provider", providerHandler)
+	http.HandleFunc("/consumer", consumerHandler)
+
+	http.HandleFunc("/health", func(writer http.ResponseWriter, request *http.Request) {
+		writer.WriteHeader(http.StatusOK)
+	})
+
+	_ = http.ListenAndServe(":8080", nil)
+}
diff --git a/test/plugins/scenarios/zap/plugin.yml b/test/plugins/scenarios/zap/plugin.yml
new file mode 100644
index 0000000..c066873
--- /dev/null
+++ b/test/plugins/scenarios/zap/plugin.yml
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+entry-service: http://${HTTP_HOST}:${HTTP_PORT}/consumer
+health-checker: http://${HTTP_HOST}:${HTTP_PORT}/health
+start-script: ./bin/startup.sh
+framework: go.uber.org/zap
+export-port: 8080
+support-version:
+  - go: 1.18
+    framework:
+      - v1.17.0
+      - v1.18.0
+      - v1.18.1
+      - v1.19.0
+      - v1.19.1
+      - v1.20.0
+      - v1.21.0
+      - v1.22.0
+      - v1.23.0
+      - v1.24.0
diff --git a/tools/go-agent/config/agent.default.yaml b/tools/go-agent/config/agent.default.yaml
index 02fa6ba..2cafd61 100644
--- a/tools/go-agent/config/agent.default.yaml
+++ b/tools/go-agent/config/agent.default.yaml
@@ -51,6 +51,11 @@ log:
     enable: ${SW_AGENT_LOG_TRACING_ENABLE:true}
     # If tracing information is enabled, the tracing information would be stored in the current Key in each log.
     key: ${SW_AGENT_LOG_TRACING_KEY:SW_CTX}
+  reporter:
+    # Whether to upload logs to the backend.
+    enable: ${SW_AGENT_LOG_REPORTER_ENABLE:true}
+    # The fields name list that needs to added to the label of the log.(multiple split by ",")
+    label_keys: ${SW_AGENT_LOG_REPORTER_LABEL_KEYS:}
 
 plugin:
   # List the names of excluded plugins, multiple plugin names should be splitted by ","
diff --git a/tools/go-agent/config/loader.go b/tools/go-agent/config/loader.go
index 8d9324d..28e2897 100644
--- a/tools/go-agent/config/loader.go
+++ b/tools/go-agent/config/loader.go
@@ -56,8 +56,9 @@ type Reporter struct {
 }
 
 type Log struct {
-	Type    StringValue `yaml:"type"`
-	Tracing LogTracing  `yaml:"tracing"`
+	Type     StringValue `yaml:"type"`
+	Tracing  LogTracing  `yaml:"tracing"`
+	Reporter LogReporter `yaml:"reporter"`
 }
 
 type LogTracing struct {
@@ -65,6 +66,11 @@ type LogTracing struct {
 	Key     StringValue `yaml:"key"`
 }
 
+type LogReporter struct {
+	Enabled   StringValue `yaml:"enable"`
+	LabelKeys StringValue `yaml:"label_keys"`
+}
+
 type Meter struct {
 	CollectInterval StringValue `yaml:"collect_interval"`
 }
@@ -181,6 +187,26 @@ func (s *StringValue) ToGoStringValue() string {
 }()`, s.EnvKey, s.Default, s.EnvKey, s.Default), "\n", ";")
 }
 
+func (s *StringValue) ToGoStringListValue() string {
+	return strings.ReplaceAll(fmt.Sprintf(`func() []string {
+	splitResult := func(s string) []string {
+		t := strings.Split(s, ",")
+		if len(t) == 1 && t[0] == "" { return nil }
+		res := make([]string, 0, 0)
+		for _, v := range t {
+			if v != "" {
+				res = append(res, v)
+			}
+		}
+		return res
+	}
+	if "%s" == "" { return splitResult("%s") }
+	tmpValue := os.Getenv("%s")
+	if tmpValue == "" { return splitResult("%s") }
+	return splitResult(tmpValue)
+}()`, s.EnvKey, s.Default, s.EnvKey, s.Default), "\n", ";")
+}
+
 func (s *StringValue) ToGoStringFunction() string {
 	return fmt.Sprintf("func() string { return %s }", s.ToGoStringValue())
 }
diff --git a/tools/go-agent/instrument/consts/operator.go b/tools/go-agent/instrument/consts/operator.go
index da8ff5c..a9b726b 100644
--- a/tools/go-agent/instrument/consts/operator.go
+++ b/tools/go-agent/instrument/consts/operator.go
@@ -27,16 +27,16 @@ const (
 
 	GlobalTracerSnapshotInterface = "skywalkingGoroutineSnapshotCreator"
 
-	GlobalTracerSetMethodName              = "_skywalking_set_global_operator"
-	GlobalTracerGetMethodName              = "_skywalking_get_global_operator"
-	GlobalLoggerSetMethodName              = "_skywalking_set_global_logger"
-	GlobalLoggerGetMethodName              = "_skywalking_get_global_logger"
-	GlobalTracerInitAppendNotifyMethodName = "_skywalking_global_init_append_notify"
-	GlobalTracerInitGetNotifyMethodName    = "_skywalking_global_init_get_notify"
+	GlobalTracerSetMethodName              = "skywalking_set_global_operator"
+	GlobalTracerGetMethodName              = "skywalking_get_global_operator"
+	GlobalLoggerSetMethodName              = "skywalking_set_global_logger"
+	GlobalLoggerGetMethodName              = "skywalking_get_global_logger"
+	GlobalTracerInitAppendNotifyMethodName = "skywalking_global_init_append_notify"
+	GlobalTracerInitGetNotifyMethodName    = "skywalking_global_init_get_notify"
 
-	MetricsRegisterAppendMethodName = "_skywalking_metrics_register_append"
-	MetricsObtainMethodName         = "_skywalking_metrics_obtain"
-	MetricsHookAppendMethodName     = "_skywalking_metrics_hook_append"
+	MetricsRegisterAppendMethodName = "skywalking_metrics_register_append"
+	MetricsObtainMethodName         = "skywalking_metrics_obtain"
+	MetricsHookAppendMethodName     = "skywalking_metrics_hook_append"
 
-	CurrentGoroutineIDGetMethodName = "_skywalking_get_goid"
+	CurrentGoroutineIDGetMethodName = "skywalking_get_goid"
 )
diff --git a/tools/go-agent/instrument/consts/tls.go b/tools/go-agent/instrument/consts/tls.go
index 7395ffa..b28e4ac 100644
--- a/tools/go-agent/instrument/consts/tls.go
+++ b/tools/go-agent/instrument/consts/tls.go
@@ -19,6 +19,6 @@ package consts
 
 const (
 	TLSFieldName     = "skywalking_tls"
-	TLSGetMethodName = "_skywalking_get_gls"
-	TLSSetMethodName = "_skywalking_set_gls"
+	TLSGetMethodName = "skywalking_get_gls"
+	TLSSetMethodName = "skywalking_set_gls"
 )
diff --git a/tools/go-agent/instrument/logger/context.go b/tools/go-agent/instrument/logger/context.go
index 54e73f5..25defd3 100644
--- a/tools/go-agent/instrument/logger/context.go
+++ b/tools/go-agent/instrument/logger/context.go
@@ -28,6 +28,7 @@ type Operator interface {
 	Tracing() interface{}
 	ChangeLogger(logger interface{})
 	Entity() interface{}
+	LogReporter() interface{}
 }
 
 type TracingOperator interface {
@@ -38,6 +39,8 @@ type TracingSpan interface {
 	GetTraceID() string
 	GetSegmentID() string
 	GetSpanID() int32
+	GetEndPointName() string
+	GetParentSpan() interface{}
 }
 
 type Entity interface {
@@ -60,24 +63,60 @@ func (span *NoopSpan) GetSpanID() int32 {
 	return -1
 }
 
+func (span *NoopSpan) GetParentSpan() interface{} {
+	return nil
+}
+
+func (span *NoopSpan) GetEndPointName() string {
+	return ""
+}
+
 type SkyWalkingLogContext struct {
 	ServiceName    string
 	InstanceName   string
 	TraceID        string
+	EndPoint       string
 	TraceSegmentID string
 	SpanID         int32
 }
 
+func (s *SkyWalkingLogContext) GetServiceName() string {
+	return s.ServiceName
+}
+
+func (s *SkyWalkingLogContext) GetInstanceName() string {
+	return s.InstanceName
+}
+
+func (s *SkyWalkingLogContext) GetTraceID() string {
+	return s.TraceID
+}
+
+func (s *SkyWalkingLogContext) GetTraceSegmentID() string {
+	return s.TraceSegmentID
+}
+
+func (s *SkyWalkingLogContext) GetSpanID() int32 {
+	return s.SpanID
+}
+
+func (s *SkyWalkingLogContext) GetEndPointName() string {
+	return s.EndPoint
+}
+
 var noopContext = &NoopSpan{}
 
-func GetLogContext() *SkyWalkingLogContext {
+func GetLogContext(withEndpoint bool) *SkyWalkingLogContext {
 	operator := GetOperator()
 	var activeSpan TracingSpan = noopContext
-	var serviceName, instanceName string
+	var serviceName, instanceName, endpoint string
 	if operator != nil {
 		tracingOperator := operator.Tracing().(TracingOperator)
-		if s, ok := tracingOperator.ActiveSpan().(TracingSpan); ok {
+		if s, ok := tracingOperator.ActiveSpan().(TracingSpan); ok && s != nil {
 			activeSpan = s
+			if withEndpoint {
+				endpoint = findEndpointNameBySpan(s)
+			}
 		}
 		entity := operator.Entity()
 		if entity != nil {
@@ -92,14 +131,31 @@ func GetLogContext() *SkyWalkingLogContext {
 		TraceID:        activeSpan.GetTraceID(),
 		TraceSegmentID: activeSpan.GetSegmentID(),
 		SpanID:         activeSpan.GetSpanID(),
+		EndPoint:       endpoint,
+	}
+}
+
+func findEndpointNameBySpan(s TracingSpan) string {
+	tmp := s
+	for tmp != nil {
+		if name := tmp.GetEndPointName(); name != "" {
+			return name
+		}
+		parent := tmp.GetParentSpan()
+		if parentTmp, ok := parent.(TracingSpan); ok && parentTmp != nil {
+			tmp = parentTmp
+		} else {
+			tmp = nil
+		}
 	}
+	return ""
 }
 
 func GetLogContextString() string {
-	return GetLogContext().String()
+	return GetLogContext(false).String()
 }
 
-func (context *SkyWalkingLogContext) String() string {
-	return fmt.Sprintf("[%s,%s,%s,%s,%d]", context.ServiceName, context.InstanceName,
-		context.TraceID, context.TraceSegmentID, context.SpanID)
+func (s *SkyWalkingLogContext) String() string {
+	return fmt.Sprintf("[%s,%s,%s,%s,%d]", s.ServiceName, s.InstanceName,
+		s.TraceID, s.TraceSegmentID, s.SpanID)
 }
diff --git a/tools/go-agent/instrument/logger/context_test.go b/tools/go-agent/instrument/logger/context_test.go
index 4642209..6469cd4 100644
--- a/tools/go-agent/instrument/logger/context_test.go
+++ b/tools/go-agent/instrument/logger/context_test.go
@@ -32,19 +32,32 @@ func init() {
 	}
 }
 
+type ExtractorWrapper struct {
+	F func(headerKey string) (string, error)
+}
+
+func (e *ExtractorWrapper) Fun() func(headerKey string) (string, error) {
+	return e.F
+}
+
 func TestGetLogContext(t *testing.T) {
 	serviceName := "test-service"
 	serviceInstanceName := "test-instance"
 	core.Tracing.ServiceEntity = &reporter.Entity{ServiceName: serviceName, ServiceInstanceName: serviceInstanceName}
-	s, err := core.Tracing.CreateLocalSpan("/test")
+	s, err := core.Tracing.CreateEntrySpan("/test", &ExtractorWrapper{
+		F: func(headerKey string) (string, error) {
+			return "", nil
+		},
+	})
 	assert.Nil(t, err, "err should be nil")
 	assert.NotNil(t, s, "span cannot be nil")
-	context := GetLogContext()
+	context := GetLogContext(true)
 	assert.NotNil(t, context, "context cannot be nil")
 	rootSpan, ok := s.(*core.RootSegmentSpan)
 	assert.True(t, ok, "span should be root span")
 	assert.Equal(t, serviceName, context.ServiceName, "service name should be equal")
 	assert.Equal(t, serviceInstanceName, serviceInstanceName, "service instance name should be equal")
+	assert.Equal(t, "/test", context.GetEndPointName(), "endpoint name should be equal")
 	assert.Equal(t, rootSpan.Context().GetTraceID(), context.TraceID, "trace id should be equal")
 	assert.Equal(t, rootSpan.Context().GetSegmentID(), context.TraceSegmentID, "trace segment id should be equal")
 	assert.Equal(t, rootSpan.Context().GetSpanID(), context.SpanID, "span id should be equal")
diff --git a/tools/go-agent/instrument/logger/frameworks/api.go b/tools/go-agent/instrument/logger/frameworks/api.go
index 9f44234..c6c9a65 100644
--- a/tools/go-agent/instrument/logger/frameworks/api.go
+++ b/tools/go-agent/instrument/logger/frameworks/api.go
@@ -19,6 +19,8 @@ package frameworks
 
 import (
 	"embed"
+	"fmt"
+	"time"
 
 	"github.com/apache/skywalking-go/plugins/core/operator"
 	"github.com/apache/skywalking-go/tools/go-agent/instrument/plugins/rewrite"
@@ -37,14 +39,21 @@ var ChangeLogger = func(i operator.LogOperator) {
 }
 
 // LogTracingContextEnable check log the tracing context enable
-var LogTracingContextEnable = func() bool {
-	return false
-}
+var LogTracingContextEnable = false
+
+// LogReporterEnable check log the reporter enable
+var LogReporterEnable = false
+
+// LogReporterLabelKeys get the reporter customized label keys
+var LogReporterLabelKeys []string
 
 // LogTracingContextKey get the tracing context key
 // nolint
-var LogTracingContextKey = func() string {
-	return "SW_CTX"
+var LogTracingContextKey = "SW_CTX"
+
+// GetLogContext get the tracing context
+var GetLogContext = func(withEndpoint bool) fmt.Stringer {
+	return nil
 }
 
 // GetLogContextString get the log context string
@@ -52,15 +61,23 @@ func GetLogContextString() string {
 	return ""
 }
 
+// ReportLog report the log to backend
+var ReportLog = func(ctx interface{}, time time.Time, level, msg string, labels map[string]string) {
+}
+
 type PackageConfiguration struct {
 	// needs to generate the operator helpers
 	NeedsHelpers bool
+	// needs to generate the operator variables
+	NeedsVariables bool
+	// needs the change logger method
+	NeedsChangeLoggerFunc bool
 }
 
 type LogFramework interface {
 	// Name of the framework
 	Name() string
-	// PackagePaths of the framework, define which package needs to be instrument
+	// PackagePaths of the framework, define which package needs to be instrumented
 	PackagePaths() map[string]*PackageConfiguration
 	// AutomaticBindFunctions if the filtered method invoke and log type is automatic detect,
 	// then when the method invoke, the log type would be current framework
@@ -69,4 +86,8 @@ type LogFramework interface {
 	GenerateExtraFiles(pkgPath, debugDir string) ([]*rewrite.FileInfo, error)
 	// CustomizedEnhance used to customized enhance the log framework
 	CustomizedEnhance(path string, curFile *dst.File, cursor *dstutil.Cursor, allFiles []*dst.File) (map[string]string, bool)
+	// InitFunctions used to init the log framework
+	InitFunctions() []*dst.FuncDecl
+	// InitImports used to import the log framework when init functions
+	InitImports() []*dst.ImportSpec
 }
diff --git a/tools/go-agent/instrument/logger/frameworks/logrus.go b/tools/go-agent/instrument/logger/frameworks/logrus.go
index 93cbb5d..ea048ee 100644
--- a/tools/go-agent/instrument/logger/frameworks/logrus.go
+++ b/tools/go-agent/instrument/logger/frameworks/logrus.go
@@ -40,9 +40,10 @@ func (l *Logrus) Name() string {
 }
 
 func (l *Logrus) PackagePaths() map[string]*PackageConfiguration {
-	return map[string]*PackageConfiguration{"github.com/sirupsen/logrus": {NeedsHelpers: true}}
+	return map[string]*PackageConfiguration{"github.com/sirupsen/logrus": {NeedsHelpers: true, NeedsVariables: true, NeedsChangeLoggerFunc: true}}
 }
 
+//nolint
 func (l *Logrus) AutomaticBindFunctions(fun *dst.FuncDecl) string {
 	// if init the output or format then the logrus would be bind
 	if fun.Recv == nil || len(fun.Recv.List) != 1 || tools.GenerateTypeNameByExp(fun.Recv.List[0].Type) != "*Logger" {
@@ -79,3 +80,11 @@ func (l *Logrus) generateReWriteFile(name, debugDir string) *rewrite.FileInfo {
 func (l *Logrus) CustomizedEnhance(path string, curFile *dst.File, cursor *dstutil.Cursor, allFiles []*dst.File) (map[string]string, bool) {
 	return nil, false
 }
+
+func (l *Logrus) InitFunctions() []*dst.FuncDecl {
+	return nil
+}
+
+func (l *Logrus) InitImports() []*dst.ImportSpec {
+	return nil
+}
diff --git a/tools/go-agent/instrument/logger/frameworks/logrus_adapt.go b/tools/go-agent/instrument/logger/frameworks/logrus_adapt.go
index 3d82cc9..adba5a5 100644
--- a/tools/go-agent/instrument/logger/frameworks/logrus_adapt.go
+++ b/tools/go-agent/instrument/logger/frameworks/logrus_adapt.go
@@ -26,9 +26,9 @@ func init() {
 }
 
 func UpdateLogrusLogger(l *logrus.Logger) {
-	if LogTracingContextEnable() {
+	if LogTracingContextEnable {
 		if _, wrapperd := l.Formatter.(*WrapFormat); !wrapperd {
-			l.Formatter = Wrap(l.Formatter, LogTracingContextKey())
+			l.Formatter = Wrap(l.Formatter, LogTracingContextKey)
 		}
 	}
 	ChangeLogger(NewLogrusAdapter(l))
diff --git a/tools/go-agent/instrument/logger/frameworks/logrus_format.go b/tools/go-agent/instrument/logger/frameworks/logrus_format.go
index 1d2c88b..dc6294f 100644
--- a/tools/go-agent/instrument/logger/frameworks/logrus_format.go
+++ b/tools/go-agent/instrument/logger/frameworks/logrus_format.go
@@ -18,6 +18,8 @@
 package frameworks
 
 import (
+	"fmt"
+
 	"github.com/sirupsen/logrus"
 )
 
@@ -39,8 +41,30 @@ func Wrap(base logrus.Formatter, contextKey string) *WrapFormat {
 
 // Format logging with trace context
 func (format *WrapFormat) Format(entry *logrus.Entry) ([]byte, error) {
+	var logContext fmt.Stringer
+	keys := LogReporterLabelKeys
+	if LogReporterEnable {
+		ctx := GetLogContext(true)
+		if ctx == nil {
+			return format.Base.Format(entry)
+		}
+		logContext = ctx
+		labels := make(map[string]string, len(keys))
+		for _, key := range keys {
+			for k, v := range entry.Data {
+				if k == key {
+					labels[key] = fmt.Sprintf("%v", v)
+				}
+			}
+		}
+		ReportLog(ctx, entry.Time, entry.Level.String(), entry.Message, labels)
+	}
 	// append trace context
-	entry.Data[format.traceContextKey] = GetLogContextString()
+	if logContext == nil {
+		entry.Data[format.traceContextKey] = GetLogContextString()
+	} else {
+		entry.Data[format.traceContextKey] = logContext.String()
+	}
 
 	return format.Base.Format(entry)
 }
diff --git a/tools/go-agent/instrument/logger/frameworks/templates/init.tmpl b/tools/go-agent/instrument/logger/frameworks/templates/init.tmpl
index 400ea4c..705d96b 100644
--- a/tools/go-agent/instrument/logger/frameworks/templates/init.tmpl
+++ b/tools/go-agent/instrument/logger/frameworks/templates/init.tmpl
@@ -1,9 +1,15 @@
-package {{.PackageName}}
-
 import (
 	_ "unsafe"
+	"time"
+	{{- if .NeedsVariables}}
 	"os"
 	"strings"
+	{{- end}}
+
+	// customized imports
+	{{- range $key, $value := .Imports}}
+	{{$key}} {{$value}}
+    {{- end}}
 )
 
 //go:linkname {{.GetGlobalOperatorLinkMethod}} {{.GetGlobalOperatorLinkMethod}}
@@ -12,8 +18,23 @@ var {{.GetGlobalOperatorLinkMethod}} func() interface{}
 //go:linkname {{.SetGlobalLoggerLinkMethod}} {{.SetGlobalLoggerLinkMethod}}
 var {{.SetGlobalLoggerLinkMethod}} func(v interface{})
 
-var {{.LogTracingEnableFuncName}} = {{.LogTypeInConfig.Tracing.Enabled.ToGoBoolFunction}}
-var {{.LogTracingContextKeyFuncName}} = {{.LogTypeInConfig.Tracing.Key.ToGoStringFunction}}
+{{- if .NeedsVariables}}
+var {{.LogTracingEnableVarName}} = {{.LogTypeInConfig.Tracing.Enabled.ToGoBoolValue}}
+var {{.LogTracingContextKeyVarName}} = {{.LogTypeInConfig.Tracing.Key.ToGoStringValue}}
+var {{.LogReporterEnableVarName}} = {{.LogTypeInConfig.Reporter.Enabled.ToGoBoolValue}}
+var {{.LogReporterLabelsVarName}} = {{.LogTypeInConfig.Reporter.LabelKeys.ToGoStringListValue}}
+{{- end}}
+
+type logReporter interface {
+    ReportLog(ctx, time interface{}, level, msg string, labels map[string]string)
+}
+var {{.LogReportFuncName}} = func(ctx interface{}, time time.Time, level, msg string, labels map[string]string) {
+    op := {{.GetOperatorMethodName}}()
+    if op == nil {
+        return
+    }
+    op.LogReporter().(logReporter).ReportLog(ctx, time, level, msg, labels)
+}
 
 func init() {
 	// for context.go getting operator
@@ -29,6 +50,7 @@ func init() {
 	}
 
 	// for context.go change logger
+	{{- if .NeedsChangeLoggerFunc}}
 	if {{.SetGlobalLoggerLinkMethod}} != nil {
 		logType := {{.LogTypeInConfig.Type.ToGoStringValue}}
 		supportLogChange := false
@@ -49,4 +71,10 @@ func init() {
 			{{.SetGlobalLoggerLinkMethod}}(logger)
 		}
 	}
+	{{- end}}
+
+	// init all log initiator
+	{{- range .InitFunctionNames}}
+    {{.}}()
+    {{- end}}
 }
\ No newline at end of file
diff --git a/tools/go-agent/instrument/logger/frameworks/zap.go b/tools/go-agent/instrument/logger/frameworks/zap.go
index e9e02bb..6af67d3 100644
--- a/tools/go-agent/instrument/logger/frameworks/zap.go
+++ b/tools/go-agent/instrument/logger/frameworks/zap.go
@@ -19,6 +19,7 @@ package frameworks
 
 import (
 	"fmt"
+	"go/token"
 	"path/filepath"
 
 	"github.com/apache/skywalking-go/tools/go-agent/instrument/plugins/rewrite"
@@ -30,17 +31,17 @@ import (
 
 const (
 	zapPackageRootPath = "go.uber.org/zap"
+	zapPackageCorePath = "go.uber.org/zap/zapcore"
 	LoggerTypeName     = "*Logger"
 )
 
 var zapStaticFuncNames = []string{
 	"New", "NewNop", "NewProduction", "NewDevelopment", "NewExample",
 }
-var zapLoggerMethodNames = []string{
-	"Log", "Debug", "Info", "Warn", "Error", "Panic", "Fatal", "DPanic",
-}
 
 type Zap struct {
+	initFunction *dst.FuncDecl
+	initImports  []*dst.ImportSpec
 }
 
 func NewZap() *Zap {
@@ -53,7 +54,8 @@ func (z *Zap) Name() string {
 
 func (z *Zap) PackagePaths() map[string]*PackageConfiguration {
 	return map[string]*PackageConfiguration{
-		zapPackageRootPath: {NeedsHelpers: true},
+		zapPackageRootPath: {NeedsHelpers: true, NeedsVariables: true, NeedsChangeLoggerFunc: true},
+		zapPackageCorePath: {NeedsHelpers: true, NeedsVariables: false, NeedsChangeLoggerFunc: false},
 	}
 }
 
@@ -77,98 +79,136 @@ func (z *Zap) AutomaticBindFunctions(fun *dst.FuncDecl) string {
 }
 
 func (z *Zap) GenerateExtraFiles(pkgPath, debugDir string) ([]*rewrite.FileInfo, error) {
+	var path string
 	if pkgPath == zapPackageRootPath {
-		file, err := FrameworkFS.ReadFile("zap_adapt.go")
-		if err != nil {
-			panic(fmt.Errorf("get zap file error: %v", err))
-		}
+		path = "zap_root.go"
+	} else if pkgPath == zapPackageCorePath {
+		path = "zap_core.go"
+	}
 
-		result := make([]*rewrite.FileInfo, 0)
-		if debugDir == "" {
-			result = append(result, rewrite.NewFile("zap", "zap_adapt.go", string(file)))
-		} else {
-			result = append(result, rewrite.NewFileWithDebug("zap", "zap_adapt.go", string(file),
-				filepath.Join(debugDir, "tools", "go-agent", "instrument", "logger", "frameworks")))
-		}
+	file, err := FrameworkFS.ReadFile(path)
+	if err != nil {
+		panic(fmt.Errorf("get zap file error: %v", err))
+	}
 
-		return result, nil
+	result := make([]*rewrite.FileInfo, 0)
+	if debugDir == "" {
+		result = append(result, rewrite.NewFile("zap", path, string(file)))
+	} else {
+		result = append(result, rewrite.NewFileWithDebug("zap", path, string(file),
+			filepath.Join(debugDir, "tools", "go-agent", "instrument", "logger", "frameworks")))
 	}
-	return nil, nil
+	return result, nil
 }
 
+//nolint
 func (z *Zap) CustomizedEnhance(path string, curFile *dst.File, cursor *dstutil.Cursor, allFiles []*dst.File) (map[string]string, bool) {
-	fun, ok := cursor.Node().(*dst.FuncDecl)
-	if !ok {
-		return nil, false
-	}
+	switch n := cursor.Node().(type) {
+	case *dst.TypeSpec:
+		// adding the context field into entry
+		st, ok := n.Type.(*dst.StructType)
+		if !ok || st.Fields == nil || n.Name == nil {
+			return nil, false
+		}
+		if n.Name.Name == "CheckedEntry" {
+			st.Fields.List = append(st.Fields.List,
+				// tracing context object
+				&dst.Field{Names: []*dst.Ident{dst.NewIdent("SWContext")}, Type: dst.NewIdent("interface{}")},
+				// tracing context field
+				&dst.Field{Names: []*dst.Ident{dst.NewIdent("SWContextField")}, Type: &dst.StarExpr{X: dst.NewIdent("Field")}},
+				// existing fields needs to be added into, such as generate from log.With("key", "value")
+				&dst.Field{Names: []*dst.Ident{dst.NewIdent("SWFields")}, Type: &dst.ArrayType{Elt: dst.NewIdent("Field")}},
+			)
+			curFile.Decls = append(curFile.Decls, &dst.GenDecl{
+				Tok: token.VAR,
+				Specs: []dst.Spec{
+					&dst.ValueSpec{Names: []*dst.Ident{
+						dst.NewIdent("SWReporterEnable"),
+						dst.NewIdent("SWLogEnable"),
+					}, Type: dst.NewIdent("bool")},
+					&dst.ValueSpec{Names: []*dst.Ident{
+						dst.NewIdent("SWReporterLabelKeys"),
+					}, Type: dst.NewIdent("[]string")},
+					&dst.ValueSpec{Names: []*dst.Ident{
+						dst.NewIdent("SWLogTracingContextKey"),
+					}, Type: dst.NewIdent("string")},
+					&dst.ValueSpec{Names: []*dst.Ident{
+						dst.NewIdent("SWFields"),
+					}, Type: dst.NewIdent("[]Field")},
+				},
+			})
+			return nil, true
+		}
+		if n.Name.Name == "Logger" {
+			st.Fields.List = append(st.Fields.List,
+				&dst.Field{Names: []*dst.Ident{dst.NewIdent("SWFields")}, Type: dst.NewIdent("[]zapcore.Field")})
+			return nil, true
+		}
+	case *dst.FuncDecl:
+		// enhance the method which check the log and generate the entry
+		if n.Recv != nil && len(n.Recv.List) == 1 && tools.GenerateTypeNameByExp(n.Recv.List[0].Type) == "*Logger" &&
+			n.Name.Name == "check" &&
+			n.Type.Results != nil && len(n.Type.Results.List) > 0 &&
+			tools.GenerateTypeNameByExp(n.Type.Results.List[0].Type) == "*zapcore.CheckedEntry" {
+			entryName := tools.EnhanceParameterNames(n.Type.Results, true)[0].Name
+			recvName := tools.EnhanceParameterNames(n.Recv, true)[0].Name
+
+			// init the zapcore variables
+			z.initFunction = tools.GoStringToDecls(fmt.Sprintf(`func initZapCore() {
+zapcore.SWReporterEnable = %s
+zapcore.SWReporterLabelKeys = %s
+zapcore.SWLogEnable = %s
+}`, "LogReporterEnable", "LogReporterLabelKeys", "LogTracingContextEnable"))[0].(*dst.FuncDecl)
+			z.initImports = []*dst.ImportSpec{
+				{Path: &dst.BasicLit{Kind: token.STRING, Value: `"go.uber.org/zap/zapcore"`}},
+			}
+
+			return z.enhanceMethod(n, fmt.Sprintf("defer func() {if %s != nil {"+
+				"%s.SWContext, %s.SWContextField = %s%s(%s); %s.SWFields = %s.SWFields;}}()", entryName,
+				entryName, entryName, rewrite.StaticMethodPrefix, "ZapTracingContextEnhance", entryName, entryName, recvName)), true
+		}
 
-	// enhance the *Logger.Info, Warn, etc. method for add tracing context field
-	if fun.Recv == nil || len(fun.Recv.List) != 1 || fun.Type.Params == nil || len(fun.Type.Params.List) <= 1 {
-		return nil, false
-	}
+		if n.Recv != nil && len(n.Recv.List) == 1 && n.Name.Name == "With" &&
+			n.Type.Params != nil && len(n.Type.Params.List) == 1 &&
+			tools.GenerateTypeNameByExp(n.Recv.List[0].Type) == "*Logger" && tools.GenerateTypeNameByExp(n.Type.Params.List[0].Type) == "[]Field" {
+			recvs := tools.EnhanceParameterNames(n.Recv, false)
+			parameters := tools.EnhanceParameterNames(n.Type.Params, false)
+			results := tools.EnhanceParameterNames(n.Type.Results, true)
 
-	if tools.GenerateTypeNameByExp(fun.Recv.List[0].Type) == LoggerTypeName {
-		return z.enhanceLoggerTracingContext(fun)
-	} else if tools.GenerateTypeNameByExp(fun.Recv.List[0].Type) == "*SugaredLogger" {
-		return z.enhanceSugaredLoggerTracingContext(fun)
-	}
+			return z.enhanceMethod(n, fmt.Sprintf(`defer func() {if %s != nil { %s.SWFields = %sZap%s(%s, %s.SWFields) }}()`,
+				results[0].Name, results[0].Name, rewrite.StaticMethodPrefix, "KnownFieldFilter", parameters[0].Name, recvs[0].Name)), true
+		}
 
+		// enhance the method which write the checked entry context
+		if n.Recv != nil && len(n.Recv.List) == 1 && tools.GenerateTypeNameByExp(n.Recv.List[0].Type) == "*CheckedEntry" &&
+			n.Name.Name == "Write" &&
+			n.Type.Params != nil && len(n.Type.Params.List) == 1 &&
+			tools.GenerateTypeNameByExp(n.Type.Params.List[0].Type) == "[]Field" {
+			recvs := tools.EnhanceParameterNames(n.Recv, false)
+			parameters := tools.EnhanceParameterNames(n.Type.Params, false)
+			return z.enhanceMethod(n, fmt.Sprintf(`if %s != nil { %s = %sZapcore%s(%s, %s, %s.SWFields, %s.SWContext, %s.SWContextField, SWReporterEnable, SWLogEnable, SWReporterLabelKeys) }`,
+				recvs[0].Name, parameters[0].Name, rewrite.StaticMethodPrefix, "ReportLogFromZapEntry", recvs[0].Name,
+				parameters[0].Name, recvs[0].Name, recvs[0].Name, recvs[0].Name)), true
+		}
+	}
 	return nil, false
 }
 
-func (z *Zap) enhanceSugaredLoggerTracingContext(fun *dst.FuncDecl) (map[string]string, bool) {
-	if fun.Name.Name != "log" {
-		return nil, false
-	}
-	parameters := tools.EnhanceParameterNames(fun.Type.Params, false)
-	var contextParameter *tools.ParameterInfo
-	for _, p := range parameters {
-		if p.Name == "context" && p.TypeName == "[]interface{}" {
-			contextParameter = p
-			break
-		}
-	}
-	if contextParameter == nil {
-		return nil, false
-	}
+func (z *Zap) enhanceMethod(fun *dst.FuncDecl, goCode string) map[string]string {
 	funcID := tools.BuildFuncIdentity(zapPackageRootPath, fun)
 	replaceKey := fmt.Sprintf("//goagent:enhance_%s", funcID)
-	replaceValue := fmt.Sprintf("%s = %s%s(%s)",
-		contextParameter.Name, rewrite.StaticMethodPrefix, "ZapAddZapTracingInterfaceField", contextParameter.Name)
 	fun.Body.Decs.Lbrace.Prepend("\n", replaceKey)
 
-	return map[string]string{replaceKey: replaceValue}, true
+	return map[string]string{replaceKey: goCode}
 }
 
-func (z *Zap) enhanceLoggerTracingContext(fun *dst.FuncDecl) (map[string]string, bool) {
-	foundMethod := false
-
-	for _, name := range zapLoggerMethodNames {
-		if fun.Name.Name == name {
-			foundMethod = true
-			break
-		}
-	}
-	if !foundMethod {
-		return nil, false
-	}
-
-	parameterNames := tools.EnhanceParameterNames(fun.Type.Params, false)
-	var fieldParameter *tools.ParameterInfo
-	for _, p := range parameterNames {
-		if p.TypeName == "...Field" {
-			fieldParameter = p
-			break
-		}
-	}
-	if fieldParameter == nil {
-		return nil, false
+func (z *Zap) InitFunctions() []*dst.FuncDecl {
+	if z.initFunction != nil {
+		return []*dst.FuncDecl{z.initFunction}
 	}
-	funcID := tools.BuildFuncIdentity(zapPackageRootPath, fun)
-	replaceKey := fmt.Sprintf("//goagent:enhance_%s", funcID)
-	replaceValue := fmt.Sprintf("%s = %s%s(%s)",
-		fieldParameter.Name, rewrite.StaticMethodPrefix, "ZapAddZapTracingField", fieldParameter.Name)
-	fun.Body.Decs.Lbrace.Prepend("\n", replaceKey)
+	return nil
+}
 
-	return map[string]string{replaceKey: replaceValue}, true
+func (z *Zap) InitImports() []*dst.ImportSpec {
+	return z.initImports
 }
diff --git a/tools/go-agent/instrument/logger/frameworks/zap_core.go b/tools/go-agent/instrument/logger/frameworks/zap_core.go
new file mode 100644
index 0000000..47f72a6
--- /dev/null
+++ b/tools/go-agent/instrument/logger/frameworks/zap_core.go
@@ -0,0 +1,61 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package frameworks
+
+import (
+	"fmt"
+
+	"go.uber.org/zap/zapcore"
+)
+
+func ReportLogFromZapEntry(entry *zapcore.CheckedEntry, fields, needs []zapcore.Field, tracingContext interface{},
+	tracingContextField *zapcore.Field, reporterEnable, logEnable bool, reportLabelsKeys []string) []zapcore.Field {
+	if reporterEnable && tracingContext != nil {
+		labels := make(map[string]string, len(reportLabelsKeys))
+		for _, key := range reportLabelsKeys {
+			for _, f := range fields {
+				if f.Key == key {
+					if k, v := generateLabelKeyValueFromField(f); k != "" {
+						labels[k] = v
+					}
+				}
+			}
+		}
+		for _, f := range needs {
+			if k, v := generateLabelKeyValueFromField(f); k != "" {
+				labels[k] = v
+			}
+		}
+		ReportLog(tracingContext, entry.Time, entry.Level.String(), entry.Message, labels)
+	}
+	if logEnable && tracingContextField != nil {
+		fields = append(fields, *tracingContextField)
+	}
+	return fields
+}
+
+func generateLabelKeyValueFromField(field zapcore.Field) (key, value string) {
+	if field.Interface != nil {
+		return field.Key, fmt.Sprintf("%v", field.Interface)
+	} else if field.Integer > 0 {
+		return field.Key, fmt.Sprintf("%d", field.Integer)
+	} else if field.String != "" {
+		return field.Key, field.String
+	}
+	return "", ""
+}
diff --git a/tools/go-agent/instrument/logger/frameworks/zap_adapt.go b/tools/go-agent/instrument/logger/frameworks/zap_root.go
similarity index 75%
rename from tools/go-agent/instrument/logger/frameworks/zap_adapt.go
rename to tools/go-agent/instrument/logger/frameworks/zap_root.go
index 1c6ae30..aca4583 100644
--- a/tools/go-agent/instrument/logger/frameworks/zap_adapt.go
+++ b/tools/go-agent/instrument/logger/frameworks/zap_root.go
@@ -21,6 +21,7 @@ import (
 	"fmt"
 
 	"go.uber.org/zap"
+	"go.uber.org/zap/zapcore"
 )
 
 type ZapLogContextStringGenerator struct {
@@ -34,18 +35,29 @@ func UpdateZapLogger(l *zap.Logger) {
 	ChangeLogger(NewZapAdapter(l))
 }
 
-func AddZapTracingField(fields []zap.Field) []zap.Field {
-	if LogTracingContextEnable() {
-		return append(fields, zap.String(LogTracingContextKey(), GetLogContextString()))
+func TracingContextEnhance(entry *zapcore.CheckedEntry) (interface{}, *zapcore.Field) {
+	var getEndpoint = LogReporterEnable
+	if LogReporterEnable || LogTracingContextEnable {
+		ctx := GetLogContext(getEndpoint)
+		f := zap.String(LogTracingContextKey, ctx.String())
+		return ctx, &f
 	}
-	return fields
+	return nil, nil
 }
 
-func AddZapTracingInterfaceField(fields []interface{}) []interface{} {
-	if LogTracingContextEnable() {
-		return append(fields, zap.String(LogTracingContextKey(), GetLogContextString()))
+func KnownFieldFilter(fs, existingFields []zapcore.Field) []zapcore.Field {
+	keys := LogReporterLabelKeys
+	res := make([]zapcore.Field, 0)
+	for _, k := range keys {
+		for _, f := range fs {
+			if f.Key == k {
+				res = append(res, f)
+			}
+		}
 	}
-	return fields
+	// copy original data
+	res = append(res, existingFields...)
+	return res
 }
 
 type ZapAdapter struct {
diff --git a/tools/go-agent/instrument/logger/instrument.go b/tools/go-agent/instrument/logger/instrument.go
index 7e3a78d..38e9caa 100644
--- a/tools/go-agent/instrument/logger/instrument.go
+++ b/tools/go-agent/instrument/logger/instrument.go
@@ -187,13 +187,15 @@ func (i *Instrument) WriteExtraFiles(dir string) ([]string, error) {
 		return nil, err
 	}
 	files = append(files, generateExtraFiles...)
+	if i.packageConf.NeedsHelpers {
+		files = append(files, rewrite.NewFile(packageName, "skywalking_init.go",
+			i.generateInitLoggerFileContent(packageName)))
+	}
 	extraFiles, err := ctx.MultipleFilesWithWritten("skywalking_", dir, packageName, files)
 	if err != nil {
 		return nil, err
 	}
-	if i.packageConf.NeedsHelpers {
-		extraFiles = append(extraFiles, i.generateInitLoggerFile(dir, packageName))
-	}
+
 	return extraFiles, nil
 }
 
@@ -222,40 +224,72 @@ func (i *Instrument) writeDelegatorFile(pkgName string) (string, error) {
 	return tools.GenerateDSTFileContent(delegator, nil)
 }
 
-func (i *Instrument) generateInitLoggerFile(dir, pkgName string) string {
+func (i *Instrument) generateInitLoggerFileContent(pkgName string) string {
 	initTmpl, err := frameworks.FrameworkFS.ReadFile("templates/init.tmpl")
 	if err != nil {
 		panic(fmt.Sprintf("cannot found init template in logger framerwork: %v", err))
 	}
-	file, err := tools.WriteFile(dir, "skywalking_init.go", tools.ExecuteTemplate(string(initTmpl), struct {
-		PackageName                  string
-		GetGlobalOperatorLinkMethod  string
-		SetGlobalLoggerLinkMethod    string
-		OperatorTypeName             string
-		LogTypeInConfig              *config.Log
-		ConfigTypeAutomaticValue     string
-		CurrentLogTypeName           string
-		GetOperatorMethodName        string
-		ChangeLoggerMethodName       string
-		LogTracingEnableFuncName     string
-		LogTracingContextKeyFuncName string
+
+	initFunctions := i.framework.InitFunctions()
+	initFuncNames := make([]string, 0)
+	for _, initFunc := range initFunctions {
+		initFuncNames = append(initFuncNames, initFunc.Name.Name)
+	}
+	importsMap := make(map[string]string)
+	for _, imp := range i.framework.InitImports() {
+		name := filepath.Base(strings.TrimSuffix(imp.Path.Value, "\""))
+		if imp.Name != nil && imp.Name.Name != "" {
+			name = imp.Name.Name
+		}
+		importsMap[name] = imp.Path.Value
+	}
+	initDecls := tools.GoStringToDecls(tools.ExecuteTemplate(string(initTmpl), struct {
+		Imports                     map[string]string
+		NeedsVariables              bool
+		NeedsChangeLoggerFunc       bool
+		GetGlobalOperatorLinkMethod string
+		SetGlobalLoggerLinkMethod   string
+		OperatorTypeName            string
+		LogTypeInConfig             *config.Log
+		ConfigTypeAutomaticValue    string
+		CurrentLogTypeName          string
+		GetOperatorMethodName       string
+		ChangeLoggerMethodName      string
+		LogTracingEnableVarName     string
+		LogTracingContextKeyVarName string
+		LogReporterEnableVarName    string
+		LogReporterLabelsVarName    string
+		LogReportFuncName           string
+		InitFunctionNames           []string
 	}{
-		PackageName:                  pkgName,
-		GetGlobalOperatorLinkMethod:  consts.GlobalTracerGetMethodName,
-		SetGlobalLoggerLinkMethod:    consts.GlobalLoggerSetMethodName,
-		OperatorTypeName:             rewrite.TypePrefix + i.generatePackageNameWithTitle() + "Operator",
-		LogTypeInConfig:              &config.GetConfig().Log,
-		ConfigTypeAutomaticValue:     config.ConfigTypeAutomatic,
-		CurrentLogTypeName:           i.framework.Name(),
-		GetOperatorMethodName:        rewrite.VarPrefix + i.generatePackageNameWithTitle() + "GetOperator",
-		ChangeLoggerMethodName:       rewrite.VarPrefix + i.generatePackageNameWithTitle() + "ChangeLogger",
-		LogTracingEnableFuncName:     rewrite.StaticMethodPrefix + i.generatePackageNameWithTitle() + "LogTracingContextEnable",
-		LogTracingContextKeyFuncName: rewrite.StaticMethodPrefix + i.generatePackageNameWithTitle() + "LogTracingContextKey",
+		Imports:                     importsMap,
+		NeedsVariables:              i.packageConf.NeedsVariables,
+		NeedsChangeLoggerFunc:       i.packageConf.NeedsChangeLoggerFunc,
+		GetGlobalOperatorLinkMethod: consts.GlobalTracerGetMethodName,
+		SetGlobalLoggerLinkMethod:   consts.GlobalLoggerSetMethodName,
+		OperatorTypeName:            "Operator",
+		LogTypeInConfig:             &config.GetConfig().Log,
+		ConfigTypeAutomaticValue:    config.ConfigTypeAutomatic,
+		CurrentLogTypeName:          i.framework.Name(),
+		GetOperatorMethodName:       "GetOperator",
+		ChangeLoggerMethodName:      "ChangeLogger",
+		LogTracingEnableVarName:     "LogTracingContextEnable",
+		LogTracingContextKeyVarName: "LogTracingContextKey",
+		LogReporterEnableVarName:    "LogReporterEnable",
+		LogReporterLabelsVarName:    "LogReporterLabelKeys",
+		LogReportFuncName:           "ReportLog",
+		InitFunctionNames:           initFuncNames,
 	}))
-	if err != nil {
+	for _, f := range initFunctions {
+		initDecls = append(initDecls, f)
+	}
+
+	f := &dst.File{Name: dst.NewIdent(pkgName), Decls: initDecls}
+	if c, err1 := tools.GenerateDSTFileContent(f, nil); err1 != nil {
 		panic(fmt.Errorf("generate logger init file error: %v", err))
+	} else {
+		return c
 	}
-	return file
 }
 
 func (i *Instrument) generatePackageNameWithTitle() string {
diff --git a/tools/go-agent/instrument/plugins/rewrite/var.go b/tools/go-agent/instrument/plugins/rewrite/var.go
index a7d3bde..4e7467a 100644
--- a/tools/go-agent/instrument/plugins/rewrite/var.go
+++ b/tools/go-agent/instrument/plugins/rewrite/var.go
@@ -28,8 +28,8 @@ func (c *Context) Var(val *dst.ValueSpec, onlyName bool) {
 		oldName := val.Names[0].Name
 		if !c.alreadyGenerated(oldName) {
 			val.Names[0] = dst.NewIdent(fmt.Sprintf("%s%s%s", VarPrefix, c.currentPackageTitle, oldName))
-			c.rewriteMapping.addVarMapping(oldName, val.Names[0].Name)
 		}
+		c.rewriteMapping.addVarMapping(oldName, val.Names[0].Name)
 	}
 	if onlyName {
 		return