You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2024/03/22 01:23:57 UTC

(skywalking-go) branch main updated: Add support trace ignore (#177)

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 e427c3e  Add support trace ignore (#177)
e427c3e is described below

commit e427c3e53a7fda57ebd85b9784e58db352d77a53
Author: Starry <co...@163.com>
AuthorDate: Fri Mar 22 09:23:52 2024 +0800

    Add support trace ignore (#177)
---
 CHANGES.md                                        |   5 +-
 docs/en/agent/tracing-metrics-logging.md          |   9 +-
 plugins/core/tracer.go                            |   4 +-
 plugins/core/tracer_ignore.go                     | 135 ++++++++++++++++++++++
 plugins/core/tracer_ignore_test.go                |  81 +++++++++++++
 plugins/core/tracing.go                           |  16 +--
 tools/go-agent/config/agent.default.yaml          |   8 +-
 tools/go-agent/config/loader.go                   |   1 +
 tools/go-agent/instrument/agentcore/instrument.go |   3 +-
 9 files changed, 239 insertions(+), 23 deletions(-)

diff --git a/CHANGES.md b/CHANGES.md
index f823c49..fe3da3b 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -4,6 +4,9 @@ Release Notes.
 
 0.5.0
 ------------------
+#### Features
+* Add support trace ignore.
+
 #### Plugins
 * Support [Pulsar](https://github.com/apache/pulsar-client-go) MQ.
 * Support [Segmentio-Kafka](https://github.com/segmentio/kafka-go) MQ.
@@ -111,7 +114,7 @@ Release Notes.
 * Support [Kratos](github.com/go-kratos/kratos) v2 server and client framework.
 * Support [Go-Micro](https://github.com/go-micro/go-micro) v4 server and client framework.
 * Support [GORM](https://github.com/go-gorm/gorm) v2 database client framework.
-  * Support [MySQL Driver](https://github.com/go-gorm/mysql) detection.
+* Support [MySQL Driver](https://github.com/go-gorm/mysql) detection.
 
 #### Documentation
 * Initialize the documentation.
diff --git a/docs/en/agent/tracing-metrics-logging.md b/docs/en/agent/tracing-metrics-logging.md
index 07ccf8d..ec6e263 100644
--- a/docs/en/agent/tracing-metrics-logging.md
+++ b/docs/en/agent/tracing-metrics-logging.md
@@ -22,10 +22,11 @@ If you wish to disable a particular plugin to prevent enhancements related to th
 
 The basic configuration is as follows:
 
-| Name                | Environment Key        | Default Value                                                | Description                                                                                                              |
-|---------------------|------------------------|--------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------|
-| agent.sampler       | SW_AGENT_SAMPLER       | 1                                                            | Sampling rate of tracing data, which is a floating-point value that must be between 0 and 1.                             |
-| agent.ignore_suffix | SW_AGENT_IGNORE_SUFFIX | .jpg,.jpeg,.js,.css,.png,.bmp,.gif,.ico,.mp3,.mp4,.html,.svg | If the operation name of the first span is included in this set, this segment should be ignored.(multiple split by ","). |
+| Name                    | Environment Key            | Default Value                                                | Description                                                                                                                                          |
+|-------------------------|----------------------------|--------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------|
+| agent.sampler           | SW_AGENT_SAMPLER           | 1                                                            | Sampling rate of tracing data, which is a floating-point value that must be between 0 and 1.                                                         |
+| agent.ignore_suffix     | SW_AGENT_IGNORE_SUFFIX     | .jpg,.jpeg,.js,.css,.png,.bmp,.gif,.ico,.mp3,.mp4,.html,.svg | If the suffix obtained by splitting the operation name by the last index of "." in this set, this segment should be ignored.(multiple split by ","). |
+| agent.trace_ignore_path | SW_AGENT_TRACE_IGNORE_PATH |                                                              | If the operation name of the first span is matching, this segment should be ignored.(multiple split by ",").                                         |
 
 ## Metrics
 
diff --git a/plugins/core/tracer.go b/plugins/core/tracer.go
index e10a56b..53a5eff 100644
--- a/plugins/core/tracer.go
+++ b/plugins/core/tracer.go
@@ -54,10 +54,11 @@ type Tracer struct {
 	meterMap              *sync.Map
 	meterCollectListeners []func()
 	ignoreSuffix          []string
+	traceIgnorePath       []string
 }
 
 func (t *Tracer) Init(entity *reporter.Entity, rep reporter.Reporter, samp Sampler, logger operator.LogOperator,
-	meterCollectSecond int, correlation *CorrelationConfig, ignoreSuffixStr string) error {
+	meterCollectSecond int, correlation *CorrelationConfig, ignoreSuffixStr string, ignorePath string) error {
 	t.ServiceEntity = entity
 	t.Reporter = rep
 	t.Sampler = samp
@@ -69,6 +70,7 @@ func (t *Tracer) Init(entity *reporter.Entity, rep reporter.Reporter, samp Sampl
 	t.initMetricsCollect(meterCollectSecond)
 	t.correlation = correlation
 	t.ignoreSuffix = strings.Split(ignoreSuffixStr, ",")
+	t.traceIgnorePath = strings.Split(ignorePath, ",")
 	// notify the tracer been init success
 	if len(GetInitNotify()) > 0 {
 		for _, fun := range GetInitNotify() {
diff --git a/plugins/core/tracer_ignore.go b/plugins/core/tracer_ignore.go
new file mode 100644
index 0000000..ae4212b
--- /dev/null
+++ b/plugins/core/tracer_ignore.go
@@ -0,0 +1,135 @@
+// 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 core
+
+import (
+	"strings"
+)
+
+func tracerIgnore(operationName string, ignoreSuffixList, ignorePath []string) bool {
+	return ignoreSuffix(operationName, ignoreSuffixList) || traceIgnorePath(operationName, ignorePath)
+}
+
+func ignoreSuffix(operationName string, ignoreSuffix []string) bool {
+	suffixIdx := strings.LastIndex(operationName, ".")
+	if suffixIdx == -1 {
+		return false
+	}
+	for _, suffix := range ignoreSuffix {
+		if suffix == operationName[suffixIdx:] {
+			return true
+		}
+	}
+	return false
+}
+
+func traceIgnorePath(operationName string, ignorePath []string) bool {
+	for _, pattern := range ignorePath {
+		if normalMatch(pattern, 0, operationName, 0) {
+			return true
+		}
+	}
+	return false
+}
+
+// normalMatch determines whether the operation name matches the wildcard pattern.
+// The parameters `p` and `s` represent the current index in pattern and operationName respectively.
+func normalMatch(pattern string, p int, operationName string, s int) bool {
+	for p < len(pattern) {
+		pc := pattern[p]
+		sc := safeCharAt(operationName, s)
+
+		if pc == '*' {
+			p++
+			if safeCharAt(pattern, p) == '*' {
+				p++
+				return multiWildcardMatch(pattern, p, operationName, s)
+			}
+			return wildcardMatch(pattern, p, operationName, s)
+		}
+
+		if (pc == '?' && sc != 0 && sc != '/') || pc == sc {
+			s++
+			p++
+			continue
+		}
+		return false
+	}
+	return s == len(operationName)
+}
+
+func wildcardMatch(pattern string, p int, operationName string, s int) bool {
+	pc := safeCharAt(pattern, p)
+
+	if pc == 0 {
+		for {
+			sc := safeCharAt(operationName, s)
+			if sc == 0 {
+				return true
+			}
+			if sc == '/' {
+				return s == len(operationName)-1
+			}
+			s++
+		}
+	}
+
+	for {
+		sc := safeCharAt(operationName, s)
+		if sc == '/' {
+			if pc == sc {
+				return normalMatch(pattern, p+1, operationName, s+1)
+			}
+			return false
+		}
+		if !normalMatch(pattern, p, operationName, s) {
+			if s >= len(operationName) {
+				return false
+			}
+			s++
+			continue
+		}
+		return true
+	}
+}
+
+func multiWildcardMatch(pattern string, p int, operationName string, s int) bool {
+	switch safeCharAt(pattern, p) {
+	case 0:
+		return true
+	case '/':
+		p++
+	}
+	for {
+		if !normalMatch(pattern, p, operationName, s) {
+			if s >= len(operationName) {
+				return false
+			}
+			s++
+			continue
+		}
+		return true
+	}
+}
+
+func safeCharAt(value string, index int) byte {
+	if index >= len(value) {
+		return 0
+	}
+	return value[index]
+}
diff --git a/plugins/core/tracer_ignore_test.go b/plugins/core/tracer_ignore_test.go
new file mode 100644
index 0000000..9bd3bf3
--- /dev/null
+++ b/plugins/core/tracer_ignore_test.go
@@ -0,0 +1,81 @@
+// 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 core
+
+import (
+	"strings"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestIgnoreSuffix(t *testing.T) {
+	ignoreSuffixStr := ".jpg,.jpeg,.js,.css,.png,.bmp,.gif,.ico,.mp3,.mp4,.html,.svg"
+	ignoreSuffixList := strings.Split(ignoreSuffixStr, ",")
+	assert.True(t, ignoreSuffix("GET:/favicon.ico", ignoreSuffixList))
+}
+
+func TestTraceIgnorePath(t *testing.T) {
+	ignorePath := []string{"/health/*"}
+	assert.False(t, traceIgnorePath("", ignorePath))
+	assert.True(t, traceIgnorePath("/health/apps", ignorePath))
+	assert.True(t, traceIgnorePath("/health/", ignorePath))
+	assert.True(t, traceIgnorePath("/health/apps/", ignorePath))
+
+	ignorePath = []string{"/health/**"}
+	assert.True(t, traceIgnorePath("/health/apps/", ignorePath))
+
+	ignorePath = []string{"/health/?"}
+	assert.True(t, traceIgnorePath("/health/a", ignorePath))
+	assert.False(t, traceIgnorePath("/health/ab", ignorePath))
+
+	ignorePath = []string{"/health/*/"}
+	assert.True(t, traceIgnorePath("/health/apps/", ignorePath))
+	assert.False(t, traceIgnorePath("/health/", ignorePath))
+	assert.False(t, traceIgnorePath("/health/apps/list", ignorePath))
+	assert.False(t, traceIgnorePath("/health/test", ignorePath))
+
+	ignorePath = []string{"/health/**"}
+	assert.True(t, traceIgnorePath("/health/", ignorePath))
+	assert.True(t, traceIgnorePath("/health/apps/test", ignorePath))
+	assert.True(t, traceIgnorePath("/health/apps/test/", ignorePath))
+
+	ignorePath = []string{"health/apps/?"}
+	assert.False(t, traceIgnorePath("health/apps/list", ignorePath))
+	assert.False(t, traceIgnorePath("health/apps/", ignorePath))
+	assert.True(t, traceIgnorePath("health/apps/a", ignorePath))
+
+	ignorePath = []string{"health/**/lists"}
+	assert.True(t, traceIgnorePath("health/apps/lists", ignorePath))
+	assert.True(t, traceIgnorePath("health/apps/test/lists", ignorePath))
+	assert.False(t, traceIgnorePath("health/apps/test/", ignorePath))
+	assert.False(t, traceIgnorePath("health/apps/test", ignorePath))
+
+	ignorePath = []string{"health/**/test/**"}
+	assert.True(t, traceIgnorePath("health/apps/test/list", ignorePath))
+	assert.True(t, traceIgnorePath("health/apps/foo/test/list/bar", ignorePath))
+	assert.True(t, traceIgnorePath("health/apps/foo/test/list/bar/", ignorePath))
+	assert.True(t, traceIgnorePath("health/apps/test/list", ignorePath))
+	assert.True(t, traceIgnorePath("health/test/list", ignorePath))
+
+	ignorePath = []string{"/health/**/b/**/*.txt", "abc/*"}
+	assert.True(t, traceIgnorePath("/health/a/aa/aaa/b/bb/bbb/xxxxxx.txt", ignorePath))
+	assert.False(t, traceIgnorePath("/health/a/aa/aaa/b/bb/bbb/xxxxxx", ignorePath))
+	assert.False(t, traceIgnorePath("abc/foo/bar", ignorePath))
+	assert.True(t, traceIgnorePath("abc/foo", ignorePath))
+}
diff --git a/plugins/core/tracing.go b/plugins/core/tracing.go
index 8fac32f..1f73c89 100644
--- a/plugins/core/tracing.go
+++ b/plugins/core/tracing.go
@@ -20,7 +20,6 @@ package core
 import (
 	"reflect"
 	"runtime/debug"
-	"strings"
 
 	"github.com/pkg/errors"
 
@@ -230,7 +229,7 @@ func (t *Tracer) createNoop(operationName string) (*TracingContext, TracingSpan,
 	if !t.InitSuccess() || t.Reporter.ConnectionStatus() == reporter.ConnectionStatusDisconnect {
 		return nil, newNoopSpan(), true
 	}
-	if ignoreSuffixFilter(operationName, t.ignoreSuffix) {
+	if tracerIgnore(operationName, t.ignoreSuffix, t.traceIgnorePath) {
 		return nil, newNoopSpan(), true
 	}
 	ctx := getTracingContext()
@@ -341,16 +340,3 @@ func saveSpanToActiveIfNotError(ctx *TracingContext, span interface{}, err error
 	ctx.SaveActiveSpan(span.(TracingSpan))
 	SetGLS(ctx)
 }
-
-func ignoreSuffixFilter(operationName string, ignoreSuffix []string) bool {
-	suffixIdx := strings.LastIndex(operationName, ".")
-	if suffixIdx == -1 {
-		return false
-	}
-	for _, suffix := range ignoreSuffix {
-		if suffix == operationName[suffixIdx:] {
-			return true
-		}
-	}
-	return false
-}
diff --git a/tools/go-agent/config/agent.default.yaml b/tools/go-agent/config/agent.default.yaml
index 0af4207..ee1e5cd 100644
--- a/tools/go-agent/config/agent.default.yaml
+++ b/tools/go-agent/config/agent.default.yaml
@@ -30,8 +30,14 @@ agent:
   correlation:
     max_key_count: ${SW_AGENT_CORRELATION_MAX_KEY_COUNT:3}
     max_value_size: ${SW_AGENT_CORRELATION_MAX_VALUE_SIZE:128}
-  # If the operation name of the first span is included in this set, this segment should be ignored.(multiple split by ",")
+  # If the suffix obtained by splitting the operation name by the last index of "." in this set, this segment should be ignored.(multiple split by ",").
   ignore_suffix: ${SW_AGENT_IGNORE_SUFFIX:.jpg,.jpeg,.js,.css,.png,.bmp,.gif,.ico,.mp3,.mp4,.html,.svg}
+  # If the operation name of the first span is matching, this segment should be ignored.(multiple split by ",").
+  # Matching rules follow Ant Path match style, like /path/*, /path/**, /path/?.
+  #       "/path/*" means matching any path that starts with "/path/".  
+  #       "/path/**" means matching any path that starts with "/path/" and includes its subpaths.
+  #       "/path/?" means matching any path that starts with "/path/" and has any single character as a wildcard.
+  trace_ignore_path: ${SW_AGENT_TRACE_IGNORE_PATH:}
 
 reporter:
   discard: ${SW_AGENT_REPORTER_DISCARD:false}
diff --git a/tools/go-agent/config/loader.go b/tools/go-agent/config/loader.go
index e42420d..466626a 100644
--- a/tools/go-agent/config/loader.go
+++ b/tools/go-agent/config/loader.go
@@ -51,6 +51,7 @@ type Agent struct {
 	Meter           Meter       `yaml:"meter"`
 	Correlation     Correlation `yaml:"correlation"`
 	IgnoreSuffix    StringValue `yaml:"ignore_suffix"`
+	TraceIgnorePath StringValue `yaml:"trace_ignore_path"`
 }
 
 type Reporter struct {
diff --git a/tools/go-agent/instrument/agentcore/instrument.go b/tools/go-agent/instrument/agentcore/instrument.go
index 83dcbb6..b46abec 100644
--- a/tools/go-agent/instrument/agentcore/instrument.go
+++ b/tools/go-agent/instrument/agentcore/instrument.go
@@ -163,7 +163,8 @@ func (t *Tracer) InitTracer(extend map[string]interface{}) {
 		MaxValueSize : {{.Config.Agent.Correlation.MaxValueSize.ToGoIntValue "loading the agent correlation maxValueSize error"}},
 	}
 	ignoreSuffixStr := {{.Config.Agent.IgnoreSuffix.ToGoStringValue}}
-	if err := t.Init(entity, rep, samp, logger, meterCollectInterval, correlation, ignoreSuffixStr); err != nil {
+	ignorePath := {{.Config.Agent.TraceIgnorePath.ToGoStringValue}}
+	if err := t.Init(entity, rep, samp, logger, meterCollectInterval, correlation, ignoreSuffixStr, ignorePath); err != nil {
 		t.Log.Errorf("cannot initialize the SkyWalking Tracer: %v", err)
 	}
 }`, struct {