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 b75bbbd  Support native SQL framework plugin with MySQL driver (#65)
b75bbbd is described below

commit b75bbbd812bcb55c2a041b4d0afe167453babaef
Author: mrproliu <[email protected]>
AuthorDate: Fri Jun 16 12:25:04 2023 +0000

    Support native SQL framework plugin with MySQL driver (#65)
---
 .github/workflows/plugin-tests.yaml                |   1 +
 CHANGES.md                                         |   1 +
 docs/en/agent/plugin-configurations.md             |   1 +
 docs/en/agent/support-plugins.md                   |   4 +-
 go.work                                            |   2 +
 plugins/core/context.go                            |   4 +
 plugins/core/instrument/method.go                  |  52 ++++-
 .../tools/types.go => plugins/sql/entry/config.go  |  20 +-
 .../types.go => plugins/sql/entry/conn_begin_tx.go |  24 +-
 .../types.go => plugins/sql/entry/conn_exec.go     |  24 +-
 .../types.go => plugins/sql/entry/conn_ping.go     |  24 +-
 .../types.go => plugins/sql/entry/conn_prepare.go  |  24 +-
 .../types.go => plugins/sql/entry/conn_query.go    |  24 +-
 .../types.go => plugins/sql/entry/conn_raw.go      |  24 +-
 .../types.go => plugins/sql/entry/db_begin_tx.go   |  24 +-
 plugins/sql/entry/db_conn.go                       |  63 ++++++
 .../tools/types.go => plugins/sql/entry/db_exec.go |  24 +-
 .../tools/types.go => plugins/sql/entry/db_ping.go |  24 +-
 .../types.go => plugins/sql/entry/db_prepare.go    |  24 +-
 .../types.go => plugins/sql/entry/db_query.go      |  24 +-
 plugins/sql/entry/general.go                       | 204 +++++++++++++++++
 plugins/sql/entry/instance_open.go                 |  58 +++++
 plugins/sql/entry/instrument.go                    | 230 +++++++++++++++++++
 plugins/sql/entry/span.go                          |  59 +++++
 plugins/sql/entry/stmt_exec.go                     |  50 +++++
 plugins/sql/entry/stmt_query.go                    |  50 +++++
 .../types.go => plugins/sql/entry/tx_commit.go     |  36 ++-
 plugins/sql/entry/tx_exec.go                       |  51 +++++
 .../types.go => plugins/sql/entry/tx_prepare.go    |  24 +-
 plugins/sql/entry/tx_query.go                      |  51 +++++
 .../types.go => plugins/sql/entry/tx_rollback.go   |  36 ++-
 .../tools/types.go => plugins/sql/entry/tx_stmt.go |  29 +--
 plugins/sql/go.mod                                 |   5 +
 plugins/sql/mysql/instrument.go                    |  67 ++++++
 .../sql/mysql/parse_interceptor.go                 |  44 +++-
 test/plugins/scenarios/gorm/config/excepted.yml    | 106 +++++++--
 test/plugins/scenarios/mongo/plugin.yml            |   1 -
 .../{mongo/plugin.yml => mysql/bin/startup.sh}     |  39 +---
 test/plugins/scenarios/mysql/config/excepted.yml   | 250 +++++++++++++++++++++
 test/plugins/scenarios/mysql/go.mod                |   5 +
 test/plugins/scenarios/mysql/go.sum                |   2 +
 test/plugins/scenarios/mysql/main.go               | 161 +++++++++++++
 test/plugins/scenarios/{mongo => mysql}/plugin.yml |  42 ++--
 tools/go-agent/config/agent.default.yaml           |   5 +-
 tools/go-agent/instrument/instrument.go            |   7 +
 tools/go-agent/instrument/plugins/register.go      |   6 +
 tools/go-agent/tools/enhancement.go                |  23 ++
 tools/go-agent/tools/types.go                      |   2 +-
 48 files changed, 1756 insertions(+), 299 deletions(-)

diff --git a/.github/workflows/plugin-tests.yaml 
b/.github/workflows/plugin-tests.yaml
index 71f9895..96f6496 100644
--- a/.github/workflows/plugin-tests.yaml
+++ b/.github/workflows/plugin-tests.yaml
@@ -78,6 +78,7 @@ jobs:
           - kratosv2
           - microv4
           - mongo
+          - mysql
           - plugin_exclusion
     steps:
       - uses: actions/checkout@v2
diff --git a/CHANGES.md b/CHANGES.md
index 5ff3eab..e02b0fc 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -13,6 +13,7 @@ Release Notes.
 * Support [go-redis](https://github.com/redis/go-redis) v9 redis client 
framework.
 * Support collecting [Native HTTP](https://pkg.go.dev/net/http) URI parameter 
on server side.
 * Support [Mongo](https://github.com/mongodb/mongo-go-driver) database client 
framework.
+* Support [Native SQL](https://pkg.go.dev/net/http) database client framework 
with [MySQL Driver](github.com/go-sql-driver/mysql).
 
 #### Documentation
 
diff --git a/docs/en/agent/plugin-configurations.md 
b/docs/en/agent/plugin-configurations.md
index 5eabfb2..088dd89 100644
--- a/docs/en/agent/plugin-configurations.md
+++ b/docs/en/agent/plugin-configurations.md
@@ -4,3 +4,4 @@
 
|--------------------------------|-------------------------------------------------------|---------------|----------------------------------------------------------------|
 | http.server_collect_parameters | 
SW_AGENT_PLUGIN_CONFIG_HTTP_SERVER_COLLECT_PARAMETERS | false         | Collect 
the parameters of the HTTP request on the server side. |
 | mongo.collect_statement        | 
SW_AGENT_PLUGIN_CONFIG_MONGO_COLLECT_STATEMENT        | false         | Collect 
the statement of the MongoDB request.                  |
+| sql.collect_parameter          | 
SW_AGENT_PLUGIN_CONFIG_SQL_COLLECT_PARAMETER          | false         | Collect 
the parameter of the SQL request.                      |
diff --git a/docs/en/agent/support-plugins.md b/docs/en/agent/support-plugins.md
index 174efb9..8ad0cab 100644
--- a/docs/en/agent/support-plugins.md
+++ b/docs/en/agent/support-plugins.md
@@ -13,6 +13,8 @@
 * Database Client
   * `gorm`: [GORM](https://github.com/go-gorm/gorm) tested v1.22.0 to v1.25.1.
     * [MySQL Driver](https://github.com/go-gorm/mysql)
-  * `mongo`: [Mongo](https://github.com/mongodb/mongo-go-driver) tested 
v1.11.0 to v1.11.7.
+  * `mongo`: [Mongo](https://github.com/mongodb/mongo-go-driver) tested 
v1.11.1 to v1.11.7.
+  * `sql`: [Native SQL](https://pkg.go.dev/database/sql) tested go v1.17 to go 
v1.20.
+    * [MySQL Driver](https://github.com/go-sql-driver/mysql) tested v1.4.0 to 
v1.7.1.
 * Cache Client
   * `go-redisv9`: [go-redis](https://github.com/redis/go-redis) tested v9.0.3 
to v9.0.5.
\ No newline at end of file
diff --git a/go.work b/go.work
index fcb85b4..30fefe5 100644
--- a/go.work
+++ b/go.work
@@ -14,6 +14,7 @@ use (
        ./plugins/kratosv2
        ./plugins/microv4
        ./plugins/mongo
+       ./plugins/sql
 
        ./test/benchmark-codebase/consumer
        ./test/benchmark-codebase/provider
@@ -30,6 +31,7 @@ use (
        ./test/plugins/scenarios/kratosv2
        ./test/plugins/scenarios/microv4
        ./test/plugins/scenarios/mongo
+       ./test/plugins/scenarios/mysql
 
        ./test/plugins/scenarios/plugin_exclusion
 
diff --git a/plugins/core/context.go b/plugins/core/context.go
index 03ec73b..d1dae7c 100644
--- a/plugins/core/context.go
+++ b/plugins/core/context.go
@@ -89,5 +89,9 @@ func (r *RuntimeContext) Get(key string) interface{} {
 }
 
 func (r *RuntimeContext) Set(key string, value interface{}) {
+       if value == nil {
+               delete(r.data, key)
+               return
+       }
        r.data[key] = value
 }
diff --git a/plugins/core/instrument/method.go 
b/plugins/core/instrument/method.go
index ea1734b..d726057 100644
--- a/plugins/core/instrument/method.go
+++ b/plugins/core/instrument/method.go
@@ -22,34 +22,28 @@ import "github.com/dave/dst"
 // WithArgsCount filter methods with specific count of arguments.
 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)
+               return fieldListParameterCount(method.Type.Params) == argsCount
        }
 }
 
 // WithResultCount filter methods with specific count of results.
 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)
+               return fieldListParameterCount(decl.Type.Results) == resultCount
        }
 }
 
 // WithArgType filter methods with specific type of the index of the argument.
 func WithArgType(argIndex int, dataType string) MethodFilterOption {
        return func(decl *dst.FuncDecl, files []*dst.File) bool {
-               if decl.Type.Params == nil || len(decl.Type.Params.List) <= 
argIndex {
-                       return false
-               }
-               return verifyTypeName(decl.Type.Params.List[argIndex].Type, 
dataType)
+               return verifyTypeSameInFieldList(decl.Type.Params, argIndex, 
dataType)
        }
 }
 
 // WithResultType filter methods with specific type of the index of the result.
 func WithResultType(argIndex int, dataType string) MethodFilterOption {
        return func(decl *dst.FuncDecl, files []*dst.File) bool {
-               if decl.Type.Results == nil || len(decl.Type.Results.List) <= 
argIndex {
-                       return false
-               }
-               return verifyTypeName(decl.Type.Results.List[argIndex].Type, 
dataType)
+               return verifyTypeSameInFieldList(decl.Type.Results, argIndex, 
dataType)
        }
 }
 
@@ -69,3 +63,41 @@ func WithReceiverType(dataType string) MethodFilterOption {
                return verifyTypeName(decl.Recv.List[0].Type, dataType)
        }
 }
+
+func fieldListParameterCount(fieldList *dst.FieldList) int {
+       if fieldList == nil || len(fieldList.List) == 0 {
+               return 0
+       }
+       res := 0
+       for _, f := range fieldList.List {
+               if len(f.Names) == 0 {
+                       res++
+                       continue
+               }
+               res += len(f.Names)
+       }
+       return res
+}
+
+func verifyTypeSameInFieldList(fieldList *dst.FieldList, inx int, typeStr 
string) bool {
+       if inx >= fieldListParameterCount(fieldList) {
+               return false
+       }
+       realInx := 0
+       for _, f := range fieldList.List {
+               if len(f.Names) == 0 {
+                       if realInx == inx {
+                               return verifyTypeName(f.Type, typeStr)
+                       }
+                       realInx++
+                       continue
+               }
+               for i := 0; i < len(f.Names); i++ {
+                       if realInx == inx {
+                               return verifyTypeName(f.Type, typeStr)
+                       }
+                       realInx++
+               }
+       }
+       return false
+}
diff --git a/tools/go-agent/tools/types.go b/plugins/sql/entry/config.go
similarity index 64%
copy from tools/go-agent/tools/types.go
copy to plugins/sql/entry/config.go
index aabda3b..5fd1e90 100644
--- a/tools/go-agent/tools/types.go
+++ b/plugins/sql/entry/config.go
@@ -15,21 +15,9 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package tools
+package entry
 
-var basicDataTypes = make(map[string]bool)
-
-func init() {
-       types := []string{
-               "bool", "int8", "int16", "int32", "int64", "uint8", "uint16", 
"uint32", "uint64", "int", "uint", "uintptr",
-               "float32", "float64", "complex64", "complex128", "string", 
"error", "interface{}", "_", "byte",
-       }
-       for _, tp := range types {
-               basicDataTypes[tp] = true
-       }
-}
-
-// nolint
-func IsBasicDataType(name string) bool {
-       return basicDataTypes[name]
+//skywalking:config
+var config struct {
+       CollectParameter bool `config:"collect_parameter"`
 }
diff --git a/tools/go-agent/tools/types.go b/plugins/sql/entry/conn_begin_tx.go
similarity index 65%
copy from tools/go-agent/tools/types.go
copy to plugins/sql/entry/conn_begin_tx.go
index aabda3b..410646c 100644
--- a/tools/go-agent/tools/types.go
+++ b/plugins/sql/entry/conn_begin_tx.go
@@ -15,21 +15,19 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package tools
+package entry
 
-var basicDataTypes = make(map[string]bool)
+import (
+       "github.com/apache/skywalking-go/plugins/core/operator"
+)
 
-func init() {
-       types := []string{
-               "bool", "int8", "int16", "int32", "int64", "uint8", "uint16", 
"uint32", "uint64", "int", "uint", "uintptr",
-               "float32", "float64", "complex64", "complex128", "string", 
"error", "interface{}", "_", "byte",
-       }
-       for _, tp := range types {
-               basicDataTypes[tp] = true
-       }
+type ConnBeginTXInterceptor struct {
 }
 
-// nolint
-func IsBasicDataType(name string) bool {
-       return basicDataTypes[name]
+func (n *ConnBeginTXInterceptor) BeforeInvoke(invocation operator.Invocation) 
error {
+       return GeneralBeginTxBeforeInvoke(invocation, "Conn/BeginTx")
+}
+
+func (n *ConnBeginTXInterceptor) AfterInvoke(invocation operator.Invocation, 
results ...interface{}) error {
+       return GeneralBeginTxAfterInvoke(invocation, results...)
 }
diff --git a/tools/go-agent/tools/types.go b/plugins/sql/entry/conn_exec.go
similarity index 65%
copy from tools/go-agent/tools/types.go
copy to plugins/sql/entry/conn_exec.go
index aabda3b..d441809 100644
--- a/tools/go-agent/tools/types.go
+++ b/plugins/sql/entry/conn_exec.go
@@ -15,21 +15,19 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package tools
+package entry
 
-var basicDataTypes = make(map[string]bool)
+import (
+       "github.com/apache/skywalking-go/plugins/core/operator"
+)
 
-func init() {
-       types := []string{
-               "bool", "int8", "int16", "int32", "int64", "uint8", "uint16", 
"uint32", "uint64", "int", "uint", "uintptr",
-               "float32", "float64", "complex64", "complex128", "string", 
"error", "interface{}", "_", "byte",
-       }
-       for _, tp := range types {
-               basicDataTypes[tp] = true
-       }
+type ConnExecInterceptor struct {
 }
 
-// nolint
-func IsBasicDataType(name string) bool {
-       return basicDataTypes[name]
+func (n *ConnExecInterceptor) BeforeInvoke(invocation operator.Invocation) 
error {
+       return GeneralExecBeforeInvoke(invocation, "Conn/Exec")
+}
+
+func (n *ConnExecInterceptor) AfterInvoke(invocation operator.Invocation, 
results ...interface{}) error {
+       return GeneralExecAfterInvoke(invocation, results...)
 }
diff --git a/tools/go-agent/tools/types.go b/plugins/sql/entry/conn_ping.go
similarity index 65%
copy from tools/go-agent/tools/types.go
copy to plugins/sql/entry/conn_ping.go
index aabda3b..b5731d0 100644
--- a/tools/go-agent/tools/types.go
+++ b/plugins/sql/entry/conn_ping.go
@@ -15,21 +15,19 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package tools
+package entry
 
-var basicDataTypes = make(map[string]bool)
+import (
+       "github.com/apache/skywalking-go/plugins/core/operator"
+)
 
-func init() {
-       types := []string{
-               "bool", "int8", "int16", "int32", "int64", "uint8", "uint16", 
"uint32", "uint64", "int", "uint", "uintptr",
-               "float32", "float64", "complex64", "complex128", "string", 
"error", "interface{}", "_", "byte",
-       }
-       for _, tp := range types {
-               basicDataTypes[tp] = true
-       }
+type ConnPingInterceptor struct {
 }
 
-// nolint
-func IsBasicDataType(name string) bool {
-       return basicDataTypes[name]
+func (n *ConnPingInterceptor) BeforeInvoke(invocation operator.Invocation) 
error {
+       return GeneralPingBeforeInvoke(invocation, "Conn/Ping")
+}
+
+func (n *ConnPingInterceptor) AfterInvoke(invocation operator.Invocation, 
results ...interface{}) error {
+       return GeneralPingAfterInvoke(invocation, results...)
 }
diff --git a/tools/go-agent/tools/types.go b/plugins/sql/entry/conn_prepare.go
similarity index 65%
copy from tools/go-agent/tools/types.go
copy to plugins/sql/entry/conn_prepare.go
index aabda3b..acc91ce 100644
--- a/tools/go-agent/tools/types.go
+++ b/plugins/sql/entry/conn_prepare.go
@@ -15,21 +15,19 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package tools
+package entry
 
-var basicDataTypes = make(map[string]bool)
+import (
+       "github.com/apache/skywalking-go/plugins/core/operator"
+)
 
-func init() {
-       types := []string{
-               "bool", "int8", "int16", "int32", "int64", "uint8", "uint16", 
"uint32", "uint64", "int", "uint", "uintptr",
-               "float32", "float64", "complex64", "complex128", "string", 
"error", "interface{}", "_", "byte",
-       }
-       for _, tp := range types {
-               basicDataTypes[tp] = true
-       }
+type ConnPrepareInterceptor struct {
 }
 
-// nolint
-func IsBasicDataType(name string) bool {
-       return basicDataTypes[name]
+func (n *ConnPrepareInterceptor) BeforeInvoke(invocation operator.Invocation) 
error {
+       return GeneralPrepareBeforeInvoke(invocation, "Conn/Prepare")
+}
+
+func (n *ConnPrepareInterceptor) AfterInvoke(invocation operator.Invocation, 
results ...interface{}) error {
+       return GeneralPrepareAfterInvoke(invocation, results...)
 }
diff --git a/tools/go-agent/tools/types.go b/plugins/sql/entry/conn_query.go
similarity index 65%
copy from tools/go-agent/tools/types.go
copy to plugins/sql/entry/conn_query.go
index aabda3b..d4819d8 100644
--- a/tools/go-agent/tools/types.go
+++ b/plugins/sql/entry/conn_query.go
@@ -15,21 +15,19 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package tools
+package entry
 
-var basicDataTypes = make(map[string]bool)
+import (
+       "github.com/apache/skywalking-go/plugins/core/operator"
+)
 
-func init() {
-       types := []string{
-               "bool", "int8", "int16", "int32", "int64", "uint8", "uint16", 
"uint32", "uint64", "int", "uint", "uintptr",
-               "float32", "float64", "complex64", "complex128", "string", 
"error", "interface{}", "_", "byte",
-       }
-       for _, tp := range types {
-               basicDataTypes[tp] = true
-       }
+type ConnQueryInterceptor struct {
 }
 
-// nolint
-func IsBasicDataType(name string) bool {
-       return basicDataTypes[name]
+func (n *ConnQueryInterceptor) BeforeInvoke(invocation operator.Invocation) 
error {
+       return GeneralQueryBeforeInvoke(invocation, "Conn/Query")
+}
+
+func (n *ConnQueryInterceptor) AfterInvoke(invocation operator.Invocation, 
results ...interface{}) error {
+       return GeneralQueryAfterInvoke(invocation, results...)
 }
diff --git a/tools/go-agent/tools/types.go b/plugins/sql/entry/conn_raw.go
similarity index 65%
copy from tools/go-agent/tools/types.go
copy to plugins/sql/entry/conn_raw.go
index aabda3b..6387bd3 100644
--- a/tools/go-agent/tools/types.go
+++ b/plugins/sql/entry/conn_raw.go
@@ -15,21 +15,19 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package tools
+package entry
 
-var basicDataTypes = make(map[string]bool)
+import (
+       "github.com/apache/skywalking-go/plugins/core/operator"
+)
 
-func init() {
-       types := []string{
-               "bool", "int8", "int16", "int32", "int64", "uint8", "uint16", 
"uint32", "uint64", "int", "uint", "uintptr",
-               "float32", "float64", "complex64", "complex128", "string", 
"error", "interface{}", "_", "byte",
-       }
-       for _, tp := range types {
-               basicDataTypes[tp] = true
-       }
+type ConnRawInterceptor struct {
 }
 
-// nolint
-func IsBasicDataType(name string) bool {
-       return basicDataTypes[name]
+func (n *ConnRawInterceptor) BeforeInvoke(invocation operator.Invocation) 
error {
+       return GeneralRawBeforeInvoke(invocation, "Conn/Raw")
+}
+
+func (n *ConnRawInterceptor) AfterInvoke(invocation operator.Invocation, 
results ...interface{}) error {
+       return GeneralRawAfterInvoke(invocation, results...)
 }
diff --git a/tools/go-agent/tools/types.go b/plugins/sql/entry/db_begin_tx.go
similarity index 65%
copy from tools/go-agent/tools/types.go
copy to plugins/sql/entry/db_begin_tx.go
index aabda3b..55910bf 100644
--- a/tools/go-agent/tools/types.go
+++ b/plugins/sql/entry/db_begin_tx.go
@@ -15,21 +15,19 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package tools
+package entry
 
-var basicDataTypes = make(map[string]bool)
+import (
+       "github.com/apache/skywalking-go/plugins/core/operator"
+)
 
-func init() {
-       types := []string{
-               "bool", "int8", "int16", "int32", "int64", "uint8", "uint16", 
"uint32", "uint64", "int", "uint", "uintptr",
-               "float32", "float64", "complex64", "complex128", "string", 
"error", "interface{}", "_", "byte",
-       }
-       for _, tp := range types {
-               basicDataTypes[tp] = true
-       }
+type BeginTXInterceptor struct {
 }
 
-// nolint
-func IsBasicDataType(name string) bool {
-       return basicDataTypes[name]
+func (n *BeginTXInterceptor) BeforeInvoke(invocation operator.Invocation) 
error {
+       return GeneralBeginTxBeforeInvoke(invocation, "BeginTx")
+}
+
+func (n *BeginTXInterceptor) AfterInvoke(invocation operator.Invocation, 
results ...interface{}) error {
+       return GeneralBeginTxAfterInvoke(invocation, results...)
 }
diff --git a/plugins/sql/entry/db_conn.go b/plugins/sql/entry/db_conn.go
new file mode 100644
index 0000000..c3c5594
--- /dev/null
+++ b/plugins/sql/entry/db_conn.go
@@ -0,0 +1,63 @@
+// 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 (
+       "database/sql"
+
+       "github.com/apache/skywalking-go/plugins/core/operator"
+       "github.com/apache/skywalking-go/plugins/core/tracing"
+)
+
+type ConnInterceptor struct {
+}
+
+type connInfo struct {
+       instance InstanceInfo
+       span     tracing.Span
+}
+
+func (n *ConnInterceptor) BeforeInvoke(invocation operator.Invocation) error {
+       span, info, err := createLocalSpan(invocation.CallerInstance(), "Conn")
+       if err != nil || span == nil {
+               return err
+       }
+       invocation.SetContext(&connInfo{
+               instance: info,
+               span:     span,
+       })
+       return nil
+}
+
+func (n *ConnInterceptor) AfterInvoke(invocation operator.Invocation, results 
...interface{}) error {
+       ctx := invocation.GetContext()
+       if ctx == nil {
+               return nil
+       }
+       // if contains error, then record it
+       if err, ok := results[1].(error); ok && err != nil {
+               ctx.(*connInfo).span.Error(err.Error())
+       }
+       ctx.(*connInfo).span.End()
+
+       // propagate the instance info
+       if instance, ok := results[0].(*sql.Conn); ok && instance != nil {
+               
results[0].(operator.EnhancedInstance).SetSkyWalkingDynamicField(ctx.(*connInfo).instance)
+       }
+       return nil
+}
diff --git a/tools/go-agent/tools/types.go b/plugins/sql/entry/db_exec.go
similarity index 65%
copy from tools/go-agent/tools/types.go
copy to plugins/sql/entry/db_exec.go
index aabda3b..7ca779d 100644
--- a/tools/go-agent/tools/types.go
+++ b/plugins/sql/entry/db_exec.go
@@ -15,21 +15,19 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package tools
+package entry
 
-var basicDataTypes = make(map[string]bool)
+import (
+       "github.com/apache/skywalking-go/plugins/core/operator"
+)
 
-func init() {
-       types := []string{
-               "bool", "int8", "int16", "int32", "int64", "uint8", "uint16", 
"uint32", "uint64", "int", "uint", "uintptr",
-               "float32", "float64", "complex64", "complex128", "string", 
"error", "interface{}", "_", "byte",
-       }
-       for _, tp := range types {
-               basicDataTypes[tp] = true
-       }
+type ExecInterceptor struct {
 }
 
-// nolint
-func IsBasicDataType(name string) bool {
-       return basicDataTypes[name]
+func (n *ExecInterceptor) BeforeInvoke(invocation operator.Invocation) error {
+       return GeneralExecBeforeInvoke(invocation, "Exec")
+}
+
+func (n *ExecInterceptor) AfterInvoke(invocation operator.Invocation, results 
...interface{}) error {
+       return GeneralExecAfterInvoke(invocation, results...)
 }
diff --git a/tools/go-agent/tools/types.go b/plugins/sql/entry/db_ping.go
similarity index 65%
copy from tools/go-agent/tools/types.go
copy to plugins/sql/entry/db_ping.go
index aabda3b..86c6394 100644
--- a/tools/go-agent/tools/types.go
+++ b/plugins/sql/entry/db_ping.go
@@ -15,21 +15,19 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package tools
+package entry
 
-var basicDataTypes = make(map[string]bool)
+import (
+       "github.com/apache/skywalking-go/plugins/core/operator"
+)
 
-func init() {
-       types := []string{
-               "bool", "int8", "int16", "int32", "int64", "uint8", "uint16", 
"uint32", "uint64", "int", "uint", "uintptr",
-               "float32", "float64", "complex64", "complex128", "string", 
"error", "interface{}", "_", "byte",
-       }
-       for _, tp := range types {
-               basicDataTypes[tp] = true
-       }
+type PingInterceptor struct {
 }
 
-// nolint
-func IsBasicDataType(name string) bool {
-       return basicDataTypes[name]
+func (n *PingInterceptor) BeforeInvoke(invocation operator.Invocation) error {
+       return GeneralPingBeforeInvoke(invocation, "Ping")
+}
+
+func (n *PingInterceptor) AfterInvoke(invocation operator.Invocation, results 
...interface{}) error {
+       return GeneralPingAfterInvoke(invocation, results...)
 }
diff --git a/tools/go-agent/tools/types.go b/plugins/sql/entry/db_prepare.go
similarity index 65%
copy from tools/go-agent/tools/types.go
copy to plugins/sql/entry/db_prepare.go
index aabda3b..5dfbf71 100644
--- a/tools/go-agent/tools/types.go
+++ b/plugins/sql/entry/db_prepare.go
@@ -15,21 +15,19 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package tools
+package entry
 
-var basicDataTypes = make(map[string]bool)
+import (
+       "github.com/apache/skywalking-go/plugins/core/operator"
+)
 
-func init() {
-       types := []string{
-               "bool", "int8", "int16", "int32", "int64", "uint8", "uint16", 
"uint32", "uint64", "int", "uint", "uintptr",
-               "float32", "float64", "complex64", "complex128", "string", 
"error", "interface{}", "_", "byte",
-       }
-       for _, tp := range types {
-               basicDataTypes[tp] = true
-       }
+type PrepareInterceptor struct {
 }
 
-// nolint
-func IsBasicDataType(name string) bool {
-       return basicDataTypes[name]
+func (n *PrepareInterceptor) BeforeInvoke(invocation operator.Invocation) 
error {
+       return GeneralPrepareBeforeInvoke(invocation, "Prepare")
+}
+
+func (n *PrepareInterceptor) AfterInvoke(invocation operator.Invocation, 
results ...interface{}) error {
+       return GeneralPrepareAfterInvoke(invocation, results...)
 }
diff --git a/tools/go-agent/tools/types.go b/plugins/sql/entry/db_query.go
similarity index 65%
copy from tools/go-agent/tools/types.go
copy to plugins/sql/entry/db_query.go
index aabda3b..6e27045 100644
--- a/tools/go-agent/tools/types.go
+++ b/plugins/sql/entry/db_query.go
@@ -15,21 +15,19 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package tools
+package entry
 
-var basicDataTypes = make(map[string]bool)
+import (
+       "github.com/apache/skywalking-go/plugins/core/operator"
+)
 
-func init() {
-       types := []string{
-               "bool", "int8", "int16", "int32", "int64", "uint8", "uint16", 
"uint32", "uint64", "int", "uint", "uintptr",
-               "float32", "float64", "complex64", "complex128", "string", 
"error", "interface{}", "_", "byte",
-       }
-       for _, tp := range types {
-               basicDataTypes[tp] = true
-       }
+type QueryInterceptor struct {
 }
 
-// nolint
-func IsBasicDataType(name string) bool {
-       return basicDataTypes[name]
+func (n *QueryInterceptor) BeforeInvoke(invocation operator.Invocation) error {
+       return GeneralQueryBeforeInvoke(invocation, "Query")
+}
+
+func (n *QueryInterceptor) AfterInvoke(invocation operator.Invocation, results 
...interface{}) error {
+       return GeneralQueryAfterInvoke(invocation, results...)
 }
diff --git a/plugins/sql/entry/general.go b/plugins/sql/entry/general.go
new file mode 100644
index 0000000..a51245e
--- /dev/null
+++ b/plugins/sql/entry/general.go
@@ -0,0 +1,204 @@
+// 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 (
+       "database/sql"
+       "fmt"
+
+       "github.com/apache/skywalking-go/plugins/core/operator"
+       "github.com/apache/skywalking-go/plugins/core/tracing"
+)
+
+type PrepareInfo struct {
+       instance InstanceInfo
+       span     tracing.Span
+}
+
+func GeneralPrepareBeforeInvoke(invocation operator.Invocation, method string) 
error {
+       span, info, err := createLocalSpan(invocation.CallerInstance(), method,
+               tracing.WithTag(tracing.TagDBStatement, 
invocation.Args()[1].(string)))
+       if err != nil || span == nil {
+               return err
+       }
+       invocation.SetContext(&PrepareInfo{
+               instance: info,
+               span:     span,
+       })
+       return nil
+}
+
+func GeneralPrepareAfterInvoke(invocation operator.Invocation, results 
...interface{}) error {
+       ctx := invocation.GetContext()
+       if ctx == nil {
+               return nil
+       }
+       // if contains error, then record it
+       if err, ok := results[1].(error); ok && err != nil {
+               ctx.(*PrepareInfo).span.Error(err.Error())
+       }
+       ctx.(*PrepareInfo).span.End()
+
+       // propagate the instance info
+       if instance, ok := results[0].(*sql.Stmt); ok && instance != nil {
+               
results[0].(operator.EnhancedInstance).SetSkyWalkingDynamicField(ctx.(*PrepareInfo).instance)
+       }
+       return nil
+}
+
+type BeginTxInfo struct {
+       instance InstanceInfo
+       span     tracing.Span
+}
+
+func GeneralBeginTxBeforeInvoke(invocation operator.Invocation, method string) 
error {
+       span, info, err := createLocalSpan(invocation.CallerInstance(), method)
+       if err != nil || span == nil {
+               return err
+       }
+       invocation.SetContext(&BeginTxInfo{
+               instance: info,
+               span:     span,
+       })
+       return nil
+}
+
+func GeneralBeginTxAfterInvoke(invocation operator.Invocation, result 
...interface{}) error {
+       ctx := invocation.GetContext()
+       if ctx == nil {
+               return nil
+       }
+       // if contains error, then record it
+       if err, ok := result[1].(error); ok && err != nil {
+               ctx.(*BeginTxInfo).span.Error(err.Error())
+       }
+       ctx.(*BeginTxInfo).span.End()
+
+       // propagate the instance info
+       if instance, ok := result[0].(*sql.Tx); ok && instance != nil {
+               
result[0].(operator.EnhancedInstance).SetSkyWalkingDynamicField(ctx.(*BeginTxInfo).instance)
+       }
+       return nil
+}
+
+func GeneralExecBeforeInvoke(invocation operator.Invocation, method string) 
error {
+       span, err := createExitSpan(invocation.CallerInstance(), method,
+               tracing.WithTag(tracing.TagDBStatement, 
invocation.Args()[1].(string)))
+       if err != nil {
+               return err
+       }
+       if config.CollectParameter && len(invocation.Args()[2].([]interface{})) 
> 0 {
+               span.Tag(tracing.TagDBSqlParameters, 
argsToString(invocation.Args()[2].([]interface{})))
+       }
+       invocation.SetContext(span)
+       return nil
+}
+
+func GeneralExecAfterInvoke(invocation operator.Invocation, results 
...interface{}) error {
+       ctx := invocation.GetContext()
+       if ctx == nil {
+               return nil
+       }
+       if err, ok := results[1].(error); ok && err != nil {
+               ctx.(tracing.Span).Error(err.Error())
+       }
+       ctx.(tracing.Span).End()
+       return nil
+}
+
+func GeneralPingBeforeInvoke(invocation operator.Invocation, method string) 
error {
+       span, err := createExitSpan(invocation.CallerInstance(), method)
+       if err != nil {
+               return err
+       }
+       invocation.SetContext(span)
+       return nil
+}
+
+func GeneralPingAfterInvoke(invocation operator.Invocation, results 
...interface{}) error {
+       ctx := invocation.GetContext()
+       if ctx == nil {
+               return nil
+       }
+       if err, ok := results[0].(error); ok && err != nil {
+               ctx.(tracing.Span).Error(err.Error())
+       }
+       ctx.(tracing.Span).End()
+       return nil
+}
+
+func GeneralQueryBeforeInvoke(invocation operator.Invocation, method string) 
error {
+       span, err := createExitSpan(invocation.CallerInstance(), method,
+               tracing.WithTag(tracing.TagDBStatement, 
invocation.Args()[1].(string)))
+       if err != nil {
+               return err
+       }
+       if config.CollectParameter && len(invocation.Args()[2].([]interface{})) 
> 0 {
+               span.Tag(tracing.TagDBSqlParameters, 
argsToString(invocation.Args()[2].([]interface{})))
+       }
+       invocation.SetContext(span)
+       return nil
+}
+
+func GeneralQueryAfterInvoke(invocation operator.Invocation, results 
...interface{}) error {
+       ctx := invocation.GetContext()
+       if ctx == nil {
+               return nil
+       }
+       if err, ok := results[1].(error); ok && err != nil {
+               ctx.(tracing.Span).Error(err.Error())
+       }
+       ctx.(tracing.Span).End()
+       return nil
+}
+
+func GeneralRawBeforeInvoke(invocation operator.Invocation, method string) 
error {
+       span, err := createExitSpan(invocation.CallerInstance(), method)
+       if err != nil {
+               return err
+       }
+       invocation.SetContext(span)
+       return nil
+}
+
+func GeneralRawAfterInvoke(invocation operator.Invocation, results 
...interface{}) error {
+       ctx := invocation.GetContext()
+       if ctx == nil {
+               return nil
+       }
+       if err, ok := results[1].(error); ok && err != nil {
+               ctx.(tracing.Span).Error(err.Error())
+       }
+       ctx.(tracing.Span).End()
+       return nil
+}
+
+func argsToString(args []interface{}) string {
+       switch len(args) {
+       case 0:
+               return ""
+       case 1:
+               return fmt.Sprintf("%v", args[0])
+       }
+
+       res := fmt.Sprintf("%v", args[0])
+       for _, arg := range args[1:] {
+               res += fmt.Sprintf(", %v", arg)
+       }
+       return res
+}
diff --git a/plugins/sql/entry/instance_open.go 
b/plugins/sql/entry/instance_open.go
new file mode 100644
index 0000000..879269b
--- /dev/null
+++ b/plugins/sql/entry/instance_open.go
@@ -0,0 +1,58 @@
+// 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 (
+       "database/sql"
+
+       "github.com/apache/skywalking-go/plugins/core/operator"
+       "github.com/apache/skywalking-go/plugins/core/tracing"
+)
+
+var needInfoKey = "needInfo"
+var infoKey = "info"
+
+type InstanceInterceptor struct {
+}
+
+type InstanceInfo interface {
+       Peer() string
+       ComponentID() int32
+       DBType() string
+}
+
+func (n *InstanceInterceptor) BeforeInvoke(invocation operator.Invocation) 
error {
+       tracing.SetRuntimeContextValue(needInfoKey, true)
+       return nil
+}
+
+func (n *InstanceInterceptor) AfterInvoke(invocation operator.Invocation, 
results ...interface{}) error {
+       tracing.SetRuntimeContextValue(needInfoKey, nil)
+       info, ok := tracing.GetRuntimeContextValue(infoKey).(InstanceInfo)
+       tracing.SetRuntimeContextValue(needInfoKey, nil)
+       tracing.SetRuntimeContextValue(infoKey, nil)
+       if !ok || info == nil {
+               return nil
+       }
+
+       // adding peer address into db
+       if db, ok := results[0].(*sql.DB); ok && db != nil {
+               
results[0].(operator.EnhancedInstance).SetSkyWalkingDynamicField(info)
+       }
+       return nil
+}
diff --git a/plugins/sql/entry/instrument.go b/plugins/sql/entry/instrument.go
new file mode 100644
index 0000000..4876fd1
--- /dev/null
+++ b/plugins/sql/entry/instrument.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 entry
+
+import (
+       "embed"
+
+       "github.com/apache/skywalking-go/plugins/core/instrument"
+)
+
+//go:embed *
+var fs embed.FS
+
+//skywalking:nocopy
+type Instrument struct {
+}
+
+func NewInstrument() *Instrument {
+       return &Instrument{}
+}
+
+func (i *Instrument) Name() string {
+       return "sql"
+}
+
+func (i *Instrument) BasePackage() string {
+       return "database/sql"
+}
+
+func (i *Instrument) VersionChecker(version string) bool {
+       return true
+}
+
+// nolint
+func (i *Instrument) Points() []*instrument.Point {
+       return []*instrument.Point{
+               {
+                       PackagePath: "",
+                       At:          instrument.NewStructEnhance("DB"),
+               },
+               {
+                       PackagePath: "",
+                       At:          instrument.NewStructEnhance("Stmt"),
+               },
+               {
+                       PackagePath: "",
+                       At:          instrument.NewStructEnhance("Tx"),
+               },
+               {
+                       PackagePath: "",
+                       At:          instrument.NewStructEnhance("Conn"),
+               },
+               {
+                       PackagePath: "",
+                       At: instrument.NewStaticMethodEnhance("Open",
+                               instrument.WithArgsCount(2), 
instrument.WithArgType(0, "string"), instrument.WithArgType(1, "string"),
+                               instrument.WithResultCount(2), 
instrument.WithResultType(0, "*DB"), instrument.WithResultType(1, "error")),
+                       Interceptor: "InstanceInterceptor",
+               },
+               {
+                       PackagePath: "",
+                       At: instrument.NewMethodEnhance("*DB", "PingContext",
+                               instrument.WithArgsCount(1), 
instrument.WithArgType(0, "context.Context"),
+                               instrument.WithResultCount(1), 
instrument.WithResultType(0, "error")),
+                       Interceptor: "PingInterceptor",
+               },
+               {
+                       PackagePath: "",
+                       At: instrument.NewMethodEnhance("*DB", "PrepareContext",
+                               instrument.WithArgsCount(2), 
instrument.WithArgType(0, "context.Context"), instrument.WithArgType(1, 
"string"),
+                               instrument.WithResultCount(2), 
instrument.WithResultType(0, "*Stmt"), instrument.WithResultType(1, "error")),
+                       Interceptor: "PrepareInterceptor",
+               },
+               {
+                       PackagePath: "",
+                       At: instrument.NewMethodEnhance("*DB", "ExecContext",
+                               instrument.WithArgsCount(3), 
instrument.WithArgType(0, "context.Context"), instrument.WithArgType(1, 
"string"),
+                               instrument.WithResultCount(2), 
instrument.WithResultType(0, "Result"), instrument.WithResultType(1, "error")),
+                       Interceptor: "ExecInterceptor",
+               },
+               {
+                       PackagePath: "",
+                       At: instrument.NewMethodEnhance("*DB", "QueryContext",
+                               instrument.WithArgsCount(3), 
instrument.WithArgType(0, "context.Context"), instrument.WithArgType(1, 
"string"),
+                               instrument.WithResultCount(2), 
instrument.WithResultType(0, "*Rows"), instrument.WithResultType(1, "error")),
+                       Interceptor: "QueryInterceptor",
+               },
+               {
+                       PackagePath: "",
+                       At: instrument.NewMethodEnhance("*DB", "BeginTx",
+                               instrument.WithArgsCount(2), 
instrument.WithArgType(0, "context.Context"), instrument.WithArgType(1, 
"*TxOptions"),
+                               instrument.WithResultCount(2), 
instrument.WithResultType(0, "*Tx"), instrument.WithResultType(1, "error")),
+                       Interceptor: "BeginTXInterceptor",
+               },
+               {
+                       PackagePath: "",
+                       At: instrument.NewMethodEnhance("*DB", "Conn",
+                               instrument.WithArgsCount(1), 
instrument.WithArgType(0, "context.Context"),
+                               instrument.WithResultCount(2), 
instrument.WithResultType(0, "*Conn"), instrument.WithResultType(1, "error")),
+                       Interceptor: "ConnInterceptor",
+               },
+               // Conn operation
+               {
+                       PackagePath: "",
+                       At: instrument.NewMethodEnhance("*Conn", "PingContext",
+                               instrument.WithArgsCount(1), 
instrument.WithArgType(0, "context.Context"),
+                               instrument.WithResultCount(1), 
instrument.WithResultType(0, "error")),
+                       Interceptor: "ConnPingInterceptor",
+               },
+               {
+                       PackagePath: "",
+                       At: instrument.NewMethodEnhance("*Conn", "ExecContext",
+                               instrument.WithArgsCount(3),
+                               instrument.WithArgType(0, "context.Context"), 
instrument.WithArgType(1, "string"),
+                               instrument.WithResultCount(2), 
instrument.WithArgType(0, "Result"), instrument.WithResultType(1, "error")),
+                       Interceptor: "ConnExecInterceptor",
+               },
+               {
+                       PackagePath: "",
+                       At: instrument.NewMethodEnhance("*Conn", "QueryContext",
+                               instrument.WithArgsCount(3),
+                               instrument.WithArgType(0, "context.Context"), 
instrument.WithArgType(1, "string"),
+                               instrument.WithResultCount(2), 
instrument.WithArgType(0, "*Rows"), instrument.WithResultType(1, "error")),
+                       Interceptor: "ConnQueryInterceptor",
+               },
+               {
+                       PackagePath: "",
+                       At: instrument.NewMethodEnhance("*Conn", 
"PrepareContext",
+                               instrument.WithArgsCount(2),
+                               instrument.WithArgType(0, "context.Context"), 
instrument.WithArgType(1, "string"),
+                               instrument.WithResultCount(2), 
instrument.WithArgType(0, "*Stmt"), instrument.WithResultType(1, "error")),
+                       Interceptor: "ConnPrepareInterceptor",
+               },
+               {
+                       PackagePath: "",
+                       At: instrument.NewMethodEnhance("*Conn", "Raw",
+                               instrument.WithArgsCount(1),
+                               instrument.WithResultCount(1), 
instrument.WithResultType(0, "error")),
+                       Interceptor: "ConnRawInterceptor",
+               },
+               {
+                       PackagePath: "",
+                       At: instrument.NewMethodEnhance("*Conn", "BeginTx",
+                               instrument.WithArgsCount(2), 
instrument.WithArgType(0, "context.Context"), instrument.WithArgType(1, 
"*TxOptions"),
+                               instrument.WithResultCount(2), 
instrument.WithResultType(0, "*Tx"), instrument.WithResultType(1, "error")),
+                       Interceptor: "ConnBeginTXInterceptor",
+               },
+               // TX operation
+               {
+                       PackagePath: "",
+                       At: instrument.NewMethodEnhance("*Tx", "Commit",
+                               instrument.WithArgsCount(0),
+                               instrument.WithResultCount(1), 
instrument.WithResultType(0, "error")),
+                       Interceptor: "TxCommitInterceptor",
+               },
+               {
+                       PackagePath: "",
+                       At: instrument.NewMethodEnhance("*Tx", "Rollback",
+                               instrument.WithArgsCount(0),
+                               instrument.WithResultCount(1), 
instrument.WithResultType(0, "error")),
+                       Interceptor: "TxRollbackInterceptor",
+               },
+               {
+                       PackagePath: "",
+                       At: instrument.NewMethodEnhance("*Tx", "PrepareContext",
+                               instrument.WithArgsCount(2), 
instrument.WithArgType(0, "context.Context"), instrument.WithArgType(1, 
"string"),
+                               instrument.WithResultCount(2), 
instrument.WithResultType(0, "*Stmt"), instrument.WithResultType(1, "error")),
+                       Interceptor: "TxPrepareInterceptor",
+               },
+               {
+                       PackagePath: "",
+                       At: instrument.NewMethodEnhance("*Tx", "StmtContext",
+                               instrument.WithArgsCount(2), 
instrument.WithArgType(0, "context.Context"), instrument.WithArgType(1, 
"*Stmt"),
+                               instrument.WithResultCount(1), 
instrument.WithResultType(0, "*Stmt")),
+                       Interceptor: "TxStmtInterceptor",
+               },
+               {
+                       PackagePath: "",
+                       At: instrument.NewMethodEnhance("*Tx", "ExecContext",
+                               instrument.WithArgsCount(3), 
instrument.WithArgType(0, "context.Context"), instrument.WithArgType(1, 
"string"),
+                               instrument.WithResultCount(2), 
instrument.WithResultType(0, "Result"), instrument.WithResultType(1, "error")),
+                       Interceptor: "TxExecInterceptor",
+               },
+               {
+                       PackagePath: "",
+                       At: instrument.NewMethodEnhance("*Tx", "QueryContext",
+                               instrument.WithArgsCount(3), 
instrument.WithArgType(0, "context.Context"), instrument.WithArgType(1, 
"string"),
+                               instrument.WithResultCount(2), 
instrument.WithResultType(0, "*Rows"), instrument.WithResultType(1, "error")),
+                       Interceptor: "TxQueryInterceptor",
+               },
+               // Stmt Operation
+               {
+                       PackagePath: "",
+                       At: instrument.NewMethodEnhance("*Stmt", "ExecContext",
+                               instrument.WithArgsCount(2), 
instrument.WithArgType(0, "context.Context"),
+                               instrument.WithResultCount(2), 
instrument.WithResultType(0, "Result"), instrument.WithResultType(1, "error")),
+                       Interceptor: "StmtExecInterceptor",
+               },
+               {
+                       PackagePath: "",
+                       At: instrument.NewMethodEnhance("*Stmt", "QueryContext",
+                               instrument.WithArgsCount(2), 
instrument.WithArgType(0, "context.Context"),
+                               instrument.WithResultCount(2), 
instrument.WithResultType(0, "*Rows"), instrument.WithResultType(1, "error")),
+                       Interceptor: "StmtQueryInterceptor",
+               },
+       }
+}
+
+func (i *Instrument) PluginSourceCodePath() string {
+       return "entry"
+}
+
+func (i *Instrument) FS() *embed.FS {
+       return &fs
+}
diff --git a/plugins/sql/entry/span.go b/plugins/sql/entry/span.go
new file mode 100644
index 0000000..e60f194
--- /dev/null
+++ b/plugins/sql/entry/span.go
@@ -0,0 +1,59 @@
+// 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/plugins/core/operator"
+       "github.com/apache/skywalking-go/plugins/core/tracing"
+)
+
+func createExitSpan(caller interface{}, method string, opts 
...tracing.SpanOption) (tracing.Span, error) {
+       info := getInstanceInfo(caller)
+       if info == nil {
+               return nil, nil
+       }
+
+       span, err := tracing.CreateExitSpan(info.DBType()+"/"+method, 
info.Peer(), func(headerKey, headerValue string) error {
+               return nil
+       }, append(opts, tracing.WithComponent(info.ComponentID()),
+               tracing.WithLayer(tracing.SpanLayerDatabase),
+               tracing.WithTag(tracing.TagDBType, info.DBType()))...)
+       return span, err
+}
+
+func createLocalSpan(caller interface{}, method string, opts 
...tracing.SpanOption) (tracing.Span, InstanceInfo, error) {
+       info := getInstanceInfo(caller)
+       if info == nil {
+               return nil, nil, nil
+       }
+
+       span, err := tracing.CreateLocalSpan(info.DBType()+"/"+method,
+               append(opts, tracing.WithComponent(info.ComponentID()),
+                       tracing.WithLayer(tracing.SpanLayerDatabase),
+                       tracing.WithTag(tracing.TagDBType, info.DBType()))...)
+       return span, info, err
+}
+
+func getInstanceInfo(caller interface{}) InstanceInfo {
+       instance, ok := caller.(operator.EnhancedInstance)
+       if !ok || instance == nil {
+               return nil
+       }
+       info := instance.GetSkyWalkingDynamicField().(InstanceInfo)
+       return info
+}
diff --git a/plugins/sql/entry/stmt_exec.go b/plugins/sql/entry/stmt_exec.go
new file mode 100644
index 0000000..fcb1714
--- /dev/null
+++ b/plugins/sql/entry/stmt_exec.go
@@ -0,0 +1,50 @@
+// 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/plugins/core/operator"
+       "github.com/apache/skywalking-go/plugins/core/tracing"
+)
+
+type StmtExecInterceptor struct {
+}
+
+func (n *StmtExecInterceptor) BeforeInvoke(invocation operator.Invocation) 
error {
+       span, err := createExitSpan(invocation.CallerInstance(), "Stmt/Exec")
+       if err != nil {
+               return err
+       }
+       if config.CollectParameter && len(invocation.Args()[1].([]interface{})) 
> 0 {
+               span.Tag(tracing.TagDBSqlParameters, 
argsToString(invocation.Args()[1].([]interface{})))
+       }
+       invocation.SetContext(span)
+       return nil
+}
+
+func (n *StmtExecInterceptor) AfterInvoke(invocation operator.Invocation, 
results ...interface{}) error {
+       ctx := invocation.GetContext()
+       if ctx == nil {
+               return nil
+       }
+       if err, ok := results[1].(error); ok && err != nil {
+               ctx.(tracing.Span).Error(err.Error())
+       }
+       ctx.(tracing.Span).End()
+       return nil
+}
diff --git a/plugins/sql/entry/stmt_query.go b/plugins/sql/entry/stmt_query.go
new file mode 100644
index 0000000..cec3b6e
--- /dev/null
+++ b/plugins/sql/entry/stmt_query.go
@@ -0,0 +1,50 @@
+// 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/plugins/core/operator"
+       "github.com/apache/skywalking-go/plugins/core/tracing"
+)
+
+type StmtQueryInterceptor struct {
+}
+
+func (n *StmtQueryInterceptor) BeforeInvoke(invocation operator.Invocation) 
error {
+       span, err := createExitSpan(invocation.CallerInstance(), "Stmt/Query")
+       if err != nil {
+               return err
+       }
+       if config.CollectParameter && len(invocation.Args()[1].([]interface{})) 
> 0 {
+               span.Tag(tracing.TagDBSqlParameters, 
argsToString(invocation.Args()[1].([]interface{})))
+       }
+       invocation.SetContext(span)
+       return nil
+}
+
+func (n *StmtQueryInterceptor) AfterInvoke(invocation operator.Invocation, 
results ...interface{}) error {
+       ctx := invocation.GetContext()
+       if ctx == nil {
+               return nil
+       }
+       if err, ok := results[1].(error); ok && err != nil {
+               ctx.(tracing.Span).Error(err.Error())
+       }
+       ctx.(tracing.Span).End()
+       return nil
+}
diff --git a/tools/go-agent/tools/types.go b/plugins/sql/entry/tx_commit.go
similarity index 54%
copy from tools/go-agent/tools/types.go
copy to plugins/sql/entry/tx_commit.go
index aabda3b..f9c76ee 100644
--- a/tools/go-agent/tools/types.go
+++ b/plugins/sql/entry/tx_commit.go
@@ -15,21 +15,33 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package tools
+package entry
 
-var basicDataTypes = make(map[string]bool)
+import (
+       "github.com/apache/skywalking-go/plugins/core/operator"
+       "github.com/apache/skywalking-go/plugins/core/tracing"
+)
 
-func init() {
-       types := []string{
-               "bool", "int8", "int16", "int32", "int64", "uint8", "uint16", 
"uint32", "uint64", "int", "uint", "uintptr",
-               "float32", "float64", "complex64", "complex128", "string", 
"error", "interface{}", "_", "byte",
-       }
-       for _, tp := range types {
-               basicDataTypes[tp] = true
+type TxCommitInterceptor struct {
+}
+
+func (n *TxCommitInterceptor) BeforeInvoke(invocation operator.Invocation) 
error {
+       span, err := createExitSpan(invocation.CallerInstance(), "Tx/Commit")
+       if err != nil {
+               return err
        }
+       invocation.SetContext(span)
+       return nil
 }
 
-// nolint
-func IsBasicDataType(name string) bool {
-       return basicDataTypes[name]
+func (n *TxCommitInterceptor) AfterInvoke(invocation operator.Invocation, 
results ...interface{}) error {
+       ctx := invocation.GetContext()
+       if ctx == nil {
+               return nil
+       }
+       if err, ok := results[0].(error); ok && err != nil {
+               ctx.(tracing.Span).Error(err.Error())
+       }
+       ctx.(tracing.Span).End()
+       return nil
 }
diff --git a/plugins/sql/entry/tx_exec.go b/plugins/sql/entry/tx_exec.go
new file mode 100644
index 0000000..fee5ca7
--- /dev/null
+++ b/plugins/sql/entry/tx_exec.go
@@ -0,0 +1,51 @@
+// 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/plugins/core/operator"
+       "github.com/apache/skywalking-go/plugins/core/tracing"
+)
+
+type TxExecInterceptor struct {
+}
+
+func (n *TxExecInterceptor) BeforeInvoke(invocation operator.Invocation) error 
{
+       span, err := createExitSpan(invocation.CallerInstance(), "Tx/Exec",
+               tracing.WithTag(tracing.TagDBStatement, 
invocation.Args()[1].(string)))
+       if err != nil {
+               return err
+       }
+       if config.CollectParameter && len(invocation.Args()[2].([]interface{})) 
> 0 {
+               span.Tag(tracing.TagDBSqlParameters, 
argsToString(invocation.Args()[2].([]interface{})))
+       }
+       invocation.SetContext(span)
+       return nil
+}
+
+func (n *TxExecInterceptor) AfterInvoke(invocation operator.Invocation, 
results ...interface{}) error {
+       ctx := invocation.GetContext()
+       if ctx == nil {
+               return nil
+       }
+       if err, ok := results[1].(error); ok && err != nil {
+               ctx.(tracing.Span).Error(err.Error())
+       }
+       ctx.(tracing.Span).End()
+       return nil
+}
diff --git a/tools/go-agent/tools/types.go b/plugins/sql/entry/tx_prepare.go
similarity index 65%
copy from tools/go-agent/tools/types.go
copy to plugins/sql/entry/tx_prepare.go
index aabda3b..1e64ae8 100644
--- a/tools/go-agent/tools/types.go
+++ b/plugins/sql/entry/tx_prepare.go
@@ -15,21 +15,19 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package tools
+package entry
 
-var basicDataTypes = make(map[string]bool)
+import (
+       "github.com/apache/skywalking-go/plugins/core/operator"
+)
 
-func init() {
-       types := []string{
-               "bool", "int8", "int16", "int32", "int64", "uint8", "uint16", 
"uint32", "uint64", "int", "uint", "uintptr",
-               "float32", "float64", "complex64", "complex128", "string", 
"error", "interface{}", "_", "byte",
-       }
-       for _, tp := range types {
-               basicDataTypes[tp] = true
-       }
+type TxPrepareInterceptor struct {
 }
 
-// nolint
-func IsBasicDataType(name string) bool {
-       return basicDataTypes[name]
+func (n *TxPrepareInterceptor) BeforeInvoke(invocation operator.Invocation) 
error {
+       return GeneralPrepareBeforeInvoke(invocation, "Tx/Prepare")
+}
+
+func (n *TxPrepareInterceptor) AfterInvoke(invocation operator.Invocation, 
results ...interface{}) error {
+       return GeneralPrepareAfterInvoke(invocation, results...)
 }
diff --git a/plugins/sql/entry/tx_query.go b/plugins/sql/entry/tx_query.go
new file mode 100644
index 0000000..0bb6336
--- /dev/null
+++ b/plugins/sql/entry/tx_query.go
@@ -0,0 +1,51 @@
+// 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/plugins/core/operator"
+       "github.com/apache/skywalking-go/plugins/core/tracing"
+)
+
+type TxQueryInterceptor struct {
+}
+
+func (n *TxQueryInterceptor) BeforeInvoke(invocation operator.Invocation) 
error {
+       span, err := createExitSpan(invocation.CallerInstance(), "Tx/Query",
+               tracing.WithTag(tracing.TagDBStatement, 
invocation.Args()[1].(string)))
+       if err != nil {
+               return err
+       }
+       if config.CollectParameter && len(invocation.Args()[2].([]interface{})) 
> 0 {
+               span.Tag(tracing.TagDBSqlParameters, 
argsToString(invocation.Args()[2].([]interface{})))
+       }
+       invocation.SetContext(span)
+       return nil
+}
+
+func (n *TxQueryInterceptor) AfterInvoke(invocation operator.Invocation, 
results ...interface{}) error {
+       ctx := invocation.GetContext()
+       if ctx == nil {
+               return nil
+       }
+       if err, ok := results[1].(error); ok && err != nil {
+               ctx.(tracing.Span).Error(err.Error())
+       }
+       ctx.(tracing.Span).End()
+       return nil
+}
diff --git a/tools/go-agent/tools/types.go b/plugins/sql/entry/tx_rollback.go
similarity index 54%
copy from tools/go-agent/tools/types.go
copy to plugins/sql/entry/tx_rollback.go
index aabda3b..b5cb3f8 100644
--- a/tools/go-agent/tools/types.go
+++ b/plugins/sql/entry/tx_rollback.go
@@ -15,21 +15,33 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package tools
+package entry
 
-var basicDataTypes = make(map[string]bool)
+import (
+       "github.com/apache/skywalking-go/plugins/core/operator"
+       "github.com/apache/skywalking-go/plugins/core/tracing"
+)
 
-func init() {
-       types := []string{
-               "bool", "int8", "int16", "int32", "int64", "uint8", "uint16", 
"uint32", "uint64", "int", "uint", "uintptr",
-               "float32", "float64", "complex64", "complex128", "string", 
"error", "interface{}", "_", "byte",
-       }
-       for _, tp := range types {
-               basicDataTypes[tp] = true
+type TxRollbackInterceptor struct {
+}
+
+func (n *TxRollbackInterceptor) BeforeInvoke(invocation operator.Invocation) 
error {
+       span, err := createExitSpan(invocation.CallerInstance(), "Tx/Rollback")
+       if err != nil {
+               return err
        }
+       invocation.SetContext(span)
+       return nil
 }
 
-// nolint
-func IsBasicDataType(name string) bool {
-       return basicDataTypes[name]
+func (n *TxRollbackInterceptor) AfterInvoke(invocation operator.Invocation, 
results ...interface{}) error {
+       ctx := invocation.GetContext()
+       if ctx == nil {
+               return nil
+       }
+       if err, ok := results[0].(error); ok && err != nil {
+               ctx.(tracing.Span).Error(err.Error())
+       }
+       ctx.(tracing.Span).End()
+       return nil
 }
diff --git a/tools/go-agent/tools/types.go b/plugins/sql/entry/tx_stmt.go
similarity index 61%
copy from tools/go-agent/tools/types.go
copy to plugins/sql/entry/tx_stmt.go
index aabda3b..2d898e8 100644
--- a/tools/go-agent/tools/types.go
+++ b/plugins/sql/entry/tx_stmt.go
@@ -15,21 +15,24 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package tools
+package entry
 
-var basicDataTypes = make(map[string]bool)
+import (
+       "database/sql"
 
-func init() {
-       types := []string{
-               "bool", "int8", "int16", "int32", "int64", "uint8", "uint16", 
"uint32", "uint64", "int", "uint", "uintptr",
-               "float32", "float64", "complex64", "complex128", "string", 
"error", "interface{}", "_", "byte",
-       }
-       for _, tp := range types {
-               basicDataTypes[tp] = true
-       }
+       "github.com/apache/skywalking-go/plugins/core/operator"
+)
+
+type TxStmtInterceptor struct {
 }
 
-// nolint
-func IsBasicDataType(name string) bool {
-       return basicDataTypes[name]
+func (n *TxStmtInterceptor) BeforeInvoke(invocation operator.Invocation) error 
{
+       return nil
+}
+
+func (n *TxStmtInterceptor) AfterInvoke(invocation operator.Invocation, 
results ...interface{}) error {
+       if stmt, ok := results[0].(*sql.Stmt); ok && stmt != nil {
+               
results[0].(operator.EnhancedInstance).SetSkyWalkingDynamicField(getInstanceInfo(invocation.CallerInstance()))
+       }
+       return nil
 }
diff --git a/plugins/sql/go.mod b/plugins/sql/go.mod
new file mode 100644
index 0000000..4732679
--- /dev/null
+++ b/plugins/sql/go.mod
@@ -0,0 +1,5 @@
+module github.com/apache/skywalking-go/plugins/sql
+
+go 1.18
+
+require github.com/go-sql-driver/mysql v1.7.1 // indirect
diff --git a/plugins/sql/mysql/instrument.go b/plugins/sql/mysql/instrument.go
new file mode 100644
index 0000000..3d60876
--- /dev/null
+++ b/plugins/sql/mysql/instrument.go
@@ -0,0 +1,67 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package mysql
+
+import (
+       "embed"
+
+       "github.com/apache/skywalking-go/plugins/core/instrument"
+)
+
+//go:embed *
+var fs embed.FS
+
+//skywalking:nocopy
+type Instrument struct {
+}
+
+func NewInstrument() *Instrument {
+       return &Instrument{}
+}
+
+func (i *Instrument) Name() string {
+       return "sql"
+}
+
+func (i *Instrument) BasePackage() string {
+       return "github.com/go-sql-driver/mysql"
+}
+
+func (i *Instrument) VersionChecker(version string) bool {
+       return true
+}
+
+func (i *Instrument) Points() []*instrument.Point {
+       return []*instrument.Point{
+               {
+                       PackagePath: "",
+                       At: instrument.NewStaticMethodEnhance("ParseDSN",
+                               instrument.WithArgsCount(1), 
instrument.WithArgType(0, "string"),
+                               instrument.WithResultCount(2), 
instrument.WithResultType(0, "*Config"), instrument.WithResultType(1, "error")),
+                       Interceptor: "ParseInterceptor",
+               },
+       }
+}
+
+func (i *Instrument) PluginSourceCodePath() string {
+       return "mysql"
+}
+
+func (i *Instrument) FS() *embed.FS {
+       return &fs
+}
diff --git a/tools/go-agent/tools/types.go 
b/plugins/sql/mysql/parse_interceptor.go
similarity index 51%
copy from tools/go-agent/tools/types.go
copy to plugins/sql/mysql/parse_interceptor.go
index aabda3b..d6fd839 100644
--- a/tools/go-agent/tools/types.go
+++ b/plugins/sql/mysql/parse_interceptor.go
@@ -15,21 +15,41 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package tools
+package mysql
 
-var basicDataTypes = make(map[string]bool)
+import (
+       "github.com/go-sql-driver/mysql"
 
-func init() {
-       types := []string{
-               "bool", "int8", "int16", "int32", "int64", "uint8", "uint16", 
"uint32", "uint64", "int", "uint", "uintptr",
-               "float32", "float64", "complex64", "complex128", "string", 
"error", "interface{}", "_", "byte",
-       }
-       for _, tp := range types {
-               basicDataTypes[tp] = true
+       "github.com/apache/skywalking-go/plugins/core/operator"
+       "github.com/apache/skywalking-go/plugins/core/tracing"
+)
+
+type ParseInterceptor struct {
+}
+
+func (n *ParseInterceptor) BeforeInvoke(invocation operator.Invocation) error {
+       return nil
+}
+
+func (n *ParseInterceptor) AfterInvoke(invocation operator.Invocation, results 
...interface{}) error {
+       if cfg, ok := results[0].(*mysql.Config); ok && cfg != nil && 
tracing.GetRuntimeContextValue("needInfo") == true {
+               tracing.SetRuntimeContextValue("info", &DBInfo{Addr: cfg.Addr})
        }
+       return nil
+}
+
+type DBInfo struct {
+       Addr string
+}
+
+func (i *DBInfo) Peer() string {
+       return i.Addr
+}
+
+func (i *DBInfo) ComponentID() int32 {
+       return 5012
 }
 
-// nolint
-func IsBasicDataType(name string) bool {
-       return basicDataTypes[name]
+func (i *DBInfo) DBType() string {
+       return "Mysql"
 }
diff --git a/test/plugins/scenarios/gorm/config/excepted.yml 
b/test/plugins/scenarios/gorm/config/excepted.yml
index 7c044c7..bdd59d2 100644
--- a/test/plugins/scenarios/gorm/config/excepted.yml
+++ b/test/plugins/scenarios/gorm/config/excepted.yml
@@ -32,8 +32,8 @@ segmentItems:
             peer: mysql-server:3306
             skipAnalysis: false
             tags:
-              - {key: db.type, value: mysql}
-          - operationName: users/create
+              - { key: db.type, value: mysql }
+          - operationName: Mysql/BeginTx
             parentSpanId: 0
             spanId: 2
             spanLayer: Database
@@ -41,14 +41,40 @@ segmentItems:
             endTime: nq 0
             componentId: 5012
             isError: false
+            spanType: Local
+            peer: ''
+            skipAnalysis: false
+            tags:
+              - { key: db.type, value: Mysql }
+          - operationName: users/create
+            parentSpanId: 0
+            spanId: 3
+            spanLayer: Database
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 5012
+            isError: false
+            spanType: Exit
+            peer: mysql-server:3306
+            skipAnalysis: false
+            tags:
+              - { key: db.type, value: mysql }
+          - operationName: Mysql/Tx/Commit
+            parentSpanId: 0
+            spanId: 4
+            spanLayer: Database
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 5012
+            isError: false
             spanType: Exit
             peer: mysql-server:3306
             skipAnalysis: false
             tags:
-              - {key: db.type, value: mysql}
+              - { key: db.type, value: Mysql }
           - operationName: users/query
             parentSpanId: 0
-            spanId: 3
+            spanId: 5
             spanLayer: Database
             startTime: nq 0
             endTime: nq 0
@@ -58,10 +84,10 @@ segmentItems:
             peer: mysql-server:3306
             skipAnalysis: false
             tags:
-              - {key: db.type, value: mysql}
+              - { key: db.type, value: mysql }
           - operationName: users/row
             parentSpanId: 0
-            spanId: 4
+            spanId: 6
             spanLayer: Database
             startTime: nq 0
             endTime: nq 0
@@ -71,10 +97,23 @@ segmentItems:
             peer: mysql-server:3306
             skipAnalysis: false
             tags:
-              - {key: db.type, value: mysql}
+              - { key: db.type, value: mysql }
+          - operationName: Mysql/BeginTx
+            parentSpanId: 0
+            spanId: 7
+            spanLayer: Database
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 5012
+            isError: false
+            spanType: Local
+            peer: ''
+            skipAnalysis: false
+            tags:
+              - { key: db.type, value: Mysql }
           - operationName: users/update
             parentSpanId: 0
-            spanId: 5
+            spanId: 8
             spanLayer: Database
             startTime: nq 0
             endTime: nq 0
@@ -84,10 +123,49 @@ segmentItems:
             peer: mysql-server:3306
             skipAnalysis: false
             tags:
-              - {key: db.type, value: mysql}
+              - { key: db.type, value: mysql }
+          - operationName: Mysql/Tx/Commit
+            parentSpanId: 0
+            spanId: 9
+            spanLayer: Database
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 5012
+            isError: false
+            spanType: Exit
+            peer: mysql-server:3306
+            skipAnalysis: false
+            tags:
+              - { key: db.type, value: Mysql }
+          - operationName: Mysql/BeginTx
+            parentSpanId: 0
+            spanId: 10
+            spanLayer: Database
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 5012
+            isError: false
+            spanType: Local
+            peer: ''
+            skipAnalysis: false
+            tags:
+              - { key: db.type, value: Mysql }
           - operationName: users/delete
             parentSpanId: 0
-            spanId: 6
+            spanId: 11
+            spanLayer: Database
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 5012
+            isError: false
+            spanType: Exit
+            peer: mysql-server:3306
+            skipAnalysis: false
+            tags:
+              - { key: db.type, value: mysql }
+          - operationName: Mysql/Tx/Commit
+            parentSpanId: 0
+            spanId: 12
             spanLayer: Database
             startTime: nq 0
             endTime: nq 0
@@ -97,7 +175,7 @@ segmentItems:
             peer: mysql-server:3306
             skipAnalysis: false
             tags:
-              - {key: db.type, value: mysql}
+              - { key: db.type, value: Mysql }
           - operationName: GET:/execute
             parentSpanId: -1
             spanId: 0
@@ -110,8 +188,8 @@ segmentItems:
             peer: ''
             skipAnalysis: false
             tags:
-              - {key: http.method, value: GET}
-              - {key: url, value: 'service:8080/execute'}
-              - {key: status_code, value: '200'}
+              - { key: http.method, value: GET }
+              - { key: url, value: 'service:8080/execute' }
+              - { key: status_code, value: '200' }
 meterItems: []
 logItems: []
diff --git a/test/plugins/scenarios/mongo/plugin.yml 
b/test/plugins/scenarios/mongo/plugin.yml
index 1e785b5..a57750c 100644
--- a/test/plugins/scenarios/mongo/plugin.yml
+++ b/test/plugins/scenarios/mongo/plugin.yml
@@ -22,7 +22,6 @@ export-port: 8080
 support-version:
   - go: 1.18
     framework:
-      - v1.11.0
       - v1.10.5
       - v1.11.1
       - v1.10.6
diff --git a/test/plugins/scenarios/mongo/plugin.yml 
b/test/plugins/scenarios/mysql/bin/startup.sh
old mode 100644
new mode 100755
similarity index 50%
copy from test/plugins/scenarios/mongo/plugin.yml
copy to test/plugins/scenarios/mysql/bin/startup.sh
index 1e785b5..f1f80c2
--- a/test/plugins/scenarios/mongo/plugin.yml
+++ b/test/plugins/scenarios/mysql/bin/startup.sh
@@ -1,3 +1,5 @@
+#!/bin/bash
+#
 # Licensed to the Apache Software Foundation (ASF) under one
 # or more contributor license agreements.  See the NOTICE file
 # distributed with this work for additional information
@@ -14,35 +16,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-entry-service: http://${HTTP_HOST}:${HTTP_PORT}/execute
-health-checker: http://${HTTP_HOST}:${HTTP_PORT}/health
-start-script: ./bin/startup.sh
-framework: go.mongodb.org/mongo-driver
-export-port: 8080
-support-version:
-  - go: 1.18
-    framework:
-      - v1.11.0
-      - v1.10.5
-      - v1.11.1
-      - v1.10.6
-      - v1.11.2
-      - v1.11.3
-      - v1.11.4
-      - v1.11.6
-      - v1.11.7
-dependencies:
-  mongo:
-    image: mongo
-    hostname: mongo
-    expose:
-      - "27017"
-    environment:
-      MONGO_INITDB_ROOT_USERNAME: user
-      MONGO_INITDB_ROOT_PASSWORD: password
-      MONGO_INITDB_DATABASE: database
-    healthcheck:
-      test: [ "CMD", "bash", "-c", "cat < /dev/null > 
/dev/tcp/127.0.0.1/27017" ]
-      interval: 5s
-      timeout: 60s
-      retries: 120
\ No newline at end of file
+home="$(cd "$(dirname $0)"; pwd)"
+go build ${GO_BUILD_OPTS} -o mysql main.go
+
+export SW_AGENT_PLUGIN_CONFIG_SQL_COLLECT_PARAMETER=true
+./mysql
\ No newline at end of file
diff --git a/test/plugins/scenarios/mysql/config/excepted.yml 
b/test/plugins/scenarios/mysql/config/excepted.yml
new file mode 100644
index 0000000..7df8c23
--- /dev/null
+++ b/test/plugins/scenarios/mysql/config/excepted.yml
@@ -0,0 +1,250 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+segmentItems:
+  - serviceName: mysql
+    segmentSize: ge 1
+    segments:
+      - segmentId: not null
+        spans:
+          - operationName: Mysql/Ping
+            parentSpanId: 0
+            spanId: 1
+            spanLayer: Database
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 5012
+            isError: false
+            spanType: Exit
+            peer: mysql:3306
+            skipAnalysis: false
+            tags:
+              - { key: db.type, value: Mysql }
+          - operationName: Mysql/Exec
+            parentSpanId: 0
+            spanId: 2
+            spanLayer: Database
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 5012
+            isError: false
+            spanType: Exit
+            peer: mysql:3306
+            skipAnalysis: false
+            tags:
+              - { key: db.statement, value: "DROP TABLE IF EXISTS users" }
+              - { key: db.type, value: Mysql }
+          - operationName: Mysql/Exec
+            parentSpanId: 0
+            spanId: 3
+            spanLayer: Database
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 5012
+            isError: false
+            spanType: Exit
+            peer: mysql:3306
+            skipAnalysis: false
+            tags:
+              - { key: db.statement, value: 'CREATE TABLE IF NOT EXISTS users 
(id char(255), name VARCHAR(255), age INTEGER)' }
+              - { key: db.type, value: Mysql }
+          - operationName: Mysql/Exec
+            parentSpanId: 0
+            spanId: 4
+            spanLayer: Database
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 5012
+            isError: false
+            spanType: Exit
+            peer: mysql:3306
+            skipAnalysis: false
+            tags:
+              - { key: db.statement, value: 'INSERT INTO users (id, name, age) 
VALUE ( ?, ?, ?)' }
+              - { key: db.type, value: Mysql }
+              - {key: db.sql.parameters, value: '0, foo, 10'}
+          - operationName: Mysql/Query
+            parentSpanId: 0
+            spanId: 5
+            spanLayer: Database
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 5012
+            isError: false
+            spanType: Exit
+            peer: mysql:3306
+            skipAnalysis: false
+            tags:
+              - { key: db.statement, value: 'SELECT name FROM users WHERE id = 
?' }
+              - { key: db.type, value: Mysql }
+              - {key: db.sql.parameters, value: '0'}
+          - operationName: Mysql/Prepare
+            parentSpanId: 0
+            spanId: 6
+            spanLayer: Database
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 5012
+            isError: false
+            spanType: Local
+            peer: ''
+            skipAnalysis: false
+            tags:
+              - { key: db.statement, value: 'INSERT INTO users (id, name, age) 
VALUE ( ?, ?, ?)' }
+              - { key: db.type, value: Mysql }
+          - operationName: Mysql/Stmt/Exec
+            parentSpanId: 0
+            spanId: 7
+            spanLayer: Database
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 5012
+            isError: false
+            spanType: Exit
+            peer: mysql:3306
+            skipAnalysis: false
+            tags:
+              - { key: db.type, value: Mysql }
+              - {key: db.sql.parameters, value: '1, bar, 11'}
+          - operationName: Mysql/BeginTx
+            parentSpanId: 0
+            spanId: 8
+            spanLayer: Database
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 5012
+            isError: false
+            spanType: Local
+            peer: ''
+            skipAnalysis: false
+            tags:
+              - { key: db.type, value: Mysql }
+          - operationName: Mysql/Tx/Exec
+            parentSpanId: 0
+            spanId: 9
+            spanLayer: Database
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 5012
+            isError: false
+            spanType: Exit
+            peer: mysql:3306
+            skipAnalysis: false
+            tags:
+              - { key: db.statement, value: 'INSERT INTO users (id, name, age) 
VALUE ( ?, ?, ? )' }
+              - { key: db.type, value: Mysql }
+              - {key: db.sql.parameters, value: '2, foobar, 24'}
+          - operationName: Mysql/Tx/Exec
+            parentSpanId: 0
+            spanId: 10
+            spanLayer: Database
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 5012
+            isError: false
+            spanType: Exit
+            peer: mysql:3306
+            skipAnalysis: false
+            tags:
+              - { key: db.statement, value: 'UPDATE users SET name = ? WHERE 
id = ?' }
+              - { key: db.type, value: Mysql }
+              - {key: db.sql.parameters, value: 'foobar, 0'}
+          - operationName: Mysql/Tx/Commit
+            parentSpanId: 0
+            spanId: 11
+            spanLayer: Database
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 5012
+            isError: false
+            spanType: Exit
+            peer: mysql:3306
+            skipAnalysis: false
+            tags:
+              - { key: db.type, value: Mysql }
+          - operationName: Mysql/BeginTx
+            parentSpanId: 0
+            spanId: 12
+            spanLayer: Database
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 5012
+            isError: false
+            spanType: Local
+            peer: ''
+            skipAnalysis: false
+            tags:
+              - { key: db.type, value: Mysql }
+          - operationName: Mysql/Tx/Exec
+            parentSpanId: 0
+            spanId: 13
+            spanLayer: Database
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 5012
+            isError: false
+            spanType: Exit
+            peer: mysql:3306
+            skipAnalysis: false
+            tags:
+              - { key: db.statement, value: 'UPDATE users SET age = ? WHERE id 
= ?' }
+              - { key: db.type, value: Mysql }
+              - {key: db.sql.parameters, value: '48, 2'}
+          - operationName: Mysql/Tx/Exec
+            parentSpanId: 0
+            spanId: 14
+            spanLayer: Database
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 5012
+            isError: false
+            spanType: Exit
+            peer: mysql:3306
+            skipAnalysis: false
+            tags:
+              - { key: db.statement, value: 'UPDATE users SET name = ? WHERE 
id = ?' }
+              - { key: db.type, value: Mysql }
+              - {key: db.sql.parameters, value: 'foobar, 1'}
+          - operationName: Mysql/Tx/Rollback
+            parentSpanId: 0
+            spanId: 15
+            spanLayer: Database
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 5012
+            isError: false
+            spanType: Exit
+            peer: mysql:3306
+            skipAnalysis: false
+            tags:
+              - { key: db.type, value: Mysql }
+          - operationName: GET:/execute
+            parentSpanId: -1
+            spanId: 0
+            spanLayer: Http
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 5004
+            isError: false
+            spanType: Entry
+            peer: ''
+            skipAnalysis: false
+            tags:
+              - { key: http.method, value: GET }
+              - { key: url, value: 'service:8080/execute' }
+              - { key: status_code, value: '200' }
+meterItems: []
+logItems: []
diff --git a/test/plugins/scenarios/mysql/go.mod 
b/test/plugins/scenarios/mysql/go.mod
new file mode 100644
index 0000000..73340f6
--- /dev/null
+++ b/test/plugins/scenarios/mysql/go.mod
@@ -0,0 +1,5 @@
+module test/plugins/scenarios/mysql
+
+go 1.18
+
+require github.com/go-sql-driver/mysql v1.7.1 // indirect
diff --git a/test/plugins/scenarios/mysql/go.sum 
b/test/plugins/scenarios/mysql/go.sum
new file mode 100644
index 0000000..fd7ae07
--- /dev/null
+++ b/test/plugins/scenarios/mysql/go.sum
@@ -0,0 +1,2 @@
+github.com/go-sql-driver/mysql v1.7.1 
h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
+github.com/go-sql-driver/mysql v1.7.1/go.mod 
h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
diff --git a/test/plugins/scenarios/mysql/main.go 
b/test/plugins/scenarios/mysql/main.go
new file mode 100644
index 0000000..791cb19
--- /dev/null
+++ b/test/plugins/scenarios/mysql/main.go
@@ -0,0 +1,161 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package main
+
+import (
+       "context"
+       "database/sql"
+       "fmt"
+       "log"
+       "net/http"
+       "time"
+
+       _ "github.com/go-sql-driver/mysql"
+
+       _ "github.com/apache/skywalking-go"
+)
+
+type testFunc func(context.Context, *sql.DB) error
+
+func main() {
+       db, err := sql.Open("mysql", "user:password@tcp(mysql:3306)/database")
+       if err != nil {
+               panic(err)
+       }
+       // See "Important settings" section.
+       db.SetConnMaxLifetime(time.Minute * 3)
+       db.SetMaxOpenConns(10)
+       db.SetMaxIdleConns(10)
+
+       route := http.NewServeMux()
+       route.HandleFunc("/execute", func(res http.ResponseWriter, req 
*http.Request) {
+               tests := []struct {
+                       name string
+                       fn   testFunc
+               }{
+                       {"exec", testExec},
+                       {"stmt", testStmt},
+                       {"commitTx", testCommitTx},
+                       {"rollbackTx", testRollbackTx},
+               }
+
+               for _, test := range tests {
+                       log.Printf("excute test case %s", test.name)
+                       if err1 := test.fn(req.Context(), db); err1 != nil {
+                               log.Printf("test case %s failed: %v", 
test.name, err1)
+                       }
+               }
+               _, _ = res.Write([]byte("execute sql success"))
+       })
+
+       route.HandleFunc("/health", func(writer http.ResponseWriter, request 
*http.Request) {
+               writer.Write([]byte("ok"))
+       })
+
+       log.Println("start client")
+       err = http.ListenAndServe(":8080", route)
+       if err != nil {
+               log.Fatalf("client start error: %v \n", err)
+       }
+
+}
+
+func testExec(ctx context.Context, db *sql.DB) error {
+       if err := db.PingContext(ctx); err != nil {
+               return err
+       }
+
+       if _, err := db.ExecContext(ctx, `DROP TABLE IF EXISTS users`); err != 
nil {
+               return fmt.Errorf("exec drop error: %w", err)
+       }
+
+       if _, err := db.ExecContext(ctx, `CREATE TABLE IF NOT EXISTS users (id 
char(255), name VARCHAR(255), age INTEGER)`); err != nil {
+               return fmt.Errorf("exec create error: %w", err)
+       }
+
+       // test insert
+       if _, err := db.ExecContext(ctx, `INSERT INTO users (id, name, age) 
VALUE ( ?, ?, ?)`, "0", "foo", 10); err != nil {
+               return fmt.Errorf("exec insert error: %w", err)
+       }
+
+       var name string
+       // test select
+       if err := db.QueryRowContext(ctx, `SELECT name FROM users WHERE id = 
?`, "0").Scan(&name); err != nil {
+               return fmt.Errorf("query select error: %w", err)
+       }
+
+       return nil
+}
+
+func testStmt(ctx context.Context, db *sql.DB) error {
+       stmt, err := db.PrepareContext(ctx, `INSERT INTO users (id, name, age) 
VALUE ( ?, ?, ?)`)
+       if err != nil {
+               return err
+       }
+       defer func() {
+               _ = stmt.Close()
+       }()
+
+       _, err = stmt.ExecContext(ctx, "1", "bar", 11)
+       if err != nil {
+               return err
+       }
+
+       return nil
+}
+
+func testCommitTx(ctx context.Context, db *sql.DB) error {
+       tx, err := db.BeginTx(ctx, nil)
+       if err != nil {
+               return fmt.Errorf("begin tx error: %v", err)
+       }
+
+       if _, err := tx.Exec(`INSERT INTO users (id, name, age) VALUE ( ?, ?, ? 
)`, "2", "foobar", 24); err != nil {
+               return err
+       }
+
+       if _, err := tx.ExecContext(ctx, `UPDATE users SET name = ? WHERE id = 
?`, "foobar", "0"); err != nil {
+               return err
+       }
+
+       if err := tx.Commit(); err != nil {
+               return err
+       }
+
+       return nil
+}
+
+func testRollbackTx(ctx context.Context, db *sql.DB) error {
+       tx, err := db.BeginTx(ctx, nil)
+       if err != nil {
+               return fmt.Errorf("begin tx error: %v", err)
+       }
+
+       if _, err := tx.Exec(`UPDATE users SET age = ? WHERE id = ?`, 48, "2"); 
err != nil {
+               return err
+       }
+
+       if _, err := tx.ExecContext(ctx, `UPDATE users SET name = ? WHERE id = 
?`, "foobar", "1"); err != nil {
+               return err
+       }
+
+       if err := tx.Rollback(); err != nil {
+               return err
+       }
+       return nil
+}
diff --git a/test/plugins/scenarios/mongo/plugin.yml 
b/test/plugins/scenarios/mysql/plugin.yml
similarity index 67%
copy from test/plugins/scenarios/mongo/plugin.yml
copy to test/plugins/scenarios/mysql/plugin.yml
index 1e785b5..6b93abe 100644
--- a/test/plugins/scenarios/mongo/plugin.yml
+++ b/test/plugins/scenarios/mysql/plugin.yml
@@ -17,32 +17,38 @@
 entry-service: http://${HTTP_HOST}:${HTTP_PORT}/execute
 health-checker: http://${HTTP_HOST}:${HTTP_PORT}/health
 start-script: ./bin/startup.sh
-framework: go.mongodb.org/mongo-driver
+framework: github.com/go-sql-driver/mysql
 export-port: 8080
 support-version:
+  - go: 1.17
+    framework:
+      - v1.7.1
   - go: 1.18
     framework:
-      - v1.11.0
-      - v1.10.5
-      - v1.11.1
-      - v1.10.6
-      - v1.11.2
-      - v1.11.3
-      - v1.11.4
-      - v1.11.6
-      - v1.11.7
+      - v1.4.0
+      - v1.4.1
+      - v1.5.0
+      - v1.6.0
+      - v1.7.1
+  - go: 1.19
+    framework:
+      - v1.7.1
+  - go: 1.20
+    framework:
+      - v1.7.1
 dependencies:
-  mongo:
-    image: mongo
-    hostname: mongo
+  mysql:
+    image: mysql:5.7
+    hostname: mysql-server
     expose:
-      - "27017"
+      - "3306"
     environment:
-      MONGO_INITDB_ROOT_USERNAME: user
-      MONGO_INITDB_ROOT_PASSWORD: password
-      MONGO_INITDB_DATABASE: database
+      MYSQL_ROOT_PASSWORD: "password"
+      MYSQL_USER: "user"
+      MYSQL_PASSWORD: "password"
+      MYSQL_DATABASE: "database"
     healthcheck:
-      test: [ "CMD", "bash", "-c", "cat < /dev/null > 
/dev/tcp/127.0.0.1/27017" ]
+      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
       interval: 5s
       timeout: 60s
       retries: 120
\ No newline at end of file
diff --git a/tools/go-agent/config/agent.default.yaml 
b/tools/go-agent/config/agent.default.yaml
index 413fc59..6e563bd 100644
--- a/tools/go-agent/config/agent.default.yaml
+++ b/tools/go-agent/config/agent.default.yaml
@@ -59,4 +59,7 @@ plugin:
       server_collect_parameters: 
${SW_AGENT_PLUGIN_CONFIG_HTTP_SERVER_COLLECT_PARAMETERS:false}
     mongo:
       # Collect the statement of the MongoDB request
-      collect_statement: 
${SW_AGENT_PLUGIN_CONFIG_MONGO_COLLECT_STATEMENT:false}
\ No newline at end of file
+      collect_statement: 
${SW_AGENT_PLUGIN_CONFIG_MONGO_COLLECT_STATEMENT:false}
+    sql:
+      # Collect the parameter of the SQL request
+      collect_parameter: ${SW_AGENT_PLUGIN_CONFIG_SQL_COLLECT_PARAMETER:false}
diff --git a/tools/go-agent/instrument/instrument.go 
b/tools/go-agent/instrument/instrument.go
index e0b8a03..f32c298 100644
--- a/tools/go-agent/instrument/instrument.go
+++ b/tools/go-agent/instrument/instrument.go
@@ -150,11 +150,18 @@ func instrumentFiles(buildDir string, inst 
api.Instrument, args []string) error
 
 func parseFilesInArgs(args []string) (map[string]*fileInfo, error) {
        parsedFiles := make(map[string]*fileInfo)
+       var lastPath string
+       defer func() {
+               if e := recover(); e != nil {
+                       logrus.Errorf("panic when parsing files: %s: %v", 
lastPath, e)
+               }
+       }()
        for inx, path := range args {
                // only process the go file
                if !strings.HasSuffix(path, ".go") {
                        continue
                }
+               lastPath = path
 
                // parse the file
                file, err := decorator.ParseFile(nil, path, nil, 
parser.ParseComments)
diff --git a/tools/go-agent/instrument/plugins/register.go 
b/tools/go-agent/instrument/plugins/register.go
index 0afdf5f..0089122 100644
--- a/tools/go-agent/instrument/plugins/register.go
+++ b/tools/go-agent/instrument/plugins/register.go
@@ -29,6 +29,8 @@ import (
        "github.com/apache/skywalking-go/plugins/kratosv2"
        "github.com/apache/skywalking-go/plugins/microv4"
        "github.com/apache/skywalking-go/plugins/mongo"
+       sql_entry "github.com/apache/skywalking-go/plugins/sql/entry"
+       sql_mysql "github.com/apache/skywalking-go/plugins/sql/mysql"
 )
 
 var instruments = make([]instrument.Instrument, 0)
@@ -47,6 +49,10 @@ func init() {
        // gorm related instruments
        registerFramework(gorm_entry.NewInstrument())
        registerFramework(gorm_mysql.NewInstrument())
+
+       // sql related instruments
+       registerFramework(sql_entry.NewInstrument())
+       registerFramework(sql_mysql.NewInstrument())
 }
 
 func registerFramework(ins instrument.Instrument) {
diff --git a/tools/go-agent/tools/enhancement.go 
b/tools/go-agent/tools/enhancement.go
index 2ef0acb..927b06d 100644
--- a/tools/go-agent/tools/enhancement.go
+++ b/tools/go-agent/tools/enhancement.go
@@ -28,6 +28,7 @@ import (
 
 const interfaceName = "interface{}"
 const OtherPackageRefPrefix = "swref_"
+const parameterAppender = ", "
 
 type ParameterInfo struct {
        Name                 string
@@ -144,6 +145,7 @@ func (p *PackagedParameterInfo) PackagedTypeName() string {
        return GenerateTypeNameByExp(p.PackagedType())
 }
 
+// nolint
 func GenerateTypeNameByExp(exp dst.Expr) string {
        var data string
        switch n := exp.(type) {
@@ -161,6 +163,27 @@ func GenerateTypeNameByExp(exp dst.Expr) string {
                data = "[]" + GenerateTypeNameByExp(n.Elt)
        case *dst.ArrayType:
                data = "[]" + GenerateTypeNameByExp(n.Elt)
+       case *dst.FuncType:
+               data = "func("
+               if n.Params != nil && len(n.Params.List) > 0 {
+                       for i, f := range n.Params.List {
+                               if i > 0 {
+                                       data += parameterAppender
+                               }
+                               data += GenerateTypeNameByExp(f.Type)
+                       }
+               }
+               data += ")"
+               if n.Results != nil && len(n.Results.List) > 0 {
+                       data += "("
+                       for i, f := range n.Results.List {
+                               if i > 0 {
+                                       data += parameterAppender
+                               }
+                               data += GenerateTypeNameByExp(f.Type)
+                       }
+                       data += ")"
+               }
        default:
                return ""
        }
diff --git a/tools/go-agent/tools/types.go b/tools/go-agent/tools/types.go
index aabda3b..8bbf785 100644
--- a/tools/go-agent/tools/types.go
+++ b/tools/go-agent/tools/types.go
@@ -22,7 +22,7 @@ var basicDataTypes = make(map[string]bool)
 func init() {
        types := []string{
                "bool", "int8", "int16", "int32", "int64", "uint8", "uint16", 
"uint32", "uint64", "int", "uint", "uintptr",
-               "float32", "float64", "complex64", "complex128", "string", 
"error", "interface{}", "_", "byte",
+               "float32", "float64", "complex64", "complex128", "string", 
"error", "interface{}", "_", "byte", "any",
        }
        for _, tp := range types {
                basicDataTypes[tp] = true


Reply via email to