wu-sheng commented on code in PR #13:
URL: https://github.com/apache/skywalking-go/pull/13#discussion_r1174985369
##########
docs/en/development-and-contribution/development-guide.md:
##########
@@ -0,0 +1,333 @@
+# Plugin Development Guide
+
+This documentation introduces how developers can create a plugin.
+
+All plugins must follow these steps:
+
+1. **Create a new plugin module**: Create a new project in the specified
directory and import the plugin API module.
+2. **Define the enhancement object**: Define the description for the plugin.
+3. **Invoke the plugin API**: Call the API provided by the core to complete
the core invocation.
+4. **Import the plugin module**: Import the plugin into the management module
for users to use.
+
+## Create a new plugin module
+
+The plugin must create a new module, which is currently stored in the
project's [plugins directory](../../../plugins).
+
+Plugins can import the following two modules:
+
+1. **Agent core**: This module provides all the dependencies needed for the
plugin, including the plugin API, enhancement declaration objects, etc.
+Agent core plugin should be `github.com/apache/skywalking-go/plugins/core` and
replaced by the relative location.
+2. **Framework to be enhanced**: Import the framework you wish to enhance.
+
+Note: Plugins should not import and use other unrelated modules, as this may
cause compilation issues for users. If certain tools are needed, they should be
provided by the agent core.
+
+## Define the enhancement object
+
+In the root directory of the project, **create a new go file** to define the
basic information of the plugin.
+The basic information includes the following methods, corresponding to the
[Instrument interface](../../../plugins/core/instrument/declare.go):
+
+1. **Name**: The name of the plugin. Please keep this name consistent with the
newly created project name. The reason will be explained later.
+2. **Base Package**: Declare which package this plugin intercepts. For
example, if you want to intercept gin, you can write:
"github.com/gin-gonic/gin".
+3. **Version Checker**: This method passes the version number to the
enhancement object to verify whether the specified version of the framework is
supported. If not, the enhancement program will not be executed.
+4. **Points**: A plugin can define one or more enhancement points. This will
be explained in more detail in the following sections.
+5. **File System**: Use `//go:embed *` in the current file to import all files
in this module, which will be used for file copying during the mixed
compilation process.
+
+Note: Please declare `//skywalking:nocopy` at any position in this file to
indicate that the file would not be copied. This file is only used for guidance
during hybrid compilation.
+Also, this file involves the use of the `embed` package, and if the target
framework does not import the package `embed`, a compilation error may occur.
+
+### Instrument Point
+
+Instrument points are used to enhance methods and struct in the current
package. They mainly include the following information:
+
+1. **Package path**: If the interception point that needs to be intercepted is
not in the root directory of the current package, you need to fill in the
relative path to the package.
+For example, if this interception point wants to instrument content in the
`github.com/gin-gonic/gin/render` directory, you need to fill in `render` here.
+2. **Matcher(At)**: Specify which eligible content in the current package path
needs to be enhanced.
+3. **Interceptor**: If the current method is being intercepted (whether it's a
static method or an instance method), the name of the interceptor must be
specified.
+
+#### Method Matcher
+
+Method matchers are used to intercept both static and non-static methods. The
specific definitions are as follows:
+
+```go
+// NewStaticMethodEnhance creates a new EnhanceMatcher for static method.
+// name: method name needs to be enhanced.(Public and private methods are
supported)
+// filters: filters for method.
+func NewStaticMethodEnhance(name string, filters ...MethodFilterOption)
+
+// NewMethodEnhance creates a new EnhanceMatcher for method.
+// receiver: receiver type name of method needs to be enhanced.
+// name: method name needs to be enhanced.(Public and private methods are
supported)
+// filters: filters for method.
+func NewMethodEnhance(receiver, name string, filters ...MethodFilterOption)
+```
+
+##### Filter Option
+
+Filter Options are used to validate the parameters or return values in the
method.
+If the method name matches but the Options validation fails, the enhancement
would not be performed.
+
+```go
+// WithArgsCount filter methods with specific count of arguments.
+func WithArgsCount(argsCount int)
+
+// WithResultCount filter methods with specific count of results.
+func WithResultCount(resultCount int)
+
+// WithArgType filter methods with specific type of the index of the argument.
+func WithArgType(argIndex int, dataType string)
+
+// WithResultType filter methods with specific type of the index of the result.
+func WithResultType(argIndex int, dataType string)
+```
+
+##### Demo
+
+For example, if you have the following method that needs to be intercepted:
+
+```go
+func (c *Context) HandleMethod(name string) bool
+```
+
+you can describe it using this condition:
+
+```go
+instrument.NewMethodEnhance("*Context", "HandleMethod",
+ instrument.WithArgsCount(1), instrument.WithArgType(0, "string"),
+ instrument.WithResultCount(1), instrument.WithResultType(0, "bool"))
+```
+
+#### Struct Matcher
+
+Enhancement structures can embed enhanced fields within specified structs.
+After the struct is instantiated, custom data content can be added to the
specified struct in the method interceptor.
+
+Struct matchers are used to intercept struct methods. The specific definitions
are as follows:
+
+```go
+// NewStructEnhance creates a new EnhanceMatcher for struct.
+// name: struct name needs to be enhanced.(Public and private structs are
supported)
+// filters: filters for struct.
+func NewStructEnhance(name string, filters ...StructFilterOption)
+```
+
+##### Filter Option
+
+Filter Options are used to validate the fields in the structure.
+
+```go
+// WithFieldExists filter the struct has the field with specific name.
+func WithFieldExists(fieldName string)
+
+// WithFiledType filter the struct has the field with specific name and type.
+func WithFiledType(filedName, filedType string)
+```
+
+##### Enhanced Instance
+
+After completing the definition of the struct enhancement, you can convert the
specified instance into the following interface when intercepting methods,
+and get or set custom field information. The interface definition is as
follows:
+
+```go
+type EnhancedInstance interface {
+ // GetSkyWalkingDynamicField get the customized data from instance
+ GetSkyWalkingDynamicField() interface{}
+ // SetSkyWalkingDynamicField set the customized data into the instance
+ SetSkyWalkingDynamicField(interface{})
+}
+```
+
+##### Demo
+
+For example, if you have the following struct that needs to be enhanced:
+
+```go
+type Test struct {
+ value *Context
+}
+```
+
+you can describe it using this condition:
+
+```go
+instrument.NewStructEnhance("Test", instrument.WithFieldExists("value"),
instrument.WithFiledType("value", "*Context"))
+```
+
+Next, you can set custom content for the specified enhanced instance when
intercepting methods.
+
+```go
+ins := testInstance.(instrument.EnhancedInstance)
+// setting custom content
+ins.SetSkyWalkingDynamicField("custom content")
+// getting custom content
+res := ins.GetSkyWalkingDynamicField()
+```
+
+#### Interceptor
+
+Interceptors are used to define custom business logic before and after method
execution,
+allowing you to access data from before and after method execution and
interact with the Agent Core by using the Agent API.
+
+The interceptor definition is as follows, you need to create a new structure
and implement it:
+
+```go
+type Interceptor interface {
+ // BeforeInvoke would be called before the target method invocation.
+ BeforeInvoke(invocation *Invocation) error
+ // AfterInvoke would be called after the target method invocation.
+ AfterInvoke(invocation *Invocation, result ...interface{}) error
+}
+```
+
+Within the interface, you can see the `Invocation` struct, which defines the
context of an interception. The specific definition is as follows:
+
+```go
+type Invocation struct {
+ // CallerInstance is the instance of the caller, nil if the method is
static method.
+ CallerInstance interface{}
+ // Args is the arguments data of the method, please cast to the
specific type to get more inforamtion.
+ Args []interface{}
+
+ // Continue is the flag to control the method invocation, if it is
false, the target method would not be invoked.
+ Continue bool
+ // Return is the return data of the method, the result must be provided
when continue the target method invoke.
+ // and the result size must be the same as the method return value size.
+ Return []interface{}
+
+ // Context is the customized context of the method invocation, it
should be propagated the tracing span.
+ Context interface{}
+}
+```
+
+##### Thread safe
+
+The `Interceptor` instance would **define new instance at the current package
level**,
+rather than creating a new instance each time a method is intercepted.
+
+Therefore, please try not to define intercepted objects in the interceptor,
and instead use `Invocation.Context` to pass data.
Review Comment:
```suggestion
Therefore, do not declare objects in the interceptor, and instead use
`Invocation.Context` to pass data.
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]