Skip to content

Commit

Permalink
docs: polish how-to-add-a-new-rule.md (#33)
Browse files Browse the repository at this point in the history
  • Loading branch information
y1yang0 committed Aug 13, 2024
1 parent 79a8ac4 commit 9d76c6f
Showing 1 changed file with 62 additions and 26 deletions.
88 changes: 62 additions & 26 deletions docs/how-to-add-a-new-rule.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,73 @@
# How to add a new rule

To instrument a new framework, you call follow the steps:
## 1. Create a new rule
We demonstrate how to inject code for a new package through an example. Here we choose `os.Setenv()` and inject logging code at the beginning of its function to record the key and value whenever user calls it.

1. Create a new directory in the **pkg/rules** directory and create a new **rule.go** file
2. Register a new rule that specifies the framework import path, function
name, and the function signature you want to instrument, and onEnter/onExit
functions you want to insert before/after calling original function, respectively, in the **rule.go** file, as shown
below:
```go
package rules
First, we create the following file structure under the `pkg/rules` directory:
```
pkg/rules/os
├── rule.go
└── setup.go
```
The `os` directory is the package name, and `rule.go` is the rule file where we define the rule. `setup.go` is the setup file where we register the rule.

func init() {
api.NewRule("framework_name", "function_name", "function_signature", "onEnterFunc", "onExitFunc").Register()
}
```go
package os

```
3. Implement the onEnter/onExit functions in the same directory with the **rule.go** file, as shown below:
import "github.com/alibaba/opentelemetry-go-auto-instrumentation/api"

```go
package rules
func init() {
api.NewRule("os", "Setenv", "", "onEnterSetenv", "").
Register()
}
```
In the `rule.go` file, we define a new rule for the `os` package. The `NewRule` function takes five arguments: the package name, the function name, the function signature, the onEnter function name, and the onExit function name. The `Register` function registers the rule.

import framework_name
`setup.go` contains the definition of `onEnterSetenv`:

func onEnterFunc(ctx *framework_name.Context, arg1 int, arg2 bool) {
println("onEnter")
}
```go
//go:build ignore
package os

func onExitFunc(ctx *framework_name.Context, ret1 string) {
println("onExit")
}
```
import (
"fmt"
"os"
)

4. Import your new rule package by adding import statement within `rule_enabler.go`
func onEnterSetenv(call os.CallContext, key, value string) {
fmt.Printf("Setting environment variable %s to %s", key, value)
}
```

There are some concrete examples in the **pkg/rules** directory, such as **pkg/rules/test**.
You can refer to them for more details.
The `onEnterSetenv` function is the probe code that will be injected at the beginning of the `os.Setenv()` function. It takes the `os.CallContext` as the first argument and the key and value as the second and third arguments, respectively.

## 2. Register the rule
After completing this process, we introduce our newly created package in `rule_enabler.go` to make the rule take effect:

```go
package main
import (
...
_ "github.com/alibaba/opentelemetry-go-auto-instrumentation/pkg/rules/os"
)
```
Dont forget recomplie the tool after adding the new rule, because currently `rules` is coded within the tool.

## 3. Verify the rule
To make sure the rule is working as expected, we can write a simple demo program to test it:

```bash
$ mkdir setenv
$ go mod init setenv
$ cat <<EOF > main.go
package main
import "os"
func main(){ os.Setenv("hello", "world") }
EOF
$ ~/opentelemetry-go-auto-instrumentation/otel-go-auto-instrumentation -- main.go
$ ./main
Setting environment variable hello to world%
```
The output shows that the rule is working as expected. The `Setting environment variable hello to world` message is printed when the `os.Setenv()` function is called, that is, the probe code is injected successfully.

There are many advanced features that is not covered in this example, such as the `InstStructRule`, `InstFileRule` and APIs of `CallContext`. You can refer to the existing rules in the `pkg/rules` directory for more information.

0 comments on commit 9d76c6f

Please sign in to comment.