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/22 13:19:50 UTC

[skywalking-go] branch main updated: Support init the skywalking tracer in the application (#11)

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 ec175e8  Support init the skywalking tracer in the application (#11)
ec175e8 is described below

commit ec175e8a50ad293385d4677aee409b90030b75aa
Author: mrproliu <74...@qq.com>
AuthorDate: Sat Apr 22 21:19:45 2023 +0800

    Support init the skywalking tracer in the application (#11)
---
 agent/core/compile.go                              |   5 +
 plugins/core/operator/logger.go                    |   4 +
 plugins/core/reporter/grpc_opts_enhance.go         |  64 ++++++++
 plugins/core/reporter/grpc_struct.go               |  62 ++++++++
 plugins/core/test_base.go                          |   2 +-
 plugins/core/tool.go                               |  93 +++++++++++
 plugins/core/tracer.go                             | 143 ++++++++++++++++-
 plugins/core/tracing.go                            |   2 +-
 reporter/grpc.go                                   |   6 +-
 .../core/operator/logger.go => reporter/imports.go |  13 +-
 reporter/reporter.go                               |   2 +-
 tools/go-agent/cmd/helper.go                       |   5 +-
 tools/go-agent/cmd/main.go                         |   6 +
 tools/go-agent/config/agent.default.yaml           |  29 ++++
 tools/go-agent/config/loader.go                    | 175 +++++++++++++++++++++
 tools/go-agent/go.mod                              |   2 +-
 tools/go-agent/instrument/agentcore/instrument.go  |  87 +++++-----
 tools/go-agent/instrument/entry/instrument.go      |  94 +++++++++++
 tools/go-agent/instrument/instrument.go            |   8 +-
 .../{framework => plugins}/enhance_instance.go     |   2 +-
 .../{framework => plugins}/enhance_method.go       |   4 +-
 .../{framework => plugins}/instrument.go           |   4 +-
 .../instrument/{framework => plugins}/register.go  |   4 +-
 .../{framework => plugins}/rewrite/context.go      |   0
 .../{framework => plugins}/rewrite/func.go         |   0
 .../{framework => plugins}/rewrite/import.go       |   0
 .../{framework => plugins}/rewrite/rewrite.go      |   0
 .../{framework => plugins}/rewrite/type.go         |   0
 .../{framework => plugins}/rewrite/var.go          |   0
 .../templates/method_inserts.tmpl                  |   0
 .../templates/method_intercept_after.tmpl          |   0
 .../templates/method_intercept_before.tmpl         |   0
 tools/go-agent/instrument/reporter/instrument.go   | 109 +++++++++++++
 tools/go-agent/tools/copy.go                       |  73 +++++++++
 34 files changed, 933 insertions(+), 65 deletions(-)

diff --git a/agent/core/compile.go b/agent/core/compile.go
index 9cbc9e3..599458c 100644
--- a/agent/core/compile.go
+++ b/agent/core/compile.go
@@ -21,9 +21,13 @@ import (
 	//go:nolint
 	_ "encoding/base64"
 	_ "fmt"
+	_ "log"
 	_ "math"
 	_ "math/rand"
+	_ "net"
+	_ "os"
 	_ "reflect"
+	_ "runtime"
 	_ "strconv"
 	_ "strings"
 	_ "sync"
@@ -33,6 +37,7 @@ import (
 	//go:nolint
 	_ "github.com/apache/skywalking-go/agent/core/operator"
 	_ "github.com/apache/skywalking-go/agent/core/tracing"
+	_ "github.com/apache/skywalking-go/log"
 	_ "github.com/apache/skywalking-go/reporter"
 
 	//go:nolint
diff --git a/plugins/core/operator/logger.go b/plugins/core/operator/logger.go
index 3534b1e..1945cee 100644
--- a/plugins/core/operator/logger.go
+++ b/plugins/core/operator/logger.go
@@ -17,8 +17,12 @@
 
 package operator
 
+// LogOperator should be same with the log.Logger from the API of the library
 type LogOperator interface {
+	Info(args ...interface{})
 	Infof(format string, args ...interface{})
+	Warn(args ...interface{})
 	Warnf(format string, args ...interface{})
+	Error(args ...interface{})
 	Errorf(format string, args ...interface{})
 }
diff --git a/plugins/core/reporter/grpc_opts_enhance.go b/plugins/core/reporter/grpc_opts_enhance.go
new file mode 100644
index 0000000..4338b21
--- /dev/null
+++ b/plugins/core/reporter/grpc_opts_enhance.go
@@ -0,0 +1,64 @@
+// 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 reporter
+
+import (
+	"time"
+
+	"google.golang.org/grpc/credentials"
+	"google.golang.org/grpc/metadata"
+
+	agentv3 "skywalking.apache.org/repo/goapi/collect/language/agent/v3"
+)
+
+var authKey = "Authentication"
+
+// WithCheckInterval setup service and endpoint registry check interval
+func WithCheckInterval(interval time.Duration) GRPCReporterOption {
+	return func(r *gRPCReporter) {
+		r.checkInterval = interval
+	}
+}
+
+// WithMaxSendQueueSize setup send span queue buffer length
+func WithMaxSendQueueSize(maxSendQueueSize int) GRPCReporterOption {
+	return func(r *gRPCReporter) {
+		r.sendCh = make(chan *agentv3.SegmentObject, maxSendQueueSize)
+	}
+}
+
+// WithTransportCredentials setup transport layer security
+func WithTransportCredentials(creds credentials.TransportCredentials) GRPCReporterOption {
+	return func(r *gRPCReporter) {
+		r.creds = creds
+	}
+}
+
+// WithAuthentication used Authentication for gRPC
+func WithAuthentication(auth string) GRPCReporterOption {
+	return func(r *gRPCReporter) {
+		r.md = metadata.New(map[string]string{authKey: auth})
+	}
+}
+
+// WithCDS setup Configuration Discovery Service to dynamic config
+func WithCDS(interval time.Duration) GRPCReporterOption {
+	return func(r *gRPCReporter) {
+		r.cdsInterval = interval
+	}
+}
diff --git a/plugins/core/reporter/grpc_struct.go b/plugins/core/reporter/grpc_struct.go
new file mode 100644
index 0000000..294a638
--- /dev/null
+++ b/plugins/core/reporter/grpc_struct.go
@@ -0,0 +1,62 @@
+// 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 reporter
+
+import (
+	"time"
+
+	"google.golang.org/grpc"
+	"google.golang.org/grpc/credentials"
+	"google.golang.org/grpc/metadata"
+
+	configuration "skywalking.apache.org/repo/goapi/collect/agent/configuration/v3"
+	commonv3 "skywalking.apache.org/repo/goapi/collect/common/v3"
+	agentv3 "skywalking.apache.org/repo/goapi/collect/language/agent/v3"
+	managementv3 "skywalking.apache.org/repo/goapi/collect/management/v3"
+)
+
+//skywalking:nocopy
+
+// All struct are from the reporter package in the library, copy these files is works for compiler
+
+// nolint
+type Entity struct {
+	ServiceName         string
+	ServiceInstanceName string
+	Props               []*commonv3.KeyStringValuePair
+	Layer               string
+}
+
+// nolint
+type gRPCReporter struct {
+	entity           Entity
+	sendCh           chan *agentv3.SegmentObject
+	conn             *grpc.ClientConn
+	traceClient      agentv3.TraceSegmentReportServiceClient
+	managementClient managementv3.ManagementServiceClient
+	checkInterval    time.Duration
+	cdsInterval      time.Duration
+	cdsClient        configuration.ConfigurationDiscoveryServiceClient
+
+	md    metadata.MD
+	creds credentials.TransportCredentials
+}
+
+// GRPCReporterOption allows for functional options to adjust behavior
+// of a gRPC reporter to be created by NewGRPCReporter
+type GRPCReporterOption func(r *gRPCReporter)
diff --git a/plugins/core/test_base.go b/plugins/core/test_base.go
index 8561ede..bdadee4 100644
--- a/plugins/core/test_base.go
+++ b/plugins/core/test_base.go
@@ -66,7 +66,7 @@ func NewStoreReporter() *StoreReporter {
 	return &StoreReporter{}
 }
 
-func (r *StoreReporter) Boot(entity reporter.Entity, cdsWatchers []reporter.AgentConfigChangeWatcher) {
+func (r *StoreReporter) Boot(entity *reporter.Entity, cdsWatchers []reporter.AgentConfigChangeWatcher) {
 }
 
 func (r *StoreReporter) Send(spans []reporter.ReportedSpan) {
diff --git a/plugins/core/tool.go b/plugins/core/tool.go
index 1db067d..a3b5bc3 100644
--- a/plugins/core/tool.go
+++ b/plugins/core/tool.go
@@ -18,10 +18,16 @@
 package core
 
 import (
+	"net"
+	"os"
+	"runtime"
+	"strconv"
 	"strings"
 	"time"
 
 	"github.com/google/uuid"
+
+	commonv3 "skywalking.apache.org/repo/goapi/collect/common/v3"
 )
 
 // Millisecond converts time to unix millisecond
@@ -42,3 +48,90 @@ func UUID() (string, error) {
 func GenerateGlobalID() (globalID string, err error) {
 	return UUID()
 }
+
+func ProcessNo() string {
+	if os.Getpid() > 0 {
+		return strconv.Itoa(os.Getpid())
+	}
+	return ""
+}
+
+func HostName() string {
+	if hs, err := os.Hostname(); err == nil {
+		return hs
+	}
+	return "unknown"
+}
+
+func OSName() string {
+	return runtime.GOOS
+}
+
+func AllIPV4() (ipv4s []string) {
+	adders, err := net.InterfaceAddrs()
+	if err != nil {
+		return
+	}
+
+	for _, addr := range adders {
+		if ipNet, ok := addr.(*net.IPNet); ok && !ipNet.IP.IsLoopback() {
+			if ipNet.IP.To4() != nil {
+				ipv4 := ipNet.IP.String()
+				if ipv4 == "127.0.0.1" || ipv4 == "localhost" {
+					continue
+				}
+				ipv4s = append(ipv4s, ipv4)
+			}
+		}
+	}
+	return
+}
+
+func IPV4() string {
+	ipv4s := AllIPV4()
+	if len(ipv4s) > 0 {
+		return ipv4s[0]
+	}
+	return "no-hostname"
+}
+
+func buildOSInfo() (props []*commonv3.KeyStringValuePair) {
+	processNo := ProcessNo()
+	if processNo != "" {
+		kv := &commonv3.KeyStringValuePair{
+			Key:   "Process No.",
+			Value: processNo,
+		}
+		props = append(props, kv)
+	}
+
+	hostname := &commonv3.KeyStringValuePair{
+		Key:   "hostname",
+		Value: HostName(),
+	}
+	props = append(props, hostname)
+
+	language := &commonv3.KeyStringValuePair{
+		Key:   "language",
+		Value: "go",
+	}
+	props = append(props, language)
+
+	osName := &commonv3.KeyStringValuePair{
+		Key:   "OS Name",
+		Value: OSName(),
+	}
+	props = append(props, osName)
+
+	ipv4s := AllIPV4()
+	if len(ipv4s) > 0 {
+		for _, ipv4 := range ipv4s {
+			kv := &commonv3.KeyStringValuePair{
+				Key:   "ipv4",
+				Value: ipv4,
+			}
+			props = append(props, kv)
+		}
+	}
+	return props
+}
diff --git a/plugins/core/tracer.go b/plugins/core/tracer.go
index 3331a85..f249135 100644
--- a/plugins/core/tracer.go
+++ b/plugins/core/tracer.go
@@ -18,10 +18,19 @@
 package core
 
 import (
+	"fmt"
+	defLog "log"
+	"os"
+	"reflect"
+
+	"github.com/apache/skywalking-go/log"
 	"github.com/apache/skywalking-go/plugins/core/operator"
 	"github.com/apache/skywalking-go/reporter"
 )
 
+// nolint
+var defaultLogPrefix = "skywalking-go "
+
 type CorrelationConfig struct {
 	MaxKeyCount  int
 	MaxValueSize int
@@ -34,11 +43,143 @@ type Tracer struct {
 	// 0 not init 1 init
 	initFlag int32
 	Sampler  Sampler
-	Log      operator.LogOperator
+	Log      *LogWrapper
 	// correlation *CorrelationConfig	// temporarily disable, because haven't been implemented yet
 	cdsWatchers []reporter.AgentConfigChangeWatcher
 }
 
+func (t *Tracer) Init(entity *reporter.Entity, rep reporter.Reporter, samp Sampler, logger log.Logger) error {
+	t.Service = entity.ServiceName
+	t.Instance = entity.ServiceInstanceName
+	t.Reporter = rep
+	t.Sampler = samp
+	if logger != nil && !reflect.ValueOf(logger).IsZero() {
+		t.Log.ChangeLogger(logger)
+	}
+	t.Reporter.Boot(entity, t.cdsWatchers)
+	t.initFlag = 1
+	return nil
+}
+
+func NewEntity(service, instanceEnvName, layer string) *reporter.Entity {
+	instanceName := os.Getenv(instanceEnvName)
+	if instanceName == "" {
+		id, err := UUID()
+		if err != nil {
+			panic(fmt.Sprintf("generate UUID failure: %v", err))
+		}
+		instanceName = id + "@" + IPV4()
+	}
+	propResult := buildOSInfo()
+	return &reporter.Entity{
+		ServiceName:         service,
+		ServiceInstanceName: instanceName,
+		Props:               propResult,
+		Layer:               layer,
+	}
+}
+
+// create tracer when init the agent core
+// nolint
+func newTracer() *Tracer {
+	return &Tracer{
+		initFlag:    0,
+		Reporter:    &emptyReporter{},
+		Sampler:     NewConstSampler(false),
+		Log:         &LogWrapper{newDefaultLogger()},
+		cdsWatchers: make([]reporter.AgentConfigChangeWatcher, 0),
+	}
+}
+
 func (t *Tracer) InitSuccess() bool {
 	return t.initFlag == 1
 }
+
+// nolint
+type emptyReporter struct{}
+
+// nolint
+func (e *emptyReporter) Boot(entity *reporter.Entity, cdsWatchers []reporter.AgentConfigChangeWatcher) {
+}
+
+// nolint
+func (e *emptyReporter) Send(spans []reporter.ReportedSpan) {
+}
+
+// nolint
+func (e *emptyReporter) Close() {
+}
+
+type LogWrapper struct {
+	Logger operator.LogOperator
+}
+
+func (l *LogWrapper) ChangeLogger(logger operator.LogOperator) {
+	l.Logger = logger
+}
+
+func (l *LogWrapper) Info(args ...interface{}) {
+	l.Logger.Info(args...)
+}
+
+func (l *LogWrapper) Infof(format string, args ...interface{}) {
+	l.Logger.Infof(format, args...)
+}
+
+func (l *LogWrapper) Warn(args ...interface{}) {
+	l.Logger.Warn(args...)
+}
+
+func (l *LogWrapper) Warnf(format string, args ...interface{}) {
+	l.Logger.Warnf(format, args...)
+}
+
+func (l *LogWrapper) Error(args ...interface{}) {
+	l.Logger.Error(args...)
+}
+
+func (l *LogWrapper) Errorf(format string, args ...interface{}) {
+	l.Logger.Errorf(format, args...)
+}
+
+// nolint
+type defaultLogger struct {
+	log *defLog.Logger
+}
+
+// nolint
+func newDefaultLogger() *defaultLogger {
+	return &defaultLogger{
+		log: defLog.New(os.Stderr, defaultLogPrefix, defLog.LstdFlags),
+	}
+}
+
+// nolint
+func (d *defaultLogger) Info(args ...interface{}) {
+	d.log.Print(args...)
+}
+
+// nolint
+func (d *defaultLogger) Infof(format string, args ...interface{}) {
+	d.log.Printf(format, args...)
+}
+
+// nolint
+func (d *defaultLogger) Warn(args ...interface{}) {
+	d.log.Print(args...)
+}
+
+// nolint
+func (d *defaultLogger) Warnf(format string, args ...interface{}) {
+	d.log.Printf(format, args...)
+}
+
+// nolint
+func (d *defaultLogger) Error(args ...interface{}) {
+	d.log.Print(args...)
+}
+
+// nolint
+func (d *defaultLogger) Errorf(format string, args ...interface{}) {
+	d.log.Printf(format, args...)
+}
diff --git a/plugins/core/tracing.go b/plugins/core/tracing.go
index 1f4c383..5ae1fe6 100644
--- a/plugins/core/tracing.go
+++ b/plugins/core/tracing.go
@@ -41,7 +41,7 @@ func (t *Tracer) Logger() interface{} {
 func (t *Tracer) CreateEntrySpan(operationName string, extractor interface{}, opts ...interface{}) (s interface{}, err error) {
 	ctx, tracingSpan, noop := t.createNoop()
 	if noop {
-		return s, nil
+		return tracingSpan, nil
 	}
 	defer func() {
 		saveSpanToActiveIfNotError(ctx, s, err)
diff --git a/reporter/grpc.go b/reporter/grpc.go
index 63eb2b5..2d3c782 100644
--- a/reporter/grpc.go
+++ b/reporter/grpc.go
@@ -77,7 +77,7 @@ func NewGRPCReporter(logger log.Logger, serverAddr string, opts ...GRPCReporterO
 }
 
 type gRPCReporter struct {
-	entity           Entity
+	entity           *Entity
 	logger           log.Logger
 	sendCh           chan *agentv3.SegmentObject
 	conn             *grpc.ClientConn
@@ -95,7 +95,7 @@ type gRPCReporter struct {
 	bootFlag bool
 }
 
-func (r *gRPCReporter) Boot(entity Entity, cdsWatchers []AgentConfigChangeWatcher) {
+func (r *gRPCReporter) Boot(entity *Entity, cdsWatchers []AgentConfigChangeWatcher) {
 	r.entity = entity
 	r.initSendPipeline()
 	r.check()
@@ -114,7 +114,7 @@ func (r *gRPCReporter) Send(spans []ReportedSpan) {
 		TraceId:         rootCtx.GetTraceID(),
 		TraceSegmentId:  rootCtx.GetSegmentID(),
 		Spans:           make([]*agentv3.SpanObject, spanSize),
-		Service:         r.entity.ServiceInstanceName,
+		Service:         r.entity.ServiceName,
 		ServiceInstance: r.entity.ServiceInstanceName,
 	}
 	for i, s := range spans {
diff --git a/plugins/core/operator/logger.go b/reporter/imports.go
similarity index 82%
copy from plugins/core/operator/logger.go
copy to reporter/imports.go
index 3534b1e..87c2170 100644
--- a/plugins/core/operator/logger.go
+++ b/reporter/imports.go
@@ -15,10 +15,11 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package operator
+package reporter
 
-type LogOperator interface {
-	Infof(format string, args ...interface{})
-	Warnf(format string, args ...interface{})
-	Errorf(format string, args ...interface{})
-}
+import (
+	// imports required packages for gRPC reporter
+	_ "fmt"
+	_ "os"
+	_ "strconv"
+)
diff --git a/reporter/reporter.go b/reporter/reporter.go
index 679777f..b9e2542 100644
--- a/reporter/reporter.go
+++ b/reporter/reporter.go
@@ -88,7 +88,7 @@ type Entity struct {
 }
 
 type Reporter interface {
-	Boot(entity Entity, cdsWatchers []AgentConfigChangeWatcher)
+	Boot(entity *Entity, cdsWatchers []AgentConfigChangeWatcher)
 	Send(spans []ReportedSpan)
 	Close()
 }
diff --git a/tools/go-agent/cmd/helper.go b/tools/go-agent/cmd/helper.go
index 751d163..f3cccff 100644
--- a/tools/go-agent/cmd/helper.go
+++ b/tools/go-agent/cmd/helper.go
@@ -23,8 +23,9 @@ import (
 )
 
 type EnhancementToolFlags struct {
-	Help  bool   `swflag:"-h"`
-	Debug string `swflag:"-debug"`
+	Help   bool   `swflag:"-h"`
+	Debug  string `swflag:"-debug"`
+	Config string `swflag:"-config"`
 }
 
 func PrintUsageWithExit() {
diff --git a/tools/go-agent/cmd/main.go b/tools/go-agent/cmd/main.go
index 85b1148..2c721af 100644
--- a/tools/go-agent/cmd/main.go
+++ b/tools/go-agent/cmd/main.go
@@ -23,6 +23,7 @@ import (
 	"os"
 	"os/exec"
 
+	"github.com/apache/skywalking-go/tools/go-agent/config"
 	"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"
@@ -59,6 +60,11 @@ func main() {
 		return
 	}
 
+	// loading config
+	if err1 := config.LoadConfig(toolFlags.Config); err1 != nil {
+		log.Fatalf("loading config file error: %s", err1)
+	}
+
 	// parse the args
 	compileOptions := &api.CompileOptions{}
 	if _, err = tools.ParseFlags(compileOptions, args); err != nil {
diff --git a/tools/go-agent/config/agent.default.yaml b/tools/go-agent/config/agent.default.yaml
new file mode 100644
index 0000000..502e64b
--- /dev/null
+++ b/tools/go-agent/config/agent.default.yaml
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+agent:
+  service_name: ${SW_AGENT_NAME:Your_ApplicationName}
+  instance_env_name: SW_AGENT_INSTANCE_NAME
+  layer: GENERAL
+  sampler: ${SW_AGENT_SAMPLE:1}
+
+reporter:
+  grpc:
+    backend_service: ${SW_AGENT_REPORTER_GRPC_BACKEND_SERVICE:127.0.0.1:11800}
+    max_send_queue: ${SW_AGENT_REPORTER_GRPC_MAX_SEND_QUEUE:5000}
diff --git a/tools/go-agent/config/loader.go b/tools/go-agent/config/loader.go
new file mode 100644
index 0000000..f0b5e19
--- /dev/null
+++ b/tools/go-agent/config/loader.go
@@ -0,0 +1,175 @@
+// 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 config
+
+import (
+	"embed"
+	"fmt"
+	"os"
+	"reflect"
+	"regexp"
+	"strings"
+
+	"gopkg.in/yaml.v3"
+)
+
+//go:embed agent.default.yaml
+var defaultAgentFS embed.FS
+
+var config *Config
+
+var EnvRegularRegex = regexp.MustCompile(`\${(?P<ENV>[_A-Z0-9]+):(?P<DEF>.*)}`)
+
+type Config struct {
+	Agent    Agent    `yaml:"agent"`
+	Reporter Reporter `yaml:"reporter"`
+}
+
+type Agent struct {
+	ServiceName     StringValue `yaml:"service_name"`
+	InstanceEnvName StringValue `yaml:"instance_env_name"`
+	Sampler         StringValue `yaml:"sampler"`
+	Layer           StringValue `yaml:"layer"`
+}
+
+type Reporter struct {
+	GRPC GRPCReporter `yaml:"grpc"`
+}
+
+type GRPCReporter struct {
+	BackendService StringValue `yaml:"backend_service"`
+	MaxSendQueue   StringValue `yaml:"max_send_queue"`
+}
+
+func LoadConfig(path string) error {
+	// load the default config
+	defaultConfig, err := defaultAgentFS.ReadFile("agent.default.yaml")
+	if err != nil {
+		return err
+	}
+	if err1 := yaml.Unmarshal(defaultConfig, &config); err1 != nil {
+		return err1
+	}
+
+	// if the path defined, then merge this two files
+	if path == "" {
+		return nil
+	}
+	definedContent, err := os.ReadFile(path)
+	if err != nil {
+		return err
+	}
+	userConfig := &Config{}
+	if err := yaml.Unmarshal(definedContent, userConfig); err != nil {
+		return err
+	}
+	config.overwriteFrom(userConfig)
+
+	return nil
+}
+
+func GetConfig() *Config {
+	return config
+}
+
+type StringValue struct {
+	EnvKey  string
+	Default string
+}
+
+func (s *StringValue) UnmarshalYAML(value *yaml.Node) error {
+	var val string
+	if e := value.Decode(&val); e != nil {
+		return e
+	}
+
+	groups := EnvRegularRegex.FindStringSubmatch(val)
+	if len(groups) == 0 {
+		s.Default = val
+		return nil
+	}
+
+	s.EnvKey = groups[1]
+	s.Default = groups[2]
+	return nil
+}
+
+func (s *StringValue) ToGoStringValue() string {
+	return strings.ReplaceAll(fmt.Sprintf(`func() string {
+	if "%s" == "" { return "%s"}
+	tmpValue := os.Getenv("%s")
+	if tmpValue == "" { return "%s"}
+	return tmpValue
+}()`, s.EnvKey, s.Default, s.EnvKey, s.Default), "\n", ";")
+}
+
+func (s *StringValue) ToGoIntValue(errorMessage string) string {
+	return strings.ReplaceAll(fmt.Sprintf(`func() int {
+	if "%s" == "" {return %s}
+	tmpValue := os.Getenv("%s")
+	if tmpValue == "" {return %s}
+	res, err := strconv.Atoi(tmpValue)
+	if err != nil { panic(fmt.Errorf("%s", err))}
+	return res
+}()`,
+		s.EnvKey, s.Default, s.EnvKey, s.Default, errorMessage), "\n", ";")
+}
+
+func (s *StringValue) ToGoFloatValue(errorMessage string) string {
+	return strings.ReplaceAll(fmt.Sprintf(`func() float64 {
+	if "%s" == "" {return %s}
+	tmpValue := os.Getenv("%s")
+	if tmpValue == "" {return %s}
+	res, err := strconv.ParseFloat(tmpValue, 64)
+	if err != nil { panic(fmt.Errorf("%s", err))}
+	return res
+}()`,
+		s.EnvKey, s.Default, s.EnvKey, s.Default, errorMessage), "\n", ";")
+}
+
+func (s *StringValue) overwriteFrom(other StringValue) {
+	if other.EnvKey != "" {
+		s.EnvKey = other.EnvKey
+	}
+	if other.Default != "" {
+		s.Default = other.Default
+	}
+}
+
+func (c *Config) overwriteFrom(other *Config) {
+	c1Value := reflect.ValueOf(&c).Elem()
+	c2Value := reflect.ValueOf(&other).Elem()
+	combineConfigFields(c1Value, c2Value)
+}
+
+func combineConfigFields(field1, field2 reflect.Value) {
+	if field1.Type() != field2.Type() {
+		panic("config are not the same")
+	}
+
+	if field1.Kind() == reflect.Struct {
+		if s, ok := field1.Addr().Interface().(StringValue); ok {
+			s2 := field2.Addr().Interface().(StringValue)
+			s.overwriteFrom(s2)
+		} else {
+			for i := 0; i < field1.NumField(); i++ {
+				combineConfigFields(field1.Field(i), field2.Field(i))
+			}
+		}
+	}
+}
diff --git a/tools/go-agent/go.mod b/tools/go-agent/go.mod
index 4413213..0ded49d 100644
--- a/tools/go-agent/go.mod
+++ b/tools/go-agent/go.mod
@@ -8,6 +8,7 @@ require (
 	github.com/dave/dst v0.27.2
 	github.com/sirupsen/logrus v1.9.0
 	golang.org/x/text v0.8.0
+	gopkg.in/yaml.v3 v3.0.1
 )
 
 require (
@@ -41,7 +42,6 @@ require (
 	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
 )
 
diff --git a/tools/go-agent/instrument/agentcore/instrument.go b/tools/go-agent/instrument/agentcore/instrument.go
index 7c589db..6cb4184 100644
--- a/tools/go-agent/instrument/agentcore/instrument.go
+++ b/tools/go-agent/instrument/agentcore/instrument.go
@@ -18,18 +18,19 @@
 package agentcore
 
 import (
-	"bytes"
+	"html"
 	"io/fs"
 	"path/filepath"
 	"strings"
 
 	"github.com/apache/skywalking-go/plugins/core"
+	"github.com/apache/skywalking-go/tools/go-agent/config"
 	"github.com/apache/skywalking-go/tools/go-agent/instrument/api"
+	"github.com/apache/skywalking-go/tools/go-agent/instrument/reporter"
 	"github.com/apache/skywalking-go/tools/go-agent/instrument/runtime"
 	"github.com/apache/skywalking-go/tools/go-agent/tools"
 
 	"github.com/dave/dst"
-	"github.com/dave/dst/decorator"
 	"github.com/dave/dst/dstutil"
 )
 
@@ -84,49 +85,18 @@ func (i *Instrument) WriteExtraFiles(dir string) ([]string, error) {
 	if sub == "" {
 		sub = "."
 	}
-	files, err := core.FS.ReadDir(sub)
-	if err != nil {
-		return nil, err
-	}
 
 	pkgUpdates := make(map[string]string)
 	for _, p := range CopiedSubPackages {
 		pkgUpdates[filepath.Join(EnhanceFromBasePackage, p)] = filepath.Join(EnhanceBasePackage, p)
 	}
-	for _, f := range files {
-		if !strings.HasSuffix(f.Name(), ".go") {
-			continue
-		}
-		if strings.HasSuffix(f.Name(), "_test.go") {
-			continue
-		}
-
-		readFile, err := fs.ReadFile(core.FS, filepath.Join(sub, f.Name()))
-		if err != nil {
-			return nil, err
-		}
-
-		// ignore nocopy files
-		if bytes.Contains(readFile, []byte("//skywalking:nocopy")) {
-			continue
-		}
-
-		parse, err := decorator.Parse(readFile)
-		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, debugInfo); err != nil {
-			return nil, err
-		}
-		results = append(results, copiedFilePath)
+	copiedFiles, err := tools.CopyGoFiles(core.FS, sub, dir, i.buildDSTDebugInfo, func(file *dst.File) {
+		tools.ChangePackageImportPath(file, pkgUpdates)
+	})
+	if err != nil {
+		return nil, err
 	}
+	results = append(results, copiedFiles...)
 
 	// write extra file to link the operator and TLS methods
 	if sub == "." {
@@ -135,6 +105,12 @@ func (i *Instrument) WriteExtraFiles(dir string) ([]string, error) {
 			return nil, err
 		}
 		results = append(results, file)
+
+		file1, err := i.writeTracerInitLink(dir)
+		if err != nil {
+			return nil, err
+		}
+		results = append(results, file1)
 	}
 
 	return results, nil
@@ -148,6 +124,37 @@ func (i *Instrument) buildDSTDebugInfo(entry fs.DirEntry) (*tools.DebugInfo, err
 	return tools.BuildDSTDebugInfo(debugPath, nil)
 }
 
+func (i *Instrument) writeTracerInitLink(dir string) (string, error) {
+	return tools.WriteFile(dir, "tracer_init.go", html.UnescapeString(tools.ExecuteTemplate(`package core
+
+import (
+	"github.com/apache/skywalking-go/reporter"
+	"fmt"
+	"os"
+	"strconv"
+)
+
+func (t *Tracer) InitTracer(extend map[string]interface{}) {
+	rep, err := reporter.{{.GRPCReporterFuncName}}(t.Log)
+	if err != nil {
+		t.Log.Errorf("cannot initialize the reporter: %v", err)
+		return
+	}
+	entity := NewEntity({{.Config.Agent.ServiceName.ToGoStringValue}}, {{.Config.Agent.InstanceEnvName.ToGoStringValue}}, 
+		{{.Config.Agent.Layer.ToGoStringValue}})
+	samp := NewDynamicSampler({{.Config.Agent.Sampler.ToGoFloatValue "loading the agent sampler error"}}, t)
+	if err := t.Init(entity, rep, samp, nil); err != nil {
+		t.Log.Errorf("cannot initialize the SkyWalking Tracer: %v", err)
+	}
+}`, struct {
+		GRPCReporterFuncName string
+		Config               *config.Config
+	}{
+		GRPCReporterFuncName: reporter.GRPCInitFuncName,
+		Config:               config.GetConfig(),
+	})))
+}
+
 func (i *Instrument) writeLinkerFile(dir string) (string, error) {
 	return tools.WriteFile(dir, "runtime_linker.go", tools.ExecuteTemplate(`package core
 
@@ -175,7 +182,7 @@ func init() {
 	if {{.SetGlobalOperatorLinkMethod}} != nil && {{.GetGlobalOperatorLinkMethod}} != nil {
 		SetGlobalOperator = {{.SetGlobalOperatorLinkMethod}}
 		GetGlobalOperator = {{.GetGlobalOperatorLinkMethod}}
-		SetGlobalOperator(&Tracer{initFlag: 1, Sampler: NewConstSampler(true)})
+		SetGlobalOperator(newTracer())	// setting the global tracer when init the agent core
 	}
 }
 `, struct {
diff --git a/tools/go-agent/instrument/entry/instrument.go b/tools/go-agent/instrument/entry/instrument.go
new file mode 100644
index 0000000..374a4a4
--- /dev/null
+++ b/tools/go-agent/instrument/entry/instrument.go
@@ -0,0 +1,94 @@
+// 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 entry
+
+import (
+	"github.com/apache/skywalking-go/tools/go-agent/config"
+	"github.com/apache/skywalking-go/tools/go-agent/instrument/api"
+	"github.com/apache/skywalking-go/tools/go-agent/instrument/plugins/rewrite"
+	"github.com/apache/skywalking-go/tools/go-agent/tools"
+
+	"github.com/dave/dst"
+	"github.com/dave/dst/dstutil"
+)
+
+type Instrument struct {
+	hasFound bool
+}
+
+func NewInstrument() *Instrument {
+	return &Instrument{}
+}
+
+func (i *Instrument) CouldHandle(opts *api.CompileOptions) bool {
+	return opts.Package == "main"
+}
+
+func (i *Instrument) FilterAndEdit(path string, cursor *dstutil.Cursor, allFiles []*dst.File) bool {
+	if i.hasFound {
+		return false
+	}
+	i.hasFound = true
+	return true
+}
+
+func (i *Instrument) AfterEnhanceFile(fromPath, newPath string) error {
+	return nil
+}
+
+func (i *Instrument) WriteExtraFiles(dir string) ([]string, error) {
+	file, err := tools.WriteFile(dir, "skywalking_init.go", tools.ExecuteTemplate(`package main
+
+import (
+	_ "unsafe"
+)
+
+//go:linkname {{.GetGlobalOperatorLinkMethod}} {{.GetGlobalOperatorLinkMethod}}
+var {{.GetGlobalOperatorLinkMethod}} func() interface{}
+
+type skywalkingTracerInitiator interface {
+	InitTracer(map[string]interface{})
+}
+
+func init() {
+	if {{.GetGlobalOperatorLinkMethod}} != nil {
+		op := {{.GetGlobalOperatorLinkMethod}}()
+		if op == nil {
+			return
+		}
+		tracer, ok := op.(skywalkingTracerInitiator)
+		if !ok {
+			return
+		}
+		tracer.InitTracer(nil)
+	}
+}
+`, struct {
+		GetGlobalOperatorLinkMethod string
+		Config                      *config.Config
+	}{
+		GetGlobalOperatorLinkMethod: rewrite.GlobalOperatorLinkGetMethodName,
+		Config:                      config.GetConfig(),
+	}))
+	if err != nil {
+		return nil, err
+	}
+	result := make([]string, 0)
+	result = append(result, file)
+	return result, nil
+}
diff --git a/tools/go-agent/instrument/instrument.go b/tools/go-agent/instrument/instrument.go
index 4d2b501..0c70d60 100644
--- a/tools/go-agent/instrument/instrument.go
+++ b/tools/go-agent/instrument/instrument.go
@@ -31,7 +31,9 @@ import (
 
 	"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/entry"
+	"github.com/apache/skywalking-go/tools/go-agent/instrument/plugins"
+	"github.com/apache/skywalking-go/tools/go-agent/instrument/reporter"
 	"github.com/apache/skywalking-go/tools/go-agent/instrument/runtime"
 	"github.com/apache/skywalking-go/tools/go-agent/tools"
 )
@@ -39,7 +41,9 @@ import (
 var instruments = []api.Instrument{
 	runtime.NewInstrument(),
 	agentcore.NewInstrument(),
-	framework.NewInstrument(),
+	reporter.NewGRPCInstrument(),
+	entry.NewInstrument(),
+	plugins.NewInstrument(),
 }
 
 func Execute(opts *api.CompileOptions, args []string) ([]string, error) {
diff --git a/tools/go-agent/instrument/framework/enhance_instance.go b/tools/go-agent/instrument/plugins/enhance_instance.go
similarity index 99%
rename from tools/go-agent/instrument/framework/enhance_instance.go
rename to tools/go-agent/instrument/plugins/enhance_instance.go
index 990618b..e3b6ab2 100644
--- a/tools/go-agent/instrument/framework/enhance_instance.go
+++ b/tools/go-agent/instrument/plugins/enhance_instance.go
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package framework
+package plugins
 
 import (
 	"fmt"
diff --git a/tools/go-agent/instrument/framework/enhance_method.go b/tools/go-agent/instrument/plugins/enhance_method.go
similarity index 98%
rename from tools/go-agent/instrument/framework/enhance_method.go
rename to tools/go-agent/instrument/plugins/enhance_method.go
index 64674ce..ab64320 100644
--- a/tools/go-agent/instrument/framework/enhance_method.go
+++ b/tools/go-agent/instrument/plugins/enhance_method.go
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package framework
+package plugins
 
 import (
 	"fmt"
@@ -25,7 +25,7 @@ import (
 
 	"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/instrument/plugins/rewrite"
 	"github.com/apache/skywalking-go/tools/go-agent/tools"
 
 	"github.com/dave/dst"
diff --git a/tools/go-agent/instrument/framework/instrument.go b/tools/go-agent/instrument/plugins/instrument.go
similarity index 99%
rename from tools/go-agent/instrument/framework/instrument.go
rename to tools/go-agent/instrument/plugins/instrument.go
index 55dedd5..de1ac90 100644
--- a/tools/go-agent/instrument/framework/instrument.go
+++ b/tools/go-agent/instrument/plugins/instrument.go
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package framework
+package plugins
 
 import (
 	"bytes"
@@ -29,7 +29,7 @@ import (
 	"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/instrument/plugins/rewrite"
 	"github.com/apache/skywalking-go/tools/go-agent/tools"
 
 	"github.com/dave/dst"
diff --git a/tools/go-agent/instrument/framework/register.go b/tools/go-agent/instrument/plugins/register.go
similarity index 95%
rename from tools/go-agent/instrument/framework/register.go
rename to tools/go-agent/instrument/plugins/register.go
index 0c0bcf1..6caf205 100644
--- a/tools/go-agent/instrument/framework/register.go
+++ b/tools/go-agent/instrument/plugins/register.go
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package framework
+package plugins
 
 import (
 	"github.com/apache/skywalking-go/plugins/core/instrument"
@@ -25,7 +25,7 @@ import (
 var instruments = make([]instrument.Instrument, 0)
 
 func init() {
-	// register the framework instrument
+	// register the plugins instrument
 	registerFramework(ginv2.NewInstrument())
 }
 
diff --git a/tools/go-agent/instrument/framework/rewrite/context.go b/tools/go-agent/instrument/plugins/rewrite/context.go
similarity index 100%
rename from tools/go-agent/instrument/framework/rewrite/context.go
rename to tools/go-agent/instrument/plugins/rewrite/context.go
diff --git a/tools/go-agent/instrument/framework/rewrite/func.go b/tools/go-agent/instrument/plugins/rewrite/func.go
similarity index 100%
rename from tools/go-agent/instrument/framework/rewrite/func.go
rename to tools/go-agent/instrument/plugins/rewrite/func.go
diff --git a/tools/go-agent/instrument/framework/rewrite/import.go b/tools/go-agent/instrument/plugins/rewrite/import.go
similarity index 100%
rename from tools/go-agent/instrument/framework/rewrite/import.go
rename to tools/go-agent/instrument/plugins/rewrite/import.go
diff --git a/tools/go-agent/instrument/framework/rewrite/rewrite.go b/tools/go-agent/instrument/plugins/rewrite/rewrite.go
similarity index 100%
rename from tools/go-agent/instrument/framework/rewrite/rewrite.go
rename to tools/go-agent/instrument/plugins/rewrite/rewrite.go
diff --git a/tools/go-agent/instrument/framework/rewrite/type.go b/tools/go-agent/instrument/plugins/rewrite/type.go
similarity index 100%
rename from tools/go-agent/instrument/framework/rewrite/type.go
rename to tools/go-agent/instrument/plugins/rewrite/type.go
diff --git a/tools/go-agent/instrument/framework/rewrite/var.go b/tools/go-agent/instrument/plugins/rewrite/var.go
similarity index 100%
rename from tools/go-agent/instrument/framework/rewrite/var.go
rename to tools/go-agent/instrument/plugins/rewrite/var.go
diff --git a/tools/go-agent/instrument/framework/templates/method_inserts.tmpl b/tools/go-agent/instrument/plugins/templates/method_inserts.tmpl
similarity index 100%
rename from tools/go-agent/instrument/framework/templates/method_inserts.tmpl
rename to tools/go-agent/instrument/plugins/templates/method_inserts.tmpl
diff --git a/tools/go-agent/instrument/framework/templates/method_intercept_after.tmpl b/tools/go-agent/instrument/plugins/templates/method_intercept_after.tmpl
similarity index 100%
rename from tools/go-agent/instrument/framework/templates/method_intercept_after.tmpl
rename to tools/go-agent/instrument/plugins/templates/method_intercept_after.tmpl
diff --git a/tools/go-agent/instrument/framework/templates/method_intercept_before.tmpl b/tools/go-agent/instrument/plugins/templates/method_intercept_before.tmpl
similarity index 100%
rename from tools/go-agent/instrument/framework/templates/method_intercept_before.tmpl
rename to tools/go-agent/instrument/plugins/templates/method_intercept_before.tmpl
diff --git a/tools/go-agent/instrument/reporter/instrument.go b/tools/go-agent/instrument/reporter/instrument.go
new file mode 100644
index 0000000..c05caf8
--- /dev/null
+++ b/tools/go-agent/instrument/reporter/instrument.go
@@ -0,0 +1,109 @@
+// 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 reporter
+
+import (
+	"html"
+	"io/fs"
+	"path/filepath"
+
+	"github.com/apache/skywalking-go/plugins/core"
+	"github.com/apache/skywalking-go/tools/go-agent/config"
+	"github.com/apache/skywalking-go/tools/go-agent/instrument/api"
+	"github.com/apache/skywalking-go/tools/go-agent/tools"
+
+	"github.com/dave/dst"
+	"github.com/dave/dst/dstutil"
+)
+
+var GRPCInitFuncName = "GRPCReporterInit"
+
+type GRPCInstrument struct {
+	hasToEnhance bool
+	compileOpts  *api.CompileOptions
+}
+
+func NewGRPCInstrument() *GRPCInstrument {
+	return &GRPCInstrument{}
+}
+
+func (i *GRPCInstrument) CouldHandle(opts *api.CompileOptions) bool {
+	i.compileOpts = opts
+	return opts.Package == "github.com/apache/skywalking-go/reporter"
+}
+
+func (i *GRPCInstrument) FilterAndEdit(path string, cursor *dstutil.Cursor, allFiles []*dst.File) bool {
+	if i.hasToEnhance {
+		return false
+	}
+	i.hasToEnhance = true
+	return true
+}
+
+func (i *GRPCInstrument) AfterEnhanceFile(fromPath, newPath string) error {
+	return nil
+}
+
+func (i *GRPCInstrument) WriteExtraFiles(dir string) ([]string, error) {
+	// copy gRPC reporter enhance files
+	results := make([]string, 0)
+	copiedFiles, err := tools.CopyGoFiles(core.FS, "reporter", dir, func(entry fs.DirEntry) (*tools.DebugInfo, error) {
+		if i.compileOpts.DebugDir == "" {
+			return nil, nil
+		}
+		debugPath := filepath.Join(i.compileOpts.DebugDir, "reporter", entry.Name())
+		return tools.BuildDSTDebugInfo(debugPath, nil)
+	}, func(file *dst.File) {
+	})
+	if err != nil {
+		return nil, err
+	}
+	results = append(results, copiedFiles...)
+
+	// generate the file for export the reporter
+	file, err := i.generateReporterInitFile(dir)
+	if err != nil {
+		return nil, err
+	}
+	results = append(results, file)
+
+	return results, nil
+}
+
+func (i *GRPCInstrument) generateReporterInitFile(dir string) (string, error) {
+	return tools.WriteFile(dir, "grpc_init.go", html.UnescapeString(tools.ExecuteTemplate(`package reporter
+
+import (
+	"github.com/apache/skywalking-go/log"
+	"fmt"
+	"strconv"
+	"os"
+)
+
+func {{.InitFuncName}}(logger log.Logger) (Reporter, error) {
+	return NewGRPCReporter(logger, {{.Config.Reporter.GRPC.BackendService.ToGoStringValue}},
+		WithMaxSendQueueSize({{.Config.Reporter.GRPC.MaxSendQueue.ToGoIntValue "the GRPC reporter max queue size must be number"}}))
+}
+`, struct {
+		InitFuncName string
+		Config       *config.Config
+	}{
+		InitFuncName: GRPCInitFuncName,
+		Config:       config.GetConfig(),
+	})))
+}
diff --git a/tools/go-agent/tools/copy.go b/tools/go-agent/tools/copy.go
new file mode 100644
index 0000000..0ceeb1a
--- /dev/null
+++ b/tools/go-agent/tools/copy.go
@@ -0,0 +1,73 @@
+// 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 tools
+
+import (
+	"bytes"
+	"io/fs"
+	"path/filepath"
+	"strings"
+
+	"github.com/dave/dst"
+	"github.com/dave/dst/decorator"
+)
+
+func CopyGoFiles(fromFS fs.ReadDirFS, fromDir, targetDir string,
+	debugInfoBuilder func(entry fs.DirEntry) (*DebugInfo, error),
+	peek func(file *dst.File)) ([]string, error) {
+	results := make([]string, 0)
+	files, err := fromFS.ReadDir(fromDir)
+	if err != nil {
+		return nil, err
+	}
+	for _, f := range files {
+		if !strings.HasSuffix(f.Name(), ".go") {
+			continue
+		}
+		if strings.HasSuffix(f.Name(), "_test.go") {
+			continue
+		}
+
+		readFile, err := fs.ReadFile(fromFS, filepath.Join(fromDir, f.Name()))
+		if err != nil {
+			return nil, err
+		}
+
+		// ignore nocopy files
+		if bytes.Contains(readFile, []byte("//skywalking:nocopy")) {
+			continue
+		}
+
+		parse, err := decorator.Parse(readFile)
+		if err != nil {
+			return nil, err
+		}
+		debugInfo, err := debugInfoBuilder(f)
+		if err != nil {
+			return nil, err
+		}
+
+		peek(parse)
+		copiedFilePath := filepath.Join(targetDir, f.Name())
+		if err := WriteDSTFile(copiedFilePath, parse, debugInfo); err != nil {
+			return nil, err
+		}
+		results = append(results, copiedFilePath)
+	}
+	return results, nil
+}