You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2023/04/21 10:29:40 UTC

[skywalking-go] branch main updated: Add the plugin API (#9)

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

wusheng 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 3bd9f26  Add the plugin API (#9)
3bd9f26 is described below

commit 3bd9f2606a87ab0daa738f7241b0f59d3b518fd4
Author: mrproliu <74...@qq.com>
AuthorDate: Fri Apr 21 18:29:34 2023 +0800

    Add the plugin API (#9)
---
 .licenserc.yaml                                    |   1 +
 Makefile                                           |   1 +
 agent/core/compile.go                              |   3 +
 imports.go => agent/core/operator/compile.go       |  12 +-
 agent/core/tracing/compile.go                      |   2 +-
 imports.go                                         |   1 +
 plugins/core/context.go                            |  60 ++--
 plugins/core/go.mod                                |   3 +
 plugins/core/go.sum                                |   9 +
 imports.go => plugins/core/instrument/declare.go   |  24 +-
 plugins/core/instrument/enhance.go                 |  74 ++++
 plugins/core/instrument/method.go                  |  56 +++
 plugins/core/instrument/method_test.go             | 127 +++++++
 .../files.go => plugins/core/instrument/struct.go  |  34 +-
 plugins/core/instrument/struct_test.go             |  93 +++++
 plugins/core/{intercepter.go => log/logger.go}     |  34 +-
 .../flags.go => plugins/core/operator/common.go    |  23 +-
 plugins/core/{ => operator}/intercepter.go         |   2 +-
 imports.go => plugins/core/operator/logger.go      |  16 +-
 .../core/{intercepter.go => operator/tracing.go}   |  26 +-
 plugins/core/span.go                               |  31 +-
 plugins/core/span_default.go                       |  28 +-
 plugins/core/span_noop.go                          |  12 +-
 plugins/core/span_tracing.go                       |  19 +-
 plugins/core/test_base.go                          |  20 +-
 plugins/core/tracer.go                             |   2 +
 plugins/core/tracing.go                            | 241 +++++++++++++
 plugins/core/tracing/api.go                        | 254 ++++----------
 plugins/core/tracing/api_test.go                   | 346 -------------------
 .../compile.go => plugins/core/tracing/bridge.go   |  63 +++-
 plugins/core/tracing/span.go                       | 111 ++++++
 plugins/core/tracing_test.go                       | 364 +++++++++++++++++++
 plugins/ginv2/go.mod                               |  39 +++
 plugins/ginv2/go.sum                               |  91 +++++
 plugins/{core/tracer.go => ginv2/instrument.go}    |  53 ++-
 plugins/ginv2/intercepter.go                       |  60 ++++
 tools/go-agent/cmd/helper.go                       |   3 +-
 tools/go-agent/cmd/main.go                         |  49 ++-
 tools/go-agent/go.mod                              |  29 +-
 tools/go-agent/go.sum                              |  51 +++
 tools/go-agent/instrument/agentcore/instrument.go  |  98 ++++--
 tools/go-agent/instrument/api/flags.go             |   7 +-
 tools/go-agent/instrument/api/instrument.go        |   5 +-
 .../instrument/framework/enhance_instance.go       | 100 ++++++
 .../instrument/framework/enhance_method.go         | 230 ++++++++++++
 tools/go-agent/instrument/framework/instrument.go  | 384 +++++++++++++++++++++
 .../go-agent/instrument/framework/register.go      |  25 +-
 .../instrument/framework/rewrite/context.go        | 298 ++++++++++++++++
 .../go-agent/instrument/framework/rewrite/func.go  | 205 +++++++++++
 .../instrument/framework/rewrite/import.go         |  57 +++
 .../instrument/framework/rewrite/rewrite.go        | 115 ++++++
 .../go-agent/instrument/framework/rewrite/type.go  |  56 +++
 .../framework/rewrite/var.go}                      |  33 +-
 .../framework/templates/method_inserts.tmpl        |  11 +
 .../templates/method_intercept_after.tmpl          |  17 +
 .../templates/method_intercept_before.tmpl         |  33 ++
 tools/go-agent/instrument/instrument.go            |  25 +-
 tools/go-agent/instrument/runtime/instrument.go    | 106 ++++--
 tools/go-agent/tools/dst.go                        | 142 +++++++-
 tools/go-agent/tools/enhancement.go                |  11 +
 tools/go-agent/tools/files.go                      |   8 +
 tools/go-agent/tools/flags.go                      |  44 ++-
 62 files changed, 3608 insertions(+), 869 deletions(-)

diff --git a/.licenserc.yaml b/.licenserc.yaml
index 1a02b30..9c588cd 100644
--- a/.licenserc.yaml
+++ b/.licenserc.yaml
@@ -31,6 +31,7 @@ header:
     - 'NOTICE'
     - '.gitignore'
     - 'dist/LICENSE.tpl'
+    - '**/*.tmpl'
 
   comment: on-failure
 
diff --git a/Makefile b/Makefile
index 4494050..790f1d8 100644
--- a/Makefile
+++ b/Makefile
@@ -41,6 +41,7 @@ test:
 	echo "mode: atomic" > ${REPODIR}/coverage.txt;
 	@for dir in $$(find . -name go.mod -exec dirname {} \; ); do \
 		cd $$dir; \
+		echo "Testing $$dir"; \
 		go test -v -coverprofile=module_coverage.txt -covermode=atomic ./...; \
 		test_status=$$?; \
 		if [ -f module_coverage.txt ]; then \
diff --git a/agent/core/compile.go b/agent/core/compile.go
index c6b078a..9cbc9e3 100644
--- a/agent/core/compile.go
+++ b/agent/core/compile.go
@@ -23,6 +23,7 @@ import (
 	_ "fmt"
 	_ "math"
 	_ "math/rand"
+	_ "reflect"
 	_ "strconv"
 	_ "strings"
 	_ "sync"
@@ -30,6 +31,8 @@ import (
 	_ "time"
 
 	//go:nolint
+	_ "github.com/apache/skywalking-go/agent/core/operator"
+	_ "github.com/apache/skywalking-go/agent/core/tracing"
 	_ "github.com/apache/skywalking-go/reporter"
 
 	//go:nolint
diff --git a/imports.go b/agent/core/operator/compile.go
similarity index 76%
copy from imports.go
copy to agent/core/operator/compile.go
index ae50979..be5da0e 100644
--- a/imports.go
+++ b/agent/core/operator/compile.go
@@ -15,14 +15,4 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package skywalking
-
-import (
-	// base module imports
-	_ "github.com/google/uuid"
-	_ "github.com/pkg/errors"
-
-	// force compile for the agent core copied
-	_ "github.com/apache/skywalking-go/agent/core"
-	_ "github.com/apache/skywalking-go/agent/core/tracing"
-)
+package operator
diff --git a/agent/core/tracing/compile.go b/agent/core/tracing/compile.go
index 5ccde8b..a7a5458 100644
--- a/agent/core/tracing/compile.go
+++ b/agent/core/tracing/compile.go
@@ -26,7 +26,7 @@ import (
 	_ "github.com/pkg/errors"
 
 	//go:nolint
-	_ "github.com/apache/skywalking-go/agent/core"
+	_ "github.com/apache/skywalking-go/agent/core/operator"
 	_ "github.com/apache/skywalking-go/reporter"
 
 	//go:nolint
diff --git a/imports.go b/imports.go
index ae50979..5f0f76b 100644
--- a/imports.go
+++ b/imports.go
@@ -24,5 +24,6 @@ import (
 
 	// force compile for the agent core copied
 	_ "github.com/apache/skywalking-go/agent/core"
+	_ "github.com/apache/skywalking-go/agent/core/operator"
 	_ "github.com/apache/skywalking-go/agent/core/tracing"
 )
diff --git a/plugins/core/context.go b/plugins/core/context.go
index 87b7f6e..cc8ddf4 100644
--- a/plugins/core/context.go
+++ b/plugins/core/context.go
@@ -17,16 +17,47 @@
 
 package core
 
+import "reflect"
+
 var (
-	GetGLS = func() interface{} { return nil }
-	SetGLS = func(interface{}) {}
+	GetGLS            = func() interface{} { return nil }
+	SetGLS            = func(interface{}) {}
+	SetGlobalOperator = func(interface{}) {}
+	GetGlobalOperator = func() interface{} { return nil }
 )
 
+type ContextSnapshoter interface {
+	TakeSnapShot(val interface{}) interface{}
+}
+
 type TracingContext struct {
-	ActiveSpan Span
+	activeSpan TracingSpan
 	Runtime    *RuntimeContext
 }
 
+func (t *TracingContext) TakeSnapShot(val interface{}) interface{} {
+	snapshot := newSnapshotSpan(t.ActiveSpan())
+	return &TracingContext{
+		activeSpan: snapshot,
+		Runtime:    t.Runtime.clone(),
+	}
+}
+
+func (t *TracingContext) ActiveSpan() TracingSpan {
+	if t.activeSpan == nil || reflect.ValueOf(t.activeSpan).IsZero() {
+		return nil
+	}
+	return t.activeSpan
+}
+
+func (t *TracingContext) SaveActiveSpan(s TracingSpan) {
+	t.activeSpan = s
+}
+
+func (t *TracingContext) RuntimeContext() *RuntimeContext {
+	return t.Runtime
+}
+
 type RuntimeContext struct {
 	data map[string]interface{}
 }
@@ -49,14 +80,6 @@ func (r *RuntimeContext) clone() *RuntimeContext {
 	}
 }
 
-func GetTracingContext() *TracingContext {
-	gls := GetGLS()
-	if gls == nil {
-		return nil
-	}
-	return gls.(*TracingContext)
-}
-
 func (r *RuntimeContext) Get(key string) interface{} {
 	return r.data[key]
 }
@@ -64,18 +87,3 @@ func (r *RuntimeContext) Get(key string) interface{} {
 func (r *RuntimeContext) Set(key string, value interface{}) {
 	r.data[key] = value
 }
-
-func TaskTracingContextSnapshot(val interface{}) interface{} {
-	if val == nil {
-		return nil
-	}
-	context, ok := val.(*TracingContext)
-	if !ok {
-		return nil
-	}
-	snapshot := newSnapshotSpan(context.ActiveSpan)
-	return &TracingContext{
-		ActiveSpan: snapshot,
-		Runtime:    context.Runtime.clone(),
-	}
-}
diff --git a/plugins/core/go.mod b/plugins/core/go.mod
index 2ade84b..4700958 100644
--- a/plugins/core/go.mod
+++ b/plugins/core/go.mod
@@ -4,6 +4,7 @@ go 1.18
 
 require (
 	github.com/apache/skywalking-go v0.0.0-20230411034404-b9270e98036b
+	github.com/dave/dst v0.27.2
 	github.com/google/uuid v1.3.0
 	github.com/pkg/errors v0.9.1
 	github.com/stretchr/testify v1.8.2
@@ -14,9 +15,11 @@ require (
 	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/golang/protobuf v1.5.2 // indirect
 	github.com/pmezard/go-difflib v1.0.0 // indirect
+	golang.org/x/mod v0.8.0 // indirect
 	golang.org/x/net v0.8.0 // indirect
 	golang.org/x/sys v0.6.0 // indirect
 	golang.org/x/text v0.8.0 // indirect
+	golang.org/x/tools v0.6.0 // indirect
 	google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
 	google.golang.org/grpc v1.54.0 // indirect
 	google.golang.org/protobuf v1.29.0 // indirect
diff --git a/plugins/core/go.sum b/plugins/core/go.sum
index 7003eeb..c7e5d5a 100644
--- a/plugins/core/go.sum
+++ b/plugins/core/go.sum
@@ -9,6 +9,9 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
 github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
 github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
 github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
+github.com/dave/dst v0.27.2 h1:4Y5VFTkhGLC1oddtNwuxxe36pnyLxMFXT51FOzH8Ekc=
+github.com/dave/dst v0.27.2/go.mod h1:jHh6EOibnHgcUW3WjKHisiooEkYwqpHLBSX1iOBhEyc=
+github.com/dave/jennifer v1.5.0 h1:HmgPN93bVDpkQyYbqhCHj5QlgvUkvEOzMyEvKLgCRrg=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -54,6 +57,7 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
+github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
 github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
@@ -78,6 +82,8 @@ golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPI
 golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
 golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
+golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -100,6 +106,7 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -132,6 +139,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
 golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
 golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
+golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/imports.go b/plugins/core/instrument/declare.go
similarity index 75%
copy from imports.go
copy to plugins/core/instrument/declare.go
index ae50979..79a8709 100644
--- a/imports.go
+++ b/plugins/core/instrument/declare.go
@@ -15,14 +15,20 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package skywalking
+package instrument
 
-import (
-	// base module imports
-	_ "github.com/google/uuid"
-	_ "github.com/pkg/errors"
+import "embed"
 
-	// force compile for the agent core copied
-	_ "github.com/apache/skywalking-go/agent/core"
-	_ "github.com/apache/skywalking-go/agent/core/tracing"
-)
+type Instrument interface {
+	Name() string
+	BasePackage() string
+	VersionChecker(version string) bool
+	Points() []*Point
+	FS() *embed.FS
+}
+
+type Point struct {
+	PackagePath string
+	At          *EnhanceMatcher
+	Interceptor string
+}
diff --git a/plugins/core/instrument/enhance.go b/plugins/core/instrument/enhance.go
new file mode 100644
index 0000000..cf24b86
--- /dev/null
+++ b/plugins/core/instrument/enhance.go
@@ -0,0 +1,74 @@
+// 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 instrument
+
+import "github.com/dave/dst"
+
+type EnhanceType int
+
+var (
+	EnhanceTypeMethod EnhanceType = 1
+	EnhanceTypeStruct EnhanceType = 2
+)
+
+type MethodFilterOption func(decl *dst.FuncDecl, files []*dst.File) bool
+type StructFilterOption func(structType *dst.TypeSpec, files []*dst.File) bool
+
+type EnhanceMatcher struct {
+	Type          EnhanceType
+	Name          string
+	Receiver      string
+	MethodFilters []MethodFilterOption
+	StructFilters []StructFilterOption
+}
+
+func NewStaticMethodEnhance(name string, filters ...MethodFilterOption) *EnhanceMatcher {
+	return &EnhanceMatcher{Type: EnhanceTypeMethod, Name: name, MethodFilters: filters}
+}
+
+func NewMethodEnhance(receiver, name string, filters ...MethodFilterOption) *EnhanceMatcher {
+	return &EnhanceMatcher{Type: EnhanceTypeMethod, Name: name, Receiver: receiver, MethodFilters: filters}
+}
+
+func NewStructEnhance(name string, filters ...StructFilterOption) *EnhanceMatcher {
+	return &EnhanceMatcher{Type: EnhanceTypeStruct, Name: name, StructFilters: filters}
+}
+
+func verifyTypeName(exp dst.Expr, val string) bool {
+	data := generateTypeNameByExp(exp)
+	return data == val
+}
+
+func generateTypeNameByExp(exp dst.Expr) string {
+	var data string
+	switch n := exp.(type) {
+	case *dst.StarExpr:
+		data = "*" + generateTypeNameByExp(n.X)
+	case *dst.TypeAssertExpr:
+		data = generateTypeNameByExp(n.X)
+	case *dst.InterfaceType:
+		data = "interface{}"
+	case *dst.Ident:
+		data = n.Name
+	case *dst.SelectorExpr:
+		data = generateTypeNameByExp(n.X) + "." + generateTypeNameByExp(n.Sel)
+	default:
+		return ""
+	}
+	return data
+}
diff --git a/plugins/core/instrument/method.go b/plugins/core/instrument/method.go
new file mode 100644
index 0000000..f4706bb
--- /dev/null
+++ b/plugins/core/instrument/method.go
@@ -0,0 +1,56 @@
+// 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 instrument
+
+import "github.com/dave/dst"
+
+func WithArgsCount(argsCount int) MethodFilterOption {
+	return func(method *dst.FuncDecl, files []*dst.File) bool {
+		return (method.Type.Params == nil && len(method.Type.Params.List) == argsCount) || (len(method.Type.Params.List) == argsCount)
+	}
+}
+
+func WithResultCount(resultCount int) MethodFilterOption {
+	return func(decl *dst.FuncDecl, files []*dst.File) bool {
+		return (decl.Type.Results == nil && resultCount == 0) || (len(decl.Type.Results.List) == resultCount)
+	}
+}
+
+func WithArgType(argIndex int, dataType string) MethodFilterOption {
+	return func(decl *dst.FuncDecl, files []*dst.File) bool {
+		if len(decl.Type.Params.List) <= argIndex {
+			return false
+		}
+		return verifyTypeName(decl.Type.Params.List[argIndex].Type, dataType)
+	}
+}
+
+func WithStaticMethod() MethodFilterOption {
+	return func(decl *dst.FuncDecl, files []*dst.File) bool {
+		return decl.Recv == nil || len(decl.Recv.List) == 0
+	}
+}
+
+func WithReceiverType(dataType string) MethodFilterOption {
+	return func(decl *dst.FuncDecl, files []*dst.File) bool {
+		if decl.Recv == nil || len(decl.Recv.List) == 0 {
+			return false
+		}
+		return verifyTypeName(decl.Recv.List[0].Type, dataType)
+	}
+}
diff --git a/plugins/core/instrument/method_test.go b/plugins/core/instrument/method_test.go
new file mode 100644
index 0000000..b545a6d
--- /dev/null
+++ b/plugins/core/instrument/method_test.go
@@ -0,0 +1,127 @@
+// 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 instrument
+
+import (
+	"embed"
+	"go/parser"
+	"testing"
+
+	"github.com/dave/dst"
+	"github.com/dave/dst/decorator"
+	"github.com/dave/dst/dstutil"
+
+	"github.com/stretchr/testify/assert"
+)
+
+//go:embed method_test.go
+var methodFS embed.FS
+
+// nolint
+func testStaticMethod(i int) *TestStruct {
+	return nil
+}
+
+// nolint
+func (t *TestStruct) testMethod(d interface{}) {
+
+}
+
+func TestStaticMethodFilter(t *testing.T) {
+	var tests = []struct {
+		filter MethodFilterOption
+		found  bool
+	}{
+		{
+			filter: WithArgsCount(1),
+			found:  true,
+		},
+		{
+			filter: WithResultCount(1),
+			found:  true,
+		},
+		{
+			filter: WithArgType(0, "int"),
+			found:  true,
+		},
+		{
+			filter: WithStaticMethod(),
+			found:  true,
+		},
+	}
+
+	file, err := methodFS.ReadFile("method_test.go")
+	assert.Nil(t, err, "reading file error: %v", err)
+	f, err := decorator.ParseFile(nil, "method.go", file, parser.ParseComments)
+	assert.Nil(t, err, "parse file error: %v", err)
+	var funcDecl *dst.FuncDecl
+	dstutil.Apply(f, func(cursor *dstutil.Cursor) bool {
+		if s, ok := cursor.Node().(*dst.FuncDecl); ok && s.Name.Name == "testStaticMethod" {
+			funcDecl = s
+			return false
+		}
+		return true
+	}, func(cursor *dstutil.Cursor) bool {
+		return true
+	})
+	assert.NotNil(t, funcDecl, "cannot found the function")
+	for i, tt := range tests {
+		got := tt.filter(funcDecl, []*dst.File{f})
+		assert.Equal(t, tt.found, got, "not correct with case: %d", i)
+	}
+}
+
+func TestReceiverMethodFilter(t *testing.T) {
+	var tests = []struct {
+		filter MethodFilterOption
+		found  bool
+	}{
+		{
+			filter: WithArgType(0, "interface{}"),
+			found:  true,
+		},
+		{
+			filter: WithResultCount(0),
+			found:  true,
+		},
+		{
+			filter: WithReceiverType("*TestStruct"),
+			found:  true,
+		},
+	}
+
+	file, err := methodFS.ReadFile("method_test.go")
+	assert.Nil(t, err, "reading file error: %v", err)
+	f, err := decorator.ParseFile(nil, "method.go", file, parser.ParseComments)
+	assert.Nil(t, err, "parse file error: %v", err)
+	var funcDecl *dst.FuncDecl
+	dstutil.Apply(f, func(cursor *dstutil.Cursor) bool {
+		if s, ok := cursor.Node().(*dst.FuncDecl); ok && s.Name.Name == "testMethod" {
+			funcDecl = s
+			return false
+		}
+		return true
+	}, func(cursor *dstutil.Cursor) bool {
+		return true
+	})
+	assert.NotNil(t, funcDecl, "cannot found the function")
+	for i, tt := range tests {
+		got := tt.filter(funcDecl, []*dst.File{f})
+		assert.Equal(t, tt.found, got, "not correct with case: %d", i)
+	}
+}
diff --git a/tools/go-agent/tools/files.go b/plugins/core/instrument/struct.go
similarity index 55%
copy from tools/go-agent/tools/files.go
copy to plugins/core/instrument/struct.go
index 99ba059..cd35aac 100644
--- a/tools/go-agent/tools/files.go
+++ b/plugins/core/instrument/struct.go
@@ -15,22 +15,30 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package tools
+package instrument
 
-import (
-	"os"
-	"path/filepath"
-)
+import "github.com/dave/dst"
 
-func WriteMultipleFile(baseDir string, nameWithData map[string]string) ([]string, error) {
-	paths := make([]string, 0)
-	for name, data := range nameWithData {
-		fileName := filepath.Join(baseDir, name)
-		if err := os.WriteFile(fileName, []byte(data), 0o600); err != nil {
-			return nil, err
+func WithFieldExists(fieldName string) StructFilterOption {
+	return func(structType *dst.TypeSpec, files []*dst.File) bool {
+		st := structType.Type.(*dst.StructType)
+		for _, field := range st.Fields.List {
+			if field.Names[0].Name == fieldName {
+				return true
+			}
 		}
-		paths = append(paths, fileName)
+		return false
 	}
+}
 
-	return paths, nil
+func WithFiledType(filedName, filedType string) StructFilterOption {
+	return func(structType *dst.TypeSpec, files []*dst.File) bool {
+		st := structType.Type.(*dst.StructType)
+		for _, field := range st.Fields.List {
+			if field.Names[0].Name == filedName {
+				return verifyTypeName(field.Type, filedType)
+			}
+		}
+		return false
+	}
 }
diff --git a/plugins/core/instrument/struct_test.go b/plugins/core/instrument/struct_test.go
new file mode 100644
index 0000000..2c3e1c1
--- /dev/null
+++ b/plugins/core/instrument/struct_test.go
@@ -0,0 +1,93 @@
+// 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 instrument
+
+import (
+	"embed"
+	"go/parser"
+	"testing"
+
+	"github.com/dave/dst"
+	"github.com/dave/dst/decorator"
+	"github.com/dave/dst/dstutil"
+
+	"github.com/stretchr/testify/assert"
+)
+
+//go:embed struct_test.go
+var structFS embed.FS
+
+// nolint
+type TestStruct struct {
+	field1 interface{}
+	field2 int
+	field3 *TestStruct
+	field4 *embed.FS
+}
+
+func TestStructFilter(t *testing.T) {
+	var tests = []struct {
+		filter StructFilterOption
+		found  bool
+	}{
+		{
+			filter: WithFieldExists("field1"),
+			found:  true,
+		},
+		{
+			filter: WithFieldExists("field5"),
+			found:  false,
+		},
+		{
+			filter: WithFiledType("field1", "interface{}"),
+			found:  true,
+		},
+		{
+			filter: WithFiledType("field3", "*TestStruct"),
+			found:  true,
+		},
+		{
+			filter: WithFiledType("field4", "*embed.FS"),
+			found:  true,
+		},
+		{
+			filter: WithFiledType("field2", "string"),
+			found:  false,
+		},
+	}
+
+	file, err := structFS.ReadFile("struct_test.go")
+	assert.Nil(t, err, "reading file error: %v", err)
+	f, err := decorator.ParseFile(nil, "struct.go", file, parser.ParseComments)
+	assert.Nil(t, err, "parse file error: %v", err)
+	var typeSpec *dst.TypeSpec
+	dstutil.Apply(f, func(cursor *dstutil.Cursor) bool {
+		if s, ok := cursor.Node().(*dst.TypeSpec); ok {
+			typeSpec = s
+			return false
+		}
+		return true
+	}, func(cursor *dstutil.Cursor) bool {
+		return true
+	})
+	assert.NotNil(t, typeSpec, "cannot found the structure")
+	for i, tt := range tests {
+		got := tt.filter(typeSpec, []*dst.File{f})
+		assert.Equal(t, tt.found, got, "not correct with case: %d", i)
+	}
+}
diff --git a/plugins/core/intercepter.go b/plugins/core/log/logger.go
similarity index 59%
copy from plugins/core/intercepter.go
copy to plugins/core/log/logger.go
index 8efa903..3e9388f 100644
--- a/plugins/core/intercepter.go
+++ b/plugins/core/log/logger.go
@@ -15,24 +15,30 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package core
+package log
 
-type Invocation struct {
-	CallerInstance interface{}
-	Args           []interface{}
+import "github.com/apache/skywalking-go/plugins/core/operator"
 
-	Continue bool
-	Return   []interface{}
-
-	Context interface{}
+func Infof(format string, args ...interface{}) {
+	op := operator.GetOperator()
+	if op == nil {
+		return
+	}
+	op.Logger().(operator.LogOperator).Infof(format, args...)
 }
 
-type EnhancedInstance interface {
-	GetSkyWalkingDynamicField() interface{}
-	SetSkyWalkingDynamicField(interface{})
+func Warnf(format string, args ...interface{}) {
+	op := operator.GetOperator()
+	if op == nil {
+		return
+	}
+	op.Logger().(operator.LogOperator).Warnf(format, args...)
 }
 
-type Interceptor interface {
-	BeforeInvoke(invocation *Invocation) error
-	AfterInvoke(invocation *Invocation, result ...interface{}) error
+func Errorf(format string, args ...interface{}) {
+	op := operator.GetOperator()
+	if op == nil {
+		return
+	}
+	op.Logger().(operator.LogOperator).Errorf(format, args...)
 }
diff --git a/tools/go-agent/instrument/api/flags.go b/plugins/core/operator/common.go
similarity index 67%
copy from tools/go-agent/instrument/api/flags.go
copy to plugins/core/operator/common.go
index 0a39718..24d4e18 100644
--- a/tools/go-agent/instrument/api/flags.go
+++ b/plugins/core/operator/common.go
@@ -15,19 +15,24 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package api
+package operator
 
-import "path/filepath"
+var GetOperator = func() Operator { return nil }
 
-type CompileOptions struct {
-	Package string `skyflag:"-p"`
-	Output  string `skyflag:"-o"`
+type Operator interface {
+	Tracing() interface{} // to TracingOperator
+	Logger() interface{}  // to LogOperator
 }
 
-func (c *CompileOptions) IsValid() bool {
-	return c.Package != "" && c.Output != ""
+// OperateError reduce the "fmt" package import
+type OperateError struct {
+	message string
 }
 
-func (c *CompileOptions) CompileBaseDir() string {
-	return filepath.Dir(filepath.Dir(c.Output))
+func (e OperateError) Error() string {
+	return e.message
+}
+
+func NewError(message string) error {
+	return OperateError{message: message}
 }
diff --git a/plugins/core/intercepter.go b/plugins/core/operator/intercepter.go
similarity index 98%
copy from plugins/core/intercepter.go
copy to plugins/core/operator/intercepter.go
index 8efa903..fe3146a 100644
--- a/plugins/core/intercepter.go
+++ b/plugins/core/operator/intercepter.go
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package core
+package operator
 
 type Invocation struct {
 	CallerInstance interface{}
diff --git a/imports.go b/plugins/core/operator/logger.go
similarity index 76%
copy from imports.go
copy to plugins/core/operator/logger.go
index ae50979..3534b1e 100644
--- a/imports.go
+++ b/plugins/core/operator/logger.go
@@ -15,14 +15,10 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package skywalking
+package operator
 
-import (
-	// base module imports
-	_ "github.com/google/uuid"
-	_ "github.com/pkg/errors"
-
-	// force compile for the agent core copied
-	_ "github.com/apache/skywalking-go/agent/core"
-	_ "github.com/apache/skywalking-go/agent/core/tracing"
-)
+type LogOperator interface {
+	Infof(format string, args ...interface{})
+	Warnf(format string, args ...interface{})
+	Errorf(format string, args ...interface{})
+}
diff --git a/plugins/core/intercepter.go b/plugins/core/operator/tracing.go
similarity index 62%
rename from plugins/core/intercepter.go
rename to plugins/core/operator/tracing.go
index 8efa903..c98a45a 100644
--- a/plugins/core/intercepter.go
+++ b/plugins/core/operator/tracing.go
@@ -15,24 +15,14 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package core
+package operator
 
-type Invocation struct {
-	CallerInstance interface{}
-	Args           []interface{}
+type TracingOperator interface {
+	CreateEntrySpan(operationName string, extractor interface{}, opts ...interface{}) (s interface{}, err error)
+	CreateLocalSpan(operationName string, opts ...interface{}) (s interface{}, err error)
+	CreateExitSpan(operationName, peer string, injector interface{}, opts ...interface{}) (s interface{}, err error)
+	ActiveSpan() interface{} // to Span
 
-	Continue bool
-	Return   []interface{}
-
-	Context interface{}
-}
-
-type EnhancedInstance interface {
-	GetSkyWalkingDynamicField() interface{}
-	SetSkyWalkingDynamicField(interface{})
-}
-
-type Interceptor interface {
-	BeforeInvoke(invocation *Invocation) error
-	AfterInvoke(invocation *Invocation, result ...interface{}) error
+	GetRuntimeContextValue(key string) interface{}
+	SetRuntimeContextValue(key string, value interface{})
 }
diff --git a/plugins/core/span.go b/plugins/core/span.go
index 4d797d5..0099ef2 100644
--- a/plugins/core/span.go
+++ b/plugins/core/span.go
@@ -18,7 +18,7 @@
 package core
 
 import (
-	"time"
+	"github.com/apache/skywalking-go/plugins/core/tracing"
 
 	agentv3 "skywalking.apache.org/repo/goapi/collect/language/agent/v3"
 )
@@ -26,11 +26,6 @@ import (
 // SpanType is used to identify entry, exit and local
 type SpanType int32
 
-// Tag are supported by sky-walking engine.
-// As default, all Tags will be stored, but these ones have
-// particular meanings.
-type Tag string
-
 const (
 	// SpanTypeEntry is a entry span, eg http server
 	SpanTypeEntry SpanType = 0
@@ -40,35 +35,19 @@ const (
 	SpanTypeLocal SpanType = 2
 )
 
-const (
-	TagURL             Tag = "url"
-	TagStatusCode      Tag = "status_code"
-	TagHTTPMethod      Tag = "http.method"
-	TagDBType          Tag = "db.type"
-	TagDBInstance      Tag = "db.instance"
-	TagDBStatement     Tag = "db.statement"
-	TagDBSqlParameters Tag = "db.sql.parameters"
-	TagMQQueue         Tag = "mq.queue"
-	TagMQBroker        Tag = "mq.broker"
-	TagMQTopic         Tag = "mq.topic"
-)
-
-// Span interface as commonv3 span specification
-type Span interface {
+// TracingSpan interface as commonv3 span specification
+type TracingSpan interface {
+	tracing.AdaptSpan
 	SetOperationName(string)
 	GetOperationName() string
 	SetPeer(string)
 	GetPeer() string
-	SetSpanLayer(agentv3.SpanLayer)
 	GetSpanLayer() agentv3.SpanLayer
 	SetComponent(int32)
 	GetComponent() int32
-	Tag(Tag, string)
-	Log(time.Time, ...string)
-	Error(time.Time, ...string)
 	End()
 	IsEntry() bool
 	IsExit() bool
 	IsValid() bool
-	ParentSpan() Span
+	ParentSpan() TracingSpan
 }
diff --git a/plugins/core/span_default.go b/plugins/core/span_default.go
index ad9db39..f887883 100644
--- a/plugins/core/span_default.go
+++ b/plugins/core/span_default.go
@@ -40,10 +40,10 @@ type DefaultSpan struct {
 	Logs          []*agentv3.Log
 	IsError       bool
 	SpanType      SpanType
-	Parent        Span
+	Parent        TracingSpan
 }
 
-func NewDefaultSpan(tracer *Tracer, parent Span) *DefaultSpan {
+func NewDefaultSpan(tracer *Tracer, parent TracingSpan) *DefaultSpan {
 	return &DefaultSpan{
 		tracer:    tracer,
 		StartTime: time.Now(),
@@ -52,7 +52,7 @@ func NewDefaultSpan(tracer *Tracer, parent Span) *DefaultSpan {
 	}
 }
 
-// For Span
+// For TracingSpan
 func (ds *DefaultSpan) SetOperationName(name string) {
 	ds.OperationName = name
 }
@@ -69,8 +69,8 @@ func (ds *DefaultSpan) GetPeer() string {
 	return ds.Peer
 }
 
-func (ds *DefaultSpan) SetSpanLayer(layer agentv3.SpanLayer) {
-	ds.Layer = layer
+func (ds *DefaultSpan) SetSpanLayer(layer int32) {
+	ds.Layer = agentv3.SpanLayer(layer)
 }
 
 func (ds *DefaultSpan) GetSpanLayer() agentv3.SpanLayer {
@@ -85,11 +85,11 @@ func (ds *DefaultSpan) GetComponent() int32 {
 	return ds.ComponentID
 }
 
-func (ds *DefaultSpan) Tag(key Tag, value string) {
-	ds.Tags = append(ds.Tags, &commonv3.KeyStringValuePair{Key: string(key), Value: value})
+func (ds *DefaultSpan) Tag(key, value string) {
+	ds.Tags = append(ds.Tags, &commonv3.KeyStringValuePair{Key: key, Value: value})
 }
 
-func (ds *DefaultSpan) Log(t time.Time, ll ...string) {
+func (ds *DefaultSpan) Log(ll ...string) {
 	data := make([]*commonv3.KeyStringValuePair, 0, int32(math.Ceil(float64(len(ll))/2.0)))
 	var kvp *commonv3.KeyStringValuePair
 	for i, l := range ll {
@@ -101,18 +101,18 @@ func (ds *DefaultSpan) Log(t time.Time, ll ...string) {
 			kvp.Value = l
 		}
 	}
-	ds.Logs = append(ds.Logs, &agentv3.Log{Time: Millisecond(t), Data: data})
+	ds.Logs = append(ds.Logs, &agentv3.Log{Time: Millisecond(time.Now()), Data: data})
 }
 
-func (ds *DefaultSpan) Error(t time.Time, ll ...string) {
+func (ds *DefaultSpan) Error(ll ...string) {
 	ds.IsError = true
-	ds.Log(t, ll...)
+	ds.Log(ll...)
 }
 
 func (ds *DefaultSpan) End() {
 	ds.EndTime = time.Now()
-	if ctx := GetTracingContext(); ctx != nil {
-		ctx.ActiveSpan = ds.Parent
+	if ctx := getTracingContext(); ctx != nil {
+		ctx.SaveActiveSpan(ds.Parent)
 	}
 }
 
@@ -128,6 +128,6 @@ func (ds *DefaultSpan) IsValid() bool {
 	return ds.EndTime.IsZero()
 }
 
-func (ds *DefaultSpan) ParentSpan() Span {
+func (ds *DefaultSpan) ParentSpan() TracingSpan {
 	return ds.Parent
 }
diff --git a/plugins/core/span_noop.go b/plugins/core/span_noop.go
index 9810228..30062f9 100644
--- a/plugins/core/span_noop.go
+++ b/plugins/core/span_noop.go
@@ -18,8 +18,6 @@
 package core
 
 import (
-	"time"
-
 	agentv3 "skywalking.apache.org/repo/goapi/collect/language/agent/v3"
 )
 
@@ -40,7 +38,7 @@ func (*NoopSpan) GetPeer() string {
 	return ""
 }
 
-func (*NoopSpan) SetSpanLayer(agentv3.SpanLayer) {
+func (*NoopSpan) SetSpanLayer(layer int32) {
 }
 
 func (*NoopSpan) GetSpanLayer() agentv3.SpanLayer {
@@ -54,13 +52,13 @@ func (*NoopSpan) GetComponent() int32 {
 	return 0
 }
 
-func (*NoopSpan) Tag(Tag, string) {
+func (*NoopSpan) Tag(string, string) {
 }
 
-func (*NoopSpan) Log(time.Time, ...string) {
+func (*NoopSpan) Log(...string) {
 }
 
-func (*NoopSpan) Error(time.Time, ...string) {
+func (*NoopSpan) Error(...string) {
 }
 
 func (*NoopSpan) End() {
@@ -78,6 +76,6 @@ func (*NoopSpan) IsValid() bool {
 	return true
 }
 
-func (n *NoopSpan) ParentSpan() Span {
+func (n *NoopSpan) ParentSpan() TracingSpan {
 	return nil
 }
diff --git a/plugins/core/span_tracing.go b/plugins/core/span_tracing.go
index 129b02d..27a530b 100644
--- a/plugins/core/span_tracing.go
+++ b/plugins/core/span_tracing.go
@@ -20,7 +20,6 @@ package core
 import (
 	"fmt"
 	"sync/atomic"
-	"time"
 
 	"github.com/apache/skywalking-go/reporter"
 
@@ -59,7 +58,7 @@ type SegmentContext struct {
 	collect            chan<- reporter.ReportedSpan
 	refNum             *int32
 	spanIDGenerator    *int32
-	FirstSpan          Span `json:"-"`
+	FirstSpan          TracingSpan `json:"-"`
 	CorrelationContext map[string]string
 }
 
@@ -84,7 +83,7 @@ func (c *SegmentContext) GetParentSegmentID() string {
 }
 
 type SegmentSpan interface {
-	Span
+	TracingSpan
 	GetSegmentContext() SegmentContext
 	tracer() *Tracer
 	segmentRegister() bool
@@ -95,7 +94,7 @@ type SegmentSpanImpl struct {
 	SegmentContext
 }
 
-// For Span
+// For TracingSpan
 func (s *SegmentSpanImpl) End() {
 	if !s.IsValid() {
 		return
@@ -110,7 +109,7 @@ func (s *SegmentSpanImpl) GetDefaultSpan() DefaultSpan {
 	return s.DefaultSpan
 }
 
-// For Reported Span
+// For Reported TracingSpan
 
 func (s *SegmentSpanImpl) Context() reporter.SegmentContext {
 	return &s.SegmentContext
@@ -251,7 +250,7 @@ func (s *SnapshotSpan) SetOperationName(_ string) {
 	panic(fmt.Errorf("cannot update the operation name of span in other goroutine"))
 }
 
-func (s *SnapshotSpan) SetSpanLayer(_ agentv3.SpanLayer) {
+func (s *SnapshotSpan) SetSpanLayer(_ int32) {
 	panic(fmt.Errorf("cannot update the layer of span in other goroutine"))
 }
 
@@ -259,15 +258,15 @@ func (s *SnapshotSpan) SetComponent(_ int32) {
 	panic(fmt.Errorf("cannot update the compoenent of span in other goroutine"))
 }
 
-func (s *SnapshotSpan) Tag(key Tag, value string) {
+func (s *SnapshotSpan) Tag(key, value string) {
 	panic(fmt.Errorf("cannot add tag of span in other goroutine"))
 }
 
-func (s *SnapshotSpan) Log(_ time.Time, _ ...string) {
+func (s *SnapshotSpan) Log(_ ...string) {
 	panic(fmt.Errorf("cannot add log of span in other goroutine"))
 }
 
-func (s *SnapshotSpan) Error(_ time.Time, _ ...string) {
+func (s *SnapshotSpan) Error(_ ...string) {
 	panic(fmt.Errorf("cannot add error of span in other goroutine"))
 }
 
@@ -322,7 +321,7 @@ func newSegmentRoot(segmentSpan *SegmentSpanImpl) *RootSegmentSpan {
 	return s
 }
 
-func newSnapshotSpan(current Span) *SnapshotSpan {
+func newSnapshotSpan(current TracingSpan) *SnapshotSpan {
 	if current == nil {
 		return nil
 	}
diff --git a/plugins/core/test_base.go b/plugins/core/test_base.go
index 2825e6c..8561ede 100644
--- a/plugins/core/test_base.go
+++ b/plugins/core/test_base.go
@@ -18,10 +18,12 @@
 package core
 
 import (
+	"github.com/apache/skywalking-go/plugins/core/operator"
 	"github.com/apache/skywalking-go/reporter"
 )
 
 var tlsData interface{}
+var Tracing *Tracer
 
 func init() {
 	SetGLS = func(i interface{}) {
@@ -30,16 +32,30 @@ func init() {
 	GetGLS = func() interface{} {
 		return tlsData
 	}
+	operator.GetOperator = func() operator.Operator {
+		return Tracing
+	}
 	ResetTracingContext()
 }
 
 func ResetTracingContext() {
 	SetGLS(nil)
-	SetGlobalTracer(&Tracer{initFlag: 1, Sampler: NewConstSampler(true), Reporter: &StoreReporter{}})
+	Tracing = &Tracer{initFlag: 1, Sampler: NewConstSampler(true), Reporter: &StoreReporter{}}
+	SetAsNewGoroutine()
+}
+
+func SetAsNewGoroutine() {
+	gls := GetGLS()
+	if gls == nil {
+		return
+	}
+	if e := gls.(ContextSnapshoter); e != nil {
+		SetGLS(e.TakeSnapShot(GetGLS()))
+	}
 }
 
 func GetReportedSpans() []reporter.ReportedSpan {
-	return GetGlobalTracer().Reporter.(*StoreReporter).Spans
+	return Tracing.Reporter.(*StoreReporter).Spans
 }
 
 type StoreReporter struct {
diff --git a/plugins/core/tracer.go b/plugins/core/tracer.go
index 9890dfc..3331a85 100644
--- a/plugins/core/tracer.go
+++ b/plugins/core/tracer.go
@@ -18,6 +18,7 @@
 package core
 
 import (
+	"github.com/apache/skywalking-go/plugins/core/operator"
 	"github.com/apache/skywalking-go/reporter"
 )
 
@@ -33,6 +34,7 @@ type Tracer struct {
 	// 0 not init 1 init
 	initFlag int32
 	Sampler  Sampler
+	Log      operator.LogOperator
 	// correlation *CorrelationConfig	// temporarily disable, because haven't been implemented yet
 	cdsWatchers []reporter.AgentConfigChangeWatcher
 }
diff --git a/plugins/core/tracing.go b/plugins/core/tracing.go
new file mode 100644
index 0000000..1f4c383
--- /dev/null
+++ b/plugins/core/tracing.go
@@ -0,0 +1,241 @@
+// 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 (
+	"reflect"
+
+	"github.com/pkg/errors"
+
+	"github.com/apache/skywalking-go/plugins/core/tracing"
+	"github.com/apache/skywalking-go/reporter"
+)
+
+func (t *Tracer) Test() bool {
+	return true
+}
+
+func (t *Tracer) Tracing() interface{} {
+	return t
+}
+
+func (t *Tracer) Logger() interface{} {
+	return t.Log
+}
+
+func (t *Tracer) CreateEntrySpan(operationName string, extractor interface{}, opts ...interface{}) (s interface{}, err error) {
+	ctx, tracingSpan, noop := t.createNoop()
+	if noop {
+		return s, nil
+	}
+	defer func() {
+		saveSpanToActiveIfNotError(ctx, s, err)
+	}()
+	var ref = &SpanContext{}
+	if err := ref.Decode(extractor.(tracing.ExtractorWrapper).Fun()); err != nil {
+		return nil, err
+	}
+	if !ref.Valid {
+		ref = nil
+	}
+
+	return t.createSpan0(tracingSpan, append(opts, withRef(ref), withSpanType(SpanTypeEntry), withOperationName(operationName))...)
+}
+
+func (t *Tracer) CreateLocalSpan(operationName string, opts ...interface{}) (s interface{}, err error) {
+	ctx, tracingSpan, noop := t.createNoop()
+	if noop {
+		return tracingSpan, nil
+	}
+	defer func() {
+		saveSpanToActiveIfNotError(ctx, s, err)
+	}()
+
+	return t.createSpan0(tracingSpan, append(opts, withSpanType(SpanTypeLocal), withOperationName(operationName))...)
+}
+
+func (t *Tracer) CreateExitSpan(operationName, peer string, injector interface{}, opts ...interface{}) (s interface{}, err error) {
+	ctx, tracingSpan, noop := t.createNoop()
+	if noop {
+		return tracingSpan, nil
+	}
+	defer func() {
+		saveSpanToActiveIfNotError(ctx, s, err)
+	}()
+
+	span, err := t.createSpan0(tracingSpan, append(opts, withSpanType(SpanTypeExit), withOperationName(operationName), withPeer(peer))...)
+	if err != nil {
+		return nil, err
+	}
+	spanContext := &SpanContext{}
+	reportedSpan, ok := span.(SegmentSpan)
+	if !ok {
+		return nil, errors.New("span type is wrong")
+	}
+
+	firstSpan := reportedSpan.GetSegmentContext().FirstSpan
+	spanContext.Sample = 1
+	spanContext.TraceID = reportedSpan.GetSegmentContext().TraceID
+	spanContext.ParentSegmentID = reportedSpan.GetSegmentContext().SegmentID
+	spanContext.ParentSpanID = reportedSpan.GetSegmentContext().SpanID
+	spanContext.ParentService = t.Service
+	spanContext.ParentServiceInstance = t.Instance
+	spanContext.ParentEndpoint = firstSpan.GetOperationName()
+	spanContext.AddressUsedAtClient = peer
+	spanContext.CorrelationContext = reportedSpan.GetSegmentContext().CorrelationContext
+
+	err = spanContext.Encode(injector.(tracing.InjectorWrapper).Fun())
+	if err != nil {
+		return nil, err
+	}
+	return span, nil
+}
+
+func (t *Tracer) ActiveSpan() interface{} {
+	ctx := getTracingContext()
+	if ctx == nil || ctx.ActiveSpan() == nil {
+		return nil
+	}
+	span := ctx.ActiveSpan()
+	if _, ok := span.(*SnapshotSpan); ok {
+		return nil
+	}
+	return span
+}
+
+func (t *Tracer) GetRuntimeContextValue(key string) interface{} {
+	context := getTracingContext()
+	if context == nil {
+		return nil
+	}
+	return context.Runtime.Get(key)
+}
+
+func (t *Tracer) SetRuntimeContextValue(key string, value interface{}) {
+	context := getTracingContext()
+	if context == nil {
+		context = NewTracingContext()
+		SetGLS(context)
+	}
+	context.Runtime.Set(key, value)
+}
+
+func (t *Tracer) createNoop() (*TracingContext, TracingSpan, bool) {
+	if !t.InitSuccess() {
+		return nil, &NoopSpan{}, true
+	}
+	ctx := getTracingContext()
+	if ctx != nil {
+		span := ctx.ActiveSpan()
+		_, ok := span.(*NoopSpan)
+		return ctx, span, ok
+	}
+	return nil, nil, false
+}
+
+func (t *Tracer) createSpan0(parent TracingSpan, opts ...interface{}) (s TracingSpan, err error) {
+	ds := NewDefaultSpan(t, parent)
+	for _, opt := range opts {
+		opt.(tracing.SpanOption).Apply(ds)
+	}
+	var parentSpan SegmentSpan
+	if parent != nil {
+		tmpSpan, ok := parent.(SegmentSpan)
+		if ok {
+			parentSpan = tmpSpan
+		}
+	}
+	isForceSample := len(ds.Refs) > 0
+	// Try to sample when it is not force sample
+	if parentSpan == nil && !isForceSample {
+		// Force sample
+		sampled := t.Sampler.IsSampled(ds.OperationName)
+		if !sampled {
+			// Filter by sample just return noop span
+			s = &NoopSpan{}
+			return s, nil
+		}
+	}
+	s, err = NewSegmentSpan(ds, parentSpan)
+	if err != nil {
+		return nil, err
+	}
+	return s, nil
+}
+
+func withSpanType(spanType SpanType) tracing.SpanOption {
+	return buildSpanOption(func(span *DefaultSpan) {
+		span.SpanType = spanType
+	})
+}
+
+func withOperationName(opName string) tracing.SpanOption {
+	return buildSpanOption(func(span *DefaultSpan) {
+		span.OperationName = opName
+	})
+}
+
+func withRef(sc reporter.SpanContext) tracing.SpanOption {
+	return buildSpanOption(func(span *DefaultSpan) {
+		if sc == nil {
+			return
+		}
+		v := reflect.ValueOf(sc)
+		if v.Interface() == reflect.Zero(v.Type()).Interface() {
+			return
+		}
+		span.Refs = append(span.Refs, sc)
+	})
+}
+
+func withPeer(peer string) tracing.SpanOption {
+	return buildSpanOption(func(span *DefaultSpan) {
+		span.Peer = peer
+	})
+}
+
+type spanOpImpl struct {
+	exe func(s *DefaultSpan)
+}
+
+func (s *spanOpImpl) Apply(span interface{}) {
+	s.exe(span.(*DefaultSpan))
+}
+
+func buildSpanOption(e func(s *DefaultSpan)) tracing.SpanOption {
+	return &spanOpImpl{exe: e}
+}
+
+func getTracingContext() *TracingContext {
+	gls := GetGLS()
+	if gls == nil {
+		return nil
+	}
+	return gls.(*TracingContext)
+}
+
+func saveSpanToActiveIfNotError(ctx *TracingContext, span interface{}, err error) {
+	if err != nil || span == nil {
+		return
+	}
+	if ctx == nil {
+		ctx = NewTracingContext()
+	}
+	ctx.SaveActiveSpan(span.(TracingSpan))
+	SetGLS(ctx)
+}
diff --git a/plugins/core/tracing/api.go b/plugins/core/tracing/api.go
index a53c086..0c07a41 100644
--- a/plugins/core/tracing/api.go
+++ b/plugins/core/tracing/api.go
@@ -18,246 +18,132 @@
 package tracing
 
 import (
-	"fmt"
-	"reflect"
-
-	"github.com/apache/skywalking-go/plugins/core"
-	"github.com/apache/skywalking-go/reporter"
-
-	"github.com/pkg/errors"
-
-	commonv3 "skywalking.apache.org/repo/goapi/collect/common/v3"
-	agentv3 "skywalking.apache.org/repo/goapi/collect/language/agent/v3"
+	"github.com/apache/skywalking-go/plugins/core/operator"
 )
 
 var (
-	errParameter = fmt.Errorf("parameter are nil")
+	errParameter = operator.NewError("parameter are nil")
 )
 
-// Extractor is a tool specification which define how to
-// extract trace parent context from propagation context
-type Extractor func(headerKey string) (string, error)
-
-// Injector is a tool specification which define how to
-// inject trace context into propagation context
-type Injector func(headerKey, headerValue string) error
-
-func CreateEntrySpan(operationName string, extractor Extractor, opts ...SpanOption) (s core.Span, err error) {
+func CreateEntrySpan(operationName string, extractor Extractor, opts ...SpanOption) (s Span, err error) {
 	if operationName == "" || extractor == nil {
 		return nil, errParameter
 	}
-	tracer, ctx, s, noop := createNoop()
-	if noop {
-		return s, nil
+	op := operator.GetOperator()
+	if op == nil {
+		return &NoopSpan{}, nil
 	}
-	defer func() {
-		saveSpanToActiveIfNotError(ctx, s, err)
-	}()
-	var ref = &core.SpanContext{}
-	if err := ref.Decode(extractor); err != nil {
+	span, err := op.Tracing().(operator.TracingOperator).CreateEntrySpan(operationName, extractorWrapper(extractor), copyOptsAsInterface(opts)...)
+	if err != nil {
 		return nil, err
 	}
-	if !ref.Valid {
-		ref = nil
-	}
-
-	return createSpan0(tracer, s, append(opts, withRef(ref), withSpanType(core.SpanTypeEntry), withOperationName(operationName))...)
+	return newSpanAdapter(span.(AdaptSpan)), nil
 }
 
-func CreateLocalSpan(operationName string, opts ...SpanOption) (s core.Span, err error) {
+func CreateLocalSpan(operationName string, opts ...SpanOption) (s Span, err error) {
 	if operationName == "" {
 		return nil, errParameter
 	}
-	tracer, ctx, s, noop := createNoop()
-	if noop {
-		return s, nil
+	op := operator.GetOperator()
+	if op == nil {
+		return &NoopSpan{}, nil
 	}
-	defer func() {
-		saveSpanToActiveIfNotError(ctx, s, err)
-	}()
-
-	return createSpan0(tracer, s, append(opts, withSpanType(core.SpanTypeLocal), withOperationName(operationName))...)
+	span, err := op.Tracing().(operator.TracingOperator).CreateLocalSpan(operationName, copyOptsAsInterface(opts)...)
+	if err != nil {
+		return nil, err
+	}
+	return newSpanAdapter(span.(AdaptSpan)), nil
 }
 
-func CreateExitSpan(operationName, peer string, injector Injector, opts ...SpanOption) (s core.Span, err error) {
+func CreateExitSpan(operationName, peer string, injector Injector, opts ...SpanOption) (s Span, err error) {
 	if operationName == "" || peer == "" || injector == nil {
 		return nil, errParameter
 	}
-	tracer, ctx, s, noop := createNoop()
-	if noop {
-		return s, nil
+	op := operator.GetOperator()
+	if op == nil {
+		return &NoopSpan{}, nil
 	}
-	defer func() {
-		saveSpanToActiveIfNotError(ctx, s, err)
-	}()
-
-	span, err := createSpan0(tracer, s, append(opts, withSpanType(core.SpanTypeExit), withOperationName(operationName), withPeer(peer))...)
+	span, err := op.Tracing().(operator.TracingOperator).CreateExitSpan(operationName, peer, injectorWrapper(injector), copyOptsAsInterface(opts)...)
 	if err != nil {
 		return nil, err
 	}
-	spanContext := &core.SpanContext{}
-	reportedSpan, ok := span.(core.SegmentSpan)
-	if !ok {
-		return nil, errors.New("span type is wrong")
-	}
-
-	firstSpan := reportedSpan.GetSegmentContext().FirstSpan
-	spanContext.Sample = 1
-	spanContext.TraceID = reportedSpan.GetSegmentContext().TraceID
-	spanContext.ParentSegmentID = reportedSpan.GetSegmentContext().SegmentID
-	spanContext.ParentSpanID = reportedSpan.GetSegmentContext().SpanID
-	spanContext.ParentService = tracer.Service
-	spanContext.ParentServiceInstance = tracer.Instance
-	spanContext.ParentEndpoint = firstSpan.GetOperationName()
-	spanContext.AddressUsedAtClient = peer
-	spanContext.CorrelationContext = reportedSpan.GetSegmentContext().CorrelationContext
-
-	err = spanContext.Encode(injector)
-	if err != nil {
-		return nil, err
-	}
-	return span, nil
+	return newSpanAdapter(span.(AdaptSpan)), nil
 }
 
-func ActiveSpan() core.Span {
-	ctx := getTracingContext()
-	if ctx == nil || ctx.ActiveSpan == nil {
+func ActiveSpan() Span {
+	op := operator.GetOperator()
+	if op == nil {
 		return nil
 	}
-	if _, ok := ctx.ActiveSpan.(*core.SnapshotSpan); ok {
-		return nil
+	if span, ok := op.Tracing().(operator.TracingOperator).ActiveSpan().(AdaptSpan); ok {
+		return newSpanAdapter(span)
 	}
-	return ctx.ActiveSpan
+	return nil
 }
 
-// SpanOption allows for functional options to adjust behavior
-// of a Span to be created by CreateLocalSpan
-type SpanOption func(s *core.DefaultSpan)
-
-func WithLayer(layer agentv3.SpanLayer) SpanOption {
-	return func(s *core.DefaultSpan) {
-		s.Layer = layer
+func GetRuntimeContextValue(key string) interface{} {
+	op := operator.GetOperator()
+	if op == nil {
+		return nil
 	}
+	return op.Tracing().(operator.TracingOperator).GetRuntimeContextValue(key)
 }
 
-func WithComponent(componentID int32) SpanOption {
-	return func(s *core.DefaultSpan) {
-		s.ComponentID = componentID
+func SetRuntimeContextValue(key string, val interface{}) {
+	op := operator.GetOperator()
+	if op != nil {
+		op.Tracing().(operator.TracingOperator).SetRuntimeContextValue(key, val)
 	}
 }
 
-func WithTag(key, value string) SpanOption {
-	return func(s *core.DefaultSpan) {
-		s.Tags = append(s.Tags, &commonv3.KeyStringValuePair{Key: key, Value: value})
+func copyOptsAsInterface(opts []SpanOption) []interface{} {
+	optsVal := make([]interface{}, len(opts))
+	for i := range opts {
+		optsVal[i] = opts[i]
 	}
+	return optsVal
 }
 
-func GetRuntimeContextValue(key string) interface{} {
-	context := core.GetTracingContext()
-	if context == nil {
-		return nil
-	}
-	return context.Runtime.Get(key)
+type extractorWrapperImpl struct {
+	extractor Extractor
 }
 
-func SetRuntimeContextValue(key string, val interface{}) {
-	context := core.GetTracingContext()
-	if context == nil {
-		context = core.NewTracingContext()
-		core.SetGLS(context)
-	}
-	context.Runtime.Set(key, val)
+func (e *extractorWrapperImpl) Fun() func(headerKey string) (string, error) {
+	return e.extractor
 }
 
-func createNoop() (*core.Tracer, *core.TracingContext, core.Span, bool) {
-	tracer := core.GetGlobalTracer()
-	if tracer == nil || !tracer.InitSuccess() {
-		return nil, nil, &core.NoopSpan{}, true
-	}
-	ctx := getTracingContext()
-	if ctx != nil {
-		_, ok := ctx.ActiveSpan.(*core.NoopSpan)
-		return tracer, ctx, ctx.ActiveSpan, ok
-	}
-	return tracer, nil, nil, false
+func extractorWrapper(extractor Extractor) *extractorWrapperImpl {
+	return &extractorWrapperImpl{extractor: extractor}
 }
 
-func createSpan0(tracer *core.Tracer, parent core.Span, opts ...SpanOption) (s core.Span, err error) {
-	ds := core.NewDefaultSpan(tracer, parent)
-	for _, opt := range opts {
-		opt(ds)
-	}
-	var parentSpan core.SegmentSpan
-	if parent != nil {
-		tmpSpan, ok := parent.(core.SegmentSpan)
-		if ok {
-			parentSpan = tmpSpan
-		}
-	}
-	isForceSample := len(ds.Refs) > 0
-	// Try to sample when it is not force sample
-	if parentSpan == nil && !isForceSample {
-		// Force sample
-		sampled := tracer.Sampler.IsSampled(ds.OperationName)
-		if !sampled {
-			// Filter by sample just return noop span
-			s = &core.NoopSpan{}
-			return s, nil
-		}
-	}
-	s, err = core.NewSegmentSpan(ds, parentSpan)
-	if err != nil {
-		return nil, err
-	}
-	return s, nil
+type injectorWrapperImpl struct {
+	injector Injector
 }
 
-func withSpanType(spanType core.SpanType) SpanOption {
-	return func(span *core.DefaultSpan) {
-		span.SpanType = spanType
-	}
+func (i *injectorWrapperImpl) Fun() func(headerKey, headerValue string) error {
+	return i.injector
 }
 
-func withOperationName(opName string) SpanOption {
-	return func(span *core.DefaultSpan) {
-		span.OperationName = opName
-	}
+func injectorWrapper(injector Injector) *injectorWrapperImpl {
+	return &injectorWrapperImpl{injector: injector}
 }
 
-func withRef(sc reporter.SpanContext) SpanOption {
-	return func(span *core.DefaultSpan) {
-		if sc == nil {
-			return
-		}
-		v := reflect.ValueOf(sc)
-		if v.Interface() == reflect.Zero(v.Type()).Interface() {
-			return
-		}
-		span.Refs = append(span.Refs, sc)
-	}
+type NoopSpan struct {
 }
 
-func withPeer(peer string) SpanOption {
-	return func(span *core.DefaultSpan) {
-		span.Peer = peer
-	}
+func (n *NoopSpan) SetOperationName(string) {
 }
-
-func getTracingContext() *core.TracingContext {
-	ctx := core.GetGLS()
-	if ctx == nil {
-		return nil
-	}
-	return ctx.(*core.TracingContext)
+func (n *NoopSpan) SetPeer(string) {
 }
-
-func saveSpanToActiveIfNotError(ctx *core.TracingContext, span core.Span, err error) {
-	if err != nil {
-		return
-	}
-	if ctx == nil {
-		ctx = core.NewTracingContext()
-	}
-	ctx.ActiveSpan = span
-	core.SetGLS(ctx)
+func (n *NoopSpan) SetSpanLayer(SpanLayer) {
+}
+func (n *NoopSpan) SetComponent(int32) {
+}
+func (n *NoopSpan) Tag(Tag, string) {
+}
+func (n *NoopSpan) Log(...string) {
+}
+func (n *NoopSpan) Error(...string) {
+}
+func (n *NoopSpan) End() {
 }
diff --git a/plugins/core/tracing/api_test.go b/plugins/core/tracing/api_test.go
deleted file mode 100644
index 2560042..0000000
--- a/plugins/core/tracing/api_test.go
+++ /dev/null
@@ -1,346 +0,0 @@
-// 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 tracing
-
-import (
-	"testing"
-	"time"
-
-	"github.com/apache/skywalking-go/plugins/core"
-
-	"github.com/stretchr/testify/assert"
-
-	agentv3 "skywalking.apache.org/repo/goapi/collect/language/agent/v3"
-)
-
-const (
-	sample                = 1
-	traceID               = "1f2d4bf47bf711eab794acde48001122"
-	parentSegmentID       = "1e7c204a7bf711eab858acde48001122"
-	parentSpanID          = 0
-	parentService         = "service"
-	parentServiceInstance = "instance"
-	parentEndpoint        = "/foo/bar"
-	addressUsedAtClient   = "foo.svc:8787"
-)
-
-var header string
-
-func init() {
-	scx := core.SpanContext{
-		Sample:                sample,
-		TraceID:               traceID,
-		ParentSegmentID:       parentSegmentID,
-		ParentSpanID:          parentSpanID,
-		ParentService:         parentService,
-		ParentServiceInstance: parentServiceInstance,
-		ParentEndpoint:        parentEndpoint,
-		AddressUsedAtClient:   addressUsedAtClient,
-	}
-	header = scx.EncodeSW8()
-}
-
-type spanOperationTestCase struct {
-	operations    []func(existingSpans []core.Span) (core.Span, error)
-	exceptedSpans []struct {
-		spanType         core.SpanType
-		operationName    string
-		parentSpanOpName string
-		peer             string
-	}
-}
-
-func TestCreateSpanInSingleGoroutine(t *testing.T) {
-	defer core.ResetTracingContext()
-	validateSpanOperation(t, []spanOperationTestCase{
-		{
-			operations: []func(existingSpans []core.Span) (core.Span, error){
-				func(existingSpans []core.Span) (core.Span, error) {
-					return CreateEntrySpan("/entry", func(key string) (string, error) { return "", nil })
-				},
-				func(existingSpans []core.Span) (core.Span, error) {
-					return CreateLocalSpan("/local1")
-				},
-				func(existingSpans []core.Span) (core.Span, error) {
-					return CreateLocalSpan("/local1-1")
-				},
-				func(existingSpans []core.Span) (core.Span, error) {
-					return CreateExitSpan("/local1-1-exit", "localhost:8080", func(key, value string) error { return nil })
-				},
-				func(existingSpans []core.Span) (core.Span, error) { existingSpans[3].End(); return nil, nil },
-				func(existingSpans []core.Span) (core.Span, error) { existingSpans[2].End(); return nil, nil },
-				func(existingSpans []core.Span) (core.Span, error) {
-					return CreateExitSpan("/local1-exit", "localhost:8080", func(key, value string) error { return nil })
-				},
-				func(existingSpans []core.Span) (core.Span, error) { existingSpans[4].End(); return nil, nil },
-				func(existingSpans []core.Span) (core.Span, error) { existingSpans[1].End(); return nil, nil },
-				func(existingSpans []core.Span) (core.Span, error) {
-					return CreateExitSpan("/entry-exit", "localhost:8080", func(key, value string) error { return nil })
-				},
-				func(existingSpans []core.Span) (core.Span, error) { existingSpans[5].End(); return nil, nil },
-				func(existingSpans []core.Span) (core.Span, error) { existingSpans[0].End(); return nil, nil },
-			},
-			exceptedSpans: []struct {
-				spanType         core.SpanType
-				operationName    string
-				parentSpanOpName string
-				peer             string
-			}{
-				{core.SpanTypeEntry, "/entry", "", ""},
-				{core.SpanTypeLocal, "/local1", "/entry", ""},
-				{core.SpanTypeLocal, "/local1-1", "/local1", ""},
-				{core.SpanTypeExit, "/local1-1-exit", "/local1-1", "localhost:8080"},
-				{core.SpanTypeExit, "/local1-exit", "/local1", "localhost:8080"},
-				{core.SpanTypeExit, "/entry-exit", "/entry", "localhost:8080"},
-			},
-		},
-	})
-}
-
-func TestCreateSpanInDifferenceGoroutine(t *testing.T) {
-	defer core.ResetTracingContext()
-	validateSpanOperation(t, []spanOperationTestCase{
-		{
-			operations: []func(existingSpans []core.Span) (core.Span, error){
-				func(existingSpans []core.Span) (core.Span, error) {
-					return CreateEntrySpan("/entry", func(key string) (string, error) { return "", nil })
-				},
-				func(existingSpans []core.Span) (core.Span, error) { // new goroutine
-					core.SetGLS(core.TaskTracingContextSnapshot(core.GetGLS()))
-					return nil, nil
-				},
-				func(existingSpans []core.Span) (core.Span, error) {
-					return CreateLocalSpan("/local")
-				},
-				func(existingSpans []core.Span) (core.Span, error) { // new goroutine
-					core.SetGLS(core.TaskTracingContextSnapshot(core.GetGLS()))
-					return nil, nil
-				},
-				func(existingSpans []core.Span) (core.Span, error) {
-					return CreateExitSpan("/local-exit", "localhost:8080", func(key, value string) error { return nil })
-				},
-				func(existingSpans []core.Span) (core.Span, error) {
-					existingSpans[2].End()
-					return nil, nil
-				},
-				func(existingSpans []core.Span) (core.Span, error) {
-					existingSpans[1].End()
-					return nil, nil
-				},
-				func(existingSpans []core.Span) (core.Span, error) {
-					existingSpans[0].End()
-					return nil, nil
-				},
-			},
-			exceptedSpans: []struct {
-				spanType         core.SpanType
-				operationName    string
-				parentSpanOpName string
-				peer             string
-			}{
-				{core.SpanTypeEntry, "/entry", "", ""},
-				{core.SpanTypeLocal, "/local", "/entry", ""},
-				{core.SpanTypeExit, "/local-exit", "/local", "localhost:8080"},
-			},
-		},
-	})
-}
-
-func TestSpanContextWriting(t *testing.T) {
-	defer core.ResetTracingContext()
-	s, err := CreateEntrySpan("/entry", func(key string) (string, error) { return "", nil })
-	assert.NoError(t, err)
-	s.End()
-	s, err = CreateExitSpan("/exit", "localhost:8080", func(key, value string) error {
-		ctx := core.SpanContext{}
-		if key == core.Header {
-			assert.NoError(t, ctx.DecodeSW8(value))
-		}
-		if key == core.HeaderCorrelation {
-			assert.NoError(t, ctx.DecodeSW8Correlation(value))
-		}
-		return nil
-	})
-	assert.NoError(t, err)
-	s.End()
-}
-
-func TestSpanContextReading(t *testing.T) {
-	defer core.ResetTracingContext()
-	s, err := CreateEntrySpan("/entry", func(key string) (string, error) {
-		if key == core.Header {
-			return header, nil
-		}
-		return "", nil
-	})
-	assert.NoError(t, err)
-	s.End()
-	time.Sleep(time.Millisecond * 50)
-	spans := core.GetReportedSpans()
-	assert.Equal(t, 1, len(spans), "span count not correct")
-	tracingContext := spans[0].Context()
-	assert.Equal(t, traceID, tracingContext.GetTraceID(), "trace id not correct")
-	assert.Equal(t, 1, len(spans[0].Refs()), "refs not correct")
-	refCtx := spans[0].Refs()[0]
-	assert.Equal(t, traceID, refCtx.GetTraceID(), "ref trace id not correct")
-	assert.Equal(t, parentSegmentID, refCtx.GetParentSegmentID(), "ref segment id not correct")
-	assert.Equal(t, parentEndpoint, refCtx.GetParentEndpoint(), "ref endpoint not correct")
-	assert.Equal(t, int32(parentSpanID), refCtx.GetParentSpanID(), "ref span id not correct")
-	assert.Equal(t, parentService, refCtx.GetParentService(), "ref service not correct")
-	assert.Equal(t, parentServiceInstance, refCtx.GetParentServiceInstance(), "ref service instance not correct")
-	assert.Equal(t, parentEndpoint, refCtx.GetParentEndpoint(), "ref endpoint not correct")
-}
-
-func TestSpanOperation(t *testing.T) {
-	defer core.ResetTracingContext()
-	spanCreations := []func(op SpanOption) (core.Span, error){
-		func(op SpanOption) (core.Span, error) {
-			return CreateEntrySpan("test", func(headerKey string) (string, error) {
-				return "", nil
-			}, op)
-		},
-		func(op SpanOption) (core.Span, error) {
-			return CreateLocalSpan("test", op)
-		},
-		func(op SpanOption) (core.Span, error) {
-			return CreateExitSpan("test", "localhost:8080", func(headerKey, headerValue string) error {
-				return nil
-			}, op)
-		},
-	}
-
-	spanOptions := []struct {
-		op       SpanOption
-		validate func(s *core.RootSegmentSpan) bool
-	}{
-		{WithLayer(agentv3.SpanLayer_Http), func(s *core.RootSegmentSpan) bool {
-			return s.DefaultSpan.Layer == agentv3.SpanLayer_Http
-		}},
-		{WithComponent(1), func(s *core.RootSegmentSpan) bool {
-			return s.DefaultSpan.ComponentID == 1
-		}},
-		{WithTag("test", "test1"), func(s *core.RootSegmentSpan) bool {
-			for _, k := range s.DefaultSpan.Tags {
-				if k.Key == "test" {
-					return k.Value == "test1"
-				}
-			}
-			return false
-		}},
-	}
-
-	for createInx, spanCreate := range spanCreations {
-		for _, op := range spanOptions {
-			create, err := spanCreate(op.op)
-			if err != nil {
-				assert.Nil(t, err, "create span error")
-			}
-			span := create.(*core.RootSegmentSpan)
-			assert.Truef(t, op.validate(span), "span validation failed, create index: %d, option index: %d", createInx, op)
-			create.End()
-		}
-	}
-}
-
-func TestActiveSpan(t *testing.T) {
-	defer core.ResetTracingContext()
-	// active span in same goroutine
-	span, err := CreateEntrySpan("/entry", func(key string) (string, error) { return "", nil })
-	assert.NoError(t, err)
-	assert.Equal(t, span, ActiveSpan(), "active span not correct")
-	oldGLS := core.GetGLS()
-	// change goroutine
-	core.SetGLS(core.TaskTracingContextSnapshot(oldGLS))
-	assert.Nil(t, ActiveSpan(), "active span should be nil when cross goroutine")
-	// change back
-	core.SetGLS(oldGLS)
-	span.End()
-	assert.Nil(t, ActiveSpan(), "active span not correct")
-}
-
-func TestRuntimeContext(t *testing.T) {
-	defer core.ResetTracingContext()
-	assert.Nilf(t, GetRuntimeContextValue("test"), "runtime context data should be nil")
-	SetRuntimeContextValue("test", "test")
-	assert.Equal(t, "test", GetRuntimeContextValue("test"), "runtime context data should be \"test\"")
-	// switch to the new goroutine
-	oldGLS := core.GetGLS()
-	core.SetGLS(core.TaskTracingContextSnapshot(oldGLS))
-	assert.Equal(t, "test", GetRuntimeContextValue("test"), "runtime context data should be \"test\"")
-	assert.Nilf(t, GetRuntimeContextValue("test1"), "runtime context data should be nil")
-	SetRuntimeContextValue("test1", "test1")
-	assert.Equal(t, "test1", GetRuntimeContextValue("test1"), "runtime context data should be \"test1\"")
-	// switch back to the old goroutine
-	core.SetGLS(oldGLS)
-	assert.Nilf(t, GetRuntimeContextValue("test1"), "runtime context data should be nil")
-}
-
-func validateSpanOperation(t *testing.T, cases []spanOperationTestCase) {
-	for _, tt := range cases {
-		spans := make([]core.Span, 0)
-		for i, op := range tt.operations {
-			span, err := op(spans)
-			assert.Nilf(t, err, "create span error, operation index: %d", i)
-			time.Sleep(time.Millisecond * 50)
-			if span != nil {
-				spans = append(spans, span)
-			}
-		}
-
-		time.Sleep(time.Millisecond * 100)
-		assert.Equal(t, len(tt.exceptedSpans), len(core.GetReportedSpans()), "span count not equal")
-		for i, exceptedSpan := range tt.exceptedSpans {
-			var span core.DefaultSpan
-			if i == 0 {
-				tmp, ok := core.GetReportedSpans()[len(core.GetReportedSpans())-1-i].(*core.RootSegmentSpan)
-				assert.True(t, ok, "first span is not root segment span")
-				span = tmp.DefaultSpan
-			} else {
-				found := false
-				for _, s := range core.GetReportedSpans() {
-					if s.OperationName() != exceptedSpan.operationName {
-						continue
-					}
-					tmp, ok := s.(*core.SegmentSpanImpl)
-					assert.Truef(t, ok, "span is not segment span, span index: %d", i)
-					span = tmp.DefaultSpan
-					found = true
-					break
-				}
-				assert.Truef(t, found, "span not found, span index: %d, name: %s", i, exceptedSpan.operationName)
-			}
-			assert.Equalf(t, exceptedSpan.spanType, span.SpanType, "span type not equal, span index: %d", i)
-			assert.Equalf(t, exceptedSpan.operationName, span.OperationName, "operation name not equal, span index: %d", i)
-			if exceptedSpan.parentSpanOpName != "" {
-				assert.Equalf(t, exceptedSpan.parentSpanOpName, span.Parent.GetOperationName(), "parent operation name not equal, span index: %d", i)
-			} else {
-				assert.Nilf(t, span.Parent, "parent span not nil, span index: %d", i)
-			}
-			if exceptedSpan.peer != "" {
-				assert.Equalf(t, exceptedSpan.peer, span.Peer, "span peer not equal, span index: %d", i)
-			} else {
-				assert.Truef(t, span.Peer == "", "span peer not empty, span index: %d", i)
-			}
-
-			assert.Greaterf(t, core.Millisecond(span.StartTime), int64(0), "start time not greater than 0, span index: %d", i)
-			assert.Greaterf(t, core.Millisecond(span.EndTime), core.Millisecond(span.StartTime), "end time not greater than 0, span indeX: %d", i)
-		}
-
-		core.GetGlobalTracer().Reporter = core.NewStoreReporter()
-	}
-}
diff --git a/agent/core/tracing/compile.go b/plugins/core/tracing/bridge.go
similarity index 50%
copy from agent/core/tracing/compile.go
copy to plugins/core/tracing/bridge.go
index 5ccde8b..356c2b0 100644
--- a/agent/core/tracing/compile.go
+++ b/plugins/core/tracing/bridge.go
@@ -17,19 +17,50 @@
 
 package tracing
 
-import (
-	//go:nolint
-	_ "fmt"
-	_ "reflect"
-
-	//go:nolint
-	_ "github.com/pkg/errors"
-
-	//go:nolint
-	_ "github.com/apache/skywalking-go/agent/core"
-	_ "github.com/apache/skywalking-go/reporter"
-
-	//go:nolint
-	_ "skywalking.apache.org/repo/goapi/collect/common/v3"
-	_ "skywalking.apache.org/repo/goapi/collect/language/agent/v3"
-)
+// AdaptSpan for adapt with agent core
+type AdaptSpan interface {
+	SetOperationName(string)
+	SetPeer(string)
+	SetSpanLayer(int32)
+	SetComponent(int32)
+	Tag(string, string)
+	Log(...string)
+	Error(...string)
+	End()
+}
+
+type SpanWrapper struct {
+	Span AdaptSpan
+}
+
+func newSpanAdapter(s AdaptSpan) Span {
+	return &SpanWrapper{Span: s}
+}
+
+func (s *SpanWrapper) Tag(k Tag, v string) {
+	s.Span.Tag(string(k), v)
+}
+
+func (s *SpanWrapper) SetSpanLayer(l SpanLayer) {
+	s.Span.SetSpanLayer(int32(l))
+}
+
+func (s *SpanWrapper) SetOperationName(name string) {
+	s.Span.SetOperationName(name)
+}
+
+func (s *SpanWrapper) SetPeer(v string) {
+	s.Span.SetPeer(v)
+}
+
+func (s *SpanWrapper) Log(v ...string) {
+	s.Span.Log(v...)
+}
+
+func (s *SpanWrapper) Error(v ...string) {
+	s.Span.Error(v...)
+}
+
+func (s *SpanWrapper) End() {
+	s.Span.End()
+}
diff --git a/plugins/core/tracing/span.go b/plugins/core/tracing/span.go
new file mode 100644
index 0000000..9b6d022
--- /dev/null
+++ b/plugins/core/tracing/span.go
@@ -0,0 +1,111 @@
+// 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 tracing
+
+// Extractor is a tool specification which define how to
+// extract trace parent context from propagation context
+type Extractor func(headerKey string) (string, error)
+
+// Injector is a tool specification which define how to
+// inject trace context into propagation context
+type Injector func(headerKey, headerValue string) error
+
+// SpanOption allows for functional options to adjust behavior
+// of a AdaptSpan to be created by CreateLocalSpan
+type SpanOption interface {
+	Apply(interface{})
+}
+
+// SpanLayer define the Span belong to which layer
+type SpanLayer int32
+
+var (
+	SpanLayerDatabase     SpanLayer = 1
+	SpanLayerRPCFramework SpanLayer = 2
+	SpanLayerHTTP         SpanLayer = 3
+	SpanLayerMQ           SpanLayer = 4
+	SpanLayerCache        SpanLayer = 5
+	SpanLayerFAAS         SpanLayer = 6
+)
+
+// Tag are supported by sky-walking engine.
+// As default, all Tags will be stored, but these ones have
+// particular meanings.
+type Tag string
+
+const (
+	TagURL             Tag = "url"
+	TagStatusCode      Tag = "status_code"
+	TagHTTPMethod      Tag = "http.method"
+	TagDBType          Tag = "db.type"
+	TagDBInstance      Tag = "db.instance"
+	TagDBStatement     Tag = "db.statement"
+	TagDBSqlParameters Tag = "db.sql.parameters"
+	TagMQQueue         Tag = "mq.queue"
+	TagMQBroker        Tag = "mq.broker"
+	TagMQTopic         Tag = "mq.topic"
+)
+
+func WithLayer(layer SpanLayer) SpanOption {
+	return buildSpanOption(func(s AdaptSpan) {
+		s.SetSpanLayer(int32(layer))
+	})
+}
+
+func WithComponent(componentID int32) SpanOption {
+	return buildSpanOption(func(s AdaptSpan) {
+		s.SetComponent(componentID)
+	})
+}
+
+func WithTag(key Tag, value string) SpanOption {
+	return buildSpanOption(func(s AdaptSpan) {
+		s.Tag(string(key), value)
+	})
+}
+
+type spanOpImpl struct {
+	exe func(s AdaptSpan)
+}
+
+func (s *spanOpImpl) Apply(span interface{}) {
+	s.exe(span.(AdaptSpan))
+}
+
+func buildSpanOption(e func(s AdaptSpan)) SpanOption {
+	return &spanOpImpl{exe: e}
+}
+
+type ExtractorWrapper interface {
+	Fun() func(headerKey string) (string, error)
+}
+
+type InjectorWrapper interface {
+	Fun() func(headerKey, headerValue string) error
+}
+
+// Span for plugin API
+type Span interface {
+	Tag(Tag, string)
+	SetSpanLayer(SpanLayer)
+	SetOperationName(string)
+	SetPeer(string)
+	Log(...string)
+	Error(...string)
+	End()
+}
diff --git a/plugins/core/tracing_test.go b/plugins/core/tracing_test.go
new file mode 100644
index 0000000..3356326
--- /dev/null
+++ b/plugins/core/tracing_test.go
@@ -0,0 +1,364 @@
+// 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 (
+	"testing"
+	"time"
+
+	"github.com/stretchr/testify/assert"
+
+	agentv3 "skywalking.apache.org/repo/goapi/collect/language/agent/v3"
+
+	"github.com/apache/skywalking-go/plugins/core/tracing"
+)
+
+const (
+	sample                = 1
+	traceID               = "1f2d4bf47bf711eab794acde48001122"
+	parentSegmentID       = "1e7c204a7bf711eab858acde48001122"
+	parentSpanID          = 0
+	parentService         = "service"
+	parentServiceInstance = "instance"
+	parentEndpoint        = "/foo/bar"
+	addressUsedAtClient   = "foo.svc:8787"
+)
+
+var header string
+
+func init() {
+	scx := SpanContext{
+		Sample:                sample,
+		TraceID:               traceID,
+		ParentSegmentID:       parentSegmentID,
+		ParentSpanID:          parentSpanID,
+		ParentService:         parentService,
+		ParentServiceInstance: parentServiceInstance,
+		ParentEndpoint:        parentEndpoint,
+		AddressUsedAtClient:   addressUsedAtClient,
+	}
+	header = scx.EncodeSW8()
+}
+
+type spanOperationTestCase struct {
+	operations    []func(existingSpans []tracing.Span) (tracing.Span, error)
+	exceptedSpans []struct {
+		spanType         SpanType
+		operationName    string
+		parentSpanOpName string
+		peer             string
+	}
+}
+
+func TestCreateSpanInSingleGoroutine(t *testing.T) {
+	defer ResetTracingContext()
+	validateSpanOperation(t, []spanOperationTestCase{
+		{
+			operations: []func(existingSpans []tracing.Span) (tracing.Span, error){
+				func(existingSpans []tracing.Span) (tracing.Span, error) {
+					return tracing.CreateEntrySpan("/entry", func(key string) (string, error) { return "", nil })
+				},
+				func(existingSpans []tracing.Span) (tracing.Span, error) {
+					return tracing.CreateLocalSpan("/local1")
+				},
+				func(existingSpans []tracing.Span) (tracing.Span, error) {
+					return tracing.CreateLocalSpan("/local1-1")
+				},
+				func(existingSpans []tracing.Span) (tracing.Span, error) {
+					return tracing.CreateExitSpan("/local1-1-exit", "localhost:8080", func(key, value string) error { return nil })
+				},
+				func(existingSpans []tracing.Span) (tracing.Span, error) {
+					existingSpans[3].End()
+					return nil, nil
+				},
+				func(existingSpans []tracing.Span) (tracing.Span, error) {
+					existingSpans[2].End()
+					return nil, nil
+				},
+				func(existingSpans []tracing.Span) (tracing.Span, error) {
+					return tracing.CreateExitSpan("/local1-exit", "localhost:8080", func(key, value string) error { return nil })
+				},
+				func(existingSpans []tracing.Span) (tracing.Span, error) {
+					existingSpans[4].End()
+					return nil, nil
+				},
+				func(existingSpans []tracing.Span) (tracing.Span, error) {
+					existingSpans[1].End()
+					return nil, nil
+				},
+				func(existingSpans []tracing.Span) (tracing.Span, error) {
+					return tracing.CreateExitSpan("/entry-exit", "localhost:8080", func(key, value string) error { return nil })
+				},
+				func(existingSpans []tracing.Span) (tracing.Span, error) {
+					existingSpans[5].End()
+					return nil, nil
+				},
+				func(existingSpans []tracing.Span) (tracing.Span, error) {
+					existingSpans[0].End()
+					return nil, nil
+				},
+			},
+			exceptedSpans: []struct {
+				spanType         SpanType
+				operationName    string
+				parentSpanOpName string
+				peer             string
+			}{
+				{SpanTypeEntry, "/entry", "", ""},
+				{SpanTypeLocal, "/local1", "/entry", ""},
+				{SpanTypeLocal, "/local1-1", "/local1", ""},
+				{SpanTypeExit, "/local1-1-exit", "/local1-1", "localhost:8080"},
+				{SpanTypeExit, "/local1-exit", "/local1", "localhost:8080"},
+				{SpanTypeExit, "/entry-exit", "/entry", "localhost:8080"},
+			},
+		},
+	})
+}
+
+func TestCreateSpanInDifferenceGoroutine(t *testing.T) {
+	defer ResetTracingContext()
+	validateSpanOperation(t, []spanOperationTestCase{
+		{
+			operations: []func(existingSpans []tracing.Span) (tracing.Span, error){
+				func(existingSpans []tracing.Span) (tracing.Span, error) {
+					return tracing.CreateEntrySpan("/entry", func(key string) (string, error) { return "", nil })
+				},
+				func(existingSpans []tracing.Span) (tracing.Span, error) { // new goroutine
+					SetAsNewGoroutine()
+					return nil, nil
+				},
+				func(existingSpans []tracing.Span) (tracing.Span, error) {
+					return tracing.CreateLocalSpan("/local")
+				},
+				func(existingSpans []tracing.Span) (tracing.Span, error) { // new goroutine
+					SetAsNewGoroutine()
+					return nil, nil
+				},
+				func(existingSpans []tracing.Span) (tracing.Span, error) {
+					return tracing.CreateExitSpan("/local-exit", "localhost:8080", func(key, value string) error { return nil })
+				},
+				func(existingSpans []tracing.Span) (tracing.Span, error) {
+					existingSpans[2].End()
+					return nil, nil
+				},
+				func(existingSpans []tracing.Span) (tracing.Span, error) {
+					existingSpans[1].End()
+					return nil, nil
+				},
+				func(existingSpans []tracing.Span) (tracing.Span, error) {
+					existingSpans[0].End()
+					return nil, nil
+				},
+			},
+			exceptedSpans: []struct {
+				spanType         SpanType
+				operationName    string
+				parentSpanOpName string
+				peer             string
+			}{
+				{SpanTypeEntry, "/entry", "", ""},
+				{SpanTypeLocal, "/local", "/entry", ""},
+				{SpanTypeExit, "/local-exit", "/local", "localhost:8080"},
+			},
+		},
+	})
+}
+
+func TestSpanContextWriting(t *testing.T) {
+	defer ResetTracingContext()
+	s, err := tracing.CreateEntrySpan("/entry", func(key string) (string, error) { return "", nil })
+	assert.NoError(t, err)
+	s.End()
+	s, err = tracing.CreateExitSpan("/exit", "localhost:8080", func(key, value string) error {
+		ctx := SpanContext{}
+		if key == Header {
+			assert.NoError(t, ctx.DecodeSW8(value))
+		}
+		if key == HeaderCorrelation {
+			assert.NoError(t, ctx.DecodeSW8Correlation(value))
+		}
+		return nil
+	})
+	assert.NoError(t, err)
+	s.End()
+}
+
+func TestSpanContextReading(t *testing.T) {
+	defer ResetTracingContext()
+	s, err := tracing.CreateEntrySpan("/entry", func(key string) (string, error) {
+		if key == Header {
+			return header, nil
+		}
+		return "", nil
+	})
+	assert.NoError(t, err)
+	s.End()
+	time.Sleep(time.Millisecond * 50)
+	spans := GetReportedSpans()
+	assert.Equal(t, 1, len(spans), "span count not correct")
+	tracingContext := spans[0].Context()
+	assert.Equal(t, traceID, tracingContext.GetTraceID(), "trace id not correct")
+	assert.Equal(t, 1, len(spans[0].Refs()), "refs not correct")
+	refCtx := spans[0].Refs()[0]
+	assert.Equal(t, traceID, refCtx.GetTraceID(), "ref trace id not correct")
+	assert.Equal(t, parentSegmentID, refCtx.GetParentSegmentID(), "ref segment id not correct")
+	assert.Equal(t, parentEndpoint, refCtx.GetParentEndpoint(), "ref endpoint not correct")
+	assert.Equal(t, int32(parentSpanID), refCtx.GetParentSpanID(), "ref span id not correct")
+	assert.Equal(t, parentService, refCtx.GetParentService(), "ref service not correct")
+	assert.Equal(t, parentServiceInstance, refCtx.GetParentServiceInstance(), "ref service instance not correct")
+	assert.Equal(t, parentEndpoint, refCtx.GetParentEndpoint(), "ref endpoint not correct")
+}
+
+func TestSpanOperation(t *testing.T) {
+	defer ResetTracingContext()
+	spanCreations := []func(op tracing.SpanOption) (tracing.Span, error){
+		func(op tracing.SpanOption) (tracing.Span, error) {
+			return tracing.CreateEntrySpan("test", func(headerKey string) (string, error) {
+				return "", nil
+			}, op)
+		},
+		func(op tracing.SpanOption) (tracing.Span, error) {
+			return tracing.CreateLocalSpan("test", op)
+		},
+		func(op tracing.SpanOption) (tracing.Span, error) {
+			return tracing.CreateExitSpan("test", "localhost:8080", func(headerKey, headerValue string) error {
+				return nil
+			}, op)
+		},
+	}
+
+	spanOptions := []struct {
+		op       tracing.SpanOption
+		validate func(s *RootSegmentSpan) bool
+	}{
+		{tracing.WithLayer(tracing.SpanLayerHTTP), func(s *RootSegmentSpan) bool {
+			return s.DefaultSpan.Layer == agentv3.SpanLayer_Http
+		}},
+		{tracing.WithComponent(1), func(s *RootSegmentSpan) bool {
+			return s.DefaultSpan.ComponentID == 1
+		}},
+		{tracing.WithTag("test", "test1"), func(s *RootSegmentSpan) bool {
+			for _, k := range s.DefaultSpan.Tags {
+				if k.Key == "test" {
+					return k.Value == "test1"
+				}
+			}
+			return false
+		}},
+	}
+
+	for createInx, spanCreate := range spanCreations {
+		for _, op := range spanOptions {
+			create, err := spanCreate(op.op)
+			if err != nil {
+				assert.Nil(t, err, "create span error")
+			}
+			span := create.(*tracing.SpanWrapper).Span.(*RootSegmentSpan)
+			assert.Truef(t, op.validate(span), "span validation failed, create index: %d, option index: %d", createInx, op)
+			create.End()
+		}
+	}
+}
+
+func TestActiveSpan(t *testing.T) {
+	defer ResetTracingContext()
+	// active span in same goroutine
+	span, err := tracing.CreateEntrySpan("/entry", func(key string) (string, error) { return "", nil })
+	assert.NoError(t, err)
+	assert.Equal(t, span, tracing.ActiveSpan(), "active span not correct")
+	oldGLS := GetGLS()
+	// change goroutine
+	SetAsNewGoroutine()
+	assert.Nil(t, tracing.ActiveSpan(), "active span should be nil when cross goroutine")
+	// change back
+	SetGLS(oldGLS)
+	span.End()
+	assert.Nil(t, tracing.ActiveSpan(), "active span not correct")
+}
+
+func TestRuntimeContext(t *testing.T) {
+	defer ResetTracingContext()
+	assert.Nilf(t, tracing.GetRuntimeContextValue("test"), "runtime context data should be nil")
+	tracing.SetRuntimeContextValue("test", "test")
+	assert.Equal(t, "test", tracing.GetRuntimeContextValue("test"), "runtime context data should be \"test\"")
+	// switch to the new goroutine
+	oldGLS := GetGLS()
+	SetAsNewGoroutine()
+	assert.Equal(t, "test", tracing.GetRuntimeContextValue("test"), "runtime context data should be \"test\"")
+	assert.Nilf(t, tracing.GetRuntimeContextValue("test1"), "runtime context data should be nil")
+	tracing.SetRuntimeContextValue("test1", "test1")
+	assert.Equal(t, "test1", tracing.GetRuntimeContextValue("test1"), "runtime context data should be \"test1\"")
+	// switch back to the old goroutine
+	SetGLS(oldGLS)
+	assert.Nilf(t, tracing.GetRuntimeContextValue("test1"), "runtime context data should be nil")
+}
+
+func validateSpanOperation(t *testing.T, cases []spanOperationTestCase) {
+	for _, tt := range cases {
+		spans := make([]tracing.Span, 0)
+		for i, op := range tt.operations {
+			span, err := op(spans)
+			assert.Nilf(t, err, "create span error, operation index: %d", i)
+			time.Sleep(time.Millisecond * 50)
+			if span != nil {
+				spans = append(spans, span)
+			}
+		}
+
+		time.Sleep(time.Millisecond * 100)
+		assert.Equal(t, len(tt.exceptedSpans), len(GetReportedSpans()), "span count not equal")
+		for i, exceptedSpan := range tt.exceptedSpans {
+			var span DefaultSpan
+			if i == 0 {
+				tmp, ok := GetReportedSpans()[len(GetReportedSpans())-1-i].(*RootSegmentSpan)
+				assert.True(t, ok, "first span is not root segment span")
+				span = tmp.DefaultSpan
+			} else {
+				found := false
+				for _, s := range GetReportedSpans() {
+					if s.OperationName() != exceptedSpan.operationName {
+						continue
+					}
+					tmp, ok := s.(*SegmentSpanImpl)
+					assert.Truef(t, ok, "span is not segment span, span index: %d", i)
+					span = tmp.DefaultSpan
+					found = true
+					break
+				}
+				assert.Truef(t, found, "span not found, span index: %d, name: %s", i, exceptedSpan.operationName)
+			}
+			assert.Equalf(t, exceptedSpan.spanType, span.SpanType, "span type not equal, span index: %d", i)
+			assert.Equalf(t, exceptedSpan.operationName, span.OperationName, "operation name not equal, span index: %d", i)
+			if exceptedSpan.parentSpanOpName != "" {
+				assert.Equalf(t, exceptedSpan.parentSpanOpName, span.Parent.GetOperationName(), "parent operation name not equal, span index: %d", i)
+			} else {
+				assert.Nilf(t, span.Parent, "parent span not nil, span index: %d", i)
+			}
+			if exceptedSpan.peer != "" {
+				assert.Equalf(t, exceptedSpan.peer, span.Peer, "span peer not equal, span index: %d", i)
+			} else {
+				assert.Truef(t, span.Peer == "", "span peer not empty, span index: %d", i)
+			}
+
+			assert.Greaterf(t, Millisecond(span.StartTime), int64(0), "start time not greater than 0, span index: %d", i)
+			assert.Greaterf(t, Millisecond(span.EndTime), Millisecond(span.StartTime), "end time not greater than 0, span indeX: %d", i)
+		}
+
+		Tracing.Reporter = NewStoreReporter()
+	}
+}
diff --git a/plugins/ginv2/go.mod b/plugins/ginv2/go.mod
new file mode 100644
index 0000000..e5f7a8b
--- /dev/null
+++ b/plugins/ginv2/go.mod
@@ -0,0 +1,39 @@
+module github.com/apache/skywalking-go/plugins/ginv2
+
+go 1.18
+
+require (
+	github.com/apache/skywalking-go/plugins/core v0.0.0-20230414024435-7b292984eb80
+	github.com/gin-gonic/gin v1.9.0
+)
+
+require (
+	github.com/bytedance/sonic v1.8.0 // indirect
+	github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
+	github.com/dave/dst v0.27.2 // indirect
+	github.com/gin-contrib/sse v0.1.0 // indirect
+	github.com/go-playground/locales v0.14.1 // indirect
+	github.com/go-playground/universal-translator v0.18.1 // indirect
+	github.com/go-playground/validator/v10 v10.11.2 // indirect
+	github.com/goccy/go-json v0.10.0 // indirect
+	github.com/json-iterator/go v1.1.12 // indirect
+	github.com/klauspost/cpuid/v2 v2.0.9 // indirect
+	github.com/leodido/go-urn v1.2.1 // indirect
+	github.com/mattn/go-isatty v0.0.17 // indirect
+	github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
+	github.com/modern-go/reflect2 v1.0.2 // indirect
+	github.com/pelletier/go-toml/v2 v2.0.6 // indirect
+	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
+	github.com/ugorji/go/codec v1.2.9 // indirect
+	golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
+	golang.org/x/crypto v0.5.0 // indirect
+	golang.org/x/net v0.8.0 // indirect
+	golang.org/x/sys v0.6.0 // indirect
+	golang.org/x/text v0.8.0 // indirect
+	google.golang.org/protobuf v1.29.0 // indirect
+	gopkg.in/yaml.v3 v3.0.1 // indirect
+)
+
+replace github.com/apache/skywalking-go/plugins/core => ../core
+
+replace github.com/apache/skywalking-go => ../../
diff --git a/plugins/ginv2/go.sum b/plugins/ginv2/go.sum
new file mode 100644
index 0000000..302cee1
--- /dev/null
+++ b/plugins/ginv2/go.sum
@@ -0,0 +1,91 @@
+github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
+github.com/bytedance/sonic v1.8.0 h1:ea0Xadu+sHlu7x5O3gKhRpQ1IKiMrSiHttPF0ybECuA=
+github.com/bytedance/sonic v1.8.0/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
+github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
+github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
+github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
+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.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
+github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
+github.com/gin-gonic/gin v1.9.0 h1:OjyFBKICoexlu99ctXNR2gg+c5pKrKMuyjgARg9qeY8=
+github.com/gin-gonic/gin v1.9.0/go.mod h1:W1Me9+hsUSyj3CePGrd1/QrKJMSJ1Tu/0hFEH89961k=
+github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
+github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
+github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
+github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
+github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
+github.com/go-playground/validator/v10 v10.11.2 h1:q3SHpufmypg+erIExEKUmsgmhDTyhcJ38oeKGACXohU=
+github.com/go-playground/validator/v10 v10.11.2/go.mod h1:NieE624vt4SCTJtD87arVLvdmjPAeV8BQlHtMnw9D7s=
+github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA=
+github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
+github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
+github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
+github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
+github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
+github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
+github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
+github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
+github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
+github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
+github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
+github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
+github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
+github.com/ugorji/go/codec v1.2.9 h1:rmenucSohSTiyL09Y+l2OCk+FrMxGMzho2+tjr5ticU=
+github.com/ugorji/go/codec v1.2.9/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
+golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
+golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
+golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
+golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
+golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
+golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
+golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
+golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w=
+google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.29.0 h1:44S3JjaKmLEE4YIkjzexaP+NzZsudE3Zin5Njn/pYX0=
+google.golang.org/protobuf v1.29.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
+skywalking.apache.org/repo/goapi v0.0.0-20230314034821-0c5a44bb767a h1:m8DTnaSEOEnPXRWmA6g7isbdqw7WPZP6SnaEHz1Sx7s=
diff --git a/plugins/core/tracer.go b/plugins/ginv2/instrument.go
similarity index 51%
copy from plugins/core/tracer.go
copy to plugins/ginv2/instrument.go
index 9890dfc..f6b8076 100644
--- a/plugins/core/tracer.go
+++ b/plugins/ginv2/instrument.go
@@ -15,28 +15,49 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package core
+package ginv2
 
 import (
-	"github.com/apache/skywalking-go/reporter"
+	"embed"
+	"strings"
+
+	"github.com/apache/skywalking-go/plugins/core/instrument"
 )
 
-type CorrelationConfig struct {
-	MaxKeyCount  int
-	MaxValueSize int
+//go:embed *
+var fs embed.FS
+
+//skywalking:nocopy
+type Instrument struct {
+}
+
+func NewInstrument() *Instrument {
+	return &Instrument{}
+}
+
+func (i *Instrument) Name() string {
+	return "ginv2"
+}
+
+func (i *Instrument) BasePackage() string {
+	return "github.com/gin-gonic/gin"
+}
+
+func (i *Instrument) VersionChecker(version string) bool {
+	return strings.HasPrefix(version, "v1.")
 }
 
-type Tracer struct {
-	Service  string
-	Instance string
-	Reporter reporter.Reporter
-	// 0 not init 1 init
-	initFlag int32
-	Sampler  Sampler
-	// correlation *CorrelationConfig	// temporarily disable, because haven't been implemented yet
-	cdsWatchers []reporter.AgentConfigChangeWatcher
+func (i *Instrument) Points() []*instrument.Point {
+	return []*instrument.Point{
+		{
+			PackagePath: "",
+			At: instrument.NewMethodEnhance("Engine", "handleHTTPRequest",
+				instrument.WithArgsCount(1), instrument.WithArgType(0, "*Context")),
+			Interceptor: "HTTPInterceptor",
+		},
+	}
 }
 
-func (t *Tracer) InitSuccess() bool {
-	return t.initFlag == 1
+func (i *Instrument) FS() *embed.FS {
+	return &fs
 }
diff --git a/plugins/ginv2/intercepter.go b/plugins/ginv2/intercepter.go
new file mode 100644
index 0000000..49c5412
--- /dev/null
+++ b/plugins/ginv2/intercepter.go
@@ -0,0 +1,60 @@
+// 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 ginv2
+
+import (
+	"fmt"
+
+	"github.com/gin-gonic/gin"
+
+	"github.com/apache/skywalking-go/plugins/core/operator"
+	"github.com/apache/skywalking-go/plugins/core/tracing"
+)
+
+type HTTPInterceptor struct {
+}
+
+func (h *HTTPInterceptor) BeforeInvoke(invocation *operator.Invocation) error {
+	context := invocation.Args[0].(*gin.Context)
+	s, err := tracing.CreateEntrySpan(
+		fmt.Sprintf("%s:%s", context.Request.Method, context.Request.RequestURI), func(headerKey string) (string, error) {
+			return context.Request.Header.Get(headerKey), nil
+		},
+		tracing.WithLayer(tracing.SpanLayerHTTP),
+		tracing.WithTag(tracing.TagHTTPMethod, context.Request.Method),
+		tracing.WithTag(tracing.TagURL, context.Request.Host+context.Request.URL.Path))
+	if err != nil {
+		return err
+	}
+	invocation.Context = s
+	return nil
+}
+
+func (h *HTTPInterceptor) AfterInvoke(invocation *operator.Invocation, result ...interface{}) error {
+	if invocation.Context == nil {
+		return nil
+	}
+	context := invocation.Args[0].(*gin.Context)
+	span := invocation.Context.(tracing.Span)
+	span.Tag(tracing.TagStatusCode, fmt.Sprintf("%d", context.Writer.Status()))
+	if len(context.Errors) > 0 {
+		span.Error(context.Errors.String())
+	}
+	span.End()
+	return nil
+}
diff --git a/tools/go-agent/cmd/helper.go b/tools/go-agent/cmd/helper.go
index d97e152..751d163 100644
--- a/tools/go-agent/cmd/helper.go
+++ b/tools/go-agent/cmd/helper.go
@@ -23,7 +23,8 @@ import (
 )
 
 type EnhancementToolFlags struct {
-	Help bool `skyflag:"-h"`
+	Help  bool   `swflag:"-h"`
+	Debug string `swflag:"-debug"`
 }
 
 func PrintUsageWithExit() {
diff --git a/tools/go-agent/cmd/main.go b/tools/go-agent/cmd/main.go
index 77b3ac1..85b1148 100644
--- a/tools/go-agent/cmd/main.go
+++ b/tools/go-agent/cmd/main.go
@@ -18,46 +18,75 @@
 package main
 
 import (
+	"fmt"
 	"log"
 	"os"
 	"os/exec"
 
-	"github.com/apache/skywalking-go/tools/go-agent-enhance/instrument"
-	"github.com/apache/skywalking-go/tools/go-agent-enhance/instrument/api"
-	"github.com/apache/skywalking-go/tools/go-agent-enhance/tools"
+	"github.com/apache/skywalking-go/tools/go-agent/instrument"
+	"github.com/apache/skywalking-go/tools/go-agent/instrument/api"
+	"github.com/apache/skywalking-go/tools/go-agent/tools"
 )
 
 var toolFlags = &EnhancementToolFlags{}
 
 func main() {
+	writeArgs()
 	args := os.Args[1:]
+	var err error
+	var firstNonOptionIndex int
 	// Print usage
-	if err := tools.ParseFlags(toolFlags, args); err != nil || toolFlags.Help {
+	if firstNonOptionIndex, err = tools.ParseFlags(toolFlags, args); err != nil || toolFlags.Help {
 		PrintUsageWithExit()
 	}
 
+	if toolFlags.Debug != "" {
+		stat, err1 := os.Stat(toolFlags.Debug)
+		if err1 != nil {
+			fmt.Printf("debug path not existing: %s", toolFlags.Debug)
+			return
+		}
+		if !stat.IsDir() {
+			fmt.Printf("debug path must be a directory: %s", toolFlags.Debug)
+			return
+		}
+	}
+
 	// only enhance the "compile" phase
-	cmdName := tools.ParseProxyCommandName(args)
+	cmdName := tools.ParseProxyCommandName(args, firstNonOptionIndex)
 	if cmdName != "compile" {
-		executeDelegateCommand(args)
+		executeDelegateCommand(args[firstNonOptionIndex:])
 		return
 	}
 
 	// parse the args
 	compileOptions := &api.CompileOptions{}
-	if err := tools.ParseFlags(compileOptions, args); err != nil {
-		executeDelegateCommand(args)
+	if _, err = tools.ParseFlags(compileOptions, args); err != nil {
+		executeDelegateCommand(args[firstNonOptionIndex:])
 		return
 	}
 
 	// execute the enhancement
-	args, err := instrument.Execute(compileOptions, args)
+	args, err = instrument.Execute(compileOptions, args)
 	if err != nil {
 		log.Fatal(err)
 	}
 
 	// execute the delegate command with updated args
-	executeDelegateCommand(args)
+	executeDelegateCommand(args[firstNonOptionIndex:])
+}
+
+func writeArgs() {
+	homeDir, err := os.UserHomeDir()
+	if err != nil {
+		panic(err)
+	}
+	file, err := os.OpenFile(homeDir+"/Desktop/skywalking-go.txt", os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0o666)
+	if err != nil {
+		os.Exit(1)
+	}
+	defer file.Close()
+	_, _ = fmt.Fprintf(file, "%v\n", os.Args[1:])
 }
 
 func executeDelegateCommand(args []string) {
diff --git a/tools/go-agent/go.mod b/tools/go-agent/go.mod
index 7a43be9..4413213 100644
--- a/tools/go-agent/go.mod
+++ b/tools/go-agent/go.mod
@@ -1,29 +1,52 @@
-module github.com/apache/skywalking-go/tools/go-agent-enhance
+module github.com/apache/skywalking-go/tools/go-agent
 
 go 1.18
 
 require (
-	github.com/apache/skywalking-go/plugins/core v0.0.0-20230412041451-ba963278b31e
+	github.com/apache/skywalking-go/plugins/core v0.0.0-20230414024435-7b292984eb80
+	github.com/apache/skywalking-go/plugins/ginv2 v0.0.0-20230412041451-ba963278b31e
 	github.com/dave/dst v0.27.2
 	github.com/sirupsen/logrus v1.9.0
+	golang.org/x/text v0.8.0
 )
 
 require (
 	github.com/apache/skywalking-go v0.0.0-20230412041451-ba963278b31e // indirect
+	github.com/bytedance/sonic v1.8.0 // indirect
+	github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
+	github.com/gin-contrib/sse v0.1.0 // indirect
+	github.com/gin-gonic/gin v1.9.0 // indirect
+	github.com/go-playground/locales v0.14.1 // indirect
+	github.com/go-playground/universal-translator v0.18.1 // indirect
+	github.com/go-playground/validator/v10 v10.11.2 // indirect
+	github.com/goccy/go-json v0.10.0 // indirect
 	github.com/golang/protobuf v1.5.2 // indirect
 	github.com/google/uuid v1.3.0 // indirect
+	github.com/json-iterator/go v1.1.12 // indirect
+	github.com/klauspost/cpuid/v2 v2.0.9 // indirect
+	github.com/leodido/go-urn v1.2.1 // indirect
+	github.com/mattn/go-isatty v0.0.17 // indirect
+	github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
+	github.com/modern-go/reflect2 v1.0.2 // indirect
+	github.com/pelletier/go-toml/v2 v2.0.6 // indirect
 	github.com/pkg/errors v0.9.1 // indirect
+	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
+	github.com/ugorji/go/codec v1.2.9 // indirect
+	golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
+	golang.org/x/crypto v0.5.0 // indirect
 	golang.org/x/mod v0.8.0 // indirect
 	golang.org/x/net v0.8.0 // indirect
 	golang.org/x/sys v0.6.0 // indirect
-	golang.org/x/text v0.8.0 // indirect
 	golang.org/x/tools v0.6.0 // indirect
 	google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
 	google.golang.org/grpc v1.54.0 // indirect
 	google.golang.org/protobuf v1.29.0 // indirect
+	gopkg.in/yaml.v3 v3.0.1 // indirect
 	skywalking.apache.org/repo/goapi v0.0.0-20230314034821-0c5a44bb767a // indirect
 )
 
 replace github.com/apache/skywalking-go => ../../
 
 replace github.com/apache/skywalking-go/plugins/core => ../../plugins/core
+
+replace github.com/apache/skywalking-go/plugins/ginv2 => ../../plugins/ginv2
diff --git a/tools/go-agent/go.sum b/tools/go-agent/go.sum
index 451cfeb..27c2af3 100644
--- a/tools/go-agent/go.sum
+++ b/tools/go-agent/go.sum
@@ -3,8 +3,14 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
 github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
+github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
+github.com/bytedance/sonic v1.8.0 h1:ea0Xadu+sHlu7x5O3gKhRpQ1IKiMrSiHttPF0ybECuA=
+github.com/bytedance/sonic v1.8.0/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
+github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
+github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
+github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
 github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
 github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
@@ -23,6 +29,18 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.m
 github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
+github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
+github.com/gin-gonic/gin v1.9.0 h1:OjyFBKICoexlu99ctXNR2gg+c5pKrKMuyjgARg9qeY8=
+github.com/gin-gonic/gin v1.9.0/go.mod h1:W1Me9+hsUSyj3CePGrd1/QrKJMSJ1Tu/0hFEH89961k=
+github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
+github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
+github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
+github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
+github.com/go-playground/validator/v10 v10.11.2 h1:q3SHpufmypg+erIExEKUmsgmhDTyhcJ38oeKGACXohU=
+github.com/go-playground/validator/v10 v10.11.2/go.mod h1:NieE624vt4SCTJtD87arVLvdmjPAeV8BQlHtMnw9D7s=
+github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA=
+github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
 github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
 github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -47,10 +65,25 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
 github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
+github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
+github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
+github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
+github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
+github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
+github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
+github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
+github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
+github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -62,16 +95,31 @@ github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0
 github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
 github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
 github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
+github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
+github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
+github.com/ugorji/go/codec v1.2.9 h1:rmenucSohSTiyL09Y+l2OCk+FrMxGMzho2+tjr5ticU=
+github.com/ugorji/go/codec v1.2.9/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
 github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
+golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
+golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
+golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@@ -116,6 +164,7 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -181,7 +230,9 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
 skywalking.apache.org/repo/goapi v0.0.0-20230314034821-0c5a44bb767a h1:m8DTnaSEOEnPXRWmA6g7isbdqw7WPZP6SnaEHz1Sx7s=
 skywalking.apache.org/repo/goapi v0.0.0-20230314034821-0c5a44bb767a/go.mod h1:LcZMcxDjdJPn5yetydFnxe0l7rmiv8lvHEnzRbsey14=
diff --git a/tools/go-agent/instrument/agentcore/instrument.go b/tools/go-agent/instrument/agentcore/instrument.go
index 5331e0d..7c589db 100644
--- a/tools/go-agent/instrument/agentcore/instrument.go
+++ b/tools/go-agent/instrument/agentcore/instrument.go
@@ -24,11 +24,11 @@ import (
 	"strings"
 
 	"github.com/apache/skywalking-go/plugins/core"
+	"github.com/apache/skywalking-go/tools/go-agent/instrument/api"
+	"github.com/apache/skywalking-go/tools/go-agent/instrument/runtime"
+	"github.com/apache/skywalking-go/tools/go-agent/tools"
 
-	"github.com/apache/skywalking-go/tools/go-agent-enhance/instrument/api"
-	"github.com/apache/skywalking-go/tools/go-agent-enhance/instrument/runtime"
-	"github.com/apache/skywalking-go/tools/go-agent-enhance/tools"
-
+	"github.com/dave/dst"
 	"github.com/dave/dst/decorator"
 	"github.com/dave/dst/dstutil"
 )
@@ -38,12 +38,13 @@ var (
 	EnhanceFromBasePackage = "github.com/apache/skywalking-go/plugins/core"
 
 	CopiedBasePackage = "skywalking-go/agent/core"
-	CopiedSubPackages = []string{"", "tracing"}
+	CopiedSubPackages = []string{"", "tracing", "operator"}
 )
 
 type Instrument struct {
 	hasCopyPath  bool
 	needsCopyDir string
+	compileOpts  *api.CompileOptions
 }
 
 func NewInstrument() *Instrument {
@@ -51,10 +52,11 @@ func NewInstrument() *Instrument {
 }
 
 func (i *Instrument) CouldHandle(opts *api.CompileOptions) bool {
+	i.compileOpts = opts
 	return strings.HasPrefix(opts.Package, EnhanceBasePackage)
 }
 
-func (i *Instrument) FilterAndEdit(path string, cursor *dstutil.Cursor) bool {
+func (i *Instrument) FilterAndEdit(path string, cursor *dstutil.Cursor, allFiles []*dst.File) bool {
 	if i.hasCopyPath {
 		return false
 	}
@@ -69,7 +71,7 @@ func (i *Instrument) FilterAndEdit(path string, cursor *dstutil.Cursor) bool {
 	return false
 }
 
-func (i *Instrument) AfterEnhanceFile(path string) error {
+func (i *Instrument) AfterEnhanceFile(fromPath, newPath string) error {
 	return nil
 }
 
@@ -81,22 +83,6 @@ func (i *Instrument) WriteExtraFiles(dir string) ([]string, error) {
 	results := make([]string, 0)
 	if sub == "" {
 		sub = "."
-		// append the context adapter if is root package
-		tmp, err := tools.WriteMultipleFile(dir, map[string]string{
-			"adapter_context.go": tools.ExecuteTemplate(`package core
-
-import (
-	_ "unsafe"
-)
-
-//go:linkname {{.}} {{.}}
-var {{.}} = TaskTracingContextSnapshot
-`, runtime.TLSTakeSnapshotMethodName),
-		})
-		if err != nil {
-			return nil, err
-		}
-		results = append(results, tmp...)
 	}
 	files, err := core.FS.ReadDir(sub)
 	if err != nil {
@@ -129,14 +115,78 @@ var {{.}} = TaskTracingContextSnapshot
 		if err != nil {
 			return nil, err
 		}
+		debugInfo, err := i.buildDSTDebugInfo(f)
+		if err != nil {
+			return nil, err
+		}
 
 		tools.ChangePackageImportPath(parse, pkgUpdates)
 		copiedFilePath := filepath.Join(dir, f.Name())
-		if err := tools.WriteDSTFile(copiedFilePath, "", parse); err != nil {
+		if err := tools.WriteDSTFile(copiedFilePath, parse, debugInfo); err != nil {
 			return nil, err
 		}
 		results = append(results, copiedFilePath)
 	}
 
+	// write extra file to link the operator and TLS methods
+	if sub == "." {
+		file, err := i.writeLinkerFile(dir)
+		if err != nil {
+			return nil, err
+		}
+		results = append(results, file)
+	}
+
 	return results, nil
 }
+
+func (i *Instrument) buildDSTDebugInfo(entry fs.DirEntry) (*tools.DebugInfo, error) {
+	if i.compileOpts.DebugDir == "" {
+		return nil, nil
+	}
+	debugPath := filepath.Join(i.compileOpts.DebugDir, "plugins", "core", entry.Name())
+	return tools.BuildDSTDebugInfo(debugPath, nil)
+}
+
+func (i *Instrument) writeLinkerFile(dir string) (string, error) {
+	return tools.WriteFile(dir, "runtime_linker.go", tools.ExecuteTemplate(`package core
+
+import (
+	_ "unsafe"
+)
+
+//go:linkname {{.TLSGetLinkMethod}} {{.TLSGetLinkMethod}}
+var {{.TLSGetLinkMethod}} func() interface{}
+
+//go:linkname {{.TLSSetLinkMethod}} {{.TLSSetLinkMethod}}
+var {{.TLSSetLinkMethod}} func(interface{})
+
+//go:linkname {{.SetGlobalOperatorLinkMethod}} {{.SetGlobalOperatorLinkMethod}}
+var {{.SetGlobalOperatorLinkMethod}} func(interface{}) 
+
+//go:linkname {{.GetGlobalOperatorLinkMethod}} {{.GetGlobalOperatorLinkMethod}}
+var {{.GetGlobalOperatorLinkMethod}} func() interface{}
+
+func init() {
+	if {{.TLSGetLinkMethod}} != nil && {{.TLSSetLinkMethod}} != nil {
+		GetGLS = {{.TLSGetLinkMethod}}
+		SetGLS = {{.TLSSetLinkMethod}}
+	}
+	if {{.SetGlobalOperatorLinkMethod}} != nil && {{.GetGlobalOperatorLinkMethod}} != nil {
+		SetGlobalOperator = {{.SetGlobalOperatorLinkMethod}}
+		GetGlobalOperator = {{.GetGlobalOperatorLinkMethod}}
+		SetGlobalOperator(&Tracer{initFlag: 1, Sampler: NewConstSampler(true)})
+	}
+}
+`, struct {
+		TLSGetLinkMethod            string
+		TLSSetLinkMethod            string
+		SetGlobalOperatorLinkMethod string
+		GetGlobalOperatorLinkMethod string
+	}{
+		TLSGetLinkMethod:            runtime.TLSGetMethodName,
+		TLSSetLinkMethod:            runtime.TLSSetMethodName,
+		SetGlobalOperatorLinkMethod: runtime.GlobalTracerSetMethodName,
+		GetGlobalOperatorLinkMethod: runtime.GlobalTracerGetMethodName,
+	}))
+}
diff --git a/tools/go-agent/instrument/api/flags.go b/tools/go-agent/instrument/api/flags.go
index 0a39718..48e5fc5 100644
--- a/tools/go-agent/instrument/api/flags.go
+++ b/tools/go-agent/instrument/api/flags.go
@@ -20,8 +20,11 @@ package api
 import "path/filepath"
 
 type CompileOptions struct {
-	Package string `skyflag:"-p"`
-	Output  string `skyflag:"-o"`
+	Package string   `swflag:"-p"`
+	Output  string   `swflag:"-o"`
+	AllArgs []string `swflag:"all-args"`
+
+	DebugDir string `swflag:"-debug"` // from tools flag
 }
 
 func (c *CompileOptions) IsValid() bool {
diff --git a/tools/go-agent/instrument/api/instrument.go b/tools/go-agent/instrument/api/instrument.go
index 9376803..a309fc2 100644
--- a/tools/go-agent/instrument/api/instrument.go
+++ b/tools/go-agent/instrument/api/instrument.go
@@ -18,6 +18,7 @@
 package api
 
 import (
+	"github.com/dave/dst"
 	"github.com/dave/dst/dstutil"
 )
 
@@ -25,9 +26,9 @@ type Instrument interface {
 	// CouldHandle verify current instrument can handle this request
 	CouldHandle(opts *CompileOptions) bool
 	// FilterAndEdit filter the matched data which decode by DST, and edit the data
-	FilterAndEdit(path string, cursor *dstutil.Cursor) bool
+	FilterAndEdit(path string, cursor *dstutil.Cursor, allFiles []*dst.File) bool
 	// AfterEnhanceFile after the enhanced file been written, check the file is needs rewrite
-	AfterEnhanceFile(path string) error
+	AfterEnhanceFile(fromPath, newPath string) error
 	// WriteExtraFiles customized the extra files when there have instrumented files
 	WriteExtraFiles(dir string) ([]string, error)
 }
diff --git a/tools/go-agent/instrument/framework/enhance_instance.go b/tools/go-agent/instrument/framework/enhance_instance.go
new file mode 100644
index 0000000..990618b
--- /dev/null
+++ b/tools/go-agent/instrument/framework/enhance_instance.go
@@ -0,0 +1,100 @@
+// 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 framework
+
+import (
+	"fmt"
+
+	"github.com/apache/skywalking-go/tools/go-agent/tools"
+
+	"github.com/dave/dst"
+)
+
+var EnhanceInstanceField = "skywalkingDynamicField"
+
+type InstanceEnhance struct {
+	typeSpec *dst.TypeSpec
+}
+
+func NewInstanceEnhance(typeSpec *dst.TypeSpec) *InstanceEnhance {
+	return &InstanceEnhance{typeSpec: typeSpec}
+}
+
+func (i *InstanceEnhance) EnhanceField() {
+	structType := i.typeSpec.Type.(*dst.StructType)
+	structType.Fields.List = append(structType.Fields.List, &dst.Field{
+		Names: []*dst.Ident{dst.NewIdent(EnhanceInstanceField)},
+		Type:  dst.NewIdent("interface{}"),
+	})
+}
+
+func (i *InstanceEnhance) BuildForAdapter() []dst.Decl {
+	return []dst.Decl{
+		&dst.FuncDecl{
+			Name: &dst.Ident{Name: "GetSkyWalkingDynamicField"},
+			Recv: &dst.FieldList{
+				List: []*dst.Field{
+					{
+						Names: []*dst.Ident{dst.NewIdent("receiver")},
+						Type:  &dst.StarExpr{X: dst.NewIdent(i.typeSpec.Name.Name)},
+					},
+				},
+			},
+			Type: &dst.FuncType{
+				Params: &dst.FieldList{},
+				Results: &dst.FieldList{
+					List: []*dst.Field{
+						{Type: dst.NewIdent("interface{}")},
+					},
+				},
+			},
+			Body: &dst.BlockStmt{
+				List: tools.GoStringToStats(fmt.Sprintf("return receiver.%s", EnhanceInstanceField)),
+			},
+		},
+		&dst.FuncDecl{
+			Name: &dst.Ident{Name: "SetSkyWalkingDynamicField"},
+			Recv: &dst.FieldList{
+				List: []*dst.Field{
+					{
+						Names: []*dst.Ident{dst.NewIdent("receiver")},
+						Type:  &dst.StarExpr{X: dst.NewIdent(i.typeSpec.Name.Name)},
+					},
+				},
+			},
+			Type: &dst.FuncType{
+				Params: &dst.FieldList{
+					List: []*dst.Field{
+						{
+							Names: []*dst.Ident{dst.NewIdent("param")},
+							Type:  dst.NewIdent("interface{}"),
+						},
+					},
+				},
+				Results: &dst.FieldList{},
+			},
+			Body: &dst.BlockStmt{
+				List: tools.GoStringToStats(fmt.Sprintf("receiver.%s = param", EnhanceInstanceField)),
+			},
+		},
+	}
+}
+
+func (i *InstanceEnhance) ReplaceFileContent(path, content string) string {
+	return content
+}
diff --git a/tools/go-agent/instrument/framework/enhance_method.go b/tools/go-agent/instrument/framework/enhance_method.go
new file mode 100644
index 0000000..64674ce
--- /dev/null
+++ b/tools/go-agent/instrument/framework/enhance_method.go
@@ -0,0 +1,230 @@
+// 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 framework
+
+import (
+	"fmt"
+	"path/filepath"
+	"regexp"
+	"strings"
+
+	"github.com/apache/skywalking-go/plugins/core/instrument"
+	"github.com/apache/skywalking-go/tools/go-agent/instrument/agentcore"
+	"github.com/apache/skywalking-go/tools/go-agent/instrument/framework/rewrite"
+	"github.com/apache/skywalking-go/tools/go-agent/tools"
+
+	"github.com/dave/dst"
+
+	"golang.org/x/text/cases"
+	"golang.org/x/text/language"
+)
+
+var GenerateMethodPrefix = "_skywalking_enhance_"
+var GenerateVarPrefix = "_skywalking_var_"
+
+var methodEnhanceAdapterFiles = make(map[string]bool)
+
+type MethodEnhance struct {
+	funcDecl    *dst.FuncDecl
+	path        string
+	packageName string
+	fullPackage string
+
+	InstrumentName           string
+	InterceptorDefineName    string
+	InterceptorGeneratedName string
+	InterceptorVarName       string
+
+	Parameters []*tools.ParameterInfo
+	Recvs      []*tools.ParameterInfo
+	Results    []*tools.ParameterInfo
+
+	FuncID              string
+	AdapterPreFuncName  string
+	AdapterPostFuncName string
+
+	replacementKey   string
+	replacementValue string
+}
+
+func NewMethodEnhance(inst instrument.Instrument, matcher *instrument.Point, f *dst.FuncDecl, path string) *MethodEnhance {
+	fullPackage := filepath.Join(inst.BasePackage(), matcher.PackagePath)
+	enhance := &MethodEnhance{
+		funcDecl:              f,
+		path:                  path,
+		fullPackage:           fullPackage,
+		packageName:           filepath.Base(fullPackage),
+		InstrumentName:        inst.Name(),
+		InterceptorDefineName: matcher.Interceptor,
+		Parameters:            tools.EnhanceParameterNames(f.Type.Params, false),
+		Results:               tools.EnhanceParameterNames(f.Type.Results, true),
+	}
+	if f.Recv != nil {
+		enhance.Recvs = tools.EnhanceParameterNames(f.Recv, false)
+	}
+
+	enhance.FuncID = buildFrameworkFuncID(filepath.Join(inst.BasePackage(), matcher.PackagePath), f)
+	enhance.AdapterPreFuncName = fmt.Sprintf("%s%s", rewrite.GenerateMethodPrefix, enhance.FuncID)
+	enhance.AdapterPostFuncName = fmt.Sprintf("%s%s_ret", rewrite.GenerateMethodPrefix, enhance.FuncID)
+
+	// the interceptor name needs to add the function id ensure there no conflict in the framework package
+	titleCase := cases.Title(language.English)
+	packageTitle := filepath.Base(titleCase.String(filepath.Join(inst.BasePackage(), matcher.PackagePath)))
+	enhance.InterceptorGeneratedName = fmt.Sprintf("%s%s%s", rewrite.TypePrefix, packageTitle, enhance.InterceptorDefineName)
+	enhance.InterceptorVarName = fmt.Sprintf("%sinterceptor_%s", rewrite.GenerateVarPrefix, enhance.FuncID)
+	return enhance
+}
+
+func (m *MethodEnhance) BuildForInvoker() {
+	insertsTmpl, err := templatesFS.ReadFile("templates/method_inserts.tmpl")
+	if err != nil {
+		panic(fmt.Errorf("reading method inserts: %w", err))
+	}
+	result := tools.ExecuteTemplate(string(insertsTmpl), m)
+	m.replacementKey = fmt.Sprintf("//goagent:enhance_%s\n", m.FuncID)
+	m.replacementValue = result
+
+	m.funcDecl.Body.Decs.Lbrace.Prepend("\n", m.replacementKey)
+}
+
+func (m *MethodEnhance) BuildForAdapter() []dst.Decl {
+	result := make([]dst.Decl, 0)
+	if !methodEnhanceAdapterFiles[m.path] {
+		// append the import for logger, one file only need import once
+		result = append(result, tools.GoStringToDecls(fmt.Sprintf(`import (
+	"%s/log"
+	"%s/operator"
+
+	%s "%s"	 // current enhancing package path, for rewrite phase in next step
+)`, agentcore.EnhanceFromBasePackage, agentcore.EnhanceFromBasePackage, m.packageName, m.fullPackage))...)
+		methodEnhanceAdapterFiles[m.path] = true
+	}
+
+	result = append(result, tools.GoStringToDecls(fmt.Sprintf(`var %s = &%s{}`, m.InterceptorVarName, m.InterceptorGeneratedName))...)
+	preFunc := &dst.FuncDecl{
+		Name: &dst.Ident{Name: m.AdapterPreFuncName},
+		Type: &dst.FuncType{
+			Params:  &dst.FieldList{},
+			Results: &dst.FieldList{},
+		},
+	}
+	for i, recv := range m.Recvs {
+		preFunc.Type.Params.List = append(preFunc.Type.Params.List, &dst.Field{
+			Names: []*dst.Ident{dst.NewIdent(fmt.Sprintf("recv_%d", i))},
+			Type:  &dst.StarExpr{X: m.addPackagePrefixForArgsAndClone(m.packageName, recv.Type)},
+		})
+	}
+	for i, parameter := range m.Parameters {
+		preFunc.Type.Params.List = append(preFunc.Type.Params.List, &dst.Field{
+			Names: []*dst.Ident{dst.NewIdent(fmt.Sprintf("param_%d", i))},
+			Type:  &dst.StarExpr{X: m.addPackagePrefixForArgsAndClone(m.packageName, parameter.Type)},
+		})
+	}
+	for i, result := range m.Results {
+		preFunc.Type.Results.List = append(preFunc.Type.Results.List, &dst.Field{
+			Names: []*dst.Ident{dst.NewIdent(fmt.Sprintf("ret_%d", i))},
+			Type:  &dst.StarExpr{X: m.addPackagePrefixForArgsAndClone(m.packageName, result.Type)},
+		})
+	}
+	preFunc.Type.Results.List = append(preFunc.Type.Results.List, &dst.Field{
+		Names: []*dst.Ident{dst.NewIdent("inv")},
+		Type:  &dst.StarExpr{X: &dst.SelectorExpr{X: dst.NewIdent("operator"), Sel: dst.NewIdent("Invocation")}},
+	}, &dst.Field{
+		Names: []*dst.Ident{dst.NewIdent("keep")},
+		Type:  dst.NewIdent("bool"),
+	})
+
+	beforeFile, err := templatesFS.ReadFile("templates/method_intercept_before.tmpl")
+	if err != nil {
+		panic(fmt.Errorf("reading method before intercept template failure: %w", err))
+	}
+	preFunc.Body = &dst.BlockStmt{
+		List: tools.GoStringToStats(tools.ExecuteTemplate(string(beforeFile), m)),
+	}
+	result = append(result, preFunc)
+
+	postFunc := &dst.FuncDecl{
+		Name: &dst.Ident{Name: m.AdapterPostFuncName},
+		Type: &dst.FuncType{
+			Params:  &dst.FieldList{},
+			Results: &dst.FieldList{},
+		},
+	}
+	postFunc.Type.Params.List = append(postFunc.Type.Params.List, &dst.Field{
+		Names: []*dst.Ident{dst.NewIdent("invocation")},
+		Type:  &dst.StarExpr{X: &dst.SelectorExpr{X: dst.NewIdent("operator"), Sel: dst.NewIdent("Invocation")}},
+	})
+	for inx, f := range m.Results {
+		postFunc.Type.Params.List = append(postFunc.Type.Params.List, &dst.Field{
+			Names: []*dst.Ident{dst.NewIdent(fmt.Sprintf("ret_%d", inx))},
+			Type:  &dst.StarExpr{X: m.addPackagePrefixForArgsAndClone(m.packageName, f.Type)},
+		})
+	}
+	afterFile, err := templatesFS.ReadFile("templates/method_intercept_after.tmpl")
+	if err != nil {
+		panic(fmt.Errorf("reading method after intercept template failure: %w", err))
+	}
+	postFunc.Body = &dst.BlockStmt{
+		List: tools.GoStringToStats(tools.ExecuteTemplate(string(afterFile), m)),
+	}
+	result = append(result, postFunc)
+	return result
+}
+
+func (m *MethodEnhance) addPackagePrefixForArgsAndClone(pkg string, tp dst.Expr) dst.Expr {
+	switch t := tp.(type) {
+	case *dst.Ident:
+		if rewrite.IsBasicDataType(t.Name) {
+			return dst.Clone(tp).(dst.Expr)
+		}
+		// otherwise, add the package prefix
+		return &dst.SelectorExpr{
+			X:   dst.NewIdent(pkg),
+			Sel: dst.NewIdent(t.Name),
+		}
+	case *dst.StarExpr:
+		t.X = m.addPackagePrefixForArgsAndClone(pkg, t.X)
+		return t
+	default:
+		return dst.Clone(tp).(dst.Expr)
+	}
+}
+
+func (m *MethodEnhance) ReplaceFileContent(path, content string) string {
+	if m.path == path {
+		return strings.Replace(content, m.replacementKey, m.replacementValue, 1)
+	}
+	return content
+}
+
+func buildFrameworkFuncID(pkgPath string, node *dst.FuncDecl) string {
+	var receiver string
+	if node.Recv != nil {
+		expr, ok := node.Recv.List[0].Type.(*dst.StarExpr)
+		if !ok {
+			return ""
+		}
+		ident, ok := expr.X.(*dst.Ident)
+		if !ok {
+			return ""
+		}
+		receiver = ident.Name
+	}
+	return fmt.Sprintf("%s_%s%s",
+		regexp.MustCompile(`[/.\-@]`).ReplaceAllString(pkgPath, "_"), receiver, node.Name)
+}
diff --git a/tools/go-agent/instrument/framework/instrument.go b/tools/go-agent/instrument/framework/instrument.go
new file mode 100644
index 0000000..55dedd5
--- /dev/null
+++ b/tools/go-agent/instrument/framework/instrument.go
@@ -0,0 +1,384 @@
+// 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 framework
+
+import (
+	"bytes"
+	"embed"
+	"fmt"
+	"io/fs"
+	"os"
+	"path/filepath"
+	"strings"
+
+	"github.com/apache/skywalking-go/plugins/core"
+	"github.com/apache/skywalking-go/plugins/core/instrument"
+	"github.com/apache/skywalking-go/tools/go-agent/instrument/api"
+	"github.com/apache/skywalking-go/tools/go-agent/instrument/framework/rewrite"
+	"github.com/apache/skywalking-go/tools/go-agent/tools"
+
+	"github.com/dave/dst"
+	"github.com/dave/dst/dstutil"
+
+	"github.com/sirupsen/logrus"
+)
+
+//go:embed templates
+var templatesFS embed.FS
+
+type Instrument struct {
+	realInst      instrument.Instrument
+	methodFilters []*instrument.Point
+	structFilters []*instrument.Point
+
+	compileOpts *api.CompileOptions
+
+	enhancements    []Enhance
+	extraFilesWrote bool
+}
+
+func NewInstrument() *Instrument {
+	return &Instrument{}
+}
+
+type Enhance interface {
+	BuildForAdapter() []dst.Decl
+	ReplaceFileContent(path, content string) string
+}
+
+func (i *Instrument) CouldHandle(opts *api.CompileOptions) bool {
+	for _, ins := range instruments {
+		// must have the same base package prefix
+		if !strings.HasPrefix(opts.Package, ins.BasePackage()) {
+			continue
+		}
+		// check the version of the framework could handler
+		version, err := i.tryToFindThePluginVersion(opts, ins.BasePackage())
+		if err != nil {
+			logrus.Warnf("ignore the plugin %s, because: %s", ins.Name(), err)
+			continue
+		}
+
+		if ins.VersionChecker(version) {
+			i.realInst = ins
+			i.compileOpts = opts
+			for _, p := range ins.Points() {
+				switch p.At.Type {
+				case instrument.EnhanceTypeMethod:
+					i.methodFilters = append(i.methodFilters, p)
+				case instrument.EnhanceTypeStruct:
+					i.structFilters = append(i.structFilters, p)
+				}
+			}
+			return true
+		}
+	}
+	return false
+}
+
+func (i *Instrument) FilterAndEdit(path string, cursor *dstutil.Cursor, allFiles []*dst.File) bool {
+	switch n := cursor.Node().(type) {
+	case *dst.TypeSpec:
+		for _, filter := range i.structFilters {
+			if i.verifyPackageIsMatch(path, filter) && i.validateStructIsMatch(filter.At, n, allFiles) {
+				i.enhanceStruct(i.realInst, filter, n, path)
+				return true
+			}
+		}
+	case *dst.FuncDecl:
+		for _, filter := range i.methodFilters {
+			if i.verifyPackageIsMatch(path, filter) && i.validateMethodInsMatch(filter.At, n, allFiles) {
+				i.enhanceMethod(i.realInst, filter, n, path)
+				return true
+			}
+		}
+	}
+	return false
+}
+
+func (i *Instrument) enhanceStruct(_ instrument.Instrument, _ *instrument.Point, typeSpec *dst.TypeSpec, _ string) {
+	enhance := NewInstanceEnhance(typeSpec)
+	enhance.EnhanceField()
+	i.enhancements = append(i.enhancements, enhance)
+}
+
+func (i *Instrument) enhanceMethod(inst instrument.Instrument, matcher *instrument.Point, funcDecl *dst.FuncDecl, path string) {
+	enhance := NewMethodEnhance(inst, matcher, funcDecl, path)
+	enhance.BuildForInvoker()
+	i.enhancements = append(i.enhancements, enhance)
+}
+
+func (i *Instrument) verifyPackageIsMatch(_ string, point *instrument.Point) bool {
+	pointPackagePath := filepath.Join(i.realInst.BasePackage(), point.PackagePath)
+	// check the package path
+	return i.compileOpts.Package == pointPackagePath
+}
+
+func (i *Instrument) AfterEnhanceFile(fromPath, newPath string) error {
+	contentBytes, err := os.ReadFile(newPath)
+	if err != nil {
+		return err
+	}
+
+	// update the file content if needed
+	content := string(contentBytes)
+	var oldContent = content
+	for _, enhance := range i.enhancements {
+		content = enhance.ReplaceFileContent(fromPath, content)
+	}
+	if oldContent == content {
+		return nil
+	}
+
+	return os.WriteFile(newPath, []byte(content), 0o600)
+}
+
+func (i *Instrument) WriteExtraFiles(basePath string) ([]string, error) {
+	// if no enhancements or already wrote extra files, then ignore
+	if len(i.enhancements) == 0 || i.extraFilesWrote {
+		return nil, nil
+	}
+	i.extraFilesWrote = true
+
+	packageName := filepath.Base(i.compileOpts.Package)
+	context := rewrite.NewContext(i.compileOpts.Package, packageName)
+
+	var results = make([]string, 0)
+	// write adapter file
+	var files []string
+	var err error
+	if files, err = i.writeAdapterFile(context, basePath); err != nil {
+		return nil, err
+	}
+	results = append(results, files...)
+
+	// copy basic support files(operators)
+	if files, err = i.copyOperatorsFS(context, basePath, packageName); err != nil {
+		return nil, err
+	}
+	results = append(results, files...)
+
+	// copy user defined files(interceptors)
+	if files, err = i.copyFrameworkFS(context, i.compileOpts.Package, basePath, packageName); err != nil {
+		return nil, err
+	}
+	results = append(results, files...)
+	return results, nil
+}
+
+func (i *Instrument) copyFrameworkFS(context *rewrite.Context, compilePkgFullPath, baseDir, packageName string) ([]string, error) {
+	subPkgPath := strings.TrimPrefix(compilePkgFullPath, i.realInst.BasePackage())
+	if subPkgPath == "" {
+		subPkgPath = "."
+	}
+
+	var debugBaseDir string
+	if i.compileOpts.DebugDir != "" {
+		debugBaseDir = filepath.Join(i.compileOpts.DebugDir, "plugins", i.realInst.Name(), subPkgPath)
+	}
+	pkgCopiedEntries, err := i.realInst.FS().ReadDir(subPkgPath)
+	if err != nil {
+		return nil, err
+	}
+	files := make([]*rewrite.FileInfo, 0)
+	for _, entry := range pkgCopiedEntries {
+		if entry.IsDir() {
+			continue
+		}
+		if entry.Name() == "go.mod" || entry.Name() == "go.sum" || strings.HasSuffix(entry.Name(), "_test.go") {
+			continue
+		}
+
+		readFile, err1 := fs.ReadFile(i.realInst.FS(), filepath.Join(subPkgPath, entry.Name()))
+		if err1 != nil {
+			return nil, err1
+		}
+		// ignore nocopy files
+		if bytes.Contains(readFile, []byte("//skywalking:nocopy")) {
+			continue
+		}
+
+		files = append(files, rewrite.NewFile(packageName, entry.Name(), string(readFile)))
+	}
+
+	rewrited, err := context.MultipleFilesWithWritten("skywalking_enhance_", baseDir, packageName, files, debugBaseDir)
+	if err != nil {
+		return nil, err
+	}
+	return rewrited, nil
+}
+
+func (i *Instrument) copyOperatorsFS(context *rewrite.Context, baseDir, packageName string) ([]string, error) {
+	result := make([]string, 0)
+	var debugBaseDir string
+	for _, dir := range rewrite.OperatorDirs {
+		entries, err := core.FS.ReadDir(dir)
+		if err != nil {
+			return nil, err
+		}
+		files := make([]*rewrite.FileInfo, 0)
+		for _, entry := range entries {
+			if strings.HasSuffix(entry.Name(), "_test.go") {
+				continue
+			}
+			file, err1 := fs.ReadFile(core.FS, filepath.Join(dir, entry.Name()))
+			if err1 != nil {
+				return nil, err1
+			}
+			files = append(files, rewrite.NewFile(dir, entry.Name(), string(file)))
+		}
+		if i.compileOpts.DebugDir != "" {
+			debugBaseDir = filepath.Join(i.compileOpts.DebugDir, "plugins", "core", dir)
+		}
+
+		rewrited, err := context.MultipleFilesWithWritten("skywalking_agent_core_", baseDir, filepath.Base(dir), files, debugBaseDir)
+		if err != nil {
+			return nil, err
+		}
+		result = append(result, rewrited...)
+	}
+
+	// write extra file for link the operator function
+	tmpFiles, err := tools.WriteMultipleFile(baseDir, map[string]string{
+		"skywalking_agent_core_linker.go": tools.ExecuteTemplate(`package {{.PackageName}}
+
+import (
+	_ "unsafe"
+)
+
+//go:linkname {{.OperatorGetLinkMethod}} {{.OperatorGetLinkMethod}}
+var {{.OperatorGetLinkMethod}} func() interface{}
+
+func init() {
+	if {{.OperatorGetLinkMethod}} != nil {
+		{{.OperatorGetRealMethod}} = func() {{.OperatorTypeName}} {
+			tmpOp := {{.OperatorGetLinkMethod}}()
+			if tmpOp == nil {
+				return nil
+			}
+			if opVal, ok := tmpOp.({{.OperatorTypeName}}); ok {
+				return opVal
+			}
+			return nil
+		}
+	}
+}
+`, struct {
+			PackageName           string
+			OperatorGetLinkMethod string
+			OperatorGetRealMethod string
+			OperatorTypeName      string
+		}{
+			PackageName:           packageName,
+			OperatorGetLinkMethod: rewrite.GlobalOperatorLinkGetMethodName,
+			OperatorGetRealMethod: rewrite.GlobalOperatorRealGetMethodName,
+			OperatorTypeName:      rewrite.GlobalOperatorTypeName,
+		}),
+	})
+	if err != nil {
+		return nil, err
+	}
+	result = append(result, tmpFiles...)
+	return result, nil
+}
+
+func (i *Instrument) writeAdapterFile(ctx *rewrite.Context, basePath string) ([]string, error) {
+	file := &dst.File{
+		Name: dst.NewIdent("adapter"), // write to adapter temporary, it will be rewritten later
+	}
+
+	for _, enhance := range i.enhancements {
+		file.Decls = append(file.Decls, enhance.BuildForAdapter()...)
+	}
+
+	ctx.SingleFile(file)
+
+	adapterFile := filepath.Join(basePath, "skywalking_adapter.go")
+	if err := tools.WriteDSTFile(adapterFile, file, nil); err != nil {
+		return nil, err
+	}
+	return []string{adapterFile}, nil
+}
+
+func (i *Instrument) validateStructIsMatch(matcher *instrument.EnhanceMatcher, node *dst.TypeSpec, allFiles []*dst.File) bool {
+	if matcher.Name != node.Name.Name {
+		return false
+	}
+	if _, ok := node.Type.(*dst.StructType); !ok {
+		return false
+	}
+	for _, filter := range matcher.StructFilters {
+		if !filter(node, allFiles) {
+			return false
+		}
+	}
+	return true
+}
+
+func (i *Instrument) validateMethodInsMatch(matcher *instrument.EnhanceMatcher, node *dst.FuncDecl, allFiles []*dst.File) bool {
+	if matcher.Name != node.Name.Name {
+		return false
+	}
+	if matcher.Receiver != "" {
+		if node.Recv == nil || len(node.Recv.List) == 0 {
+			return false
+		}
+		var data dst.Expr
+		switch t := node.Recv.List[0].Type.(type) {
+		case *dst.StarExpr:
+			data = t.X
+		case *dst.TypeAssertExpr:
+			data = t.X
+		default:
+			return false
+		}
+
+		if id, ok := data.(*dst.Ident); !ok {
+			return false
+		} else if id.Name != matcher.Receiver {
+			return false
+		}
+	}
+	for _, filter := range matcher.MethodFilters {
+		if !filter(node, allFiles) {
+			return false
+		}
+	}
+	return true
+}
+
+func (i *Instrument) tryToFindThePluginVersion(opts *api.CompileOptions, pkg string) (string, error) {
+	for _, arg := range opts.AllArgs {
+		// find the go file
+		if !strings.HasSuffix(arg, ".go") {
+			continue
+		}
+
+		parts := strings.SplitN(arg, pkg, 2)
+		// example: github.com/gin-gonic/gin@1.1.1/gin.go
+		if len(parts) != 2 || !strings.HasPrefix(parts[1], "@") {
+			return "", fmt.Errorf("could not found the go version of the package %s, go file path: %s", pkg, arg)
+		}
+		firstDir := strings.Index(parts[1], "/")
+		if firstDir == -1 {
+			return "", fmt.Errorf("could not found the first directory index for package: %s, go file path: %s", pkg, arg)
+		}
+		return parts[1][1:firstDir], nil
+	}
+	return "", nil
+}
diff --git a/agent/core/tracing/compile.go b/tools/go-agent/instrument/framework/register.go
similarity index 69%
copy from agent/core/tracing/compile.go
copy to tools/go-agent/instrument/framework/register.go
index 5ccde8b..0c0bcf1 100644
--- a/agent/core/tracing/compile.go
+++ b/tools/go-agent/instrument/framework/register.go
@@ -15,21 +15,20 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package tracing
+package framework
 
 import (
-	//go:nolint
-	_ "fmt"
-	_ "reflect"
+	"github.com/apache/skywalking-go/plugins/core/instrument"
+	"github.com/apache/skywalking-go/plugins/ginv2"
+)
 
-	//go:nolint
-	_ "github.com/pkg/errors"
+var instruments = make([]instrument.Instrument, 0)
 
-	//go:nolint
-	_ "github.com/apache/skywalking-go/agent/core"
-	_ "github.com/apache/skywalking-go/reporter"
+func init() {
+	// register the framework instrument
+	registerFramework(ginv2.NewInstrument())
+}
 
-	//go:nolint
-	_ "skywalking.apache.org/repo/goapi/collect/common/v3"
-	_ "skywalking.apache.org/repo/goapi/collect/language/agent/v3"
-)
+func registerFramework(ins instrument.Instrument) {
+	instruments = append(instruments, ins)
+}
diff --git a/tools/go-agent/instrument/framework/rewrite/context.go b/tools/go-agent/instrument/framework/rewrite/context.go
new file mode 100644
index 0000000..8665c08
--- /dev/null
+++ b/tools/go-agent/instrument/framework/rewrite/context.go
@@ -0,0 +1,298 @@
+// 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 rewrite
+
+import (
+	"fmt"
+	"strconv"
+	"strings"
+
+	"github.com/dave/dst"
+
+	"golang.org/x/text/cases"
+	"golang.org/x/text/language"
+)
+
+var GenerateMethodPrefix = "_skywalking_enhance_"
+var GenerateVarPrefix = "_skywalking_var_"
+var OperatorDirs = []string{"operator", "log", "tracing"}
+
+var OperatePrefix = "skywalkingOperator"
+var TypePrefix = OperatePrefix + "Type"
+var VarPrefix = OperatePrefix + "Var"
+var StaticMethodPrefix = OperatePrefix + "StaticMethod"
+
+type Context struct {
+	pkgFullPath   string
+	titleCase     cases.Caser
+	targetPackage string
+
+	currentPackageTitle string
+
+	packageImport  map[string]*rewriteImportInfo
+	rewriteMapping *rewriteMapping
+}
+
+func NewContext(compilePkgFullPath, targetPackage string) *Context {
+	return &Context{
+		pkgFullPath:    compilePkgFullPath,
+		titleCase:      cases.Title(language.English),
+		targetPackage:  targetPackage,
+		packageImport:  make(map[string]*rewriteImportInfo),
+		rewriteMapping: newRewriteFuncMapping(make(map[string]string), make(map[string]string)),
+	}
+}
+
+type rewriteImportInfo struct {
+	pkgName     string
+	isAgentCore bool
+	ctx         *Context
+}
+
+func (c *Context) enhanceVarNameWhenRewrite(fieldType dst.Expr) (oldName, replacedName string) {
+	switch t := fieldType.(type) {
+	case *dst.Ident:
+		name := t.Name
+		if c.typeIsBasicTypeValueOrEnhanceName(name) {
+			return "", ""
+		}
+		if mappingName := c.rewriteMapping.findVarMappingName(name); mappingName != "" {
+			t.Name = mappingName
+			return "", ""
+		}
+		// keep the var name help debugging
+		c.rewriteMapping.addVarMapping(name, name)
+		return name, t.Name
+	case *dst.SelectorExpr:
+		return c.enhanceVarNameWhenRewrite(t.X)
+	case *dst.IndexExpr:
+		c.rewriteVarIfExistingMapping(t.Index)
+		return c.enhanceVarNameWhenRewrite(t.X)
+	}
+	return "", ""
+}
+
+// nolint
+func (c *Context) enhanceTypeNameWhenRewrite(fieldType dst.Expr, parent dst.Node, argIndex int) (string, string) {
+	switch t := fieldType.(type) {
+	case *dst.Ident:
+		name := t.Name
+		if c.typeIsBasicTypeValueOrEnhanceName(name) {
+			return "", ""
+		}
+		if c.callIsBasicNamesOrEnhanceName(name) {
+			return "", ""
+		}
+		if mappingName := c.rewriteMapping.findVarMappingName(name); mappingName != "" {
+			t.Name = mappingName
+			return "", ""
+		}
+		if mappingName := c.rewriteMapping.findTypeMappingName(name); mappingName != "" {
+			t.Name = mappingName
+			return "", ""
+		}
+		// if parent is function call, then the name should be method name
+		if _, ok := parent.(*dst.CallExpr); ok {
+			t.Name = fmt.Sprintf("%s%s%s", StaticMethodPrefix, c.currentPackageTitle, name)
+		} else {
+			t.Name = fmt.Sprintf("%s%s%s", TypePrefix, c.currentPackageTitle, name)
+		}
+		return name, t.Name
+	case *dst.SelectorExpr:
+		pkgRefName, ok := t.X.(*dst.Ident)
+		if !ok {
+			return c.enhanceTypeNameWhenRewrite(t.X, parent, -1)
+		}
+		// reference by package name
+		for refImportName, pkgInfo := range c.packageImport {
+			if pkgRefName.Name == refImportName {
+				switch p := parent.(type) {
+				case *dst.CallExpr:
+					if c.rewriteVarIfExistingMapping(t.Sel) {
+						if argIndex >= 0 {
+							p.Args[argIndex] = t.Sel
+						} else {
+							p.Fun = dst.NewIdent(t.Sel.Name)
+						}
+					} else {
+						p.Fun = pkgInfo.generateStaticMethod(t.Sel.Name)
+					}
+				case *dst.Field:
+					p.Type = pkgInfo.generateType(t.Sel.Name)
+				case *dst.Ellipsis:
+					p.Elt = pkgInfo.generateType(t.Sel.Name)
+				case *dst.StarExpr:
+					p.X = pkgInfo.generateType(t.Sel.Name)
+				case *dst.TypeAssertExpr:
+					p.Type = pkgInfo.generateType(t.Sel.Name)
+				case *dst.CompositeLit:
+					p.Type = pkgInfo.generateType(t.Sel.Name)
+				case *dst.ArrayType:
+					p.Elt = pkgInfo.generateType(t.Sel.Name)
+				}
+			}
+		}
+		// if the method call
+		if v := c.rewriteMapping.findVarMappingName(pkgRefName.Name); v != "" {
+			t.X = dst.NewIdent(v)
+		}
+	case *dst.StarExpr:
+		return c.enhanceTypeNameWhenRewrite(t.X, t, -1)
+	case *dst.ArrayType:
+		return c.enhanceTypeNameWhenRewrite(t.Elt, t, -1)
+	case *dst.Ellipsis:
+		return c.enhanceTypeNameWhenRewrite(t.Elt, t, -1)
+	case *dst.CompositeLit:
+		for _, elt := range t.Elts {
+			// for struct data, ex: "&xxx{k: v}"
+			if kv, ok := elt.(*dst.KeyValueExpr); ok {
+				c.rewriteVarIfExistingMapping(kv.Value)
+			}
+		}
+		return c.enhanceTypeNameWhenRewrite(t.Type, t, -1)
+	case *dst.UnaryExpr:
+		return c.enhanceTypeNameWhenRewrite(t.X, t, -1)
+	case *dst.CallExpr:
+		for inx, arg := range t.Args {
+			c.enhanceTypeNameWhenRewrite(arg, t, inx)
+		}
+
+		if id, ok := t.Fun.(*dst.Ident); ok {
+			if c.callIsBasicNamesOrEnhanceName(id.Name) {
+				return "", ""
+			}
+			return c.enhanceTypeNameWhenRewrite(t.Fun, t, -1)
+		}
+		c.enhanceTypeNameWhenRewrite(t.Fun, t, -1)
+	case *dst.FuncType:
+		c.enhanceFuncParameter(t.TypeParams)
+		c.enhanceFuncParameter(t.Params)
+		c.enhanceFuncParameter(t.Results)
+	case *dst.IndexExpr:
+		c.rewriteVarIfExistingMapping(t.Index)
+		return c.enhanceTypeNameWhenRewrite(t.X, t, -1)
+	case *dst.TypeAssertExpr:
+		c.enhanceTypeNameWhenRewrite(t.Type, t, -1)
+		return c.enhanceTypeNameWhenRewrite(t.X, t, -1)
+	case *dst.FuncLit:
+		c.enhanceTypeNameWhenRewrite(t.Type, t, -1)
+		for _, stmt := range t.Body.List {
+			c.enhanceFuncStmt(stmt)
+		}
+	case *dst.BinaryExpr:
+		c.enhanceTypeNameWhenRewrite(t.X, t, -1)
+		c.enhanceTypeNameWhenRewrite(t.Y, t, -1)
+	case *dst.ParenExpr:
+		c.rewriteVarIfExistingMapping(t.X)
+	case *dst.MapType:
+		c.enhanceTypeNameWhenRewrite(t.Key, t, -1)
+		c.enhanceTypeNameWhenRewrite(t.Value, t, -1)
+	}
+
+	return "", ""
+}
+
+func (c *Context) typeIsBasicTypeValueOrEnhanceName(name string) bool {
+	if strings.HasPrefix(name, OperatePrefix) || strings.HasPrefix(name, GenerateMethodPrefix) || IsBasicDataType(name) ||
+		name == "nil" || name == "true" || name == "false" {
+		return true
+	}
+	if _, valErr := strconv.ParseFloat(name, 64); valErr == nil {
+		return true
+	}
+	return false
+}
+
+func (c *Context) callIsBasicNamesOrEnhanceName(name string) bool {
+	return strings.HasPrefix(name, OperatePrefix) || strings.HasPrefix(name, GenerateMethodPrefix) ||
+		name == "make" || name == "recover" || name == "len"
+}
+
+// nolint
+func IsBasicDataType(name string) bool {
+	return name == "bool" || name == "int8" || name == "int16" || name == "int32" || name == "int64" || name == "uint8" ||
+		name == "uint16" || name == "uint32" || name == "uint64" || name == "int" || name == "uint" || name == "uintptr" ||
+		name == "float32" || name == "float64" || name == "complex64" || name == "complex128" || name == "string" || name == "error" ||
+		name == "interface{}" || name == "_"
+}
+
+func (r *rewriteImportInfo) generateStaticMethod(name string) *dst.Ident {
+	if r.ctx.typeIsBasicTypeValueOrEnhanceName(name) {
+		return dst.NewIdent(name)
+	}
+	if r.isAgentCore {
+		return dst.NewIdent(fmt.Sprintf("%s%s%s", StaticMethodPrefix, r.ctx.titleCase.String(r.pkgName), name))
+	}
+	return dst.NewIdent(name)
+}
+
+func (r *rewriteImportInfo) generateType(name string) *dst.Ident {
+	if r.isAgentCore {
+		return dst.NewIdent(fmt.Sprintf("%s%s%s", TypePrefix, r.ctx.titleCase.String(r.pkgName), name))
+	}
+	return dst.NewIdent(name)
+}
+
+type rewriteMapping struct {
+	// push or pop the names when the block statement is called
+	rewriteVarNames  []map[string]string
+	rewriteTypeNames []map[string]string
+}
+
+func newRewriteFuncMapping(varNames, typeNames map[string]string) *rewriteMapping {
+	return &rewriteMapping{
+		rewriteVarNames:  []map[string]string{varNames},
+		rewriteTypeNames: []map[string]string{typeNames},
+	}
+}
+
+func (m *rewriteMapping) addVarMapping(key, value string) {
+	m.rewriteVarNames[len(m.rewriteVarNames)-1][key] = value
+}
+
+func (m *rewriteMapping) addTypeMapping(key, value string) {
+	m.rewriteTypeNames[len(m.rewriteTypeNames)-1][key] = value
+}
+
+func (m *rewriteMapping) pushBlockStack() {
+	m.rewriteVarNames = append(m.rewriteVarNames, make(map[string]string))
+	m.rewriteTypeNames = append(m.rewriteTypeNames, make(map[string]string))
+}
+
+func (m *rewriteMapping) popBlockStack() {
+	m.rewriteVarNames = m.rewriteVarNames[:len(m.rewriteVarNames)-1]
+	m.rewriteTypeNames = m.rewriteTypeNames[:len(m.rewriteTypeNames)-1]
+}
+
+func (m *rewriteMapping) findVarMappingName(name string) string {
+	for i := len(m.rewriteVarNames) - 1; i >= 0; i-- {
+		if v, ok := m.rewriteVarNames[i][name]; ok {
+			return v
+		}
+	}
+	return ""
+}
+
+func (m *rewriteMapping) findTypeMappingName(name string) string {
+	for i := len(m.rewriteTypeNames) - 1; i >= 0; i-- {
+		if v, ok := m.rewriteTypeNames[i][name]; ok {
+			return v
+		}
+	}
+	return ""
+}
diff --git a/tools/go-agent/instrument/framework/rewrite/func.go b/tools/go-agent/instrument/framework/rewrite/func.go
new file mode 100644
index 0000000..5b48c85
--- /dev/null
+++ b/tools/go-agent/instrument/framework/rewrite/func.go
@@ -0,0 +1,205 @@
+// 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 rewrite
+
+import (
+	"fmt"
+	"reflect"
+	"strings"
+
+	"github.com/dave/dst"
+	"github.com/dave/dst/dstutil"
+)
+
+var (
+	GlobalOperatorRealSetMethodName = VarPrefix + "OperatorSetOperator"
+	GlobalOperatorRealGetMethodName = VarPrefix + "OperatorGetOperator"
+	GlobalOperatorLinkSetMethodName = "_skywalking_set_global_operator"
+	GlobalOperatorLinkGetMethodName = "_skywalking_get_global_operator"
+
+	GlobalOperatorTypeName = TypePrefix + "OperatorOperator"
+)
+
+func (c *Context) Func(funcDecl *dst.FuncDecl, cursor *dstutil.Cursor) {
+	// only the static method needs rewrite
+	if funcDecl.Recv == nil {
+		// if the method name is generated, then ignore to enhance(for adapter)
+		if !strings.HasPrefix(funcDecl.Name.Name, GenerateMethodPrefix) {
+			funcDecl.Name = dst.NewIdent(fmt.Sprintf("%s%s%s", StaticMethodPrefix, c.currentPackageTitle, funcDecl.Name.Name))
+		}
+	} else if len(funcDecl.Recv.List) == 1 {
+		// if contains the receiver, then enhance the receiver type
+		field := funcDecl.Recv.List[0]
+		var typeName string
+		if len(field.Names) > 0 {
+			typeName = field.Names[0].Name
+			c.rewriteMapping.addVarMapping(typeName, typeName)
+		}
+		if k, v := c.enhanceTypeNameWhenRewrite(field.Type, field, -1); k != "" {
+			c.rewriteMapping.addTypeMapping(k, v)
+		}
+	}
+
+	// enhance method parameter and return value
+	c.enhanceFuncParameter(funcDecl.Type.Params)
+	c.enhanceFuncParameter(funcDecl.Type.Results)
+
+	// enhance the method body
+	for _, stmt := range funcDecl.Body.List {
+		c.enhanceFuncStmt(stmt)
+	}
+}
+
+// nolint
+func (c *Context) enhanceFuncStmt(stmt dst.Stmt) {
+	// for the variables created in the sub statement, ex: if, func(), the temporary variable count should be recorded
+	subCallTypes := []reflect.Type{
+		reflect.TypeOf(&dst.IfStmt{}),
+		reflect.TypeOf(&dst.BlockStmt{}),
+	}
+	dstutil.Apply(stmt, func(cursor *dstutil.Cursor) bool {
+		for _, t := range subCallTypes {
+			if reflect.TypeOf(cursor.Node()) == t {
+				c.rewriteMapping.pushBlockStack()
+			}
+		}
+		switch n := cursor.Node().(type) {
+		case *dst.BlockStmt:
+			for _, tmp := range n.List {
+				c.enhanceFuncStmt(tmp)
+			}
+		case *dst.AssignStmt:
+			for _, l := range n.Lhs {
+				if k, v := c.enhanceVarNameWhenRewrite(l); k != "" {
+					c.rewriteMapping.addVarMapping(k, v)
+				}
+			}
+			for i, r := range n.Rhs {
+				if k, v := c.enhanceTypeNameWhenRewrite(r, nil, i); k != "" {
+					c.rewriteMapping.addTypeMapping(k, v)
+				}
+			}
+		case *dst.BinaryExpr:
+			c.rewriteVarIfExistingMapping(n.X)
+			c.rewriteVarIfExistingMapping(n.Y)
+		case *dst.CallExpr:
+			c.enhanceTypeNameWhenRewrite(n.Fun, n, -1)
+			for inx, arg := range n.Args {
+				c.enhanceTypeNameWhenRewrite(arg, n, inx)
+			}
+		case *dst.ReturnStmt:
+			for inx, arg := range n.Results {
+				c.enhanceTypeNameWhenRewrite(arg, n, inx)
+			}
+		case *dst.FuncType:
+			c.enhanceFuncParameter(n.Params)
+			c.enhanceFuncParameter(n.Results)
+		case *dst.ExprStmt:
+			c.enhanceTypeNameWhenRewrite(n.X, n, -1)
+		case *dst.TypeAssertExpr:
+			c.enhanceTypeNameWhenRewrite(n.X, n, -1)
+			c.enhanceTypeNameWhenRewrite(n.Type, n, -1)
+		case *dst.IfStmt:
+			c.enhanceFuncStmt(n.Init)
+			c.enhanceTypeNameWhenRewrite(n.Cond, n, -1)
+			if n.Body != nil {
+				for _, stmt := range n.Body.List {
+					c.enhanceFuncStmt(stmt)
+				}
+			}
+		case *dst.RangeStmt:
+			c.enhanceTypeNameWhenRewrite(n.X, n, -1)
+			if k, v := c.enhanceVarNameWhenRewrite(n.Key); k != "" {
+				c.rewriteMapping.addVarMapping(k, v)
+			}
+			if k, v := c.enhanceVarNameWhenRewrite(n.Value); k != "" {
+				c.rewriteMapping.addVarMapping(k, v)
+			}
+			if n.Body != nil {
+				for _, stmt := range n.Body.List {
+					c.enhanceFuncStmt(stmt)
+				}
+			}
+		case *dst.ValueSpec:
+			c.Var(n)
+		default:
+			return true
+		}
+
+		return false
+	}, func(cursor *dstutil.Cursor) bool {
+		// all templates variables should be removed
+		for _, t := range subCallTypes {
+			if reflect.TypeOf(cursor.Node()) == t {
+				c.rewriteMapping.popBlockStack()
+				break
+			}
+		}
+		return true
+	})
+}
+
+func (c *Context) rewriteVarIfExistingMapping(exp dst.Expr) bool {
+	switch n := exp.(type) {
+	case *dst.Ident:
+		if v := c.rewriteMapping.findVarMappingName(n.Name); v != "" {
+			n.Name = v
+			return true
+		}
+	case *dst.SelectorExpr:
+		return c.rewriteVarIfExistingMapping(n.X)
+	case *dst.CompositeLit:
+		c.enhanceTypeNameWhenRewrite(n.Type, n, -1)
+		for _, elt := range n.Elts {
+			// for struct data, ex: "&xxx{k: v}"
+			if kv, ok := elt.(*dst.KeyValueExpr); ok {
+				c.rewriteVarIfExistingMapping(kv.Value)
+			}
+		}
+	case *dst.UnaryExpr:
+		c.enhanceTypeNameWhenRewrite(n.X, n, -1)
+	case *dst.IndexExpr:
+		c.rewriteVarIfExistingMapping(n.Index)
+		c.rewriteVarIfExistingMapping(n.X)
+	case *dst.CallExpr:
+		c.enhanceTypeNameWhenRewrite(n.Fun, n, -1)
+		for _, arg := range n.Args {
+			c.rewriteVarIfExistingMapping(arg)
+		}
+	}
+	return false
+}
+
+func (c *Context) enhanceFuncParameter(fields *dst.FieldList) {
+	if fields == nil {
+		return
+	}
+
+	for _, field := range fields.List {
+		if len(field.Names) > 0 {
+			for inx := range field.Names {
+				name := field.Names[inx].Name
+				// keep the var names for debugging
+				c.rewriteMapping.addVarMapping(name, name)
+			}
+		}
+		if k, v := c.enhanceTypeNameWhenRewrite(field.Type, field, -1); k != "" {
+			c.rewriteMapping.addTypeMapping(k, v)
+		}
+	}
+}
diff --git a/tools/go-agent/instrument/framework/rewrite/import.go b/tools/go-agent/instrument/framework/rewrite/import.go
new file mode 100644
index 0000000..5729a0d
--- /dev/null
+++ b/tools/go-agent/instrument/framework/rewrite/import.go
@@ -0,0 +1,57 @@
+// 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 rewrite
+
+import (
+	"fmt"
+	"path/filepath"
+
+	"github.com/apache/skywalking-go/tools/go-agent/instrument/agentcore"
+
+	"github.com/dave/dst"
+	"github.com/dave/dst/dstutil"
+)
+
+func (c *Context) Import(imp *dst.ImportSpec, cursor *dstutil.Cursor) {
+	shouldRemove := false
+	operatorCode := false
+	// delete the original import("agent/core/xxx")
+	for _, subPackageName := range OperatorDirs {
+		if imp.Path.Value == fmt.Sprintf("%q", filepath.Join(agentcore.EnhanceFromBasePackage, subPackageName)) {
+			shouldRemove = true
+			operatorCode = true
+			break
+		}
+	}
+	// delete the same framework package import, such as the interceptor of http package("github.com/gin-gonic/gin")
+	if imp.Path.Value == fmt.Sprintf("%q", c.pkgFullPath) {
+		shouldRemove = true
+	}
+
+	if shouldRemove {
+		realPath := imp.Path.Value[1 : len(imp.Path.Value)-1]
+		subPath := filepath.Base(realPath)
+		info := &rewriteImportInfo{pkgName: subPath, isAgentCore: operatorCode, ctx: c}
+		if imp.Name == nil {
+			c.packageImport[subPath] = info
+		} else {
+			c.packageImport[imp.Name.Name] = info
+		}
+		cursor.Delete()
+	}
+}
diff --git a/tools/go-agent/instrument/framework/rewrite/rewrite.go b/tools/go-agent/instrument/framework/rewrite/rewrite.go
new file mode 100644
index 0000000..db8c7e3
--- /dev/null
+++ b/tools/go-agent/instrument/framework/rewrite/rewrite.go
@@ -0,0 +1,115 @@
+// 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 rewrite
+
+import (
+	"fmt"
+	"go/parser"
+	"go/token"
+	"path/filepath"
+
+	"github.com/apache/skywalking-go/tools/go-agent/tools"
+
+	"github.com/dave/dst"
+	"github.com/dave/dst/decorator"
+	"github.com/dave/dst/dstutil"
+)
+
+type FileInfo struct {
+	// the original file path, for debugging
+	OriginalFilePath string
+
+	PackageName string
+	FileName    string
+	FileData    string
+}
+
+type DebugInfo struct {
+	BaseDir string
+}
+
+func NewFile(packageName, fileName, data string) *FileInfo {
+	return &FileInfo{PackageName: packageName, FileName: fileName, FileData: data}
+}
+
+// MultipleFilesWithWritten for rewrite all operator/interceptor files
+func (c *Context) MultipleFilesWithWritten(writeFileNamePrefix, targetDir, fromPackage string,
+	originalFiles []*FileInfo, debugBaseDir string) ([]string, error) {
+	result := make([]string, 0)
+
+	for _, f := range originalFiles {
+		parseFile, err := decorator.ParseFile(nil, f.FileName, f.FileData, parser.ParseComments)
+		if err != nil {
+			return nil, err
+		}
+		var debugInfo *tools.DebugInfo
+		if debugBaseDir != "" {
+			debugInfo, err = tools.BuildDSTDebugInfo(filepath.Join(debugBaseDir, f.FileName), parseFile)
+			if err != nil {
+				return nil, err
+			}
+		}
+
+		c.processSingleFile(parseFile, fromPackage)
+		targetPath := filepath.Join(targetDir,
+			fmt.Sprintf("%s%s_%s", writeFileNamePrefix, f.PackageName, filepath.Base(f.FileName)))
+		if err := tools.WriteDSTFile(targetPath, parseFile, debugInfo); err != nil {
+			return nil, err
+		}
+		result = append(result, targetPath)
+	}
+	return result, nil
+}
+
+// SingleFile rewrite single file in memory, not write the file
+func (c *Context) SingleFile(file *dst.File) {
+	c.processSingleFile(file, c.targetPackage)
+}
+
+func (c *Context) processSingleFile(file *dst.File, fromPackage string) {
+	c.currentPackageTitle = c.titleCase.String(fromPackage)
+	file.Name.Name = c.targetPackage
+	dstutil.Apply(file, func(cursor *dstutil.Cursor) bool {
+		switch n := cursor.Node().(type) {
+		case *dst.FuncDecl:
+			c.Func(n, cursor)
+		case *dst.ImportSpec:
+			c.Import(n, cursor)
+		case *dst.TypeSpec:
+			c.Type(n)
+		case *dst.ValueSpec:
+			c.Var(n)
+		default:
+			return true
+		}
+		return false
+	}, func(cursor *dstutil.Cursor) bool {
+		return true
+	})
+
+	// remove the import decl if empty
+	dstutil.Apply(file, func(cursor *dstutil.Cursor) bool {
+		if decl, ok := cursor.Node().(*dst.GenDecl); ok && decl.Tok == token.IMPORT && len(decl.Specs) == 0 {
+			cursor.Delete()
+			return false
+		}
+		return true
+	}, func(cursor *dstutil.Cursor) bool {
+		return true
+	})
+}
diff --git a/tools/go-agent/instrument/framework/rewrite/type.go b/tools/go-agent/instrument/framework/rewrite/type.go
new file mode 100644
index 0000000..c1baa6b
--- /dev/null
+++ b/tools/go-agent/instrument/framework/rewrite/type.go
@@ -0,0 +1,56 @@
+// 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 rewrite
+
+import (
+	"fmt"
+
+	"github.com/dave/dst"
+)
+
+func (c *Context) Type(tp *dst.TypeSpec) {
+	oldName := tp.Name.Name
+	tp.Name = dst.NewIdent(fmt.Sprintf("%s%s%s", TypePrefix, c.currentPackageTitle, oldName))
+	c.rewriteMapping.addTypeMapping(oldName, tp.Name.Name)
+
+	// define interface type, ex: "type xxx interface {}"
+	if inter, ok := tp.Type.(*dst.InterfaceType); ok {
+		for _, method := range inter.Methods.List {
+			funcType, ok := method.Type.(*dst.FuncType)
+			if !ok {
+				continue
+			}
+
+			c.enhanceFuncParameter(funcType.Params)
+			c.enhanceFuncParameter(funcType.Results)
+		}
+	}
+
+	// define func type, ex: "type xxx func(x X) x"
+	if funcType, ok := tp.Type.(*dst.FuncType); ok {
+		c.enhanceFuncParameter(funcType.Params)
+		c.enhanceFuncParameter(funcType.Results)
+	}
+
+	// define struct type, ex: "type xx struct {}"
+	if structType, ok := tp.Type.(*dst.StructType); ok && structType.Fields != nil {
+		for _, field := range structType.Fields.List {
+			c.enhanceTypeNameWhenRewrite(field.Type, field, -1)
+		}
+	}
+}
diff --git a/tools/go-agent/cmd/helper.go b/tools/go-agent/instrument/framework/rewrite/var.go
similarity index 62%
copy from tools/go-agent/cmd/helper.go
copy to tools/go-agent/instrument/framework/rewrite/var.go
index d97e152..bcab56c 100644
--- a/tools/go-agent/cmd/helper.go
+++ b/tools/go-agent/instrument/framework/rewrite/var.go
@@ -15,26 +15,25 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package main
+package rewrite
 
 import (
 	"fmt"
-	"os"
-)
-
-type EnhancementToolFlags struct {
-	Help bool `skyflag:"-h"`
-}
+	"strings"
 
-func PrintUsageWithExit() {
-	fmt.Printf(`Usage: go {build,install} -a [-work] -toolexec "%s" PACKAGE...
-
-The Go-agent-enhance tool is designed for automatic enhancement of Golang programs, 
-providing the capability for Distribute Tracing.
+	"github.com/dave/dst"
+)
 
-Options:
-		-h
-				Print the usage message.
-`, os.Args[0])
-	os.Exit(1)
+func (c *Context) Var(val *dst.ValueSpec) {
+	if len(val.Names) == 1 {
+		oldName := val.Names[0].Name
+		if !strings.HasPrefix(oldName, GenerateVarPrefix) {
+			val.Names[0] = dst.NewIdent(fmt.Sprintf("%s%s%s", VarPrefix, c.currentPackageTitle, oldName))
+			c.rewriteMapping.addVarMapping(oldName, val.Names[0].Name)
+		}
+	}
+	c.enhanceTypeNameWhenRewrite(val.Type, val, -1)
+	for _, subVal := range val.Values {
+		c.enhanceTypeNameWhenRewrite(subVal, val, -1)
+	}
 }
diff --git a/tools/go-agent/instrument/framework/templates/method_inserts.tmpl b/tools/go-agent/instrument/framework/templates/method_inserts.tmpl
new file mode 100644
index 0000000..52454d5
--- /dev/null
+++ b/tools/go-agent/instrument/framework/templates/method_inserts.tmpl
@@ -0,0 +1,11 @@
+if {{ range $index, $value := .Results -}}
+	_sw_inv_res_{{$index -}},
+{{- end -}}_sw_invocation, _sw_keep := {{.AdapterPreFuncName}}({{ range $index, $value := .Recvs -}}
+	{{ if ne $index 0}},{{ end }}&{{$value.Name -}},
+{{- end -}}{{ range $index, $value := .Parameters -}}
+	{{ if ne $index 0}},{{ end }}&{{$value.Name -}}
+{{- end -}}); !_sw_keep { return {{- range $index, $value := .Results -}}
+	_sw_inv_res_{{$index -}},
+{{- end -}} } else { defer func() { {{.AdapterPostFuncName}}(_sw_invocation{{- range $index, $value := .Results -}}
+,{{- $value.Name -}}
+{{- end -}})}() };
\ No newline at end of file
diff --git a/tools/go-agent/instrument/framework/templates/method_intercept_after.tmpl b/tools/go-agent/instrument/framework/templates/method_intercept_after.tmpl
new file mode 100644
index 0000000..8b20ffa
--- /dev/null
+++ b/tools/go-agent/instrument/framework/templates/method_intercept_after.tmpl
@@ -0,0 +1,17 @@
+defer func() {
+	if r := recover(); r != nil {
+		// log error
+		// fmt.Printf("error: %v", r)
+		log.Errorf("execute interceptor after invoke error, instrument name: %s, interceptor name: %s, function ID: %s, error: %v",
+		    "{{.InstrumentName}}", "{{.InterceptorDefineName}}", "{{.FuncID}}", r)
+	}
+}()
+
+// real invoke
+if err := {{.InterceptorVarName}}.AfterInvoke(invocation{{ range $index, $value := .Results -}}
+                                                , ret_$index
+                                                {{- end}}); err != nil {
+	// using go2sky log error
+	log.Warnf("execute interceptor after invoke error, instrument name: %s, interceptor name: %s, function ID: %s, error: %v",
+        "{{.InstrumentName}}", "{{.InterceptorDefineName}}", "{{.FuncID}}", err)
+}
\ No newline at end of file
diff --git a/tools/go-agent/instrument/framework/templates/method_intercept_before.tmpl b/tools/go-agent/instrument/framework/templates/method_intercept_before.tmpl
new file mode 100644
index 0000000..2d67031
--- /dev/null
+++ b/tools/go-agent/instrument/framework/templates/method_intercept_before.tmpl
@@ -0,0 +1,33 @@
+defer func() {
+	if err := recover(); err != nil {
+		// log error
+		log.Errorf("execute interceptor before invoke error, instrument name: %s, interceptor name: %s, function ID: %s, error: %v",
+		    "{{.InstrumentName}}", "{{.InterceptorDefineName}}", "{{.FuncID}}", err)
+	}
+}()
+invocation := &operator.Invocation{}
+{{if .Recvs -}}
+invocation.CallerInstance = *recv_0	// for caller if exist
+{{- end}}
+invocation.Args = make([]interface{}, {{len .Parameters}})
+{{- range $index, $value := .Parameters}}
+invocation.Args[{{$index}}] = *param_{{$index}}
+{{- end}}
+
+// real invoke
+if err := {{.InterceptorVarName}}.BeforeInvoke(invocation); err != nil {
+	// using go2sky log error
+	log.Warnf("execute interceptor before invoke error, instrument name: %s, interceptor name: %s, function ID: %s, error: %v",
+    		    "{{.InstrumentName}}", "{{.InterceptorDefineName}}", "{{.FuncID}}", err)
+	return {{ range $index, $value := .Results -}}
+$value.DefaultValueAsString,
+{{- end}}invocation, true
+}
+if (invocation.Continue) {
+	return {{ range $index, $value := .Results -}}
+    invocation.Return[$index],
+{{- end}}invocation, false
+}
+return {{ range $index, $value := .Results -}}
+{{- if ne .index 0}}, {{end}}$value.DefaultValueAsString
+{{- end}}{{if .Results}}, {{- end}}invocation, true
\ No newline at end of file
diff --git a/tools/go-agent/instrument/instrument.go b/tools/go-agent/instrument/instrument.go
index 5c22226..4d2b501 100644
--- a/tools/go-agent/instrument/instrument.go
+++ b/tools/go-agent/instrument/instrument.go
@@ -29,15 +29,17 @@ import (
 
 	"github.com/sirupsen/logrus"
 
-	"github.com/apache/skywalking-go/tools/go-agent-enhance/instrument/agentcore"
-	"github.com/apache/skywalking-go/tools/go-agent-enhance/instrument/api"
-	"github.com/apache/skywalking-go/tools/go-agent-enhance/instrument/runtime"
-	"github.com/apache/skywalking-go/tools/go-agent-enhance/tools"
+	"github.com/apache/skywalking-go/tools/go-agent/instrument/agentcore"
+	"github.com/apache/skywalking-go/tools/go-agent/instrument/api"
+	"github.com/apache/skywalking-go/tools/go-agent/instrument/framework"
+	"github.com/apache/skywalking-go/tools/go-agent/instrument/runtime"
+	"github.com/apache/skywalking-go/tools/go-agent/tools"
 )
 
 var instruments = []api.Instrument{
 	runtime.NewInstrument(),
 	agentcore.NewInstrument(),
+	framework.NewInstrument(),
 }
 
 func Execute(opts *api.CompileOptions, args []string) ([]string, error) {
@@ -95,12 +97,17 @@ func instrumentFiles(buildDir string, inst api.Instrument, args []string) error
 		return err
 	}
 
+	allFiles := make([]*dst.File, 0)
+	for _, f := range parsedFiles {
+		allFiles = append(allFiles, f.dstFile)
+	}
+
 	// filter and edit the files
 	instrumentedFiles := make([]string, 0)
 	for path, info := range parsedFiles {
 		hasInstruted := false
 		dstutil.Apply(info.dstFile, func(cursor *dstutil.Cursor) bool {
-			if inst.FilterAndEdit(path, cursor) {
+			if inst.FilterAndEdit(path, cursor, allFiles) {
 				hasInstruted = true
 			}
 			return true
@@ -118,10 +125,14 @@ func instrumentFiles(buildDir string, inst api.Instrument, args []string) error
 		info := parsedFiles[updateFileSrc]
 		filename := filepath.Base(updateFileSrc)
 		dest := filepath.Join(buildDir, filename)
-		if err := tools.WriteDSTFile(dest, updateFileSrc, info.dstFile); err != nil {
+		debugInfo, err := tools.BuildDSTDebugInfo(updateFileSrc, nil)
+		if err != nil {
+			return err
+		}
+		if err := tools.WriteDSTFile(dest, info.dstFile, debugInfo); err != nil {
 			return err
 		}
-		if err := inst.AfterEnhanceFile(dest); err != nil {
+		if err := inst.AfterEnhanceFile(updateFileSrc, dest); err != nil {
 			return err
 		}
 		args[info.argsIndex] = dest
diff --git a/tools/go-agent/instrument/runtime/instrument.go b/tools/go-agent/instrument/runtime/instrument.go
index a916ad3..33718c8 100644
--- a/tools/go-agent/instrument/runtime/instrument.go
+++ b/tools/go-agent/instrument/runtime/instrument.go
@@ -21,15 +21,19 @@ import (
 	"github.com/dave/dst"
 	"github.com/dave/dst/dstutil"
 
-	"github.com/apache/skywalking-go/tools/go-agent-enhance/instrument/api"
-	"github.com/apache/skywalking-go/tools/go-agent-enhance/tools"
+	"github.com/apache/skywalking-go/tools/go-agent/instrument/api"
+	"github.com/apache/skywalking-go/tools/go-agent/tools"
 )
 
 var (
-	TLSFieldName              = "skywalking_tls"
-	TLSGetMethodName          = "_skywalking_get_gls"
-	TLSSetMethodName          = "_skywalking_set_gls"
-	TLSTakeSnapshotMethodName = "_skywalking_tls_take_snapshot"
+	TLSFieldName     = "skywalking_tls"
+	TLSGetMethodName = "_skywalking_get_gls"
+	TLSSetMethodName = "_skywalking_set_gls"
+
+	GlobalTracerFieldName         = "globalSkyWalkingOperator"
+	GlobalTracerSnapshotInterface = "skywalkingGoroutineSnapshotCreator"
+	GlobalTracerSetMethodName     = "_skywalking_set_global_operator"
+	GlobalTracerGetMethodName     = "_skywalking_get_global_operator"
 )
 
 type Instrument struct {
@@ -43,7 +47,7 @@ func (r *Instrument) CouldHandle(opts *api.CompileOptions) bool {
 	return opts.Package == "runtime"
 }
 
-func (r *Instrument) FilterAndEdit(path string, cursor *dstutil.Cursor) bool {
+func (r *Instrument) FilterAndEdit(path string, cursor *dstutil.Cursor, allFiles []*dst.File) bool {
 	switch n := cursor.Node().(type) {
 	case *dst.TypeSpec:
 		if n.Name != nil && n.Name.Name != "g" {
@@ -56,8 +60,7 @@ func (r *Instrument) FilterAndEdit(path string, cursor *dstutil.Cursor) bool {
 		// append the tls field
 		st.Fields.List = append(st.Fields.List, &dst.Field{
 			Names: []*dst.Ident{dst.NewIdent(TLSFieldName)},
-			Type:  dst.NewIdent("interface{}"),
-		})
+			Type:  dst.NewIdent("interface{}")})
 		tools.LogWithStructEnhance("runtime", "g", TLSFieldName, "tls field")
 		return true
 	case *dst.FuncDecl:
@@ -74,21 +77,20 @@ func (r *Instrument) FilterAndEdit(path string, cursor *dstutil.Cursor) bool {
 		results := tools.EnhanceParameterNames(n.Type.Results, true)
 
 		tools.InsertStmtsBeforeBody(n.Body, `defer func() {
-	if {{(index .Parameters 1).Name}} != nil && {{(index .Results 0).Name}} != nil && 
-		{{.SnapshotMethod}} != nil && {{(index .Parameters 1).Name}}.{{.TLSField}} != nil {
-		{{(index .Results 0).Name}}.{{.TLSField}} = {{.SnapshotMethod}}({{(index .Parameters 1).Name}}.{{.TLSField}})
-	}
+	{{(index .Results 0).Name}}.{{.TLSField}} = goroutineChange({{(index .Parameters 1).Name}}.{{.TLSField}})
 }()
 `, struct {
-			Parameters     []*tools.ParameterInfo
-			Results        []*tools.ParameterInfo
-			SnapshotMethod string
-			TLSField       string
+			Parameters        []*tools.ParameterInfo
+			Results           []*tools.ParameterInfo
+			TLSField          string
+			OperatorField     string
+			SnapshotInterface string
 		}{
-			Parameters:     parameters,
-			Results:        results,
-			SnapshotMethod: TLSTakeSnapshotMethodName,
-			TLSField:       TLSFieldName,
+			Parameters:        parameters,
+			Results:           results,
+			TLSField:          TLSFieldName,
+			OperatorField:     GlobalTracerFieldName,
+			SnapshotInterface: GlobalTracerSnapshotInterface,
 		})
 		tools.LogWithMethodEnhance("runtime", "", "newproc1", "support cross goroutine context propagating")
 		return true
@@ -96,20 +98,19 @@ func (r *Instrument) FilterAndEdit(path string, cursor *dstutil.Cursor) bool {
 	return false
 }
 
-func (r *Instrument) AfterEnhanceFile(path string) error {
+func (r *Instrument) AfterEnhanceFile(fromPath, newPath string) error {
 	return nil
 }
 
 func (r *Instrument) WriteExtraFiles(dir string) ([]string, error) {
 	return tools.WriteMultipleFile(dir, map[string]string{
-		"tls.go": tools.ExecuteTemplate(`package runtime
+		"skywalking_tls_operator.go": tools.ExecuteTemplate(`package runtime
 
 import (
 	_ "unsafe"
 )
 
-//go:linkname {{.TLSTaskSnapshotMethod}} {{.TLSTaskSnapshotMethod}}
-var {{.TLSTaskSnapshotMethod}} func(interface{}) interface{}
+var {{.GlobalTracerFieldName}} interface{}
 
 //go:linkname {{.TLSGetMethod}} {{.TLSGetMethod}}
 var {{.TLSGetMethod}} = _skywalking_tls_get_impl
@@ -117,6 +118,12 @@ var {{.TLSGetMethod}} = _skywalking_tls_get_impl
 //go:linkname {{.TLSSetMethod}} {{.TLSSetMethod}}
 var {{.TLSSetMethod}} = _skywalking_tls_set_impl
 
+//go:linkname {{.GlobalOperatorSetMethodName}} {{.GlobalOperatorSetMethodName}}
+var {{.GlobalOperatorSetMethodName}} = _skywalking_global_operator_set_impl
+
+//go:linkname {{.GlobalOperatorGetMethodName}} {{.GlobalOperatorGetMethodName}}
+var {{.GlobalOperatorGetMethodName}} = _skywalking_global_operator_get_impl
+
 //go:nosplit
 func _skywalking_tls_get_impl() interface{} {
 	return getg().m.curg.{{.TLSFiledName}}
@@ -125,16 +132,47 @@ func _skywalking_tls_get_impl() interface{} {
 //go:nosplit
 func _skywalking_tls_set_impl(v interface{}) {
 	getg().m.curg.{{.TLSFiledName}} = v
-}`, struct {
-			TLSFiledName          string
-			TLSGetMethod          string
-			TLSSetMethod          string
-			TLSTaskSnapshotMethod string
+}
+
+//go:nosplit
+func _skywalking_global_operator_set_impl(v interface{}) {
+	globalSkyWalkingOperator = v
+} 
+
+//go:nosplit
+func _skywalking_global_operator_get_impl() interface{} {
+	return globalSkyWalkingOperator
+} 
+
+type ContextSnapshoter interface {
+	TakeSnapShot(val interface{}) interface{}
+}
+
+func goroutineChange(tls interface{}) interface{} {
+	if tls == nil {
+		return nil
+	}
+	if taker, ok := tls.(ContextSnapshoter); ok {
+		return taker.TakeSnapShot(tls)
+	}
+	return tls
+}
+`, struct {
+			TLSFiledName                  string
+			TLSGetMethod                  string
+			TLSSetMethod                  string
+			GlobalTracerFieldName         string
+			GlobalTracerSnapshotInterface string
+			GlobalOperatorSetMethodName   string
+			GlobalOperatorGetMethodName   string
 		}{
-			TLSFiledName:          TLSFieldName,
-			TLSGetMethod:          TLSGetMethodName,
-			TLSSetMethod:          TLSSetMethodName,
-			TLSTaskSnapshotMethod: TLSTakeSnapshotMethodName,
+			TLSFiledName:                  TLSFieldName,
+			TLSGetMethod:                  TLSGetMethodName,
+			TLSSetMethod:                  TLSSetMethodName,
+			GlobalTracerFieldName:         GlobalTracerFieldName,
+			GlobalTracerSnapshotInterface: GlobalTracerSnapshotInterface,
+			GlobalOperatorSetMethodName:   GlobalTracerSetMethodName,
+			GlobalOperatorGetMethodName:   GlobalTracerGetMethodName,
 		}),
 	})
 }
diff --git a/tools/go-agent/tools/dst.go b/tools/go-agent/tools/dst.go
index 951596b..39b49d3 100644
--- a/tools/go-agent/tools/dst.go
+++ b/tools/go-agent/tools/dst.go
@@ -18,9 +18,14 @@
 package tools
 
 import (
+	"bytes"
 	"fmt"
+	"go/ast"
 	"go/printer"
+	"go/token"
+	"io"
 	"os"
+	"strings"
 
 	"github.com/dave/dst"
 	"github.com/dave/dst/decorator"
@@ -43,23 +48,148 @@ func ChangePackageImportPath(file dst.Node, pkgChanges map[string]string) {
 	})
 }
 
-func WriteDSTFile(path, srcPath string, file *dst.File) error {
+type DebugInfo struct {
+	FilePath     string
+	Line         int
+	CheckOldLine bool
+}
+
+func BuildDSTDebugInfo(srcPath string, file *dst.File) (*DebugInfo, error) {
+	result := &DebugInfo{FilePath: srcPath}
+	if file != nil {
+		fset, f, err := decorator.RestoreFile(file)
+		if err != nil {
+			return nil, err
+		}
+		originalFile, err := os.ReadFile(srcPath)
+		if err != nil {
+			return nil, err
+		}
+		line, err := findFirstNoImportLocation(fset, f, bytes.NewBuffer(originalFile))
+		if err != nil {
+			return nil, err
+		}
+		result.Line = line
+		result.CheckOldLine = true
+	} else {
+		result.Line = 1
+		result.CheckOldLine = false
+	}
+
+	return result, nil
+}
+
+func WriteDSTFile(path string, file *dst.File, debug *DebugInfo) error {
 	output, err := os.Create(path)
 	if err != nil {
 		return err
 	}
 	defer output.Close()
-	if srcPath != "" {
-		if _, err = output.WriteString(fmt.Sprintf("//line %s:1\n", srcPath)); err != nil {
+
+	fset, af, err := decorator.RestoreFile(file)
+	if err != nil {
+		return err
+	}
+
+	if debug != nil {
+		return writeDSTFileWithDebug(fset, af, debug, output)
+	}
+	return printer.Fprint(output, fset, af)
+}
+
+func writeDSTFileWithDebug(fset *token.FileSet, file *ast.File, debug *DebugInfo, output *os.File) error {
+	var changeInfo *dstFilePathChangeInfo
+	if !debug.CheckOldLine {
+		changeInfo = &dstFilePathChangeInfo{
+			oldDebugPath: debug.FilePath,
+			oldDebugLine: 1,
+			newDebugLine: 1,
+		}
+		if _, err := output.WriteString(fmt.Sprintf("//line %s:%d\n", debug.FilePath, debug.Line)); err != nil {
+			return err
+		}
+		if err := printer.Fprint(output, fset, file); err != nil {
 			return err
 		}
+		return nil
 	}
-	fset, af, err := decorator.RestoreFile(file)
-	if err != nil {
+	var buffer bytes.Buffer
+	if err := printer.Fprint(&buffer, fset, file); err != nil {
 		return err
 	}
-	if err := printer.Fprint(output, fset, af); err != nil {
+	newPosition, err := findFirstNoImportLocation(fset, file, bytes.NewBuffer(buffer.Bytes()))
+	if err != nil {
 		return err
 	}
+	changeInfo = &dstFilePathChangeInfo{
+		oldDebugPath: debug.FilePath,
+		oldDebugLine: debug.Line,
+		newDebugLine: newPosition,
+	}
+
+	lineCount := 1
+	alreadyChange := false
+	for {
+		line, err := buffer.ReadBytes('\n')
+		if err != nil {
+			if err == io.EOF && !alreadyChange {
+				return fmt.Errorf("rewrite file line number failure: %v", err)
+			}
+			break
+		}
+
+		if lineCount == changeInfo.newDebugLine {
+			line = []byte(fmt.Sprintf("//line %s:%d\n%s", debug.FilePath, changeInfo.oldDebugLine, line))
+			alreadyChange = true
+		}
+
+		if _, e := output.Write(line); e != nil {
+			return err
+		}
+
+		lineCount++
+	}
 	return nil
 }
+
+type dstFilePathChangeInfo struct {
+	oldDebugPath string
+	oldDebugLine int
+	newDebugLine int
+}
+
+func findFirstNoImportLocation(fset *token.FileSet, file *ast.File, fileContent *bytes.Buffer) (int, error) {
+	var pos token.Pos
+	for _, decl := range file.Decls {
+		if genDecl, ok := decl.(*ast.GenDecl); ok {
+			if genDecl.Tok == token.IMPORT {
+				pos = genDecl.End()
+				continue
+			}
+		}
+		break
+	}
+	if pos == 0 {
+		if len(file.Decls) > 0 {
+			return fset.Position(file.Decls[0].Pos()).Line, nil
+		}
+		return 1, nil
+	}
+	importEndLine := fset.Position(pos).Line
+	lineNumber := 0
+	for {
+		line, err := fileContent.ReadBytes('\n')
+		if err != nil {
+			return 0, err
+		}
+		lineNumber++
+		if lineNumber < importEndLine {
+			continue
+		}
+		trimed := strings.TrimSpace(string(line))
+		if trimed == "" || trimed == ")" {
+			continue
+		}
+		return lineNumber, nil
+	}
+}
diff --git a/tools/go-agent/tools/enhancement.go b/tools/go-agent/tools/enhancement.go
index d362fba..dca0137 100644
--- a/tools/go-agent/tools/enhancement.go
+++ b/tools/go-agent/tools/enhancement.go
@@ -75,6 +75,17 @@ func main() {
 	return parsed.Decls[0].(*dst.FuncDecl).Body.List
 }
 
+func GoStringToDecls(goString string) []dst.Decl {
+	parsed, err := decorator.Parse(fmt.Sprintf(`
+package main
+%s`, goString))
+	if err != nil {
+		panic(fmt.Sprintf("parsing go failure: %v\n%s", err, goString))
+	}
+
+	return parsed.Decls
+}
+
 func InsertStmtsBeforeBody(body *dst.BlockStmt, tmpl string, data interface{}) {
 	body.List = append(GoStringToStats(ExecuteTemplate(tmpl, data)), body.List...)
 }
diff --git a/tools/go-agent/tools/files.go b/tools/go-agent/tools/files.go
index 99ba059..cf84726 100644
--- a/tools/go-agent/tools/files.go
+++ b/tools/go-agent/tools/files.go
@@ -34,3 +34,11 @@ func WriteMultipleFile(baseDir string, nameWithData map[string]string) ([]string
 
 	return paths, nil
 }
+
+func WriteFile(baseDir, fileName, data string) (string, error) {
+	res := filepath.Join(baseDir, fileName)
+	if err := os.WriteFile(res, []byte(data), 0o600); err != nil {
+		return "", err
+	}
+	return res, nil
+}
diff --git a/tools/go-agent/tools/flags.go b/tools/go-agent/tools/flags.go
index a23c2d4..5256c76 100644
--- a/tools/go-agent/tools/flags.go
+++ b/tools/go-agent/tools/flags.go
@@ -24,67 +24,77 @@ import (
 	"strings"
 )
 
-const flagTagKey = "skyflag"
+const flagTagKey = "swflag"
 
-func ParseFlags(result interface{}, args []string) error {
+func ParseFlags(result interface{}, args []string) (noOpIndex int, err error) {
 	if len(args) == 0 {
-		return fmt.Errorf("no args")
+		return 0, fmt.Errorf("no args")
 	}
 	flags := parseFlagsFromStruct(result)
 	if len(flags) == 0 {
-		return nil
+		return 0, nil
 	}
 
 	i := 0
+	firstNonOptionIndex := -1
 	for i < len(args)-1 {
-		i += parseFlag(flags, args[i], args[i+1])
+		shift, isOption := parseFlag(flags, args[i], args[i+1])
+		if !isOption && firstNonOptionIndex == -1 {
+			firstNonOptionIndex = i
+		}
+		i += shift
 	}
 
 	if i < len(args) {
 		parseFlag(flags, args[i], "")
 	}
-	return nil
+
+	// process the all args flag
+	if v, exist := flags["all-args"]; exist {
+		v.Set(reflect.ValueOf(args))
+	}
+	return firstNonOptionIndex, nil
 }
 
-func ParseProxyCommandName(args []string) string {
+func ParseProxyCommandName(args []string, firstNonOptionIndex int) string {
 	if len(args) == 0 {
 		return ""
 	}
 
-	cmd := filepath.Base(args[0])
+	cmd := filepath.Base(args[firstNonOptionIndex])
 	if ext := filepath.Ext(cmd); ext != "" {
 		cmd = strings.TrimSuffix(cmd, ext)
 	}
 	return cmd
 }
 
-func parseFlag(flags map[string]reflect.Value, curArg, nextArg string) int {
+func parseFlag(flags map[string]reflect.Value, curArg, nextArg string) (shift int, isOption bool) {
 	if curArg[0] != '-' {
-		return 1
+		return 1, false
 	}
 
 	kv := strings.SplitN(curArg, "=", 2)
 	option := kv[0]
 	if v, exist := flags[option]; !exist {
 		if len(kv) == 2 {
-			return 1
+			return 1, true
 		} else if nextArg == "" || (len(nextArg) > 1 && nextArg[0] != '-') {
-			return 2
+			return 2, true
 		}
-		return 1
+		return 1, true
 	} else if len(kv) == 2 {
 		v.SetString(kv[1])
-		return 1
+		return 1, true
 	} else {
 		switch v.Kind() {
 		case reflect.String:
 			v.SetString(nextArg)
-			return 2
+			return 2, true
 		case reflect.Bool:
 			v.SetBool(true)
-			return 1
+			return 1, true
 		}
-		return 1
+		return 1, true
 	}
 }