diff --git a/README.md b/README.md
index abc9ddad..b210978a 100644
--- a/README.md
+++ b/README.md
@@ -35,6 +35,11 @@ $ make install # build and install
# Getting Started
+Check the version by running:
+```bash
+$ otel version
+```
+
The configuration for the tool can be set by the following command:
```bash
@@ -54,9 +59,7 @@ $ otel go build -o app cmd/app
$ otel go build -gcflags="-m" cmd/app
```
-You can also explore [**these examples**](./example/) to get hands-on experience.
-
-Also there are several [**documents**](./docs) that you may find useful for either understanding the project or contributing to it.
+The detailed usage of otel tool can be found in [**Usage**](./docs/usage.md).
> [!NOTE]
> If you find any compilation failures while `go build` works, it's likely a bug.
@@ -64,6 +67,12 @@ Also there are several [**documents**](./docs) that you may find useful for eith
> at [GitHub Issues](https://github.com/alibaba/opentelemetry-go-auto-instrumentation/issues)
> to help us enhance this project.
+# Examples
+
+You can also explore [**these examples**](./example/) to get hands-on experience. They are designed to construct a full picture of how to use the tool in different scenarios.
+
+Also there are several [**documents**](./docs) that you may find useful for either understanding the project or contributing to it.
+
# Supported Libraries
| Plugin Name | Repository Url | Min Supported Version | Max Supported Version |
@@ -108,4 +117,5 @@ to engage with us.
These are only part of the companies using this project, for reference only. If you are using this project, please [add your company here](https://github.com/alibaba/opentelemetry-go-auto-instrumentation/issues/225) to tell us your scenario to make this project better.
-![Alibaba Group](./static/alibaba.png)
\ No newline at end of file
+-
+-
\ No newline at end of file
diff --git a/static/alibaba.png b/docs/alibaba.png
similarity index 100%
rename from static/alibaba.png
rename to docs/alibaba.png
diff --git a/docs/aliyun.png b/docs/aliyun.png
new file mode 100644
index 00000000..929d4ccd
Binary files /dev/null and b/docs/aliyun.png differ
diff --git a/docs/usage.md b/docs/usage.md
new file mode 100644
index 00000000..acb9225c
--- /dev/null
+++ b/docs/usage.md
@@ -0,0 +1,75 @@
+# `Otel` Usage Guide
+
+## Introduction
+This guide provides a detailed overview of configuring and using the otel tool effectively. This tool allows you to set various configuration options, build your projects, and customize your workflow for optimal performance.
+
+## Configuration
+The primary method of configuring the tool is through the `otel set` command. This command allows you to specify various settings tailored to your needs:
+
+Verbose Logging: Enable verbose logging to receive detailed output from the tool, which is helpful for troubleshooting and understanding the tool's processes.
+```bash
+ $ otel set -verbose
+```
+
+Debug Mode: Turn on debug mode to gather debug-level insights and information.
+```bash
+ $ otel set -debug
+```
+
+Multiple Configurations: Set multiple configurations at once. For instance, enable both debug and verbose modes while using a custom rule file:
+```bash
+ $ otel set -debug -verbose -rule=custom.json
+```
+
+Custom Rules Only: Disable the default rule set and apply only specific custom rules. This is particularly useful when you need a tailored rule set for your project.
+```bash
+ $ otel set -disabledefault -rule=custom.json
+```
+
+Combination of Default and Custom Rules: Use both the default rules and custom rules to provide a comprehensive configuration:
+```bash
+ $ otel set -rule=custom.json
+```
+
+Multiple Rule Files: Combine multiple custom rule files along with the default rules, which can be specified as a comma-separated list:
+```bash
+ $ otel set -rule=a.json,b.json
+```
+
+## Using Environment Variables
+In addition to using the `otel set` command, configuration can also be overridden using environment variables. For example, the `OTELTOOL_DEBUG` environment variable allows you to force the tool into debug mode temporarily, making this approach effective for one-time configurations without altering permanent settings.
+
+```bash
+$ export OTELTOOL_DEBUG=true
+$ export OTELTOOL_VERBOSE=true
+```
+
+The names of the environment variables correspond to the configuration options available in the `otel set` command with the `OTELTOOL_` prefix.
+
+Full List of Environment Variables:
+
+- `OTELTOOL_DEBUG`: Enable debug mode.
+- `OTELTOOL_VERBOSE`: Enable verbose logging.
+- `OTELTOOL_RULE_JSON_FILES`: Specify custom rule files.
+- `OTELTOOL_DISABLE_DEFAULT`: Disable default rules.
+
+This approach provides flexibility for testing changes and experimenting with configurations without permanently altering your existing setup.
+
+## Building Projects
+Once configurations are in place, you can build your project with prefixed `otel` commands. This integrates the tool's configuration directly into the build process:
+
+Standard Build: Build your project with default settings.
+```bash
+ $ otel go build
+```
+
+Output to Specific Location: Build your project and specify an output location.
+```bash
+ $ otel go build -o app cmd/app
+```
+
+Passing Compiler Flags: Use compiler flags for more customized builds.
+```bash
+ $ otel go build -gcflags="-m" cmd/app
+```
+No matter how complex your project is, the otel tool simplifies the process by automatically instrumenting your code for effective observability, the only requirement being the addition of the `otel` prefix to your build commands.
\ No newline at end of file
diff --git a/test/flags_test.go b/test/flags_test.go
index 98e967cd..5c363ee6 100644
--- a/test/flags_test.go
+++ b/test/flags_test.go
@@ -20,8 +20,9 @@ import (
"github.com/alibaba/opentelemetry-go-auto-instrumentation/tool/shared"
)
+const AppName = "flags"
+
func TestFlags(t *testing.T) {
- const AppName = "flags"
UseApp(AppName)
RunGoBuildFallible(t, "go", "build", "-thisisnotvalid")
@@ -42,3 +43,17 @@ func TestFlags(t *testing.T) {
RunGoBuild(t)
RunGoBuild(t, "")
}
+
+func TestFlagConfigOverwriteNo(t *testing.T) {
+ UseApp(AppName)
+
+ RunSet(t, "-verbose=false")
+ RunGoBuildWithEnv(t, []string{"OTELTOOL_VERBOSE=true"},
+ "go", "build")
+ ExpectPreprocessContains(t, shared.DebugLogFile, "Available")
+
+ RunSet(t, "-verbose=true")
+ RunGoBuildWithEnv(t, []string{"OTELTOOL_VERBOSE=false"},
+ "go", "build")
+ ExpectPreprocessNotContains(t, shared.DebugLogFile, "Available")
+}
diff --git a/test/infra.go b/test/infra.go
index 9d49ea71..5def004c 100644
--- a/test/infra.go
+++ b/test/infra.go
@@ -121,6 +121,28 @@ func RunGoBuild(t *testing.T, args ...string) {
}
}
+func RunGoBuildWithEnv(t *testing.T, envs []string, args ...string) {
+ util.Assert(pwd != "", "pwd is empty")
+ RunSet(t, "-debuglog")
+ path := filepath.Join(filepath.Dir(pwd), getExecName())
+ cmd := runCmd(append([]string{path}, args...))
+ cmd.Env = append(cmd.Env, envs...)
+ err := cmd.Run()
+ if err != nil {
+ stderr := readStderrLog(t)
+ stdout := readStdoutLog(t)
+ t.Log(stdout)
+ t.Log("\n\n\n")
+ t.Log(stderr)
+ log1 := ReadPreprocessLog(t, shared.DebugLogFile)
+ log2 := ReadInstrumentLog(t, shared.DebugLogFile)
+ text := fmt.Sprintf("failed to run instrument: %v\n", err)
+ text += fmt.Sprintf("preprocess: %v\n", log1)
+ text += fmt.Sprintf("instrument: %v\n", log2)
+ t.Fatal(text)
+ }
+}
+
func RunGoBuildFallible(t *testing.T, args ...string) {
util.Assert(pwd != "", "pwd is empty")
RunSet(t, "-debuglog")
diff --git a/tool/config/config.go b/tool/config/config.go
index c41a0b3e..7052d6a0 100644
--- a/tool/config/config.go
+++ b/tool/config/config.go
@@ -21,12 +21,18 @@ import (
"log"
"os"
"path/filepath"
+ "reflect"
"strings"
+ "unicode"
"github.com/alibaba/opentelemetry-go-auto-instrumentation/tool/shared"
"github.com/alibaba/opentelemetry-go-auto-instrumentation/tool/util"
)
+const (
+ EnvPrefix = "OTELTOOL_"
+)
+
type BuildConfig struct {
// RuleJsonFiles is the name of the rule file. It is used to tell instrument
// tool where to find the instrument rules. Multiple rules are separated by
@@ -162,12 +168,56 @@ func loadConfig() (*BuildConfig, error) {
return bc, nil
}
+func toUpperSnakeCase(input string) string {
+ var result []rune
+
+ for i, char := range input {
+ if unicode.IsUpper(char) {
+ if i != 0 {
+ result = append(result, '_')
+ }
+ result = append(result, unicode.ToUpper(char))
+ } else {
+ result = append(result, unicode.ToUpper(char))
+ }
+ }
+
+ return string(result)
+}
+func loadConfigFromEnv(conf *BuildConfig) {
+ // Environment variables are able to overwrite the config items even if the
+ // config file sets them. The environment variable name is the upper snake
+ // case of the config item name, prefixed with "OTELTOOL_". For example, the
+ // environment variable for "DebugLog" is "OTELTOOL_DEBUG_LOG".
+ typ := reflect.TypeOf(*conf)
+ for i := 0; i < typ.NumField(); i++ {
+ field := typ.Field(i)
+ envKey := fmt.Sprintf("%s%s", EnvPrefix, toUpperSnakeCase(field.Name))
+ envVal := os.Getenv(envKey)
+ if envVal != "" {
+ log.Printf("Overwrite config %s with environment variable %s",
+ field.Name, envKey)
+ v := reflect.ValueOf(conf).Elem()
+ f := v.FieldByName(field.Name)
+ switch f.Kind() {
+ case reflect.Bool:
+ f.SetBool(envVal == "true")
+ case reflect.String:
+ f.SetString(envVal)
+ default:
+ log.Fatalf("Unsupported config type %s", f.Kind())
+ }
+ }
+ }
+}
+
func InitConfig() (err error) {
// Load build config from json file
conf, err = loadConfig()
if err != nil {
return fmt.Errorf("failed to load build config: %w", err)
}
+ loadConfigFromEnv(conf)
err = conf.parseRuleFiles()
if err != nil {