From 485d1cb0a69798be9a7f98a49b0db4cd5814bc5d Mon Sep 17 00:00:00 2001 From: dongdong Date: Wed, 14 Aug 2024 21:08:03 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=E6=8C=87=E6=A0=87?= =?UTF-8?q?=E5=90=8D=E6=A0=A1=E9=AA=8C=E6=80=A7=E8=83=BD=20--story=3D11919?= =?UTF-8?q?4100=20(#486)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/collector/VERSION | 2 +- pkg/collector/internal/utils/normalize.go | 14 ++++++ .../internal/utils/normalize_test.go | 45 +++++++++++++++++++ .../processor/proxyvalidator/validator.go | 7 +-- 4 files changed, 62 insertions(+), 6 deletions(-) diff --git a/pkg/collector/VERSION b/pkg/collector/VERSION index 8ac660966..bb9142357 100644 --- a/pkg/collector/VERSION +++ b/pkg/collector/VERSION @@ -1 +1 @@ -0.65.x \ No newline at end of file +0.66.x \ No newline at end of file diff --git a/pkg/collector/internal/utils/normalize.go b/pkg/collector/internal/utils/normalize.go index 8d6e72e4e..e5a1b2cee 100644 --- a/pkg/collector/internal/utils/normalize.go +++ b/pkg/collector/internal/utils/normalize.go @@ -17,3 +17,17 @@ import ( func NormalizeName(s string) string { return strings.Join(strings.FieldsFunc(s, func(r rune) bool { return !unicode.IsLetter(r) && !unicode.IsDigit(r) && r != '_' && r != ':' }), "_") } + +// IsNameNormalized 判断是否为合法指标名称 +// 此方式会比 regexp 方式要更快 参见 benchmark +func IsNameNormalized(s string) bool { + if len(s) == 0 { + return false + } + for i, b := range s { + if !((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || (b >= '0' && b <= '9' && i > 0)) { + return false + } + } + return true +} diff --git a/pkg/collector/internal/utils/normalize_test.go b/pkg/collector/internal/utils/normalize_test.go index 8e4dfdb24..d19d615c2 100644 --- a/pkg/collector/internal/utils/normalize_test.go +++ b/pkg/collector/internal/utils/normalize_test.go @@ -10,6 +10,7 @@ package utils import ( + "regexp" "testing" "github.com/stretchr/testify/assert" @@ -56,3 +57,47 @@ func TestNormalize(t *testing.T) { assert.Equal(t, c.Output, NormalizeName(c.Input)) } } + +func benchmarkIsNormalized(b *testing.B, f func(string) bool) { + type Case struct { + Input string + Validated bool + } + + cases := []Case{ + {Input: "foo.bar", Validated: false}, + {Input: "foo.bar.zzz", Validated: false}, + {Input: "foo.bar..", Validated: false}, + {Input: "TestApp_HelloGo_HelloGoObjAdapter_connectRate", Validated: true}, + {Input: "TestApp_HelloGo_HelloGoObjAdapter.connectRate", Validated: false}, + {Input: "TestApp.HelloGo.exception_single_log_more_than_3M", Validated: false}, + {Input: "TestApp_HelloGo_exception_single_log_more_than_3M", Validated: true}, + {Input: "TestApp.HelloGo.asyncqueue0", Validated: false}, + {Input: "Exception-Log", Validated: false}, + {Input: "┓(-´∀`-)┏", Validated: false}, + } + + b.ReportAllocs() + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + for _, c := range cases { + ok := f(c.Input) + if c.Validated != ok { + b.Errorf("input=(%v), want '%v' but go '%v'", c.Input, c.Validated, ok) + } + } + } + }) +} + +func BenchmarkIsNormalizedFast(b *testing.B) { + benchmarkIsNormalized(b, IsNameNormalized) +} + +func BenchmarkIsNormalizedRegex(b *testing.B) { + namePattern := regexp.MustCompile("^[a-zA-Z_][a-zA-Z0-9_]*$") + f := func(s string) bool { + return namePattern.MatchString(s) + } + benchmarkIsNormalized(b, f) +} diff --git a/pkg/collector/processor/proxyvalidator/validator.go b/pkg/collector/processor/proxyvalidator/validator.go index 08e1dccdf..cb3daca70 100644 --- a/pkg/collector/processor/proxyvalidator/validator.go +++ b/pkg/collector/processor/proxyvalidator/validator.go @@ -10,13 +10,13 @@ package proxyvalidator import ( - "regexp" "time" "github.com/pkg/errors" "github.com/spf13/cast" "github.com/TencentBlueKing/bkmonitor-datalink/pkg/collector/define" + "github.com/TencentBlueKing/bkmonitor-datalink/pkg/collector/internal/utils" ) const ( @@ -28,8 +28,6 @@ type Validator interface { Validate(*define.ProxyData) error } -var namePattern = regexp.MustCompile("^[a-zA-Z_][a-zA-Z0-9_]*$") - type noneValidator struct{} func (noneValidator) Validate(*define.ProxyData) error { @@ -39,10 +37,9 @@ func (noneValidator) Validate(*define.ProxyData) error { type nameValidator struct{} func (nv *nameValidator) Validate(s string) error { - if !namePattern.MatchString(s) { + if !utils.IsNameNormalized(s) { return errors.Errorf("name '%s' required match regex [^[a-zA-Z_][a-zA-Z0-9_]*$]", s) } - return nil }