Repository: go-kratos/kratos
Pull request #2421 (2022-10-03 18:30:08)

build(deps): bump github.com/apolloconfig/agollo/v4 from 4.2.0 to 4.2.1 in /contrib/config/apollo
Bumps [github.com/apolloconfig/agollo/v4](https://github.com/apolloconfig/agollo) from 4.2.0 to 4.2.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/apolloconfig/agollo/releases">github.com/apolloconfig/agollo/v4's releases</a>.</em></p>
<blockquote>
<h2>v4.2.1</h2>
<h2>What's Changed</h2>
<ul>
<li>[Fix] 通过 MkdirAll 替换 Mkdir by <a href="https://github.com/qshuai"><code>@​qshuai</code></a> in <a href="https://github-redirect.dependabot.com/apolloconfig/agollo/pull/243">apolloconfig/agollo#243</a></li>
<li>[Fix] 服务端返回 304 时增加 debug 日志 by <a href="https://github.com/qshuai"><code>@​qshuai</code></a> in <a href="https://github-redirect.dependabot.com/apolloconfig/agollo/pull/246">apolloconfig/agollo#246</a></li>
<li>[Fix] 修复日志格式输出问题 by <a href="https://github.com/fatelei"><code>@​fatelei</code></a> in <a href="https://github-redirect.dependabot.com/apolloconfig/agollo/pull/240">apolloconfig/agollo#240</a></li>
<li>[Fix] 获取数据类型转换至对应目标类型 by <a href="https://github.com/why444216978"><code>@​why444216978</code></a> in <a href="https://github-redirect.dependabot.com/apolloconfig/agollo/pull/247">apolloconfig/agollo#247</a></li>
<li>[Fix] 修复错误文档内容 by <a href="https://github.com/zouyx"><code>@​zouyx</code></a> in <a href="https://github-redirect.dependabot.com/apolloconfig/agollo/pull/252">apolloconfig/agollo#252</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/qshuai"><code>@​qshuai</code></a> made their first contribution in <a href="https://github-redirect.dependabot.com/apolloconfig/agollo/pull/243">apolloconfig/agollo#243</a></li>
<li><a href="https://github.com/fatelei"><code>@​fatelei</code></a> made their first contribution in <a href="https://github-redirect.dependabot.com/apolloconfig/agollo/pull/240">apolloconfig/agollo#240</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a href="https://github.com/apolloconfig/agollo/compare/v4.2.0...v4.2.1">https://github.com/apolloconfig/agollo/compare/v4.2.0...v4.2.1</a></p>
<p><a href="https://github.com/zouyx/agollo_demo/actions/runs/3148157246/jobs/5118395376">详细测试报告</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/apolloconfig/agollo/commit/c9dde042d80f79bf555bf37647753dd012330f20"><code>c9dde04</code></a> Finish v4.2.1</li>
<li><a href="https://github.com/apolloconfig/agollo/commit/800122c04a85ea88f6d4f185b1bcf645259ed283"><code>800122c</code></a> Update README.md (<a href="https://github-redirect.dependabot.com/apolloconfig/agollo/issues/252">#252</a>)</li>
<li><a href="https://github.com/apolloconfig/agollo/commit/33e025d4ff359569e433807ef7abf3447c92d2e5"><code>33e025d</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/apolloconfig/agollo/issues/247">#247</a> from why444216978/develop</li>
<li><a href="https://github.com/apolloconfig/agollo/commit/7b505c075e5a80ad8e65959ce2759fa096a7e455"><code>7b505c0</code></a> GetValueImmediately</li>
<li><a href="https://github.com/apolloconfig/agollo/commit/f9b562ebd0985a7908a59cb25454119ff25a370d"><code>f9b562e</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/apolloconfig/agollo/issues/240">#240</a> from fatelei/log</li>
<li><a href="https://github.com/apolloconfig/agollo/commit/b14ead4eb7e801bd46ed920cb875f30256136620"><code>b14ead4</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/apolloconfig/agollo/issues/246">#246</a> from qshuai/feature-not-modified-log</li>
<li><a href="https://github.com/apolloconfig/agollo/commit/f749fda2c1621a0c5a974f248be7b8afebe90ca5"><code>f749fda</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/apolloconfig/agollo/issues/243">#243</a> from qshuai/feature-fix-mkdir-error</li>
<li><a href="https://github.com/apolloconfig/agollo/commit/ba95af1cec7efe2ff909d76a613980ff95b49540"><code>ba95af1</code></a> Using debug logging when 304 http code returned from server</li>
<li><a href="https://github.com/apolloconfig/agollo/commit/7aab4fb0647331b9ba6c59d2eead4bcbb4f78d7d"><code>7aab4fb</code></a> fix repository get func string value convert to target type</li>
<li><a href="https://github.com/apolloconfig/agollo/commit/b299cedf5cd67d1be61abb62580ce5cf0adf3feb"><code>b299ced</code></a> fix unit test data race</li>
<li>Additional commits viewable in <a href="https://github.com/apolloconfig/agollo/compare/v4.2.0...v4.2.1">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/apolloconfig/agollo/v4&package-manager=go_modules&previous-version=4.2.0&new-version=4.2.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Patch:
diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml
index 552fef4a..ebd64e90 100644
--- a/.github/workflows/go.yml
+++ b/.github/workflows/go.yml
@@ -13,7 +13,7 @@ jobs:
   build:
     strategy:
       matrix:
-        go: [1.16, 1.17, 1.18]
+        go: [1.16, 1.17, 1.18, 1.19]
     name: build & test
     runs-on: ubuntu-latest
     services:
@@ -44,7 +44,7 @@ jobs:
     steps:
       - uses: actions/checkout@v3
       - name: Set up Go
-        uses: actions/setup-go@v3.3.0
+        uses: actions/setup-go@v3.3.1
         with:
           go-version: ${{ matrix.go }}
 
diff --git a/.golangci.yml b/.golangci.yml
index 441db5ee..06ee200c 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -31,6 +31,7 @@ linters:
     - varcheck
     - whitespace
     - wastedassign
+    - unconvert
 
   # don't enable:
   # - asciicheck
@@ -66,3 +67,5 @@ linters-settings:
   gocyclo:
     # recommend 10-20
     min-complexity: 50
+  goimports:
+    local-prefixes: github.com/go-kratos/kratos # Put imports beginning with prefix after 3rd-party packages
diff --git a/api/metadata/server.go b/api/metadata/server.go
index 39e468ec..b1c4c17b 100644
--- a/api/metadata/server.go
+++ b/api/metadata/server.go
@@ -7,6 +7,7 @@ import (
 	"errors"
 	"fmt"
 	"io"
+	"sort"
 	"sync"
 
 	"google.golang.org/grpc"
@@ -14,7 +15,7 @@ import (
 	"google.golang.org/grpc/status"
 	"google.golang.org/protobuf/proto"
 	"google.golang.org/protobuf/reflect/protodesc"
-	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	"google.golang.org/protobuf/reflect/protoreflect"
 	"google.golang.org/protobuf/reflect/protoregistry"
 	dpb "google.golang.org/protobuf/types/descriptorpb"
 
@@ -115,6 +116,8 @@ func (s *Server) ListServices(ctx context.Context, in *ListServicesRequest) (*Li
 			reply.Methods = append(reply.Methods, fmt.Sprintf("/%s/%s", name, method))
 		}
 	}
+	sort.Strings(reply.Services)
+	sort.Strings(reply.Methods)
 	return reply, nil
 }
 
diff --git a/app.go b/app.go
index e3d81ffb..436be294 100644
--- a/app.go
+++ b/app.go
@@ -89,8 +89,15 @@ func (a *App) Run() error {
 	a.mu.Lock()
 	a.instance = instance
 	a.mu.Unlock()
-	eg, ctx := errgroup.WithContext(NewContext(a.ctx, a))
+	sctx := NewContext(a.ctx, a)
+	eg, ctx := errgroup.WithContext(sctx)
 	wg := sync.WaitGroup{}
+
+	for _, fn := range a.opts.beforeStart {
+		if err = fn(sctx); err != nil {
+			return err
+		}
+	}
 	for _, srv := range a.opts.servers {
 		srv := srv
 		eg.Go(func() error {
@@ -102,17 +109,23 @@ func (a *App) Run() error {
 		wg.Add(1)
 		eg.Go(func() error {
 			wg.Done() // here is to ensure server start has begun running before register, so defer is not needed
-			return srv.Start(NewContext(a.opts.ctx, a))
+			return srv.Start(sctx)
 		})
 	}
 	wg.Wait()
 	if a.opts.registrar != nil {
 		rctx, rcancel := context.WithTimeout(ctx, a.opts.registrarTimeout)
 		defer rcancel()
-		if err := a.opts.registrar.Register(rctx, instance); err != nil {
+		if err = a.opts.registrar.Register(rctx, instance); err != nil {
+			return err
+		}
+	}
+	for _, fn := range a.opts.afterStart {
+		if err = fn(sctx); err != nil {
 			return err
 		}
 	}
+
 	c := make(chan os.Signal, 1)
 	signal.Notify(c, a.opts.sigs...)
 	eg.Go(func() error {
@@ -123,28 +136,36 @@ func (a *App) Run() error {
 			return a.Stop()
 		}
 	})
-	if err := eg.Wait(); err != nil && !errors.Is(err, context.Canceled) {
+	if err = eg.Wait(); err != nil && !errors.Is(err, context.Canceled) {
 		return err
 	}
-	return nil
+	for _, fn := range a.opts.afterStop {
+		err = fn(sctx)
+	}
+	return err
 }
 
 // Stop gracefully stops the application.
-func (a *App) Stop() error {
+func (a *App) Stop() (err error) {
+	sctx := NewContext(a.ctx, a)
+	for _, fn := range a.opts.beforeStop {
+		err = fn(sctx)
+	}
+
 	a.mu.Lock()
 	instance := a.instance
 	a.mu.Unlock()
 	if a.opts.registrar != nil && instance != nil {
 		ctx, cancel := context.WithTimeout(NewContext(a.ctx, a), a.opts.registrarTimeout)
 		defer cancel()
-		if err := a.opts.registrar.Deregister(ctx, instance); err != nil {
+		if err = a.opts.registrar.Deregister(ctx, instance); err != nil {
 			return err
 		}
 	}
 	if a.cancel != nil {
 		a.cancel()
 	}
-	return nil
+	return err
 }
 
 func (a *App) buildInstance() (*registry.ServiceInstance, error) {
diff --git a/cmd/kratos/internal/base/vcs_url.go b/cmd/kratos/internal/base/vcs_url.go
index ef76db30..6d3aef12 100644
--- a/cmd/kratos/internal/base/vcs_url.go
+++ b/cmd/kratos/internal/base/vcs_url.go
@@ -8,7 +8,7 @@ import (
 )
 
 var (
-	scpSyntaxRe = regexp.MustCompile(`^([a-zA-Z0-9_]+)@([a-zA-Z0-9._-]+):(.*)$`)
+	scpSyntaxRe = regexp.MustCompile(`^(\w+)@([\w.-]+):(.*)$`)
 	scheme      = []string{"git", "https", "http", "git+ssh", "ssh", "file", "ftp", "ftps"}
 )
 
diff --git a/cmd/kratos/internal/change/get.go b/cmd/kratos/internal/change/get.go
index 18e02072..32046d1e 100644
--- a/cmd/kratos/internal/change/get.go
+++ b/cmd/kratos/internal/change/get.go
@@ -43,7 +43,7 @@ func (g *GithubAPI) GetReleaseInfo(version string) ReleaseInfo {
 	if version != "latest" {
 		api = fmt.Sprintf("https://api.github.com/repos/%s/%s/releases/tags/%s", g.Owner, g.Repo, version)
 	}
-	resp, code := requestGithubAPI(api, "GET", nil, g.Token)
+	resp, code := requestGithubAPI(api, http.MethodGet, nil, g.Token)
 	if code != http.StatusOK {
 		printGithubErrorInfo(resp)
 	}
@@ -63,7 +63,7 @@ func (g *GithubAPI) GetCommitsInfo() []CommitInfo {
 	var list []CommitInfo
 	for {
 		url := fmt.Sprintf("https://api.github.com/repos/%s/%s/commits?pre_page=%d&page=%d&since=%s", g.Owner, g.Repo, prePage, page, info.PublishedAt)
-		resp, code := requestGithubAPI(url, "GET", nil, g.Token)
+		resp, code := requestGithubAPI(url, http.MethodGet, nil, g.Token)
 		if code != http.StatusOK {
 			printGithubErrorInfo(resp)
 		}
diff --git a/cmd/kratos/version.go b/cmd/kratos/version.go
index 9d205cbc..5ccc1597 100644
--- a/cmd/kratos/version.go
+++ b/cmd/kratos/version.go
@@ -1,4 +1,4 @@
 package main
 
 // release is the current kratos tool version.
-const release = "v2.5.0"
+const release = "v2.5.2"
diff --git a/cmd/protoc-gen-go-errors/version.go b/cmd/protoc-gen-go-errors/version.go
index 71fced3e..e9c17d21 100644
--- a/cmd/protoc-gen-go-errors/version.go
+++ b/cmd/protoc-gen-go-errors/version.go
@@ -1,4 +1,4 @@
 package main
 
 // release is the current protoc-gen-go-errors version.
-const release = "v2.5.0"
+const release = "v2.5.2"
diff --git a/cmd/protoc-gen-go-http/http.go b/cmd/protoc-gen-go-http/http.go
index d8827722..1c9298bf 100644
--- a/cmd/protoc-gen-go-http/http.go
+++ b/cmd/protoc-gen-go-http/http.go
@@ -2,6 +2,7 @@ package main
 
 import (
 	"fmt"
+	"net/http"
 	"os"
 	"regexp"
 	"strings"
@@ -85,7 +86,7 @@ func genService(gen *protogen.Plugin, file *protogen.File, g *protogen.Generated
 			sd.Methods = append(sd.Methods, buildHTTPRule(g, method, rule))
 		} else if !omitempty {
 			path := fmt.Sprintf("/%s/%s", service.Desc.FullName(), method.Desc.Name())
-			sd.Methods = append(sd.Methods, buildMethodDesc(g, method, "POST", path))
+			sd.Methods = append(sd.Methods, buildMethodDesc(g, method, http.MethodPost, path))
 		}
 	}
 	if len(sd.Methods) != 0 {
@@ -119,19 +120,19 @@ func buildHTTPRule(g *protogen.GeneratedFile, m *protogen.Method, rule *annotati
 	switch pattern := rule.Pattern.(type) {
 	case *annotations.HttpRule_Get:
 		path = pattern.Get
-		method = "GET"
+		method = http.MethodGet
 	case *annotations.HttpRule_Put:
 		path = pattern.Put
-		method = "PUT"
+		method = http.MethodPut
 	case *annotations.HttpRule_Post:
 		path = pattern.Post
-		method = "POST"
+		method = http.MethodPost
 	case *annotations.HttpRule_Delete:
 		path = pattern.Delete
-		method = "DELETE"
+		method = http.MethodDelete
 	case *annotations.HttpRule_Patch:
 		path = pattern.Patch
-		method = "PATCH"
+		method = http.MethodPatch
 	case *annotations.HttpRule_Custom:
 		path = pattern.Custom.Path
 		method = pattern.Custom.Kind
@@ -139,7 +140,7 @@ func buildHTTPRule(g *protogen.GeneratedFile, m *protogen.Method, rule *annotati
 	body = rule.Body
 	responseBody = rule.ResponseBody
 	md := buildMethodDesc(g, m, method, path)
-	if method == "GET" || method == "DELETE" {
+	if method == http.MethodGet || method == http.MethodDelete {
 		if body != "" {
 			_, _ = fmt.Fprintf(os.Stderr, "\u001B[31mWARN\u001B[m: %s %s body should not be declared.\n", method, path)
 		}
@@ -213,7 +214,7 @@ func buildPathVars(path string) (res map[string]*string) {
 	if strings.HasSuffix(path, "/") {
 		fmt.Fprintf(os.Stderr, "\u001B[31mWARN\u001B[m: Path %s should not end with \"/\" \n", path)
 	}
-	pattern := regexp.MustCompile(`(?i){([a-z\.0-9_\s]*)=?([^{}]*)}`)
+	pattern := regexp.MustCompile(`(?i){([a-z.0-9_\s]*)=?([^{}]*)}`)
 	matches := pattern.FindAllStringSubmatch(path, -1)
 	res = make(map[string]*string, len(matches))
 	for _, m := range matches {
diff --git a/cmd/protoc-gen-go-http/version.go b/cmd/protoc-gen-go-http/version.go
index 065e7dd5..7d929e18 100644
--- a/cmd/protoc-gen-go-http/version.go
+++ b/cmd/protoc-gen-go-http/version.go
@@ -1,4 +1,4 @@
 package main
 
 // release is the current protoc-gen-go-http version.
-const release = "v2.5.0"
+const release = "v2.5.2"
diff --git a/config/config.go b/config/config.go
index 126a6379..9efc9024 100644
--- a/config/config.go
+++ b/config/config.go
@@ -15,13 +15,13 @@ import (
 	"github.com/go-kratos/kratos/v2/log"
 )
 
+var _ Config = (*config)(nil)
+
 var (
 	// ErrNotFound is key not found.
 	ErrNotFound = errors.New("key not found")
 	// ErrTypeAssert is type assert error.
 	ErrTypeAssert = errors.New("type assert error")
-
-	_ Config = (*config)(nil)
 )
 
 // Observer is config observer.
@@ -44,7 +44,7 @@ type config struct {
 	watchers  []Watcher
 }
 
-// New new a config with options.
+// New a config with options.
 func New(opts ...Option) Config {
 	o := options{
 		decoder:  defaultDecoder,
@@ -62,11 +62,11 @@ func New(opts ...Option) Config {
 func (c *config) watch(w Watcher) {
 	for {
 		kvs, err := w.Next()
-		if errors.Is(err, context.Canceled) {
-			log.Infof("watcher's ctx cancel : %v", err)
-			return
-		}
 		if err != nil {
+			if errors.Is(err, context.Canceled) {
+				log.Infof("watcher's ctx cancel : %v", err)
+				return
+			}
 			time.Sleep(time.Second)
 			log.Errorf("failed to watch next config: %v", err)
 			continue
diff --git a/config/env/env.go b/config/env/env.go
index 30e011b9..cdd30e1b 100644
--- a/config/env/env.go
+++ b/config/env/env.go
@@ -19,11 +19,11 @@ func (e *env) Load() (kv []*config.KeyValue, err error) {
 	return e.load(os.Environ()), nil
 }
 
-func (e *env) load(envStrings []string) []*config.KeyValue {
+func (e *env) load(envs []string) []*config.KeyValue {
 	var kv []*config.KeyValue
-	for _, envstr := range envStrings {
+	for _, env := range envs {
 		var k, v string
-		subs := strings.SplitN(envstr, "=", 2) //nolint:gomnd
+		subs := strings.SplitN(env, "=", 2) //nolint:gomnd
 		k = subs[0]
 		if len(subs) > 1 {
 			v = subs[1]
diff --git a/config/env/watcher.go b/config/env/watcher.go
index 2ea02931..84e7932e 100644
--- a/config/env/watcher.go
+++ b/config/env/watcher.go
@@ -6,13 +6,13 @@ import (
 	"github.com/go-kratos/kratos/v2/config"
 )
 
+var _ config.Watcher = (*watcher)(nil)
+
 type watcher struct {
 	ctx    context.Context
 	cancel context.CancelFunc
 }
 
-var _ config.Watcher = (*watcher)(nil)
-
 func NewWatcher() (config.Watcher, error) {
 	ctx, cancel := context.WithCancel(context.Background())
 	return &watcher{ctx: ctx, cancel: cancel}, nil
diff --git a/config/file/watcher.go b/config/file/watcher.go
index ea309fa8..1f067d1a 100644
--- a/config/file/watcher.go
+++ b/config/file/watcher.go
@@ -10,6 +10,8 @@ import (
 	"github.com/go-kratos/kratos/v2/config"
 )
 
+var _ config.Watcher = (*watcher)(nil)
+
 type watcher struct {
 	f  *file
 	fw *fsnotify.Watcher
@@ -18,8 +20,6 @@ type watcher struct {
 	cancel context.CancelFunc
 }
 
-var _ config.Watcher = (*watcher)(nil)
-
 func newWatcher(f *file) (config.Watcher, error) {
 	fw, err := fsnotify.NewWatcher()
 	if err != nil {
diff --git a/config/reader.go b/config/reader.go
index 6858a0f6..2202de6b 100644
--- a/config/reader.go
+++ b/config/reader.go
@@ -8,11 +8,11 @@ import (
 	"strings"
 	"sync"
 
-	"github.com/go-kratos/kratos/v2/log"
-
 	"github.com/imdario/mergo"
 	"google.golang.org/protobuf/encoding/protojson"
 	"google.golang.org/protobuf/proto"
+
+	"github.com/go-kratos/kratos/v2/log"
 )
 
 // Reader is config reader.
@@ -38,9 +38,7 @@ func newReader(opts options) Reader {
 }
 
 func (r *reader) Merge(kvs ...*KeyValue) error {
-	r.lock.Lock()
-	merged, err := cloneMap(r.values)
-	r.lock.Unlock()
+	merged, err := r.cloneMap()
 	if err != nil {
 		return err
 	}
@@ -79,6 +77,12 @@ func (r *reader) Resolve() error {
 	return r.opts.resolver(r.values)
 }
 
+func (r *reader) cloneMap() (map[string]interface{}, error) {
+	r.lock.Lock()
+	defer r.lock.Unlock()
+	return cloneMap(r.values)
+}
+
 func cloneMap(src map[string]interface{}) (map[string]interface{}, error) {
 	// https://gist.github.com/soroushjp/0ec92102641ddfc3ad5515ca76405f4d
 	var buf bytes.Buffer
@@ -90,12 +94,12 @@ func cloneMap(src map[string]interface{}) (map[string]interface{}, error) {
 	if err != nil {
 		return nil, err
 	}
-	var copy map[string]interface{}
-	err = dec.Decode(&copy)
+	var clone map[string]interface{}
+	err = dec.Decode(&clone)
 	if err != nil {
 		return nil, err
 	}
-	return copy, nil
+	return clone, nil
 }
 
 func convertMap(src interface{}) interface{} {
diff --git a/config/value.go b/config/value.go
index 9f6234f5..11de2e89 100644
--- a/config/value.go
+++ b/config/value.go
@@ -1,7 +1,7 @@
 package config
 
 import (
-	stdjson "encoding/json"
+	"encoding/json"
 	"fmt"
 	"reflect"
 	"strconv"
@@ -10,7 +10,7 @@ import (
 
 	"google.golang.org/protobuf/proto"
 
-	"github.com/go-kratos/kratos/v2/encoding/json"
+	kratosjson "github.com/go-kratos/kratos/v2/encoding/json"
 )
 
 var (
@@ -36,6 +36,10 @@ type atomicValue struct {
 	atomic.Value
 }
 
+func (v *atomicValue) typeAssertError() error {
+	return fmt.Errorf("type assert to %v failed", reflect.TypeOf(v.Load()))
+}
+
 func (v *atomicValue) Bool() (bool, error) {
 	switch val := v.Load().(type) {
 	case bool:
@@ -43,7 +47,7 @@ func (v *atomicValue) Bool() (bool, error) {
 	case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, string:
 		return strconv.ParseBool(fmt.Sprint(val))
 	}
-	return false, fmt.Errorf("type assert to %v failed", reflect.TypeOf(v.Load()))
+	return false, v.typeAssertError()
 }
 
 func (v *atomicValue) Int() (int64, error) {
@@ -73,35 +77,37 @@ func (v *atomicValue) Int() (int64, error) {
 	case float64:
 		return int64(val), nil
 	case string:
-		return strconv.ParseInt(val, 10, 64) //nolint:gomnd
+		return strconv.ParseInt(val, 10, 64)
 	}
-	return 0, fmt.Errorf("type assert to %v failed", reflect.TypeOf(v.Load()))
+	return 0, v.typeAssertError()
 }
 
 func (v *atomicValue) Slice() ([]Value, error) {
-	if vals, ok := v.Load().([]interface{}); ok {
-		var slices []Value
-		for _, val := range vals {
-			a := &atomicValue{}
-			a.Store(val)
-			slices = append(slices, a)
-		}
-		return slices, nil
+	vals, ok := v.Load().([]interface{})
+	if !ok {
+		return nil, v.typeAssertError()
 	}
-	return nil, fmt.Errorf("type assert to %v failed", reflect.TypeOf(v.Load()))
+	slices := make([]Value, 0, len(vals))
+	for _, val := range vals {
+		a := new(atomicValue)
+		a.Store(val)
+		slices = append(slices, a)
+	}
+	return slices, nil
 }
 
 func (v *atomicValue) Map() (map[string]Value, error) {
-	if vals, ok := v.Load().(map[string]interface{}); ok {
-		m := make(map[string]Value, len(vals))
-		for key, val := range vals {
-			a := new(atomicValue)
-			a.Store(val)
-			m[key] = a
-		}
-		return m, nil
+	vals, ok := v.Load().(map[string]interface{})
+	if !ok {
+		return nil, v.typeAssertError()
+	}
+	m := make(map[string]Value, len(vals))
+	for key, val := range vals {
+		a := new(atomicValue)
+		a.Store(val)
+		m[key] = a
 	}
-	return nil, fmt.Errorf("type assert to %v failed", reflect.TypeOf(v.Load()))
+	return m, nil
 }
 
 func (v *atomicValue) Float() (float64, error) {
@@ -131,9 +137,9 @@ func (v *atomicValue) Float() (float64, error) {
 	case float64:
 		return val, nil
 	case string:
-		return strconv.ParseFloat(val, 64) //nolint:gomnd
+		return strconv.ParseFloat(val, 64)
 	}
-	return 0.0, fmt.Errorf("type assert to %v failed", reflect.TypeOf(v.Load()))
+	return 0.0, v.typeAssertError()
 }
 
 func (v *atomicValue) String() (string, error) {
@@ -147,7 +153,7 @@ func (v *atomicValue) String() (string, error) {
 	case fmt.Stringer:
 		return val.String(), nil
 	}
-	return "", fmt.Errorf("type assert to %v failed", reflect.TypeOf(v.Load()))
+	return "", v.typeAssertError()
 }
 
 func (v *atomicValue) Duration() (time.Duration, error) {
@@ -159,14 +165,14 @@ func (v *atomicValue) Duration() (time.Duration, error) {
 }
 
 func (v *atomicValue) Scan(obj interface{}) error {
-	data, err := stdjson.Marshal(v.Load())
+	data, err := json.Marshal(v.Load())
 	if err != nil {
 		return err
 	}
 	if pb, ok := obj.(proto.Message); ok {
-		return json.UnmarshalOptions.Unmarshal(data, pb)
+		return kratosjson.UnmarshalOptions.Unmarshal(data, pb)
 	}
-	return stdjson.Unmarshal(data, obj)
+	return json.Unmarshal(data, obj)
 }
 
 type errValue struct {
diff --git a/contrib/config/apollo/README.md b/contrib/config/apollo/README.md
index c03cff0f..a8eea493 100644
--- a/contrib/config/apollo/README.md
+++ b/contrib/config/apollo/README.md
@@ -97,5 +97,4 @@ config := map[string]interface{}{
         }
     }
 }
-_ = config
 ```
diff --git a/contrib/config/apollo/apollo.go b/contrib/config/apollo/apollo.go
index 259ed1a9..bd96ef11 100644
--- a/contrib/config/apollo/apollo.go
+++ b/contrib/config/apollo/apollo.go
@@ -3,15 +3,14 @@ package apollo
 import (
 	"strings"
 
-	"github.com/go-kratos/kratos/v2/config"
-	"github.com/go-kratos/kratos/v2/log"
-
 	"github.com/apolloconfig/agollo/v4"
 	"github.com/apolloconfig/agollo/v4/constant"
 	apolloConfig "github.com/apolloconfig/agollo/v4/env/config"
 	"github.com/apolloconfig/agollo/v4/extension"
 
+	"github.com/go-kratos/kratos/v2/config"
 	"github.com/go-kratos/kratos/v2/encoding"
+	"github.com/go-kratos/kratos/v2/log"
 )
 
 type apollo struct {
diff --git a/contrib/config/apollo/go.mod b/contrib/config/apollo/go.mod
index 236b4ed3..17ecbf85 100644
--- a/contrib/config/apollo/go.mod
+++ b/contrib/config/apollo/go.mod
@@ -3,7 +3,7 @@ module github.com/go-kratos/kratos/contrib/config/apollo/v2
 go 1.16
 
 require (
-	github.com/apolloconfig/agollo/v4 v4.2.0
+	github.com/apolloconfig/agollo/v4 v4.2.1
 	github.com/go-kratos/kratos/v2 v2.4.0
 )
 
diff --git a/contrib/config/apollo/go.sum b/contrib/config/apollo/go.sum
index 99e04ca3..3115b668 100644
--- a/contrib/config/apollo/go.sum
+++ b/contrib/config/apollo/go.sum
@@ -63,8 +63,8 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
 github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
 github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
-github.com/apolloconfig/agollo/v4 v4.2.0 h1:FkE8acffsUhnRnjyi37eOq6JpfUhQKuNccG2jXB3Mco=
-github.com/apolloconfig/agollo/v4 v4.2.0/go.mod h1:SuvTjtg0p4UlSzSbik+ibLRr6oR1xRsfy65QzP3GEAs=
+github.com/apolloconfig/agollo/v4 v4.2.1 h1:+cTdSZbWfLLZpEQk2LEhSbkmjLH+rzyAAPb6buhPA+Q=
+github.com/apolloconfig/agollo/v4 v4.2.1/go.mod h1:SuvTjtg0p4UlSzSbik+ibLRr6oR1xRsfy65QzP3GEAs=
 github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
 github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
 github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
diff --git a/contrib/config/apollo/watcher.go b/contrib/config/apollo/watcher.go
index 94ef2ef0..ea5ef108 100644
--- a/contrib/config/apollo/watcher.go
+++ b/contrib/config/apollo/watcher.go
@@ -4,12 +4,11 @@ import (
 	"context"
 	"strings"
 
-	"github.com/go-kratos/kratos/v2/encoding"
+	"github.com/apolloconfig/agollo/v4/storage"
 
 	"github.com/go-kratos/kratos/v2/config"
+	"github.com/go-kratos/kratos/v2/encoding"
 	"github.com/go-kratos/kratos/v2/log"
-
-	"github.com/apolloconfig/agollo/v4/storage"
 )
 
 type watcher struct {
diff --git a/contrib/config/consul/README.md b/contrib/config/consul/README.md
index a3d39a18..9dc5a066 100644
--- a/contrib/config/consul/README.md
+++ b/contrib/config/consul/README.md
@@ -2,20 +2,21 @@
 
 ```go
 import (
-    "github.com/go-kratos/kratos/contrib/config/consul/v2"
     "github.com/hashicorp/consul/api"
+
+    "github.com/go-kratos/kratos/contrib/config/consul/v2"
 )
-func main() {
 
+func main() {
     consulClient, err := api.NewClient(&api.Config{
-    Address: "127.0.0.1:8500",
+        Address: "127.0.0.1:8500",
     })
     if err != nil {
         panic(err)
     }
     cs, err := consul.New(consulClient, consul.WithPath("app/cart/configs/"))
-    //consul中需要标注文件后缀，kratos读取配置需要适配文件后缀
-    //The file suffix needs to be marked, and kratos needs to adapt the file suffix to read the configuration.
+    // consul中需要标注文件后缀，kratos读取配置需要适配文件后缀
+    // The file suffix needs to be marked, and kratos needs to adapt the file suffix to read the configuration.
     if err != nil {
         panic(err)
     }
diff --git a/contrib/config/consul/config.go b/contrib/config/consul/config.go
index dca8a88e..0404801b 100644
--- a/contrib/config/consul/config.go
+++ b/contrib/config/consul/config.go
@@ -28,9 +28,9 @@ func WithContext(ctx context.Context) Option {
 
 // WithPath is config path
 func WithPath(p string) Option {
-	return Option(func(o *options) {
+	return func(o *options) {
 		o.path = p
-	})
+	}
 }
 
 type source struct {
diff --git a/contrib/config/consul/go.mod b/contrib/config/consul/go.mod
index 49e23b74..25d459c6 100644
--- a/contrib/config/consul/go.mod
+++ b/contrib/config/consul/go.mod
@@ -4,7 +4,7 @@ go 1.15
 
 require (
 	github.com/go-kratos/kratos/v2 v2.4.0
-	github.com/hashicorp/consul/api v1.14.0
+	github.com/hashicorp/consul/api v1.15.3
 )
 
 replace github.com/go-kratos/kratos/v2 => ../../../
diff --git a/contrib/config/consul/go.sum b/contrib/config/consul/go.sum
index 25fbdf7f..b6e682aa 100644
--- a/contrib/config/consul/go.sum
+++ b/contrib/config/consul/go.sum
@@ -91,10 +91,10 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
 github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
 github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
-github.com/hashicorp/consul/api v1.14.0 h1:Y64GIJ8hYTu+tuGekwO4G4ardXoiCivX9wv1iP/kihk=
-github.com/hashicorp/consul/api v1.14.0/go.mod h1:bcaw5CSZ7NE9qfOfKCI1xb7ZKjzu/MyvQkCLTfqLqxQ=
-github.com/hashicorp/consul/sdk v0.10.0 h1:rGLEh2AWK4K0KCMvqWAz2EYxQqgciIfMagWZ0nVe5MI=
-github.com/hashicorp/consul/sdk v0.10.0/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw=
+github.com/hashicorp/consul/api v1.15.3 h1:WYONYL2rxTXtlekAqblR2SCdJsizMDIj/uXb5wNy9zU=
+github.com/hashicorp/consul/api v1.15.3/go.mod h1:/g/qgcoBcEXALCNZgRRisyTW0nY86++L0KbeAMXYCeY=
+github.com/hashicorp/consul/sdk v0.11.0 h1:HRzj8YSCln2yGgCumN5CL8lYlD3gBurnervJRJAZyC4=
+github.com/hashicorp/consul/sdk v0.11.0/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw=
 github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
 github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
 github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
diff --git a/contrib/config/etcd/README.md b/contrib/config/etcd/README.md
index d7668745..131619c1 100644
--- a/contrib/config/etcd/README.md
+++ b/contrib/config/etcd/README.md
@@ -4,10 +4,11 @@
 import (
 	"log"
 
-	cfg "github.com/go-kratos/kratos/contrib/config/etcd/v2"
-	"github.com/go-kratos/kratos/v2/config"
 	clientv3 "go.etcd.io/etcd/client/v3"
 	"google.golang.org/grpc"
+
+	cfg "github.com/go-kratos/kratos/contrib/config/etcd/v2"
+	"github.com/go-kratos/kratos/v2/config"
 )
 
 // create an etcd client
@@ -30,12 +31,16 @@ if err != nil {
 c := config.New(config.WithSource(source))
 defer c.Close()
 
+// load sources before get
+if err := c.Load(); err != nil {
+    log.Fatalln(err)
+}
+
 // acquire config value
 foo, err := c.Value("/app-config").String()
 if err != nil {
-    log.Println(err)
+    log.Fatalln(err)
 }
-println(foo)
 
+log.Println(foo)
 ```
-
diff --git a/contrib/config/etcd/go.mod b/contrib/config/etcd/go.mod
index fffcfd13..a3b15a50 100644
--- a/contrib/config/etcd/go.mod
+++ b/contrib/config/etcd/go.mod
@@ -5,7 +5,7 @@ go 1.16
 require (
 	github.com/go-kratos/kratos/v2 v2.4.0
 	go.etcd.io/etcd/client/v3 v3.5.4
-	google.golang.org/grpc v1.46.2
+	google.golang.org/grpc v1.50.1
 )
 
 replace github.com/go-kratos/kratos/v2 => ../../../
diff --git a/contrib/config/etcd/go.sum b/contrib/config/etcd/go.sum
index 0f7dae51..5905957b 100644
--- a/contrib/config/etcd/go.sum
+++ b/contrib/config/etcd/go.sum
@@ -271,8 +271,9 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp
 google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
 google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
 google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
-google.golang.org/grpc v1.46.2 h1:u+MLGgVf7vRdjEYZ8wDFhAVNmhkbJ5hmrA1LMWK1CAQ=
 google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
+google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY=
+google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
diff --git a/contrib/config/nacos/README.md b/contrib/config/nacos/README.md
index 71f186bf..fa54caf0 100644
--- a/contrib/config/nacos/README.md
+++ b/contrib/config/nacos/README.md
@@ -2,9 +2,10 @@
 
 ```go
 import (
-	kconfig "github.com/go-kratos/kratos/v2/config"
 	"github.com/nacos-group/nacos-sdk-go/clients"
 	"github.com/nacos-group/nacos-sdk-go/common/constant"
+
+	kconfig "github.com/go-kratos/kratos/v2/config"
 )
 
 
diff --git a/contrib/config/nacos/go.mod b/contrib/config/nacos/go.mod
index 7890e058..6917f24a 100644
--- a/contrib/config/nacos/go.mod
+++ b/contrib/config/nacos/go.mod
@@ -5,6 +5,9 @@ go 1.16
 require (
 	github.com/go-kratos/kratos/v2 v2.4.0
 	github.com/nacos-group/nacos-sdk-go v1.0.9
+)
+
+require (
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 )
 
diff --git a/contrib/config/polaris/README.md b/contrib/config/polaris/README.md
index 4c2694c4..b39e78f2 100644
--- a/contrib/config/polaris/README.md
+++ b/contrib/config/polaris/README.md
@@ -2,24 +2,23 @@
 
 ```go
 import (
- "log"
-
- "github.com/polarismesh/polaris-go"
- "github.com/go-kratos/kratos/contrib/config/polaris/v2"
+	"log"
+	
+	"github.com/polarismesh/polaris-go"
+	
+	"github.com/go-kratos/kratos/contrib/config/polaris/v2"
 )
 
 func main() {
+    configApi, err := polaris.NewConfigAPI()
+    if err != nil {
+    	log.Fatalln(err)
+    }
 
- configApi, err := polaris.NewConfigAPI()
- if err != nil {
-  log.Fatalln(err)
- }
-
- source, err := New(&configApi, WithNamespace("default"), WithFileGroup("default"), WithFileName("default.yaml"))
-
- if err != nil {
-  log.Fatalln(err)
- }
- source.Load()
+    source, err := New(&configApi, WithNamespace("default"), WithFileGroup("default"), WithFileName("default.yaml"))
+    if err != nil {
+    	log.Fatalln(err)
+    }
+    source.Load()
 }
 ```
diff --git a/contrib/config/polaris/config.go b/contrib/config/polaris/config.go
index c3c39ece..288db438 100644
--- a/contrib/config/polaris/config.go
+++ b/contrib/config/polaris/config.go
@@ -6,9 +6,9 @@ import (
 	"path/filepath"
 	"strings"
 
-	"github.com/go-kratos/kratos/v2/config"
-
 	"github.com/polarismesh/polaris-go"
+
+	"github.com/go-kratos/kratos/v2/config"
 )
 
 // Option is polaris config option.
diff --git a/contrib/config/polaris/watcher.go b/contrib/config/polaris/watcher.go
index dcd89055..70305550 100644
--- a/contrib/config/polaris/watcher.go
+++ b/contrib/config/polaris/watcher.go
@@ -5,11 +5,11 @@ import (
 	"path/filepath"
 	"strings"
 
-	"github.com/go-kratos/kratos/v2/config"
-	"github.com/go-kratos/kratos/v2/log"
-
 	"github.com/polarismesh/polaris-go"
 	"github.com/polarismesh/polaris-go/pkg/model"
+
+	"github.com/go-kratos/kratos/v2/config"
+	"github.com/go-kratos/kratos/v2/log"
 )
 
 type Watcher struct {
@@ -28,7 +28,7 @@ func getFullPath(namespace string, fileGroup string, fileName string) string {
 	return fmt.Sprintf("%s/%s/%s", namespace, fileGroup, fileName)
 }
 
-func recieve(event model.ConfigFileChangeEvent) {
+func receive(event model.ConfigFileChangeEvent) {
 	meta := event.ConfigFileMetadata
 	ec := eventChanMap[getFullPath(meta.GetNamespace(), meta.GetFileGroup(), meta.GetFileName())]
 	defer func() {
@@ -42,7 +42,7 @@ func recieve(event model.ConfigFileChangeEvent) {
 }
 
 func newWatcher(configFile polaris.ConfigFile) *Watcher {
-	configFile.AddChangeListener(recieve)
+	configFile.AddChangeListener(receive)
 
 	fullPath := getFullPath(configFile.GetNamespace(), configFile.GetFileGroup(), configFile.GetFileName())
 	if _, ok := eventChanMap[fullPath]; !ok {
diff --git a/contrib/encoding/msgpack/go.mod b/contrib/encoding/msgpack/go.mod
index 5d78c21b..7548f174 100644
--- a/contrib/encoding/msgpack/go.mod
+++ b/contrib/encoding/msgpack/go.mod
@@ -3,7 +3,7 @@ module github.com/go-kratos/kratos/contrib/encoding/msgpack/v2
 go 1.16
 
 require (
-	github.com/go-kratos/kratos/v2 v2.5.0
+	github.com/go-kratos/kratos/v2 v2.5.2
 	github.com/vmihailenco/msgpack/v5 v5.3.5
 )
 
diff --git a/contrib/log/aliyun/aliyun.go b/contrib/log/aliyun/aliyun.go
index a5e57ca6..836960e0 100644
--- a/contrib/log/aliyun/aliyun.go
+++ b/contrib/log/aliyun/aliyun.go
@@ -2,6 +2,7 @@ package aliyun
 
 import (
 	"encoding/json"
+	"fmt"
 	"strconv"
 	"time"
 
@@ -9,12 +10,13 @@ import (
 	"github.com/aliyun/aliyun-log-go-sdk/producer"
 	"google.golang.org/protobuf/proto"
 
-	log "github.com/go-kratos/kratos/v2/log"
+	"github.com/go-kratos/kratos/v2/log"
 )
 
 // Logger see more detail https://github.com/aliyun/aliyun-log-go-sdk
 type Logger interface {
 	log.Logger
+
 	GetProducer() *producer.Producer
 	Close() error
 }
@@ -80,22 +82,16 @@ func (a *aliyunLog) Close() error {
 }
 
 func (a *aliyunLog) Log(level log.Level, keyvals ...interface{}) error {
-	buf := level.String()
-	levelTitle := "level"
-
-	contents := make([]*sls.LogContent, 0)
+	contents := make([]*sls.LogContent, 0, len(keyvals)/2+1)
 
 	contents = append(contents, &sls.LogContent{
-		Key:   &levelTitle,
-		Value: &buf,
+		Key:   newString(level.Key()),
+		Value: newString(level.String()),
 	})
-
 	for i := 0; i < len(keyvals); i += 2 {
-		key := toString(keyvals[i])
-		value := toString(keyvals[i+1])
 		contents = append(contents, &sls.LogContent{
-			Key:   &key,
-			Value: &value,
+			Key:   newString(toString(keyvals[i])),
+			Value: newString(toString(keyvals[i+1])),
 		})
 	}
 
@@ -103,9 +99,7 @@ func (a *aliyunLog) Log(level log.Level, keyvals ...interface{}) error {
 		Time:     proto.Uint32(uint32(time.Now().Unix())),
 		Contents: contents,
 	}
-
-	err := a.producer.SendLog(a.opts.project, a.opts.logstore, "", "", logInst)
-	return err
+	return a.producer.SendLog(a.opts.project, a.opts.logstore, "", "", logInst)
 }
 
 // NewAliyunLog new a aliyun logger with options.
@@ -127,6 +121,11 @@ func NewAliyunLog(options ...Option) Logger {
 	}
 }
 
+// newString string convert to *string
+func newString(s string) *string {
+	return &s
+}
+
 // toString convert any type to string
 func toString(v interface{}) string {
 	var key string
@@ -137,23 +136,23 @@ func toString(v interface{}) string {
 	case float64:
 		key = strconv.FormatFloat(v, 'f', -1, 64)
 	case float32:
-		key = strconv.FormatFloat(float64(v), 'f', -1, 64)
+		key = strconv.FormatFloat(float64(v), 'f', -1, 32)
 	case int:
 		key = strconv.Itoa(v)
 	case uint:
-		key = strconv.Itoa(int(v))
+		key = strconv.FormatUint(uint64(v), 10)
 	case int8:
 		key = strconv.Itoa(int(v))
 	case uint8:
-		key = strconv.Itoa(int(v))
+		key = strconv.FormatUint(uint64(v), 10)
 	case int16:
 		key = strconv.Itoa(int(v))
 	case uint16:
-		key = strconv.Itoa(int(v))
+		key = strconv.FormatUint(uint64(v), 10)
 	case int32:
 		key = strconv.Itoa(int(v))
 	case uint32:
-		key = strconv.Itoa(int(v))
+		key = strconv.FormatUint(uint64(v), 10)
 	case int64:
 		key = strconv.FormatInt(v, 10)
 	case uint64:
@@ -164,6 +163,8 @@ func toString(v interface{}) string {
 		key = strconv.FormatBool(v)
 	case []byte:
 		key = string(v)
+	case fmt.Stringer:
+		key = v.String()
 	default:
 		newValue, _ := json.Marshal(v)
 		key = string(newValue)
diff --git a/contrib/log/aliyun/go.mod b/contrib/log/aliyun/go.mod
index efe1b827..54abe05f 100644
--- a/contrib/log/aliyun/go.mod
+++ b/contrib/log/aliyun/go.mod
@@ -3,8 +3,8 @@ module github.com/go-kratos/kratos/contrib/log/aliyun/v2
 go 1.16
 
 require (
-	github.com/aliyun/aliyun-log-go-sdk v0.1.37
-	github.com/go-kratos/kratos/v2 v2.5.0
+	github.com/aliyun/aliyun-log-go-sdk v0.1.40
+	github.com/go-kratos/kratos/v2 v2.5.2
 	google.golang.org/protobuf v1.28.1
 )
 
diff --git a/contrib/log/aliyun/go.sum b/contrib/log/aliyun/go.sum
index 6fde6344..0b42927b 100644
--- a/contrib/log/aliyun/go.sum
+++ b/contrib/log/aliyun/go.sum
@@ -12,8 +12,8 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
 github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
 github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
-github.com/aliyun/aliyun-log-go-sdk v0.1.37 h1:GvswbgLqVOHNeMWssQ9zA+R7YVDP6arLUP92bKyGZNw=
-github.com/aliyun/aliyun-log-go-sdk v0.1.37/go.mod h1:1QQ59pEJiVVXqKgbHcU6FWIgxT5RKBt+CT8AiQ2bEts=
+github.com/aliyun/aliyun-log-go-sdk v0.1.40 h1:GNlRoTe9Fi7dfhIMHAnb+b5837/fIw8lqs1DRqaU1CM=
+github.com/aliyun/aliyun-log-go-sdk v0.1.40/go.mod h1:1QQ59pEJiVVXqKgbHcU6FWIgxT5RKBt+CT8AiQ2bEts=
 github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
 github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
 github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
diff --git a/contrib/log/fluent/go.mod b/contrib/log/fluent/go.mod
index b316425a..cd2e6ff9 100644
--- a/contrib/log/fluent/go.mod
+++ b/contrib/log/fluent/go.mod
@@ -5,7 +5,7 @@ go 1.16
 require (
 	github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
 	github.com/fluent/fluent-logger-golang v1.9.0
-	github.com/go-kratos/kratos/v2 v2.5.0
+	github.com/go-kratos/kratos/v2 v2.5.2
 	github.com/kr/pretty v0.3.0 // indirect
 	github.com/tinylib/msgp v1.1.6 // indirect
 )
diff --git a/contrib/log/logrus/go.mod b/contrib/log/logrus/go.mod
index c41e4ecc..75465145 100644
--- a/contrib/log/logrus/go.mod
+++ b/contrib/log/logrus/go.mod
@@ -3,7 +3,7 @@ module github.com/go-kratos/kratos/contrib/log/logrus/v2
 go 1.16
 
 require (
-	github.com/go-kratos/kratos/v2 v2.5.0
+	github.com/go-kratos/kratos/v2 v2.5.2
 	github.com/sirupsen/logrus v1.8.1
 )
 
diff --git a/contrib/log/tencent/go.mod b/contrib/log/tencent/go.mod
index 2d3fa7dc..b102d725 100644
--- a/contrib/log/tencent/go.mod
+++ b/contrib/log/tencent/go.mod
@@ -3,7 +3,7 @@ module github.com/go-kratos/kratos/contrib/log/tencent/v2
 go 1.16
 
 require (
-	github.com/go-kratos/kratos/v2 v2.5.0
+	github.com/go-kratos/kratos/v2 v2.5.2
 	github.com/tencentcloud/tencentcloud-cls-sdk-go v1.0.2
 	google.golang.org/protobuf v1.28.0
 )
diff --git a/contrib/log/tencent/tencent.go b/contrib/log/tencent/tencent.go
index 40cc98cd..3016926e 100644
--- a/contrib/log/tencent/tencent.go
+++ b/contrib/log/tencent/tencent.go
@@ -9,13 +9,13 @@ import (
 	cls "github.com/tencentcloud/tencentcloud-cls-sdk-go"
 	"google.golang.org/protobuf/proto"
 
-	log "github.com/go-kratos/kratos/v2/log"
+	"github.com/go-kratos/kratos/v2/log"
 )
 
 type Logger interface {
 	log.Logger
-	GetProducer() *cls.AsyncProducerClient
 
+	GetProducer() *cls.AsyncProducerClient
 	Close() error
 }
 
@@ -66,25 +66,20 @@ func WithAccessSecret(as string) Option {
 type Option func(cls *options)
 
 func (log *tencentLog) Close() error {
-	err := log.producer.Close(5000)
-	return err
+	return log.producer.Close(5000)
 }
 
 func (log *tencentLog) Log(level log.Level, keyvals ...interface{}) error {
-	buf := level.String()
-	levelTitle := "level"
-	contents := make([]*cls.Log_Content, 0)
+	contents := make([]*cls.Log_Content, 0, len(keyvals)/2+1)
 
 	contents = append(contents, &cls.Log_Content{
-		Key:   &levelTitle,
-		Value: &buf,
+		Key:   newString(level.Key()),
+		Value: newString(level.String()),
 	})
 	for i := 0; i < len(keyvals); i += 2 {
-		key := toString(keyvals[i])
-		value := toString(keyvals[i+1])
 		contents = append(contents, &cls.Log_Content{
-			Key:   &key,
-			Value: &value,
+			Key:   newString(toString(keyvals[i])),
+			Value: newString(toString(keyvals[i+1])),
 		})
 	}
 
@@ -92,8 +87,7 @@ func (log *tencentLog) Log(level log.Level, keyvals ...interface{}) error {
 		Time:     proto.Int64(time.Now().Unix()),
 		Contents: contents,
 	}
-	err := log.producer.SendLog(log.opts.topicID, logInst, nil)
-	return err
+	return log.producer.SendLog(log.opts.topicID, logInst, nil)
 }
 
 func NewLogger(options ...Option) (Logger, error) {
@@ -115,7 +109,11 @@ func NewLogger(options ...Option) (Logger, error) {
 	}, nil
 }
 
-// toString any type to string
+func newString(s string) *string {
+	return &s
+}
+
+// toString convert any type to string
 func toString(v interface{}) string {
 	var key string
 	if v == nil {
@@ -125,27 +123,33 @@ func toString(v interface{}) string {
 	case float64:
 		key = strconv.FormatFloat(v, 'f', -1, 64)
 	case float32:
-		key = strconv.FormatFloat(float64(v), 'f', -1, 64)
+		key = strconv.FormatFloat(float64(v), 'f', -1, 32)
 	case int:
 		key = strconv.Itoa(v)
 	case uint:
-		key = strconv.Itoa(int(v))
+		key = strconv.FormatUint(uint64(v), 10)
 	case int8:
 		key = strconv.Itoa(int(v))
 	case uint8:
-		key = strconv.Itoa(int(v))
+		key = strconv.FormatUint(uint64(v), 10)
 	case int16:
 		key = strconv.Itoa(int(v))
 	case uint16:
-		key = strconv.Itoa(int(v))
+		key = strconv.FormatUint(uint64(v), 10)
 	case int32:
 		key = strconv.Itoa(int(v))
 	case uint32:
-		key = strconv.Itoa(int(v))
+		key = strconv.FormatUint(uint64(v), 10)
 	case int64:
 		key = strconv.FormatInt(v, 10)
 	case uint64:
 		key = strconv.FormatUint(v, 10)
+	case string:
+		key = v
+	case bool:
+		key = strconv.FormatBool(v)
+	case []byte:
+		key = string(v)
 	case fmt.Stringer:
 		key = v.String()
 	default:
diff --git a/contrib/log/zap/go.mod b/contrib/log/zap/go.mod
index 0a8e74f6..ad54dd22 100644
--- a/contrib/log/zap/go.mod
+++ b/contrib/log/zap/go.mod
@@ -3,7 +3,7 @@ module github.com/go-kratos/kratos/contrib/log/zap/v2
 go 1.16
 
 require (
-	github.com/go-kratos/kratos/v2 v2.5.0
+	github.com/go-kratos/kratos/v2 v2.5.2
 	go.uber.org/zap v1.23.0
 )
 
diff --git a/contrib/metrics/datadog/go.mod b/contrib/metrics/datadog/go.mod
index 206ccf4e..aebfd094 100644
--- a/contrib/metrics/datadog/go.mod
+++ b/contrib/metrics/datadog/go.mod
@@ -4,8 +4,11 @@ go 1.16
 
 require (
 	github.com/DataDog/datadog-go v4.8.3+incompatible
+	github.com/go-kratos/kratos/v2 v2.5.2
+)
+
+require (
 	github.com/Microsoft/go-winio v0.5.2 // indirect
-	github.com/go-kratos/kratos/v2 v2.5.0
 )
 
 replace github.com/go-kratos/kratos/v2 => ../../../
diff --git a/contrib/metrics/prometheus/go.mod b/contrib/metrics/prometheus/go.mod
index c6a1b5df..0b925f11 100644
--- a/contrib/metrics/prometheus/go.mod
+++ b/contrib/metrics/prometheus/go.mod
@@ -3,8 +3,8 @@ module github.com/go-kratos/kratos/contrib/metrics/prometheus/v2
 go 1.16
 
 require (
-	github.com/go-kratos/kratos/v2 v2.5.0
-	github.com/prometheus/client_golang v1.12.2
+	github.com/go-kratos/kratos/v2 v2.5.2
+	github.com/prometheus/client_golang v1.13.1
 	github.com/prometheus/common v0.37.0
 )
 
diff --git a/contrib/metrics/prometheus/go.sum b/contrib/metrics/prometheus/go.sum
index 559a32af..d40e7b4f 100644
--- a/contrib/metrics/prometheus/go.sum
+++ b/contrib/metrics/prometheus/go.sum
@@ -129,8 +129,9 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
 github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
 github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
+github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
+github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
 github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
@@ -186,8 +187,8 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn
 github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
 github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
 github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
-github.com/prometheus/client_golang v1.12.2 h1:51L9cDoUHVrXx4zWYlcLQIZ+d+VXHgqnYKkIuq4g/34=
-github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
+github.com/prometheus/client_golang v1.13.1 h1:3gMjIY2+/hzmqhtUC/aQNYldJA6DtH3CgQvwS+02K1c=
+github.com/prometheus/client_golang v1.13.1/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ=
 github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
 github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@@ -203,8 +204,9 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R
 github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
 github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
 github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
-github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
+github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
+github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
 github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 github.com/shirou/gopsutil/v3 v3.21.8/go.mod h1:YWp/H8Qs5fVmf17v7JNZzA0mPJ+mS2e9JdiUF9LlKzQ=
@@ -319,6 +321,7 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -364,8 +367,9 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0=
 golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -422,7 +426,6 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
 google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
@@ -506,8 +509,9 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
 google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
+google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
diff --git a/contrib/opensergo/go.mod b/contrib/opensergo/go.mod
index 0b920de4..90c0a85e 100644
--- a/contrib/opensergo/go.mod
+++ b/contrib/opensergo/go.mod
@@ -3,11 +3,11 @@ module github.com/go-kratos/kratos/contrib/opensergo/v2
 go 1.17
 
 require (
-	github.com/go-kratos/kratos/v2 v2.5.0
+	github.com/go-kratos/kratos/v2 v2.5.2
 	github.com/opensergo/opensergo-go v0.0.0-20220331070310-e5b01fee4d1c
 	golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2
 	google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd
-	google.golang.org/grpc v1.46.2
+	google.golang.org/grpc v1.50.1
 	google.golang.org/protobuf v1.28.1
 )
 
diff --git a/contrib/opensergo/go.sum b/contrib/opensergo/go.sum
index aa486a6f..f32f4915 100644
--- a/contrib/opensergo/go.sum
+++ b/contrib/opensergo/go.sum
@@ -153,8 +153,9 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp
 google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
 google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
 google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
-google.golang.org/grpc v1.46.2 h1:u+MLGgVf7vRdjEYZ8wDFhAVNmhkbJ5hmrA1LMWK1CAQ=
 google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
+google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY=
+google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
diff --git a/contrib/opensergo/opensergo.go b/contrib/opensergo/opensergo.go
index 112c0bab..e8f38c7b 100644
--- a/contrib/opensergo/opensergo.go
+++ b/contrib/opensergo/opensergo.go
@@ -3,6 +3,7 @@ package opensergo
 import (
 	"encoding/json"
 	"net"
+	"net/http"
 	"net/url"
 	"os"
 	"strconv"
@@ -186,15 +187,15 @@ func listDescriptors() (services []*v1.ServiceDescriptor, types []*v1.TypeDescri
 func HTTPPatternInfo(pattern interface{}) (method string, path string) {
 	switch p := pattern.(type) {
 	case *annotations.HttpRule_Get:
-		return "GET", p.Get
+		return http.MethodGet, p.Get
 	case *annotations.HttpRule_Post:
-		return "POST", p.Post
+		return http.MethodPost, p.Post
 	case *annotations.HttpRule_Delete:
-		return "DELETE", p.Delete
+		return http.MethodDelete, p.Delete
 	case *annotations.HttpRule_Patch:
-		return "PATCH", p.Patch
+		return http.MethodPatch, p.Patch
 	case *annotations.HttpRule_Put:
-		return "PUT", p.Put
+		return http.MethodPut, p.Put
 	case *annotations.HttpRule_Custom:
 		return p.Custom.Kind, p.Custom.Path
 	default:
diff --git a/contrib/registry/consul/go.mod b/contrib/registry/consul/go.mod
index 5a0965b4..c94149ce 100644
--- a/contrib/registry/consul/go.mod
+++ b/contrib/registry/consul/go.mod
@@ -3,8 +3,8 @@ module github.com/go-kratos/kratos/contrib/registry/consul/v2
 go 1.16
 
 require (
-	github.com/go-kratos/kratos/v2 v2.5.0
-	github.com/hashicorp/consul/api v1.14.0
+	github.com/go-kratos/kratos/v2 v2.5.2
+	github.com/hashicorp/consul/api v1.15.3
 )
 
 replace github.com/go-kratos/kratos/v2 => ../../../
diff --git a/contrib/registry/consul/go.sum b/contrib/registry/consul/go.sum
index 41a5b15b..b1d94b2a 100644
--- a/contrib/registry/consul/go.sum
+++ b/contrib/registry/consul/go.sum
@@ -91,10 +91,10 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
 github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
 github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
-github.com/hashicorp/consul/api v1.14.0 h1:Y64GIJ8hYTu+tuGekwO4G4ardXoiCivX9wv1iP/kihk=
-github.com/hashicorp/consul/api v1.14.0/go.mod h1:bcaw5CSZ7NE9qfOfKCI1xb7ZKjzu/MyvQkCLTfqLqxQ=
-github.com/hashicorp/consul/sdk v0.10.0 h1:rGLEh2AWK4K0KCMvqWAz2EYxQqgciIfMagWZ0nVe5MI=
-github.com/hashicorp/consul/sdk v0.10.0/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw=
+github.com/hashicorp/consul/api v1.15.3 h1:WYONYL2rxTXtlekAqblR2SCdJsizMDIj/uXb5wNy9zU=
+github.com/hashicorp/consul/api v1.15.3/go.mod h1:/g/qgcoBcEXALCNZgRRisyTW0nY86++L0KbeAMXYCeY=
+github.com/hashicorp/consul/sdk v0.11.0 h1:HRzj8YSCln2yGgCumN5CL8lYlD3gBurnervJRJAZyC4=
+github.com/hashicorp/consul/sdk v0.11.0/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw=
 github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
 github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
 github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
diff --git a/contrib/registry/consul/registry.go b/contrib/registry/consul/registry.go
index d1c47d77..b2f2a3fe 100644
--- a/contrib/registry/consul/registry.go
+++ b/contrib/registry/consul/registry.go
@@ -7,14 +7,14 @@ import (
 	"sync/atomic"
 	"time"
 
-	"github.com/go-kratos/kratos/v2/registry"
-
 	"github.com/hashicorp/consul/api"
+
+	"github.com/go-kratos/kratos/v2/registry"
 )
 
 var (
-	_ registry.Registrar = &Registry{}
-	_ registry.Discovery = &Registry{}
+	_ registry.Registrar = (*Registry)(nil)
+	_ registry.Discovery = (*Registry)(nil)
 )
 
 // Option is consul registry option.
diff --git a/contrib/registry/discovery/go.mod b/contrib/registry/discovery/go.mod
index 407af47a..55728f7c 100644
--- a/contrib/registry/discovery/go.mod
+++ b/contrib/registry/discovery/go.mod
@@ -3,7 +3,7 @@ module github.com/go-kratos/kratos/contrib/registry/discovery/v2
 go 1.16
 
 require (
-	github.com/go-kratos/kratos/v2 v2.5.0
+	github.com/go-kratos/kratos/v2 v2.5.2
 	github.com/go-resty/resty/v2 v2.7.0
 	github.com/pkg/errors v0.9.1
 )
diff --git a/contrib/registry/etcd/go.mod b/contrib/registry/etcd/go.mod
index 952e8a55..d3d16cb2 100644
--- a/contrib/registry/etcd/go.mod
+++ b/contrib/registry/etcd/go.mod
@@ -3,9 +3,9 @@ module github.com/go-kratos/kratos/contrib/registry/etcd/v2
 go 1.16
 
 require (
-	github.com/go-kratos/kratos/v2 v2.5.0
-	go.etcd.io/etcd/client/v3 v3.5.4
-	google.golang.org/grpc v1.46.2
+	github.com/go-kratos/kratos/v2 v2.5.2
+	go.etcd.io/etcd/client/v3 v3.5.5
+	google.golang.org/grpc v1.50.1
 )
 
 replace github.com/go-kratos/kratos/v2 => ../../../
diff --git a/contrib/registry/etcd/go.sum b/contrib/registry/etcd/go.sum
index e847ccab..3e7a0640 100644
--- a/contrib/registry/etcd/go.sum
+++ b/contrib/registry/etcd/go.sum
@@ -17,6 +17,7 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
 github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
 github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
 github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
+github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
 github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
 github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
 github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
@@ -33,6 +34,7 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m
 github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
 github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
 github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
+github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
 github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
@@ -151,12 +153,12 @@ github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcy
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
-go.etcd.io/etcd/api/v3 v3.5.4 h1:OHVyt3TopwtUQ2GKdd5wu3PmmipR4FTwCqoEjSyRdIc=
-go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A=
-go.etcd.io/etcd/client/pkg/v3 v3.5.4 h1:lrneYvz923dvC14R54XcA7FXoZ3mlGZAgmwhfm7HqOg=
-go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
-go.etcd.io/etcd/client/v3 v3.5.4 h1:p83BUL3tAYS0OT/r0qglgc3M1JjhM0diV8DSWAhVXv4=
-go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY=
+go.etcd.io/etcd/api/v3 v3.5.5 h1:BX4JIbQ7hl7+jL+g+2j5UAr0o1bctCm6/Ct+ArBGkf0=
+go.etcd.io/etcd/api/v3 v3.5.5/go.mod h1:KFtNaxGDw4Yx/BA4iPPwevUTAuqcsPxzyX8PHydchN8=
+go.etcd.io/etcd/client/pkg/v3 v3.5.5 h1:9S0JUVvmrVl7wCF39iTQthdaaNIiAaQbmK75ogO6GU8=
+go.etcd.io/etcd/client/pkg/v3 v3.5.5/go.mod h1:ggrwbk069qxpKPq8/FKkQ3Xq9y39kbFR4LnKszpRXeQ=
+go.etcd.io/etcd/client/v3 v3.5.5 h1:q++2WTJbUgpQu4B6hCuT7VkdwaTP7Qz6Daak3WzbrlI=
+go.etcd.io/etcd/client/v3 v3.5.5/go.mod h1:aApjR4WGlSumpnJ2kloS75h6aHUmAyaPLjHMxpc7E7c=
 go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk=
 go.opentelemetry.io/otel/sdk v1.7.0/go.mod h1:uTEOTwaqIVuTGiJN7ii13Ibp75wJmYUDe374q6cZwUU=
 go.opentelemetry.io/otel/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48yyE4TNvoHqU=
@@ -267,9 +269,11 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
 google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
 google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
 google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
+google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
 google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
-google.golang.org/grpc v1.46.2 h1:u+MLGgVf7vRdjEYZ8wDFhAVNmhkbJ5hmrA1LMWK1CAQ=
 google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
+google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY=
+google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
diff --git a/contrib/registry/etcd/registry.go b/contrib/registry/etcd/registry.go
index 5592f62d..ca858c99 100644
--- a/contrib/registry/etcd/registry.go
+++ b/contrib/registry/etcd/registry.go
@@ -12,8 +12,8 @@ import (
 )
 
 var (
-	_ registry.Registrar = &Registry{}
-	_ registry.Discovery = &Registry{}
+	_ registry.Registrar = (*Registry)(nil)
+	_ registry.Discovery = (*Registry)(nil)
 )
 
 // Option is etcd registry option.
diff --git a/contrib/registry/eureka/client.go b/contrib/registry/eureka/client.go
index f2b4e96f..ab9eb30d 100644
--- a/contrib/registry/eureka/client.go
+++ b/contrib/registry/eureka/client.go
@@ -14,14 +14,14 @@ import (
 )
 
 const (
-	statusUp            = "UP"
-	statusDown          = "DOWN"
-	statusOutOfServeice = "OUT_OF_SERVICE"
-	heartbeatRetry      = 3
-	maxIdleConns        = 100
-	heartbeatTime       = 10
-	httpTimeout         = 3
-	refreshTime         = 30
+	statusUp           = "UP"
+	statusDown         = "DOWN"
+	statusOutOfService = "OUT_OF_SERVICE"
+	heartbeatRetry     = 3
+	maxIdleConns       = 100
+	heartbeatTime      = 10
+	httpTimeout        = 3
+	refreshTime        = 30
 )
 
 type Endpoint struct {
@@ -153,7 +153,7 @@ func NewClient(urls []string, opts ...ClientOption) *Client {
 
 func (e *Client) FetchApps(ctx context.Context) []Application {
 	var m ApplicationsRootResponse
-	if err := e.do(ctx, "GET", []string{"apps"}, nil, &m); err != nil {
+	if err := e.do(ctx, http.MethodGet, []string{"apps"}, nil, &m); err != nil {
 		return nil
 	}
 
@@ -161,7 +161,7 @@ func (e *Client) FetchApps(ctx context.Context) []Application {
 }
 
 func (e *Client) FetchAppInstances(ctx context.Context, appID string) (m Application, err error) {
-	err = e.do(ctx, "GET", []string{"apps", appID}, nil, &m)
+	err = e.do(ctx, http.MethodGet, []string{"apps", appID}, nil, &m)
 	return
 }
 
@@ -174,21 +174,21 @@ func (e *Client) FetchAppUpInstances(ctx context.Context, appID string) []Instan
 }
 
 func (e *Client) FetchAppInstance(ctx context.Context, appID string, instanceID string) (m Instance, err error) {
-	err = e.do(ctx, "GET", []string{"apps", appID, instanceID}, nil, &m)
+	err = e.do(ctx, http.MethodGet, []string{"apps", appID, instanceID}, nil, &m)
 	return
 }
 
 func (e *Client) FetchInstance(ctx context.Context, instanceID string) (m Instance, err error) {
-	err = e.do(ctx, "GET", []string{"instances", instanceID}, nil, &m)
+	err = e.do(ctx, http.MethodGet, []string{"instances", instanceID}, nil, &m)
 	return
 }
 
 func (e *Client) Out(ctx context.Context, appID, instanceID string) error {
-	return e.do(ctx, "PUT", []string{"apps", appID, instanceID, fmt.Sprintf("status?value=%s", statusOutOfServeice)}, nil, nil)
+	return e.do(ctx, http.MethodPut, []string{"apps", appID, instanceID, fmt.Sprintf("status?value=%s", statusOutOfService)}, nil, nil)
 }
 
 func (e *Client) Down(ctx context.Context, appID, instanceID string) error {
-	return e.do(ctx, "PUT", []string{"apps", appID, instanceID, fmt.Sprintf("status?value=%s", statusDown)}, nil, nil)
+	return e.do(ctx, http.MethodPut, []string{"apps", appID, instanceID, fmt.Sprintf("status?value=%s", statusDown)}, nil, nil)
 }
 
 func (e *Client) FetchAllUpInstances(ctx context.Context) []Instance {
@@ -200,7 +200,7 @@ func (e *Client) Register(ctx context.Context, ep Endpoint) error {
 }
 
 func (e *Client) Deregister(ctx context.Context, appID, instanceID string) error {
-	if err := e.do(ctx, "DELETE", []string{"apps", appID, instanceID}, nil, nil); err != nil {
+	if err := e.do(ctx, http.MethodDelete, []string{"apps", appID, instanceID}, nil, nil); err != nil {
 		return err
 	}
 	go e.cancelHeartbeat(appID)
@@ -239,7 +239,7 @@ func (e *Client) registerEndpoint(ctx context.Context, ep Endpoint) error {
 	if err != nil {
 		return err
 	}
-	return e.do(ctx, "POST", []string{"apps", ep.AppID}, bytes.NewReader(body), nil)
+	return e.do(ctx, http.MethodPost, []string{"apps", ep.AppID}, bytes.NewReader(body), nil)
 }
 
 func (e *Client) Heartbeat(ep Endpoint) {
@@ -257,7 +257,7 @@ func (e *Client) Heartbeat(ep Endpoint) {
 		case <-e.keepalive[ep.AppID]:
 			return
 		case <-ticker.C:
-			if err := e.do(e.ctx, "PUT", []string{"apps", ep.AppID, ep.InstanceID}, nil, nil); err != nil {
+			if err := e.do(e.ctx, http.MethodPut, []string{"apps", ep.AppID, ep.InstanceID}, nil, nil); err != nil {
 				if retryCount++; retryCount > heartbeatRetry {
 					_ = e.registerEndpoint(e.ctx, ep)
 					retryCount = 0
@@ -268,8 +268,8 @@ func (e *Client) Heartbeat(ep Endpoint) {
 }
 
 func (e *Client) cancelHeartbeat(appID string) {
-	defer e.lock.Unlock()
 	e.lock.Lock()
+	defer e.lock.Unlock()
 	if ch, ok := e.keepalive[appID]; ok {
 		ch <- struct{}{}
 	}
@@ -307,39 +307,50 @@ func (e *Client) buildAPI(currentTimes int, params ...string) string {
 	return strings.Join(params, "/")
 }
 
-func (e *Client) do(ctx context.Context, method string, params []string, input io.Reader, output interface{}) error {
-	for i := 0; i < e.maxRetry; i++ {
-		request, err := http.NewRequest(method, e.buildAPI(i, params...), input)
+func (e *Client) request(ctx context.Context, method string, params []string, input io.Reader, output interface{}, i int) (bool, error) {
+	request, err := http.NewRequestWithContext(ctx, method, e.buildAPI(i, params...), input)
+	if err != nil {
+		return false, err
+	}
+	request.Header.Add("User-Agent", "go-eureka-client")
+	request.Header.Add("Accept", "application/json;charset=UTF-8")
+	request.Header.Add("Content-Type", "application/json;charset=UTF-8")
+	resp, err := e.client.Do(request)
+	if err != nil {
+		return true, err
+	}
+	defer func() {
+		_, _ = io.Copy(io.Discard, resp.Body)
+		_ = resp.Body.Close()
+	}()
+
+	if output != nil && resp.StatusCode/100 == 2 {
+		data, err := io.ReadAll(resp.Body)
 		if err != nil {
-			return err
+			return false, err
 		}
-		request = request.WithContext(ctx)
-		request.Header.Add("User-Agent", "go-eureka-client")
-		request.Header.Add("Accept", "application/json;charset=UTF-8")
-		request.Header.Add("Content-Type", "application/json;charset=UTF-8")
-		resp, err := e.client.Do(request)
+		err = json.Unmarshal(data, output)
 		if err != nil {
-			continue
-		}
-		defer func() {
-			_, _ = io.Copy(io.Discard, resp.Body)
-			resp.Body.Close()
-		}()
-
-		if output != nil && resp.StatusCode/100 == 2 {
-			data, err := io.ReadAll(resp.Body)
-			if err != nil {
-				return err
-			}
-			if err = json.Unmarshal(data, output); err != nil {
-				return err
-			}
+			return false, err
 		}
+	}
 
-		if resp.StatusCode >= http.StatusBadRequest {
-			return fmt.Errorf("response Error %d", resp.StatusCode)
-		}
+	if resp.StatusCode >= http.StatusBadRequest {
+		return false, fmt.Errorf("response Error %d", resp.StatusCode)
+	}
 
+	return false, nil
+}
+
+func (e *Client) do(ctx context.Context, method string, params []string, input io.Reader, output interface{}) error {
+	for i := 0; i < e.maxRetry; i++ {
+		retry, err := e.request(ctx, method, params, input, output, i)
+		if retry {
+			continue
+		}
+		if err != nil {
+			return err
+		}
 		return nil
 	}
 	return fmt.Errorf("retry after %d times", e.maxRetry)
diff --git a/contrib/registry/eureka/register.go b/contrib/registry/eureka/register.go
index 9588df64..242ec910 100644
--- a/contrib/registry/eureka/register.go
+++ b/contrib/registry/eureka/register.go
@@ -11,8 +11,8 @@ import (
 )
 
 var (
-	_ registry.Registrar = &Registry{}
-	_ registry.Discovery = &Registry{}
+	_ registry.Registrar = (*Registry)(nil)
+	_ registry.Discovery = (*Registry)(nil)
 )
 
 type Option func(o *Registry)
diff --git a/contrib/registry/kubernetes/go.mod b/contrib/registry/kubernetes/go.mod
index cad07df0..21517f5f 100644
--- a/contrib/registry/kubernetes/go.mod
+++ b/contrib/registry/kubernetes/go.mod
@@ -3,7 +3,7 @@ module github.com/go-kratos/kratos/contrib/registry/kubernetes/v2
 go 1.16
 
 require (
-	github.com/go-kratos/kratos/v2 v2.5.0
+	github.com/go-kratos/kratos/v2 v2.5.2
 	github.com/json-iterator/go v1.1.12
 	k8s.io/api v0.24.3
 	k8s.io/apimachinery v0.24.3
diff --git a/contrib/registry/nacos/go.mod b/contrib/registry/nacos/go.mod
index bdfd037e..75f67334 100644
--- a/contrib/registry/nacos/go.mod
+++ b/contrib/registry/nacos/go.mod
@@ -3,7 +3,7 @@ module github.com/go-kratos/kratos/contrib/registry/nacos/v2
 go 1.16
 
 require (
-	github.com/go-kratos/kratos/v2 v2.5.0
+	github.com/go-kratos/kratos/v2 v2.5.2
 	github.com/nacos-group/nacos-sdk-go v1.0.9
 )
 
diff --git a/contrib/registry/polaris/go.mod b/contrib/registry/polaris/go.mod
index 2789a991..256ed425 100644
--- a/contrib/registry/polaris/go.mod
+++ b/contrib/registry/polaris/go.mod
@@ -3,8 +3,8 @@ module github.com/go-kratos/kratos/contrib/registry/polaris/v2
 go 1.16
 
 require (
-	github.com/go-kratos/kratos/v2 v2.5.0
-	github.com/polarismesh/polaris-go v1.1.0
+	github.com/go-kratos/kratos/v2 v2.5.2
+	github.com/polarismesh/polaris-go v1.2.0
 )
 
 replace github.com/go-kratos/kratos/v2 => ../../../
diff --git a/contrib/registry/polaris/go.sum b/contrib/registry/polaris/go.sum
index 6205e994..77f73a2e 100644
--- a/contrib/registry/polaris/go.sum
+++ b/contrib/registry/polaris/go.sum
@@ -60,22 +60,21 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
 github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
 github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
 github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
-github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
 github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
 github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
 github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo=
+github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
 github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
 github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
 github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
 github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
-github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
 github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
-github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@@ -213,8 +212,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/polarismesh/polaris-go v1.1.0 h1:nFvn3q3XaVFhzF7pBnIySrN0ZZBwvbbYXC5r2DpsQN0=
-github.com/polarismesh/polaris-go v1.1.0/go.mod h1:tquawfjEKp1W3ffNJQSzhfditjjoZ7tvhOCElN7Efzs=
+github.com/polarismesh/polaris-go v1.2.0 h1:GIWvUno4DB0PD3HC7bHmTCeG+a54neMrVvNPiRXJUtc=
+github.com/polarismesh/polaris-go v1.2.0/go.mod h1:HsN0ierETIujHpmnnYJ3qkwQw4QGAECuHvBZTDaw1tI=
 github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
 github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
 github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
@@ -275,12 +274,12 @@ go.opentelemetry.io/otel/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48
 go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
 go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
 go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
-go.uber.org/goleak v1.1.11-0.20210813005559-691160354723 h1:sHOAIxRGBp443oHZIPB+HsUGaksVCXVQENPxwTfQdH4=
-go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
+go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
+go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
 go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
 go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
-go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI=
-go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
+go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8=
+go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -349,8 +348,8 @@ golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81R
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
 golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20210917221730-978cfadd31cf h1:R150MpwJIv1MpS0N/pc+NhTM8ajzvlmxlY5OYsrevXQ=
-golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 h1:HVyaeDAYux4pnY+D/SiwmLOR36ewZ4iGQIIrtnuCjFA=
+golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -409,19 +408,24 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0=
 golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 h1:nonptSpoQ4vQjyraW20DXPAglgQfVnM9ZC6MmNLMR60=
+golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -524,6 +528,7 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc
 google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20220504150022-98cd25cafc72/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
 google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd h1:e0TwkXOdbnH/1x5rc5MZ/VYyiZ4v+RdVfrGMqEwT68I=
 google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
@@ -540,7 +545,6 @@ google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM
 google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
 google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
 google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
-google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
 google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
 google.golang.org/grpc v1.46.2 h1:u+MLGgVf7vRdjEYZ8wDFhAVNmhkbJ5hmrA1LMWK1CAQ=
 google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
diff --git a/contrib/registry/servicecomb/registry.go b/contrib/registry/servicecomb/registry.go
index 7a532396..894cf343 100644
--- a/contrib/registry/servicecomb/registry.go
+++ b/contrib/registry/servicecomb/registry.go
@@ -9,10 +9,10 @@ import (
 	"github.com/go-chassis/cari/discovery"
 	"github.com/go-chassis/cari/pkg/errsvc"
 	"github.com/go-chassis/sc-client"
+	"github.com/gofrs/uuid"
 
 	"github.com/go-kratos/kratos/v2/log"
 	"github.com/go-kratos/kratos/v2/registry"
-	"github.com/gofrs/uuid"
 )
 
 func init() {
diff --git a/contrib/registry/servicecomb/watcher.go b/contrib/registry/servicecomb/watcher.go
index 2b2117e8..b1f4fccf 100644
--- a/contrib/registry/servicecomb/watcher.go
+++ b/contrib/registry/servicecomb/watcher.go
@@ -2,9 +2,9 @@ package servicecomb
 
 import (
 	"github.com/go-chassis/sc-client"
+	"golang.org/x/net/context"
 
 	"github.com/go-kratos/kratos/v2/registry"
-	"golang.org/x/net/context"
 )
 
 var _ registry.Watcher = (*Watcher)(nil)
diff --git a/contrib/registry/zookeeper/go.mod b/contrib/registry/zookeeper/go.mod
index a149d20a..719a78de 100644
--- a/contrib/registry/zookeeper/go.mod
+++ b/contrib/registry/zookeeper/go.mod
@@ -3,7 +3,7 @@ module github.com/go-kratos/kratos/contrib/registry/zookeeper/v2
 go 1.16
 
 require (
-	github.com/go-kratos/kratos/v2 v2.5.0
+	github.com/go-kratos/kratos/v2 v2.5.2
 	github.com/go-zookeeper/zk v1.0.3
 	golang.org/x/sync v0.0.0-20220513210516-0976fa681c29
 )
diff --git a/contrib/registry/zookeeper/register.go b/contrib/registry/zookeeper/register.go
index 771a5bbc..8f21745d 100644
--- a/contrib/registry/zookeeper/register.go
+++ b/contrib/registry/zookeeper/register.go
@@ -12,8 +12,8 @@ import (
 )
 
 var (
-	_ registry.Registrar = &Registry{}
-	_ registry.Discovery = &Registry{}
+	_ registry.Registrar = (*Registry)(nil)
+	_ registry.Discovery = (*Registry)(nil)
 )
 
 // Option is etcd registry option.
diff --git a/encoding/form/form.go b/encoding/form/form.go
index 823aeb8f..ba0447e4 100644
--- a/encoding/form/form.go
+++ b/encoding/form/form.go
@@ -4,10 +4,10 @@ import (
 	"net/url"
 	"reflect"
 
-	"github.com/go-kratos/kratos/v2/encoding"
-
 	"github.com/go-playground/form/v4"
 	"google.golang.org/protobuf/proto"
+
+	"github.com/go-kratos/kratos/v2/encoding"
 )
 
 const (
@@ -70,7 +70,8 @@ func (c codec) Unmarshal(data []byte, v interface{}) error {
 	}
 	if m, ok := v.(proto.Message); ok {
 		return DecodeValues(m, vs)
-	} else if m, ok := reflect.Indirect(reflect.ValueOf(v)).Interface().(proto.Message); ok {
+	}
+	if m, ok := rv.Interface().(proto.Message); ok {
 		return DecodeValues(m, vs)
 	}
 
diff --git a/encoding/form/proto_decode.go b/encoding/form/proto_decode.go
index 47affee1..1620162b 100644
--- a/encoding/form/proto_decode.go
+++ b/encoding/form/proto_decode.go
@@ -10,13 +10,12 @@ import (
 	"time"
 
 	"google.golang.org/protobuf/encoding/protojson"
-	"google.golang.org/protobuf/types/known/structpb"
-
 	"google.golang.org/protobuf/proto"
 	"google.golang.org/protobuf/reflect/protoreflect"
 	"google.golang.org/protobuf/reflect/protoregistry"
 	"google.golang.org/protobuf/types/known/durationpb"
 	"google.golang.org/protobuf/types/known/fieldmaskpb"
+	"google.golang.org/protobuf/types/known/structpb"
 	"google.golang.org/protobuf/types/known/timestamppb"
 	"google.golang.org/protobuf/types/known/wrapperspb"
 )
@@ -99,6 +98,9 @@ func getDescriptorByFieldAndName(fields protoreflect.FieldDescriptors, fieldName
 }
 
 func populateField(fd protoreflect.FieldDescriptor, v protoreflect.Message, value string) error {
+	if value == "" {
+		return nil
+	}
 	val, err := parseField(fd, value)
 	if err != nil {
 		return fmt.Errorf("parsing field %q: %w", fd.FullName().Name(), err)
@@ -119,15 +121,13 @@ func populateRepeatedField(fd protoreflect.FieldDescriptor, list protoreflect.Li
 }
 
 func populateMapField(fd protoreflect.FieldDescriptor, mp protoreflect.Map, fieldPath []string, values []string) error {
-	flen := len(fieldPath)
-	vlen := len(values)
 	// post sub key.
-	nkey := flen - 1
+	nkey := len(fieldPath) - 1
 	key, err := parseField(fd.MapKey(), fieldPath[nkey])
 	if err != nil {
 		return fmt.Errorf("parsing map key %q: %w", fd.FullName().Name(), err)
 	}
-	vkey := vlen - 1
+	vkey := len(values) - 1
 	value, err := parseField(fd.MapValue(), values[vkey])
 	if err != nil {
 		return fmt.Errorf("parsing map value %q: %w", fd.FullName().Name(), err)
diff --git a/encoding/form/proto_encode.go b/encoding/form/proto_encode.go
index 28ebb0bc..94eac6ab 100644
--- a/encoding/form/proto_encode.go
+++ b/encoding/form/proto_encode.go
@@ -162,7 +162,7 @@ func encodeMessage(msgDescriptor protoreflect.MessageDescriptor, value protorefl
 	case "google.protobuf.DoubleValue", "google.protobuf.FloatValue", "google.protobuf.Int64Value", "google.protobuf.Int32Value",
 		"google.protobuf.UInt64Value", "google.protobuf.UInt32Value", "google.protobuf.BoolValue", "google.protobuf.StringValue":
 		fd := msgDescriptor.Fields()
-		v := value.Message().Get(fd.ByName(protoreflect.Name("value")))
+		v := value.Message().Get(fd.ByName("value"))
 		return fmt.Sprint(v.Interface()), nil
 	case fieldMaskFullName:
 		m, ok := value.Message().Interface().(*fieldmaskpb.FieldMask)
diff --git a/log/filter.go b/log/filter.go
index ab572377..993fa926 100644
--- a/log/filter.go
+++ b/log/filter.go
@@ -64,20 +64,18 @@ func (f *Filter) Log(level Level, keyvals ...interface{}) error {
 	if level < f.level {
 		return nil
 	}
-	// fkv is used to provide a slice to contains both logger.prefix and keyvals for filter
-	var fkv []interface{}
+	// prefixkv contains the slice of arguments defined as prefixes during the log initialization
+	var prefixkv []interface{}
 	l, ok := f.logger.(*logger)
 	if ok && len(l.prefix) > 0 {
-		fkv = make([]interface{}, 0, len(l.prefix)+len(keyvals))
-		fkv = append(fkv, l.prefix...)
-		fkv = append(fkv, keyvals...)
+		prefixkv = make([]interface{}, 0, len(l.prefix))
+		prefixkv = append(prefixkv, l.prefix...)
 	}
-	if !ok {
-		fkv = keyvals
-	}
-	if f.filter != nil && f.filter(level, fkv...) {
+
+	if f.filter != nil && (f.filter(level, prefixkv...) || f.filter(level, keyvals...)) {
 		return nil
 	}
+
 	if len(f.key) > 0 || len(f.value) > 0 {
 		for i := 0; i < len(keyvals); i += 2 {
 			v := i + 1
diff --git a/log/level.go b/log/level.go
index 22f41c78..1a966423 100644
--- a/log/level.go
+++ b/log/level.go
@@ -21,6 +21,10 @@ const (
 	LevelFatal
 )
 
+func (l Level) Key() string {
+	return LevelKey
+}
+
 func (l Level) String() string {
 	switch l {
 	case LevelDebug:
diff --git a/middleware/metadata/metadata.go b/middleware/metadata/metadata.go
index 5c29189f..da9e43a9 100644
--- a/middleware/metadata/metadata.go
+++ b/middleware/metadata/metadata.go
@@ -51,16 +51,19 @@ func Server(opts ...Option) middleware.Middleware {
 	}
 	return func(handler middleware.Handler) middleware.Handler {
 		return func(ctx context.Context, req interface{}) (reply interface{}, err error) {
-			if tr, ok := transport.FromServerContext(ctx); ok {
-				md := options.md.Clone()
-				header := tr.RequestHeader()
-				for _, k := range header.Keys() {
-					if options.hasPrefix(k) {
-						md.Set(k, header.Get(k))
-					}
+			tr, ok := transport.FromServerContext(ctx)
+			if !ok {
+				return handler(ctx, req)
+			}
+
+			md := options.md.Clone()
+			header := tr.RequestHeader()
+			for _, k := range header.Keys() {
+				if options.hasPrefix(k) {
+					md.Set(k, header.Get(k))
 				}
-				ctx = metadata.NewServerContext(ctx, md)
 			}
+			ctx = metadata.NewServerContext(ctx, md)
 			return handler(ctx, req)
 		}
 	}
@@ -76,25 +79,28 @@ func Client(opts ...Option) middleware.Middleware {
 	}
 	return func(handler middleware.Handler) middleware.Handler {
 		return func(ctx context.Context, req interface{}) (reply interface{}, err error) {
-			if tr, ok := transport.FromClientContext(ctx); ok {
-				header := tr.RequestHeader()
-				// x-md-local-
-				for k, v := range options.md {
+			tr, ok := transport.FromClientContext(ctx)
+			if !ok {
+				return handler(ctx, req)
+			}
+
+			header := tr.RequestHeader()
+			// x-md-local-
+			for k, v := range options.md {
+				header.Set(k, v)
+			}
+			if md, ok := metadata.FromClientContext(ctx); ok {
+				for k, v := range md {
 					header.Set(k, v)
 				}
-				if md, ok := metadata.FromClientContext(ctx); ok {
-					for k, v := range md {
+			}
+			// x-md-global-
+			if md, ok := metadata.FromServerContext(ctx); ok {
+				for k, v := range md {
+					if options.hasPrefix(k) {
 						header.Set(k, v)
 					}
 				}
-				// x-md-global-
-				if md, ok := metadata.FromServerContext(ctx); ok {
-					for k, v := range md {
-						if options.hasPrefix(k) {
-							header.Set(k, v)
-						}
-					}
-				}
 			}
 			return handler(ctx, req)
 		}
diff --git a/options.go b/options.go
index 8f9e9a55..5e337a38 100644
--- a/options.go
+++ b/options.go
@@ -30,6 +30,12 @@ type options struct {
 	registrarTimeout time.Duration
 	stopTimeout      time.Duration
 	servers          []transport.Server
+
+	// Before and After funcs
+	beforeStart []func(context.Context) error
+	beforeStop  []func(context.Context) error
+	afterStart  []func(context.Context) error
+	afterStop   []func(context.Context) error
 }
 
 // ID with service id.
@@ -91,3 +97,33 @@ func RegistrarTimeout(t time.Duration) Option {
 func StopTimeout(t time.Duration) Option {
 	return func(o *options) { o.stopTimeout = t }
 }
+
+// Before and Afters
+
+// BeforeStart run funcs before app starts
+func BeforeStart(fn func(context.Context) error) Option {
+	return func(o *options) {
+		o.beforeStart = append(o.beforeStart, fn)
+	}
+}
+
+// BeforeStop run funcs before app stops
+func BeforeStop(fn func(context.Context) error) Option {
+	return func(o *options) {
+		o.beforeStop = append(o.beforeStop, fn)
+	}
+}
+
+// AfterStart run funcs after app starts
+func AfterStart(fn func(context.Context) error) Option {
+	return func(o *options) {
+		o.afterStart = append(o.afterStart, fn)
+	}
+}
+
+// AfterStop run funcs after app stops
+func AfterStop(fn func(context.Context) error) Option {
+	return func(o *options) {
+		o.afterStop = append(o.afterStop, fn)
+	}
+}
diff --git a/selector/global.go b/selector/global.go
index 2f951212..4d6b6202 100644
--- a/selector/global.go
+++ b/selector/global.go
@@ -1,13 +1,21 @@
 package selector
 
-var globalSelector Builder
+var globalSelector = &wrapSelector{}
+
+var _ Builder = (*wrapSelector)(nil)
+
+// wrapSelector wrapped Selector, help override global Selector implementation.
+type wrapSelector struct{ Builder }
 
 // GlobalSelector returns global selector builder.
 func GlobalSelector() Builder {
-	return globalSelector
+	if globalSelector.Builder != nil {
+		return globalSelector
+	}
+	return nil
 }
 
 // SetGlobalSelector set global selector builder.
 func SetGlobalSelector(builder Builder) {
-	globalSelector = builder
+	globalSelector.Builder = builder
 }
diff --git a/selector/node/ewma/node.go b/selector/node/ewma/node.go
index 4fed4aaa..3b8d2a02 100644
--- a/selector/node/ewma/node.go
+++ b/selector/node/ewma/node.go
@@ -4,6 +4,7 @@ import (
 	"container/list"
 	"context"
 	"math"
+	"net"
 	"sync"
 	"sync/atomic"
 	"time"
@@ -158,8 +159,9 @@ func (n *Node) Pick() selector.DoneFunc {
 			if n.errHandler != nil && n.errHandler(di.Err) {
 				success = 0
 			}
+			var netErr net.Error
 			if errors.Is(context.DeadlineExceeded, di.Err) || errors.Is(context.Canceled, di.Err) ||
-				errors.IsServiceUnavailable(di.Err) || errors.IsGatewayTimeout(di.Err) {
+				errors.IsServiceUnavailable(di.Err) || errors.IsGatewayTimeout(di.Err) || errors.As(di.Err, &netErr) {
 				success = 0
 			}
 		}
diff --git a/transport/grpc/balancer.go b/transport/grpc/balancer.go
index 948b736b..f42dc23b 100644
--- a/transport/grpc/balancer.go
+++ b/transport/grpc/balancer.go
@@ -1,13 +1,13 @@
 package grpc
 
 import (
-	"github.com/go-kratos/kratos/v2/registry"
-	"github.com/go-kratos/kratos/v2/selector"
-	"github.com/go-kratos/kratos/v2/transport"
-
 	"google.golang.org/grpc/balancer"
 	"google.golang.org/grpc/balancer/base"
 	"google.golang.org/grpc/metadata"
+
+	"github.com/go-kratos/kratos/v2/registry"
+	"github.com/go-kratos/kratos/v2/selector"
+	"github.com/go-kratos/kratos/v2/transport"
 )
 
 const (
@@ -15,8 +15,8 @@ const (
 )
 
 var (
-	_ base.PickerBuilder = &balancerBuilder{}
-	_ balancer.Picker    = &balancerPicker{}
+	_ base.PickerBuilder = (*balancerBuilder)(nil)
+	_ balancer.Picker    = (*balancerPicker)(nil)
 )
 
 func init() {
diff --git a/transport/http/binding/encode.go b/transport/http/binding/encode.go
index 9bcdbeef..72afd508 100644
--- a/transport/http/binding/encode.go
+++ b/transport/http/binding/encode.go
@@ -4,8 +4,9 @@ import (
 	"reflect"
 	"regexp"
 
-	"github.com/go-kratos/kratos/v2/encoding/form"
 	"google.golang.org/protobuf/proto"
+
+	"github.com/go-kratos/kratos/v2/encoding/form"
 )
 
 var reg = regexp.MustCompile(`{[\\.\w]+}`)
diff --git a/transport/http/codec.go b/transport/http/codec.go
index 20b1a8ec..da1b13e0 100644
--- a/transport/http/codec.go
+++ b/transport/http/codec.go
@@ -4,10 +4,14 @@ import (
 	"fmt"
 	"io"
 	"net/http"
+	"net/url"
 
 	"github.com/go-kratos/kratos/v2/encoding"
 	"github.com/go-kratos/kratos/v2/errors"
 	"github.com/go-kratos/kratos/v2/internal/httputil"
+	"github.com/go-kratos/kratos/v2/transport/http/binding"
+
+	"github.com/gorilla/mux"
 )
 
 // SupportPackageIsVersion1 These constants should not be referenced from any other code.
@@ -37,6 +41,21 @@ type EncodeResponseFunc func(http.ResponseWriter, *http.Request, interface{}) er
 // EncodeErrorFunc is encode error func.
 type EncodeErrorFunc func(http.ResponseWriter, *http.Request, error)
 
+// DefaultRequestVars decodes the request vars to object.
+func DefaultRequestVars(r *http.Request, v interface{}) error {
+	raws := mux.Vars(r)
+	vars := make(url.Values, len(raws))
+	for k, v := range raws {
+		vars[k] = []string{v}
+	}
+	return binding.BindQuery(vars, v)
+}
+
+// DefaultRequestQuery decodes the request vars to object.
+func DefaultRequestQuery(r *http.Request, v interface{}) error {
+	return binding.BindQuery(r.URL.Query(), v)
+}
+
 // DefaultRequestDecoder decodes the request body to object.
 func DefaultRequestDecoder(r *http.Request, v interface{}) error {
 	codec, ok := CodecForRequest(r, "Content-Type")
diff --git a/transport/http/context.go b/transport/http/context.go
index 347d7f2b..ab9a1d39 100644
--- a/transport/http/context.go
+++ b/transport/http/context.go
@@ -96,9 +96,9 @@ func (c *wrapper) Middleware(h middleware.Handler) middleware.Handler {
 	}
 	return middleware.Chain(c.router.srv.middleware.Match(c.req.URL.Path)...)(h)
 }
-func (c *wrapper) Bind(v interface{}) error      { return c.router.srv.dec(c.req, v) }
-func (c *wrapper) BindVars(v interface{}) error  { return binding.BindQuery(c.Vars(), v) }
-func (c *wrapper) BindQuery(v interface{}) error { return binding.BindQuery(c.Query(), v) }
+func (c *wrapper) Bind(v interface{}) error      { return c.router.srv.decBody(c.req, v) }
+func (c *wrapper) BindVars(v interface{}) error  { return c.router.srv.decVars(c.req, v) }
+func (c *wrapper) BindQuery(v interface{}) error { return c.router.srv.decQuery(c.req, v) }
 func (c *wrapper) BindForm(v interface{}) error  { return binding.BindForm(c.req, v) }
 func (c *wrapper) Returns(v interface{}, err error) error {
 	if err != nil {
diff --git a/transport/http/server.go b/transport/http/server.go
index db7d0a72..165bb99b 100644
--- a/transport/http/server.go
+++ b/transport/http/server.go
@@ -70,10 +70,24 @@ func Filter(filters ...FilterFunc) ServerOption {
 	}
 }
 
+// RequestVarsDecoder with request decoder.
+func RequestVarsDecoder(dec DecodeRequestFunc) ServerOption {
+	return func(o *Server) {
+		o.decVars = dec
+	}
+}
+
+// RequestQueryDecoder with request decoder.
+func RequestQueryDecoder(dec DecodeRequestFunc) ServerOption {
+	return func(o *Server) {
+		o.decQuery = dec
+	}
+}
+
 // RequestDecoder with request decoder.
 func RequestDecoder(dec DecodeRequestFunc) ServerOption {
 	return func(o *Server) {
-		o.dec = dec
+		o.decBody = dec
 	}
 }
 
@@ -114,6 +128,13 @@ func Listener(lis net.Listener) ServerOption {
 	}
 }
 
+// PathPrefix with mux's PathPrefix, router will replaced by a subrouter that start with prefix.
+func PathPrefix(prefix string) ServerOption {
+	return func(s *Server) {
+		s.router = s.router.PathPrefix(prefix).Subrouter()
+	}
+}
+
 // Server is an HTTP server wrapper.
 type Server struct {
 	*http.Server
@@ -126,7 +147,9 @@ type Server struct {
 	timeout     time.Duration
 	filters     []FilterFunc
 	middleware  matcher.Matcher
-	dec         DecodeRequestFunc
+	decVars     DecodeRequestFunc
+	decQuery    DecodeRequestFunc
+	decBody     DecodeRequestFunc
 	enc         EncodeResponseFunc
 	ene         EncodeErrorFunc
 	strictSlash bool
@@ -140,15 +163,18 @@ func NewServer(opts ...ServerOption) *Server {
 		address:     ":0",
 		timeout:     1 * time.Second,
 		middleware:  matcher.New(),
-		dec:         DefaultRequestDecoder,
+		decVars:     DefaultRequestVars,
+		decQuery:    DefaultRequestQuery,
+		decBody:     DefaultRequestDecoder,
 		enc:         DefaultResponseEncoder,
 		ene:         DefaultErrorEncoder,
 		strictSlash: true,
+		router:      mux.NewRouter(),
 	}
 	for _, o := range opts {
 		o(srv)
 	}
-	srv.router = mux.NewRouter().StrictSlash(srv.strictSlash)
+	srv.router.StrictSlash(srv.strictSlash)
 	srv.router.NotFoundHandler = http.DefaultServeMux
 	srv.router.MethodNotAllowedHandler = http.DefaultServeMux
 	srv.router.Use(srv.filter())
diff --git a/transport/http/transport.go b/transport/http/transport.go
index e7f53f6d..32f054ed 100644
--- a/transport/http/transport.go
+++ b/transport/http/transport.go
@@ -70,6 +70,16 @@ func SetOperation(ctx context.Context, op string) {
 	}
 }
 
+// RequestFromServerContext returns request from context.
+func RequestFromServerContext(ctx context.Context) (*http.Request, bool) {
+	if tr, ok := transport.FromServerContext(ctx); ok {
+		if tr, ok := tr.(*Transport); ok {
+			return tr.request, true
+		}
+	}
+	return nil, false
+}
+
 type headerCarrier http.Header
 
 // Get returns the value associated with the passed key.
diff --git a/version.go b/version.go
index d0afa603..e130ae2c 100644
--- a/version.go
+++ b/version.go
@@ -1,4 +1,4 @@
 package kratos
 
 // Release is the current kratos version.
-const Release = "v2.5.0"
+const Release = "v2.5.2"


Test patch:
diff --git a/app_test.go b/app_test.go
index 2b8c8c9d..92a2ca29 100644
--- a/app_test.go
+++ b/app_test.go
@@ -47,6 +47,22 @@ func TestApp(t *testing.T) {
 		Name("kratos"),
 		Version("v1.0.0"),
 		Server(hs, gs),
+		BeforeStart(func(_ context.Context) error {
+			t.Log("BeforeStart...")
+			return nil
+		}),
+		BeforeStop(func(_ context.Context) error {
+			t.Log("BeforeStop...")
+			return nil
+		}),
+		AfterStart(func(_ context.Context) error {
+			t.Log("AfterStart...")
+			return nil
+		}),
+		AfterStop(func(_ context.Context) error {
+			t.Log("AfterStop...")
+			return nil
+		}),
 		Registrar(&mockRegistry{service: make(map[string]*registry.ServiceInstance)}),
 	)
 	time.AfterFunc(time.Second, func() {
diff --git a/config/config_test.go b/config/config_test.go
index 5699dec1..9a166b00 100644
--- a/config/config_test.go
+++ b/config/config_test.go
@@ -2,7 +2,6 @@ package config
 
 import (
 	"errors"
-	"reflect"
 	"testing"
 )
 
@@ -124,7 +123,7 @@ func TestConfig(t *testing.T) {
 	)
 	err = c.Close()
 	if err != nil {
-		t.Fatal("t is not nil")
+		t.Fatal(err)
 	}
 
 	jSource := newTestJSONSource(_testJSON)
@@ -139,21 +138,21 @@ func TestConfig(t *testing.T) {
 
 	err = cf.Load()
 	if err != nil {
-		t.Fatal("t is not nil")
+		t.Fatal(err)
 	}
 
-	val, err := cf.Value("data.database.driver").String()
+	driver, err := cf.Value("data.database.driver").String()
 	if err != nil {
-		t.Fatal("t is not nil")
+		t.Fatal(err)
 	}
-	if !reflect.DeepEqual(databaseDriver, val) {
-		t.Fatal(`databaseDriver is not equal to val`)
+	if databaseDriver != driver {
+		t.Fatal("databaseDriver is not equal to val")
 	}
 
 	err = cf.Watch("endpoints", func(key string, value Value) {
 	})
 	if err != nil {
-		t.Fatal("t is not nil")
+		t.Fatal(err)
 	}
 
 	jSource.sig <- struct{}{}
@@ -162,24 +161,24 @@ func TestConfig(t *testing.T) {
 	var testConf testConfigStruct
 	err = cf.Scan(&testConf)
 	if err != nil {
-		t.Fatal("t is not nil")
+		t.Fatal(err)
 	}
-	if !reflect.DeepEqual(httpAddr, testConf.Server.HTTP.Addr) {
-		t.Fatal(`httpAddr is not equal to testConf.Server.HTTP.Addr`)
+	if httpAddr != testConf.Server.HTTP.Addr {
+		t.Errorf("testConf.Server.HTTP.Addr want: %s, got: %s", httpAddr, testConf.Server.HTTP.Addr)
 	}
-	if !reflect.DeepEqual(httpTimeout, testConf.Server.HTTP.Timeout) {
-		t.Fatal(`httpTimeout is not equal to testConf.Server.HTTP.Timeout`)
+	if httpTimeout != testConf.Server.HTTP.Timeout {
+		t.Errorf("testConf.Server.HTTP.Timeout want: %.1f, got: %.1f", httpTimeout, testConf.Server.HTTP.Timeout)
 	}
-	if !reflect.DeepEqual(true, testConf.Server.HTTP.EnableSSL) {
-		t.Fatal(`testConf.Server.HTTP.EnableSSL is not equal to true`)
+	if !testConf.Server.HTTP.EnableSSL {
+		t.Error("testConf.Server.HTTP.EnableSSL is not equal to true")
 	}
-	if !reflect.DeepEqual(grpcPort, testConf.Server.GRPC.Port) {
-		t.Fatal(`grpcPort is not equal to testConf.Server.GRPC.Port`)
+	if grpcPort != testConf.Server.GRPC.Port {
+		t.Errorf("testConf.Server.GRPC.Port want: %d, got: %d", grpcPort, testConf.Server.GRPC.Port)
 	}
-	if !reflect.DeepEqual(endpoint1, testConf.Endpoints[0]) {
-		t.Fatal(`endpoint1 is not equal to testConf.Endpoints[0]`)
+	if endpoint1 != testConf.Endpoints[0] {
+		t.Errorf("testConf.Endpoints[0] want: %s, got: %s", endpoint1, testConf.Endpoints[0])
 	}
-	if !reflect.DeepEqual(len(testConf.Endpoints), 2) {
-		t.Fatal(`len(testConf.Endpoints) is not equal to 2`)
+	if len(testConf.Endpoints) != 2 {
+		t.Error("len(testConf.Endpoints) is not equal to 2")
 	}
 }
diff --git a/config/file/file_test.go b/config/file/file_test.go
index d3c55ad3..ac6ad843 100644
--- a/config/file/file_test.go
+++ b/config/file/file_test.go
@@ -121,10 +121,10 @@ func testWatchFile(t *testing.T, path string) {
 	}
 	kvs, err := watch.Next()
 	if err != nil {
-		t.Errorf(`watch.Next() error(%v)`, err)
+		t.Errorf("watch.Next() error(%v)", err)
 	}
 	if !reflect.DeepEqual(string(kvs[0].Value), _testJSONUpdate) {
-		t.Errorf(`string(kvs[0].Value(%v) is  not equal to _testJSONUpdate(%v)`, kvs[0].Value, _testJSONUpdate)
+		t.Errorf("string(kvs[0].Value(%v) is  not equal to _testJSONUpdate(%v)", kvs[0].Value, _testJSONUpdate)
 	}
 
 	newFilepath := filepath.Join(filepath.Dir(path), "test1.json")
@@ -133,15 +133,15 @@ func testWatchFile(t *testing.T, path string) {
 	}
 	kvs, err = watch.Next()
 	if err == nil {
-		t.Errorf(`watch.Next() error(%v)`, err)
+		t.Errorf("watch.Next() error(%v)", err)
 	}
 	if kvs != nil {
-		t.Errorf(`watch.Next() error(%v)`, err)
+		t.Errorf("watch.Next() error(%v)", err)
 	}
 
 	err = watch.Stop()
 	if err != nil {
-		t.Errorf(`watch.Stop() error(%v)`, err)
+		t.Errorf("watch.Stop() error(%v)", err)
 	}
 
 	if err := os.Rename(newFilepath, path); err != nil {
@@ -171,10 +171,10 @@ func testWatchDir(t *testing.T, path, file string) {
 
 	kvs, err := watch.Next()
 	if err != nil {
-		t.Errorf(`watch.Next() error(%v)`, err)
+		t.Errorf("watch.Next() error(%v)", err)
 	}
 	if !reflect.DeepEqual(string(kvs[0].Value), _testJSONUpdate) {
-		t.Errorf(`string(kvs[0].Value(%v) is  not equal to _testJSONUpdate(%v)`, kvs[0].Value, _testJSONUpdate)
+		t.Errorf("string(kvs[0].Value(%s) is  not equal to _testJSONUpdate(%v)", kvs[0].Value, _testJSONUpdate)
 	}
 }
 
@@ -208,7 +208,7 @@ func TestConfig(t *testing.T) {
 func testConfig(t *testing.T, c config.Config) {
 	expected := map[string]interface{}{
 		"test.settings.int_key":      int64(1000),
-		"test.settings.float_key":    float64(1000.1),
+		"test.settings.float_key":    1000.1,
 		"test.settings.string_key":   "string_value",
 		"test.settings.duration_key": time.Duration(10000),
 		"test.server.addr":           "127.0.0.1",
diff --git a/config/file/format_test.go b/config/file/format_test.go
index 509a9837..75185cc6 100644
--- a/config/file/format_test.go
+++ b/config/file/format_test.go
@@ -1,6 +1,8 @@
 package file
 
-import "testing"
+import (
+	"testing"
+)
 
 func TestFormat(t *testing.T) {
 	tests := []struct {
diff --git a/config/options_test.go b/config/options_test.go
index 51e8b48e..c8cd2bf8 100644
--- a/config/options_test.go
+++ b/config/options_test.go
@@ -15,7 +15,7 @@ func TestDefaultDecoder(t *testing.T) {
 	target := make(map[string]interface{})
 	err := defaultDecoder(src, target)
 	if err != nil {
-		t.Fatal("err is not nil")
+		t.Fatal(err)
 	}
 	if !reflect.DeepEqual(target, map[string]interface{}{"service": []byte("config")}) {
 		t.Fatal(`target is not equal to map[string]interface{}{"service": "config"}`)
@@ -29,7 +29,7 @@ func TestDefaultDecoder(t *testing.T) {
 	target = make(map[string]interface{})
 	err = defaultDecoder(src, target)
 	if err != nil {
-		t.Fatal("err is not nil")
+		t.Fatal(err)
 	}
 	if !reflect.DeepEqual(map[string]interface{}{
 		"service": map[string]interface{}{
@@ -150,7 +150,7 @@ func TestDefaultResolver(t *testing.T) {
 		t.Run(test.name, func(t *testing.T) {
 			err := defaultResolver(data)
 			if err != nil {
-				t.Fatal(`err is not nil`)
+				t.Fatal(err)
 			}
 			rd := reader{
 				values: data,
@@ -161,25 +161,25 @@ func TestDefaultResolver(t *testing.T) {
 				case int:
 					if actual, err = v.Int(); err == nil {
 						if !reflect.DeepEqual(test.expect.(int), int(actual.(int64))) {
-							t.Fatal(`expect is not equal to actual`)
+							t.Fatal("expect is not equal to actual")
 						}
 					}
 				case string:
 					if actual, err = v.String(); err == nil {
 						if !reflect.DeepEqual(test.expect, actual) {
-							t.Fatal(`expect is not equal to actual`)
+							t.Fatal("expect is not equal to actual")
 						}
 					}
 				case bool:
 					if actual, err = v.Bool(); err == nil {
 						if !reflect.DeepEqual(test.expect, actual) {
-							t.Fatal(`expect is not equal to actual`)
+							t.Fatal("expect is not equal to actual")
 						}
 					}
 				case float64:
 					if actual, err = v.Float(); err == nil {
 						if !reflect.DeepEqual(test.expect, actual) {
-							t.Fatal(`expect is not equal to actual`)
+							t.Fatal("expect is not equal to actual")
 						}
 					}
 				default:
diff --git a/config/reader_test.go b/config/reader_test.go
index 15f8f617..11b2d990 100644
--- a/config/reader_test.go
+++ b/config/reader_test.go
@@ -29,7 +29,7 @@ func TestReader_Merge(t *testing.T) {
 		Format: "json",
 	})
 	if err == nil {
-		t.Fatal(`err is nil`)
+		t.Fatal("err is nil")
 	}
 
 	err = r.Merge(&KeyValue{
@@ -38,15 +38,15 @@ func TestReader_Merge(t *testing.T) {
 		Format: "json",
 	})
 	if err != nil {
-		t.Fatal(`err is not nil`)
+		t.Fatal(err)
 	}
 	vv, ok := r.Value("nice")
 	if !ok {
-		t.Fatal(`ok is false`)
+		t.Fatal("ok is false")
 	}
 	vvv, err := vv.String()
 	if err != nil {
-		t.Fatal(`err is not nil`)
+		t.Fatal(err)
 	}
 	if vvv != "boat" {
 		t.Fatal(`vvv is not equal to "boat"`)
@@ -58,18 +58,18 @@ func TestReader_Merge(t *testing.T) {
 		Format: "json",
 	})
 	if err != nil {
-		t.Fatal(`err is not nil`)
+		t.Fatal(err)
 	}
 	vv, ok = r.Value("x")
 	if !ok {
-		t.Fatal(`ok is false`)
+		t.Fatal("ok is false")
 	}
 	vvx, err := vv.Int()
 	if err != nil {
-		t.Fatal(`err is not nil`)
+		t.Fatal(err)
 	}
-	if int64(2) != vvx {
-		t.Fatal(`vvx is not equal to 2`)
+	if vvx != 2 {
+		t.Fatal("vvx is not equal to 2")
 	}
 }
 
@@ -118,27 +118,27 @@ a:
 			r := newReader(opts)
 			err := r.Merge(&test.kv)
 			if err != nil {
-				t.Fatal(`err is not nil`)
+				t.Fatal(err)
 			}
 			vv, ok := r.Value("a.b.X")
 			if !ok {
-				t.Fatal(`ok is false`)
+				t.Fatal("ok is false")
 			}
 			vvv, err := vv.Int()
 			if err != nil {
-				t.Fatal(`err is not nil`)
+				t.Fatal(err)
 			}
 			if int64(1) != vvv {
-				t.Fatal(`vvv is not equal to 1`)
+				t.Fatal("vvv is not equal to 1")
 			}
 
 			vv, ok = r.Value("a.b.Y")
 			if !ok {
-				t.Fatal(`ok is false`)
+				t.Fatal("ok is false")
 			}
 			vvy, err := vv.String()
 			if err != nil {
-				t.Fatal(`err is not nil`)
+				t.Fatal(err)
 			}
 			if vvy != "lol" {
 				t.Fatal(`vvy is not equal to "lol"`)
@@ -146,29 +146,29 @@ a:
 
 			vv, ok = r.Value("a.b.z")
 			if !ok {
-				t.Fatal(`ok is false`)
+				t.Fatal("ok is false")
 			}
 			vvz, err := vv.Bool()
 			if err != nil {
-				t.Fatal(`err is not nil`)
+				t.Fatal(err)
 			}
 			if !vvz {
-				t.Fatal(`vvz is not equal to true`)
+				t.Fatal("vvz is not equal to true")
 			}
 
 			_, ok = r.Value("aasasdg=234l.asdfk,")
 			if ok {
-				t.Fatal(`ok is true`)
+				t.Fatal("ok is true")
 			}
 
 			_, ok = r.Value("aas......asdg=234l.asdfk,")
 			if ok {
-				t.Fatal(`ok is true`)
+				t.Fatal("ok is true")
 			}
 
 			_, ok = r.Value("a.b.Y.")
 			if ok {
-				t.Fatal(`ok is true`)
+				t.Fatal("ok is true")
 			}
 		})
 	}
@@ -192,11 +192,11 @@ func TestReader_Source(t *testing.T) {
 		Format: "json",
 	})
 	if err != nil {
-		t.Fatal(`err is not nil`)
+		t.Fatal(err)
 	}
 	b, err := r.Source()
 	if err != nil {
-		t.Fatal(`err is not nil`)
+		t.Fatal(err)
 	}
 	if !reflect.DeepEqual([]byte(`{"a":{"b":{"X":1}}}`), b) {
 		t.Fatal("[]byte(`{\"a\":{\"b\":{\"X\":1}}}`) is not equal to b")
diff --git a/config/value_test.go b/config/value_test.go
index 9f674538..df771757 100644
--- a/config/value_test.go
+++ b/config/value_test.go
@@ -6,17 +6,17 @@ import (
 	"time"
 )
 
-func Test_atomicValue_Bool(t *testing.T) {
+func TestAtomicValue_Bool(t *testing.T) {
 	vlist := []interface{}{"1", "t", "T", "true", "TRUE", "True", true, 1, int32(1)}
 	for _, x := range vlist {
 		v := atomicValue{}
 		v.Store(x)
 		b, err := v.Bool()
 		if err != nil {
-			t.Fatal(`err is not nil`)
+			t.Fatal(err)
 		}
 		if !b {
-			t.Fatal(`b is not equal to true`)
+			t.Fatal("b is not equal to true")
 		}
 	}
 
@@ -26,10 +26,10 @@ func Test_atomicValue_Bool(t *testing.T) {
 		v.Store(x)
 		b, err := v.Bool()
 		if err != nil {
-			t.Fatal(`err is not nil`)
+			t.Fatal(err)
 		}
 		if b {
-			t.Fatal(`b is not equal to false`)
+			t.Fatal("b is not equal to false")
 		}
 	}
 
@@ -39,22 +39,22 @@ func Test_atomicValue_Bool(t *testing.T) {
 		v.Store(x)
 		_, err := v.Bool()
 		if err == nil {
-			t.Fatal(`err is nil`)
+			t.Fatal("err is nil")
 		}
 	}
 }
 
-func Test_atomicValue_Int(t *testing.T) {
+func TestAtomicValue_Int(t *testing.T) {
 	vlist := []interface{}{"123123", float64(123123), int64(123123), int32(123123), 123123}
 	for _, x := range vlist {
 		v := atomicValue{}
 		v.Store(x)
 		b, err := v.Int()
 		if err != nil {
-			t.Fatal(`err is not nil`)
+			t.Fatal(err)
 		}
 		if b != 123123 {
-			t.Fatal(`b is not equal to 123123`)
+			t.Fatal("b is not equal to 123123")
 		}
 	}
 
@@ -64,22 +64,22 @@ func Test_atomicValue_Int(t *testing.T) {
 		v.Store(x)
 		_, err := v.Int()
 		if err == nil {
-			t.Fatal(`err is nil`)
+			t.Fatal("err is nil")
 		}
 	}
 }
 
-func Test_atomicValue_Float(t *testing.T) {
-	vlist := []interface{}{"123123.1", float64(123123.1)}
+func TestAtomicValue_Float(t *testing.T) {
+	vlist := []interface{}{"123123.1", 123123.1}
 	for _, x := range vlist {
 		v := atomicValue{}
 		v.Store(x)
 		b, err := v.Float()
 		if err != nil {
-			t.Fatal(`err is not nil`)
+			t.Fatal(err)
 		}
-		if b != float64(123123.1) {
-			t.Fatal(`b is not equal to 123123.1`)
+		if b != 123123.1 {
+			t.Fatal("b is not equal to 123123.1")
 		}
 	}
 
@@ -89,7 +89,7 @@ func Test_atomicValue_Float(t *testing.T) {
 		v.Store(x)
 		_, err := v.Float()
 		if err == nil {
-			t.Fatal(`err is nil`)
+			t.Fatal("err is nil")
 		}
 	}
 }
@@ -103,17 +103,17 @@ func (t ts) String() string {
 	return fmt.Sprintf("%s%d", t.Name, t.Age)
 }
 
-func Test_atomicValue_String(t *testing.T) {
+func TestAtomicValue_String(t *testing.T) {
 	vlist := []interface{}{"1", float64(1), int64(1), 1, int64(1)}
 	for _, x := range vlist {
 		v := atomicValue{}
 		v.Store(x)
 		b, err := v.String()
 		if err != nil {
-			t.Fatal(`err is not nil`)
+			t.Fatal(err)
 		}
 		if b != "1" {
-			t.Fatal(`b is not equal to 1`)
+			t.Fatal("b is not equal to 1")
 		}
 	}
 
@@ -121,7 +121,7 @@ func Test_atomicValue_String(t *testing.T) {
 	v.Store(true)
 	b, err := v.String()
 	if err != nil {
-		t.Fatal(`err is not nil`)
+		t.Fatal(err)
 	}
 	if b != "true" {
 		t.Fatal(`b is not equal to "true"`)
@@ -134,48 +134,48 @@ func Test_atomicValue_String(t *testing.T) {
 	})
 	b, err = v.String()
 	if err != nil {
-		t.Fatal(`err is not nil`)
+		t.Fatal(err)
 	}
 	if b != "test10" {
 		t.Fatal(`b is not equal to "test10"`)
 	}
 }
 
-func Test_atomicValue_Duration(t *testing.T) {
+func TestAtomicValue_Duration(t *testing.T) {
 	vlist := []interface{}{int64(5)}
 	for _, x := range vlist {
 		v := atomicValue{}
 		v.Store(x)
 		b, err := v.Duration()
 		if err != nil {
-			t.Fatal(`err is not nil`)
+			t.Fatal(err)
 		}
 		if b != time.Duration(5) {
-			t.Fatal(`b is not equal to time.Duration(5)`)
+			t.Fatal("b is not equal to time.Duration(5)")
 		}
 	}
 }
 
-func Test_atomicValue_Slice(t *testing.T) {
+func TestAtomicValue_Slice(t *testing.T) {
 	vlist := []interface{}{int64(5)}
 	v := atomicValue{}
 	v.Store(vlist)
 	slices, err := v.Slice()
 	if err != nil {
-		t.Fatal(`err is not nil`)
+		t.Fatal(err)
 	}
 	for _, v := range slices {
 		b, err := v.Duration()
 		if err != nil {
-			t.Fatal(`err is not nil`)
+			t.Fatal(err)
 		}
 		if b != time.Duration(5) {
-			t.Fatal(`b is not equal to time.Duration(5)`)
+			t.Fatal("b is not equal to time.Duration(5)")
 		}
 	}
 }
 
-func Test_atomicValue_Map(t *testing.T) {
+func TestAtomicValue_Map(t *testing.T) {
 	vlist := make(map[string]interface{})
 	vlist["5"] = int64(5)
 	vlist["text"] = "text"
@@ -183,21 +183,21 @@ func Test_atomicValue_Map(t *testing.T) {
 	v.Store(vlist)
 	m, err := v.Map()
 	if err != nil {
-		t.Fatal(`err is not nil`)
+		t.Fatal(err)
 	}
 	for k, v := range m {
 		if k == "5" {
 			b, err := v.Duration()
 			if err != nil {
-				t.Fatal(`err is not nil`)
+				t.Fatal(err)
 			}
 			if b != time.Duration(5) {
-				t.Fatal(`b is not equal to time.Duration(5)`)
+				t.Fatal("b is not equal to time.Duration(5)")
 			}
 		} else {
 			b, err := v.String()
 			if err != nil {
-				t.Fatal(`err is not nil`)
+				t.Fatal(err)
 			}
 			if b != "text" {
 				t.Fatal(`b is not equal to "text"`)
@@ -206,20 +206,19 @@ func Test_atomicValue_Map(t *testing.T) {
 	}
 }
 
-func Test_atomicValue_Scan(t *testing.T) {
-	var err error
+func TestAtomicValue_Scan(t *testing.T) {
 	v := atomicValue{}
-	err = v.Scan(&struct {
+	err := v.Scan(&struct {
 		A string `json:"a"`
 	}{"a"})
 	if err != nil {
-		t.Fatal(`err is not nil`)
+		t.Fatal(err)
 	}
 
 	err = v.Scan(&struct {
 		A string `json:"a"`
 	}{"a"})
 	if err != nil {
-		t.Fatal(`err is not nil`)
+		t.Fatal(err)
 	}
 }
diff --git a/contrib/config/kubernetes/config_test.go b/contrib/config/kubernetes/config_test.go
index 6cdb1c98..b110b634 100644
--- a/contrib/config/kubernetes/config_test.go
+++ b/contrib/config/kubernetes/config_test.go
@@ -8,14 +8,14 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/go-kratos/kratos/v2/config"
-
 	v1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/client-go/kubernetes"
 	"k8s.io/client-go/rest"
 	"k8s.io/client-go/tools/clientcmd"
 	"k8s.io/client-go/util/homedir"
+
+	"github.com/go-kratos/kratos/v2/config"
 )
 
 const (
diff --git a/contrib/log/aliyun/aliyun_test.go b/contrib/log/aliyun/aliyun_test.go
index a5e1f080..e3e224ad 100644
--- a/contrib/log/aliyun/aliyun_test.go
+++ b/contrib/log/aliyun/aliyun_test.go
@@ -2,6 +2,7 @@ package aliyun
 
 import (
 	"math"
+	"reflect"
 	"testing"
 
 	"github.com/go-kratos/kratos/v2/log"
@@ -99,33 +100,45 @@ func TestLog(t *testing.T) {
 	}
 }
 
+func TestNewString(t *testing.T) {
+	ptr := newString("")
+	if kind := reflect.TypeOf(ptr).Kind(); kind != reflect.Ptr {
+		t.Errorf("want type: %v, got type: %v", reflect.Ptr, kind)
+	}
+}
+
 func TestToString(t *testing.T) {
 	tests := []struct {
-		in  interface{}
-		out string
+		name string
+		in   interface{}
+		out  string
 	}{
-		{math.MaxFloat64, "17976931348623157000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000000000000000000" +
-			"0000000000000000000000000000000"},
-		{math.MaxFloat32, "340282346638528860000000000000000000000"},
-		{1<<((32<<(^uint(0)>>63))-1) - 1, "9223372036854775807"},
-		{uint(1<<(32<<(^uint(0)>>63)) - 1), "-1"},
-		{math.MaxInt8, "127"},
-		{math.MaxUint8, "255"},
-		{math.MaxInt16, "32767"},
-		{math.MaxUint16, "65535"},
-		{math.MaxInt32, "2147483647"},
-		{math.MaxUint32, "4294967295"},
-		{math.MaxInt64, "9223372036854775807"},
-		{uint64(math.MaxUint64), "18446744073709551615"},
-		{"abc", "abc"},
-		{[]byte("abc"), "abc"},
+		{"float64", 6.66, "6.66"},
+		{"max float64", math.MaxFloat64, "179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, //nolint:lll
+		{"float32", float32(6.66), "6.66"},
+		{"max float32", float32(math.MaxFloat32), "340282350000000000000000000000000000000"},
+		{"int", math.MaxInt64, "9223372036854775807"},
+		{"uint", uint(math.MaxUint64), "18446744073709551615"},
+		{"int8", int8(math.MaxInt8), "127"},
+		{"uint8", uint8(math.MaxUint8), "255"},
+		{"int16", int16(math.MaxInt16), "32767"},
+		{"uint16", uint16(math.MaxUint16), "65535"},
+		{"int32", int32(math.MaxInt32), "2147483647"},
+		{"uint32", uint32(math.MaxUint32), "4294967295"},
+		{"int64", int64(math.MaxInt64), "9223372036854775807"},
+		{"uint64", uint64(math.MaxUint64), "18446744073709551615"},
+		{"string", "abc", "abc"},
+		{"bool", false, "false"},
+		{"[]byte", []byte("abc"), "abc"},
+		{"struct", struct{ Name string }{}, `{"Name":""}`},
+		{"nil", nil, ""},
 	}
 	for _, test := range tests {
-		if toString(test.in) != test.out {
-			t.Fatalf("want: %s, got: %s", test.out, toString(test.in))
-		}
+		t.Run(test.name, func(t *testing.T) {
+			out := toString(test.in)
+			if test.out != out {
+				t.Fatalf("want: %s, got: %s", test.out, out)
+			}
+		})
 	}
 }
diff --git a/contrib/log/fluent/fluent_test.go b/contrib/log/fluent/fluent_test.go
index 5b7b3e17..41f7080d 100644
--- a/contrib/log/fluent/fluent_test.go
+++ b/contrib/log/fluent/fluent_test.go
@@ -11,18 +11,23 @@ import (
 )
 
 func TestMain(m *testing.M) {
+	listener := func(ln net.Listener) {
+		conn, err := ln.Accept()
+		if err != nil {
+			return
+		}
+		defer conn.Close()
+		_, err = io.ReadAll(conn)
+		if err != nil {
+			return
+		}
+	}
+
 	if ln, err := net.Listen("tcp", ":24224"); err == nil {
 		defer ln.Close()
 		go func() {
 			for {
-				conn, err := ln.Accept()
-				if err != nil {
-					return
-				}
-				defer conn.Close()
-				if _, err = io.ReadAll(conn); err != nil {
-					continue
-				}
+				listener(ln)
 			}
 		}()
 	}
diff --git a/contrib/log/tencent/tencent_test.go b/contrib/log/tencent/tencent_test.go
index b37c1b22..df1fe367 100644
--- a/contrib/log/tencent/tencent_test.go
+++ b/contrib/log/tencent/tencent_test.go
@@ -1,6 +1,8 @@
 package tencent
 
 import (
+	"math"
+	"reflect"
 	"testing"
 
 	"github.com/go-kratos/kratos/v2/log"
@@ -101,3 +103,46 @@ func TestLog(t *testing.T) {
 		t.Errorf("Log() returns error:%v", err)
 	}
 }
+
+func TestNewString(t *testing.T) {
+	ptr := newString("")
+	if kind := reflect.TypeOf(ptr).Kind(); kind != reflect.Ptr {
+		t.Errorf("want type: %v, got type: %v", reflect.Ptr, kind)
+	}
+}
+
+func TestToString(t *testing.T) {
+	tests := []struct {
+		name string
+		in   interface{}
+		out  string
+	}{
+		{"float64", 6.66, "6.66"},
+		{"max float64", math.MaxFloat64, "179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, //nolint:lll
+		{"float32", float32(6.66), "6.66"},
+		{"max float32", float32(math.MaxFloat32), "340282350000000000000000000000000000000"},
+		{"int", math.MaxInt64, "9223372036854775807"},
+		{"uint", uint(math.MaxUint64), "18446744073709551615"},
+		{"int8", int8(math.MaxInt8), "127"},
+		{"uint8", uint8(math.MaxUint8), "255"},
+		{"int16", int16(math.MaxInt16), "32767"},
+		{"uint16", uint16(math.MaxUint16), "65535"},
+		{"int32", int32(math.MaxInt32), "2147483647"},
+		{"uint32", uint32(math.MaxUint32), "4294967295"},
+		{"int64", int64(math.MaxInt64), "9223372036854775807"},
+		{"uint64", uint64(math.MaxUint64), "18446744073709551615"},
+		{"string", "abc", "abc"},
+		{"bool", false, "false"},
+		{"[]byte", []byte("abc"), "abc"},
+		{"struct", struct{ Name string }{}, `{"Name":""}`},
+		{"nil", nil, ""},
+	}
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			out := toString(test.in)
+			if test.out != out {
+				t.Fatalf("want: %s, got: %s", test.out, out)
+			}
+		})
+	}
+}
diff --git a/contrib/opensergo/opensergo_test.go b/contrib/opensergo/opensergo_test.go
index b63430e2..70ffef8f 100644
--- a/contrib/opensergo/opensergo_test.go
+++ b/contrib/opensergo/opensergo_test.go
@@ -2,6 +2,7 @@ package opensergo
 
 import (
 	"net"
+	"net/http"
 	"os"
 	"path/filepath"
 	"reflect"
@@ -195,7 +196,7 @@ func TestHTTPPatternInfo(t *testing.T) {
 			args: args{
 				pattern: &annotations.HttpRule_Get{Get: "/foo"},
 			},
-			wantMethod: "GET",
+			wantMethod: http.MethodGet,
 			wantPath:   "/foo",
 		},
 		{
@@ -203,7 +204,7 @@ func TestHTTPPatternInfo(t *testing.T) {
 			args: args{
 				pattern: &annotations.HttpRule_Post{Post: "/foo"},
 			},
-			wantMethod: "POST",
+			wantMethod: http.MethodPost,
 			wantPath:   "/foo",
 		},
 		{
@@ -211,7 +212,7 @@ func TestHTTPPatternInfo(t *testing.T) {
 			args: args{
 				pattern: &annotations.HttpRule_Put{Put: "/foo"},
 			},
-			wantMethod: "PUT",
+			wantMethod: http.MethodPut,
 			wantPath:   "/foo",
 		},
 		{
@@ -219,7 +220,7 @@ func TestHTTPPatternInfo(t *testing.T) {
 			args: args{
 				pattern: &annotations.HttpRule_Delete{Delete: "/foo"},
 			},
-			wantMethod: "DELETE",
+			wantMethod: http.MethodDelete,
 			wantPath:   "/foo",
 		},
 		{
@@ -227,7 +228,7 @@ func TestHTTPPatternInfo(t *testing.T) {
 			args: args{
 				pattern: &annotations.HttpRule_Patch{Patch: "/foo"},
 			},
-			wantMethod: "PATCH",
+			wantMethod: http.MethodPatch,
 			wantPath:   "/foo",
 		},
 		{
diff --git a/contrib/registry/servicecomb/registry_test.go b/contrib/registry/servicecomb/registry_test.go
index 85afe306..4b4c2549 100644
--- a/contrib/registry/servicecomb/registry_test.go
+++ b/contrib/registry/servicecomb/registry_test.go
@@ -6,8 +6,9 @@ import (
 
 	pb "github.com/go-chassis/cari/discovery"
 	"github.com/go-chassis/sc-client"
-	"github.com/go-kratos/kratos/v2/registry"
 	"github.com/gofrs/uuid"
+
+	"github.com/go-kratos/kratos/v2/registry"
 )
 
 var r *Registry
diff --git a/encoding/form/form_test.go b/encoding/form/form_test.go
index ddd053cd..647d1edc 100644
--- a/encoding/form/form_test.go
+++ b/encoding/form/form_test.go
@@ -26,14 +26,12 @@ type TestModel struct {
 	Name string `json:"name"`
 }
 
-const contentType = "x-www-form-urlencoded"
-
 func TestFormCodecMarshal(t *testing.T) {
 	req := &LoginRequest{
 		Username: "kratos",
 		Password: "kratos_pwd",
 	}
-	content, err := encoding.GetCodec(contentType).Marshal(req)
+	content, err := encoding.GetCodec(Name).Marshal(req)
 	if err != nil {
 		t.Errorf("marshal error: %v", err)
 	}
@@ -45,7 +43,7 @@ func TestFormCodecMarshal(t *testing.T) {
 		Username: "kratos",
 		Password: "",
 	}
-	content, err = encoding.GetCodec(contentType).Marshal(req)
+	content, err = encoding.GetCodec(Name).Marshal(req)
 	if err != nil {
 		t.Errorf("expect %v, got %v", nil, err)
 	}
@@ -57,7 +55,7 @@ func TestFormCodecMarshal(t *testing.T) {
 		ID:   1,
 		Name: "kratos",
 	}
-	content, err = encoding.GetCodec(contentType).Marshal(m)
+	content, err = encoding.GetCodec(Name).Marshal(m)
 	t.Log(string(content))
 	if err != nil {
 		t.Errorf("expect %v, got %v", nil, err)
@@ -72,13 +70,13 @@ func TestFormCodecUnmarshal(t *testing.T) {
 		Username: "kratos",
 		Password: "kratos_pwd",
 	}
-	content, err := encoding.GetCodec(contentType).Marshal(req)
+	content, err := encoding.GetCodec(Name).Marshal(req)
 	if err != nil {
 		t.Errorf("expect %v, got %v", nil, err)
 	}
 
 	bindReq := new(LoginRequest)
-	err = encoding.GetCodec(contentType).Unmarshal(content, bindReq)
+	err = encoding.GetCodec(Name).Unmarshal(content, bindReq)
 	if err != nil {
 		t.Errorf("expect %v, got %v", nil, err)
 	}
@@ -119,7 +117,7 @@ func TestProtoEncodeDecode(t *testing.T) {
 		String_:   &wrapperspb.StringValue{Value: "go-kratos"},
 		Bytes:     &wrapperspb.BytesValue{Value: []byte("123")},
 	}
-	content, err := encoding.GetCodec(contentType).Marshal(in)
+	content, err := encoding.GetCodec(Name).Marshal(in)
 	if err != nil {
 		t.Errorf("expect %v, got %v", nil, err)
 	}
@@ -130,7 +128,7 @@ func TestProtoEncodeDecode(t *testing.T) {
 		t.Errorf("rawpath is not equal to %v", string(content))
 	}
 	in2 := &complex.Complex{}
-	err = encoding.GetCodec(contentType).Unmarshal(content, in2)
+	err = encoding.GetCodec(Name).Unmarshal(content, in2)
 	if err != nil {
 		t.Errorf("expect %v, got %v", nil, err)
 	}
@@ -163,7 +161,7 @@ func TestProtoEncodeDecode(t *testing.T) {
 func TestDecodeStructPb(t *testing.T) {
 	req := new(ectest.StructPb)
 	query := `data={"name":"kratos"}&data_list={"name1": "kratos"}&data_list={"name2": "go-kratos"}`
-	if err := encoding.GetCodec(contentType).Unmarshal([]byte(query), req); err != nil {
+	if err := encoding.GetCodec(Name).Unmarshal([]byte(query), req); err != nil {
 		t.Errorf("expect %v, got %v", nil, err)
 	}
 	if !reflect.DeepEqual("kratos", req.Data.GetFields()["name"].GetStringValue()) {
@@ -186,7 +184,7 @@ func TestDecodeBytesValuePb(t *testing.T) {
 	val := base64.URLEncoding.EncodeToString([]byte(url))
 	content := "bytes=" + val
 	in2 := &complex.Complex{}
-	if err := encoding.GetCodec(contentType).Unmarshal([]byte(content), in2); err != nil {
+	if err := encoding.GetCodec(Name).Unmarshal([]byte(content), in2); err != nil {
 		t.Errorf("expect %v, got %v", nil, err)
 	}
 	if !reflect.DeepEqual(url, string(in2.Bytes.Value)) {
diff --git a/encoding/form/proto_decode_test.go b/encoding/form/proto_decode_test.go
new file mode 100644
index 00000000..fbe23433
--- /dev/null
+++ b/encoding/form/proto_decode_test.go
@@ -0,0 +1,217 @@
+package form
+
+import (
+	"fmt"
+	"net/url"
+	"reflect"
+	"strconv"
+	"testing"
+
+	"google.golang.org/protobuf/reflect/protoreflect"
+
+	"github.com/go-kratos/kratos/v2/internal/testdata/complex"
+)
+
+func TestDecodeValues(t *testing.T) {
+	form, err := url.ParseQuery("a=19&age=18&b=true&bool=false&byte=MTIz&bytes=MTIz&count=3&d=22.22&double=12.33&duration=" +
+		"2m0.000000022s&field=1%2C2&float=12.34&id=2233&int32=32&int64=64&numberOne=2233&price=11.23&sex=woman&simples=3344&" +
+		"simples=5566&string=go-kratos&timestamp=1970-01-01T00%3A00%3A20.000000002Z&uint32=32&uint64=64&very_simple.component=5566")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	comp := &complex.Complex{}
+	err = DecodeValues(comp, form)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if comp.Id != int64(2233) {
+		t.Errorf("want %v, got %v", int64(2233), comp.Id)
+	}
+	if comp.NoOne != "2233" {
+		t.Errorf("want %v, got %v", "2233", comp.NoOne)
+	}
+	if comp.Simple == nil {
+		t.Fatalf("want %v, got %v", nil, comp.Simple)
+	}
+	if comp.Simple.Component != "5566" {
+		t.Errorf("want %v, got %v", "5566", comp.Simple.Component)
+	}
+	if len(comp.Simples) != 2 {
+		t.Fatalf("want %v, got %v", 2, len(comp.Simples))
+	}
+	if comp.Simples[0] != "3344" {
+		t.Errorf("want %v, got %v", "3344", comp.Simples[0])
+	}
+	if comp.Simples[1] != "5566" {
+		t.Errorf("want %v, got %v", "5566", comp.Simples[1])
+	}
+}
+
+func TestGetFieldDescriptor(t *testing.T) {
+	comp := &complex.Complex{}
+
+	field := getFieldDescriptor(comp.ProtoReflect(), "id")
+	if field.Kind() != protoreflect.Int64Kind {
+		t.Errorf("want: %d, got: %d", protoreflect.Int64Kind, field.Kind())
+	}
+
+	field = getFieldDescriptor(comp.ProtoReflect(), "simples")
+	if field.Kind() != protoreflect.StringKind {
+		t.Errorf("want: %d, got: %d", protoreflect.StringKind, field.Kind())
+	}
+}
+
+func TestPopulateRepeatedField(t *testing.T) {
+	query, err := url.ParseQuery("simples=3344&simples=5566")
+	if err != nil {
+		t.Fatal(err)
+	}
+	comp := &complex.Complex{}
+	field := getFieldDescriptor(comp.ProtoReflect(), "simples")
+
+	err = populateRepeatedField(field, comp.ProtoReflect().Mutable(field).List(), query["simples"])
+	if err != nil {
+		t.Fatal(err)
+	}
+	if !reflect.DeepEqual([]string{"3344", "5566"}, comp.GetSimples()) {
+		t.Errorf("want: %v, got: %v", []string{"3344", "5566"}, comp.GetSimples())
+	}
+}
+
+func TestPopulateMapField(t *testing.T) {
+	query, err := url.ParseQuery("map%5Bkratos%5D=https://go-kratos.dev/")
+	if err != nil {
+		t.Fatal(err)
+	}
+	comp := &complex.Complex{}
+	field := getFieldDescriptor(comp.ProtoReflect(), "map")
+	// Fill the comp map field with the url query values
+	err = populateMapField(field, comp.ProtoReflect().Mutable(field).Map(), []string{"kratos"}, query["map[kratos]"])
+	if err != nil {
+		t.Fatal(err)
+	}
+	// Get the comp map field value
+	if query["map[kratos]"][0] != comp.Map["kratos"] {
+		t.Errorf("want: %s, got: %s", query["map[kratos]"], comp.Map["kratos"])
+	}
+}
+
+func TestParseField(t *testing.T) {
+	tests := []struct {
+		name                    string
+		fieldName               string
+		protoReflectKind        protoreflect.Kind
+		value                   string
+		targetProtoReflectValue protoreflect.Value
+		targetErr               error
+	}{
+		{
+			name:                    "BoolKind",
+			fieldName:               "b",
+			protoReflectKind:        protoreflect.BoolKind,
+			value:                   "true",
+			targetProtoReflectValue: protoreflect.ValueOfBool(true),
+			targetErr:               nil,
+		},
+		{
+			name:                    "BoolKind",
+			fieldName:               "b",
+			protoReflectKind:        protoreflect.BoolKind,
+			value:                   "a",
+			targetProtoReflectValue: protoreflect.Value{},
+			targetErr:               &strconv.NumError{Func: "ParseBool", Num: "a", Err: strconv.ErrSyntax},
+		},
+		{
+			name:                    "EnumKind",
+			fieldName:               "sex",
+			protoReflectKind:        protoreflect.EnumKind,
+			value:                   "1",
+			targetProtoReflectValue: protoreflect.ValueOfEnum(1),
+			targetErr:               nil,
+		},
+		{
+			name:                    "EnumKind",
+			fieldName:               "sex",
+			protoReflectKind:        protoreflect.EnumKind,
+			value:                   "2",
+			targetProtoReflectValue: protoreflect.Value{},
+			targetErr:               fmt.Errorf("%q is not a valid value", "2"),
+		},
+	}
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			comp := &complex.Complex{}
+			field := getFieldDescriptor(comp.ProtoReflect(), test.fieldName)
+			if test.protoReflectKind != field.Kind() {
+				t.Fatalf("want: %d, got: %d", test.protoReflectKind, field.Kind())
+			}
+			val, err := parseField(field, test.value)
+			if !reflect.DeepEqual(test.targetErr, err) {
+				t.Fatalf("want: %s, got: %s", test.targetErr, err)
+			}
+			if !reflect.DeepEqual(test.targetProtoReflectValue, val) {
+				t.Errorf("want: %s, got: %s", test.targetProtoReflectValue, val)
+			}
+		})
+	}
+}
+
+func TestJsonSnakeCase(t *testing.T) {
+	tests := []struct {
+		camelCase string
+		snakeCase string
+	}{
+		{
+			"userId", "user_id",
+		},
+		{
+			"user", "user",
+		},
+		{
+			"userIdAndUsername", "user_id_and_username",
+		},
+		{
+			"", "",
+		},
+	}
+	for _, test := range tests {
+		t.Run(test.camelCase, func(t *testing.T) {
+			snake := jsonSnakeCase(test.camelCase)
+			if snake != test.snakeCase {
+				t.Errorf("want: %s, got: %s", test.snakeCase, snake)
+			}
+		})
+	}
+}
+
+func TestIsASCIIUpper(t *testing.T) {
+	tests := []struct {
+		b     byte
+		upper bool
+	}{
+		{
+			'A', true,
+		},
+		{
+			'a', false,
+		},
+		{
+			',', false,
+		},
+		{
+			'1', false,
+		},
+		{
+			' ', false,
+		},
+	}
+	for _, test := range tests {
+		t.Run(string(test.b), func(t *testing.T) {
+			upper := isASCIIUpper(test.b)
+			if test.upper != upper {
+				t.Errorf("'%s' is not ascii upper", string(test.b))
+			}
+		})
+	}
+}
diff --git a/encoding/xml/xml_test.go b/encoding/xml/xml_test.go
index 6c53c3dd..09e7d03b 100644
--- a/encoding/xml/xml_test.go
+++ b/encoding/xml/xml_test.go
@@ -25,7 +25,7 @@ func TestCodec_Marshal(t *testing.T) {
 		// Test value types
 		{Value: &Plain{true}, ExpectXML: `<Plain><V>true</V></Plain>`},
 		{Value: &Plain{false}, ExpectXML: `<Plain><V>false</V></Plain>`},
-		{Value: &Plain{int(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
+		{Value: &Plain{42}, ExpectXML: `<Plain><V>42</V></Plain>`},
 		{
 			Value: &NestedOrder{Field1: "C", Field2: "B", Field3: "A"},
 			ExpectXML: `<result>` +
diff --git a/log/filter_test.go b/log/filter_test.go
index d3c8d548..3e36deac 100644
--- a/log/filter_test.go
+++ b/log/filter_test.go
@@ -102,13 +102,19 @@ func TestFilterFuncWitchLoggerPrefix(t *testing.T) {
 			want:   "",
 		},
 		{
+			// Filtered value
 			logger: NewFilter(With(NewStdLogger(buf), "caller", "caller"), FilterFunc(testFilterFuncWithLoggerPrefix)),
-			want:   "INFO caller=caller msg=msg\n",
+			want:   "INFO caller=caller msg=msg filtered=***\n",
+		},
+		{
+			// NO prefix
+			logger: NewFilter(With(NewStdLogger(buf)), FilterFunc(testFilterFuncWithLoggerPrefix)),
+			want:   "INFO msg=msg filtered=***\n",
 		},
 	}
 
 	for _, tt := range tests {
-		err := tt.logger.Log(LevelInfo, "msg", "msg")
+		err := tt.logger.Log(LevelInfo, "msg", "msg", "filtered", "true")
 		if err != nil {
 			t.Fatal("err should be nil")
 		}
@@ -128,6 +134,9 @@ func testFilterFuncWithLoggerPrefix(level Level, keyvals ...interface{}) bool {
 		if keyvals[i] == "prefix" {
 			return true
 		}
+		if keyvals[i] == "filtered" {
+			keyvals[i+1] = fuzzyStr
+		}
 	}
 	return false
 }
diff --git a/log/level_test.go b/log/level_test.go
index d3688291..193503c6 100644
--- a/log/level_test.go
+++ b/log/level_test.go
@@ -2,6 +2,12 @@ package log
 
 import "testing"
 
+func TestLevel_Key(t *testing.T) {
+	if LevelInfo.Key() != LevelKey {
+		t.Errorf("want: %s, got: %s", LevelKey, LevelInfo.Key())
+	}
+}
+
 func TestLevel_String(t *testing.T) {
 	tests := []struct {
 		name string
diff --git a/middleware/auth/jwt/jwt_test.go b/middleware/auth/jwt/jwt_test.go
index 188744b0..711757bc 100644
--- a/middleware/auth/jwt/jwt_test.go
+++ b/middleware/auth/jwt/jwt_test.go
@@ -254,7 +254,7 @@ func TestServer(t *testing.T) {
 			}
 			if test.exceptErr == nil {
 				if testToken == nil {
-					t.Errorf("except testToken not nil, but got nil")
+					t.Fatal("except testToken not nil, but got nil")
 				}
 				_, ok := testToken.(jwt.MapClaims)
 				if !ok {
@@ -493,3 +493,26 @@ func TestClientMissKey(t *testing.T) {
 		}
 	})
 }
+
+func TestNewContextAndFromContext(t *testing.T) {
+	tests := []struct {
+		name   string
+		claims jwt.MapClaims
+	}{
+		{"val not nil", jwt.MapClaims{"name": "kratos"}},
+		{"val nil", nil},
+	}
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			ctx := NewContext(context.Background(), test.claims)
+
+			claims, ok := FromContext(ctx)
+			if !ok {
+				t.Fatal("ctx not found authKey{}")
+			}
+			if !reflect.DeepEqual(test.claims, claims) {
+				t.Errorf(`want: %s, got: %v`, test.claims, claims)
+			}
+		})
+	}
+}
diff --git a/middleware/logging/logging_test.go b/middleware/logging/logging_test.go
index 6ad1a02c..431d8901 100644
--- a/middleware/logging/logging_test.go
+++ b/middleware/logging/logging_test.go
@@ -111,7 +111,7 @@ func (d *dummyStringer) String() string {
 	return "my value"
 }
 
-func Test_extractArgs(t *testing.T) {
+func TestExtractArgs(t *testing.T) {
 	if extractArgs(&dummyStringer{field: ""}) != "my value" {
 		t.Errorf(`The stringified dummyStringer structure must be equal to "my value", %v given`, extractArgs(&dummyStringer{field: ""}))
 	}
@@ -120,3 +120,30 @@ func Test_extractArgs(t *testing.T) {
 		t.Errorf(`The stringified dummy structure must be equal to "&{field:value}", %v given`, extractArgs(&dummy{field: "value"}))
 	}
 }
+
+func TestExtractError(t *testing.T) {
+	tests := []struct {
+		name       string
+		err        error
+		wantLevel  log.Level
+		wantErrStr string
+	}{
+		{
+			"no error", nil, log.LevelInfo, "",
+		},
+		{
+			"error", errors.New("test error"), log.LevelError, "test error",
+		},
+	}
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			level, errStr := extractError(test.err)
+			if level != test.wantLevel {
+				t.Errorf("want: %d, got: %d", test.wantLevel, level)
+			}
+			if errStr != test.wantErrStr {
+				t.Errorf("want: %s, got: %s", test.wantErrStr, errStr)
+			}
+		})
+	}
+}
diff --git a/middleware/metadata/metadata_test.go b/middleware/metadata/metadata_test.go
index e46a94f5..b083f9c1 100644
--- a/middleware/metadata/metadata_test.go
+++ b/middleware/metadata/metadata_test.go
@@ -4,6 +4,7 @@ import (
 	"context"
 	"errors"
 	"net/http"
+	"reflect"
 	"testing"
 
 	"github.com/go-kratos/kratos/v2/metadata"
@@ -33,15 +34,18 @@ func (tr *testTransport) Operation() string               { return "" }
 func (tr *testTransport) RequestHeader() transport.Header { return tr.header }
 func (tr *testTransport) ReplyHeader() transport.Header   { return tr.header }
 
+var (
+	globalKey   = "x-md-global-key"
+	globalValue = "global-value"
+	localKey    = "x-md-local-key"
+	localValue  = "local-value"
+	customKey   = "x-md-local-custom"
+	customValue = "custom-value"
+	constKey    = "x-md-local-const"
+	constValue  = "x-md-local-const"
+)
+
 func TestSever(t *testing.T) {
-	var (
-		globalKey   = "x-md-global-key"
-		globalValue = "global-value"
-		localKey    = "x-md-local-key"
-		localValue  = "local-value"
-		constKey    = "x-md-local-const"
-		constValue  = "x-md-local-const"
-	)
 	hs := func(ctx context.Context, in interface{}) (interface{}, error) {
 		md, ok := metadata.FromServerContext(ctx)
 		if !ok {
@@ -75,16 +79,6 @@ func TestSever(t *testing.T) {
 }
 
 func TestClient(t *testing.T) {
-	var (
-		globalKey   = "x-md-global-key"
-		globalValue = "global-value"
-		localKey    = "x-md-local-key"
-		localValue  = "local-value"
-		customKey   = "x-md-local-custom"
-		customValue = "custom-value"
-		constKey    = "x-md-local-const"
-		constValue  = "x-md-local-const"
-	)
 	hs := func(ctx context.Context, in interface{}) (interface{}, error) {
 		tr, ok := transport.FromClientContext(ctx)
 		if !ok {
@@ -127,13 +121,52 @@ func TestClient(t *testing.T) {
 	}
 }
 
-func Test_WithPropagatedPrefix(t *testing.T) {
-	o := &options{
+func TestWithConstants(t *testing.T) {
+	md := metadata.Metadata{
+		constKey: constValue,
+	}
+	options := &options{
+		md: metadata.Metadata{
+			"override": "override",
+		},
+	}
+
+	WithConstants(md)(options)
+	if !reflect.DeepEqual(md, options.md) {
+		t.Errorf("want: %v, got: %v", md, options.md)
+	}
+}
+
+func TestOptions_WithPropagatedPrefix(t *testing.T) {
+	options := &options{
 		prefix: []string{"override"},
 	}
-	WithPropagatedPrefix("something", "another")(o)
+	prefixes := []string{"something", "another"}
 
-	if len(o.prefix) != 2 {
+	WithPropagatedPrefix(prefixes...)(options)
+	if !reflect.DeepEqual(prefixes, options.prefix) {
 		t.Error("The prefix must be overridden.")
 	}
 }
+
+func TestOptions_hasPrefix(t *testing.T) {
+	tests := []struct {
+		name    string
+		options *options
+		key     string
+		exists  bool
+	}{
+		{"exists key upper", &options{prefix: []string{"prefix"}}, "PREFIX_true", true},
+		{"exists key lower", &options{prefix: []string{"prefix"}}, "prefix_true", true},
+		{"not exists key upper", &options{prefix: []string{"prefix"}}, "false_PREFIX", false},
+		{"not exists key lower", &options{prefix: []string{"prefix"}}, "false_prefix", false},
+	}
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			exists := test.options.hasPrefix(test.key)
+			if test.exists != exists {
+				t.Errorf("key: '%sr', not exists prefixs: %v", test.key, test.options.prefix)
+			}
+		})
+	}
+}
diff --git a/options_test.go b/options_test.go
index 438de3d8..60600173 100644
--- a/options_test.go
+++ b/options_test.go
@@ -152,3 +152,39 @@ func TestStopTimeout(t *testing.T) {
 		t.Fatal("o.stopTimeout is not equal to v")
 	}
 }
+
+func TestBeforeStart(t *testing.T) {
+	o := &options{}
+	v := func(_ context.Context) error {
+		t.Log("BeforeStart...")
+		return nil
+	}
+	BeforeStart(v)(o)
+}
+
+func TestBeforeStop(t *testing.T) {
+	o := &options{}
+	v := func(_ context.Context) error {
+		t.Log("BeforeStop...")
+		return nil
+	}
+	BeforeStop(v)(o)
+}
+
+func TestAfterStart(t *testing.T) {
+	o := &options{}
+	v := func(_ context.Context) error {
+		t.Log("AfterStart...")
+		return nil
+	}
+	AfterStart(v)(o)
+}
+
+func TestAfterStop(t *testing.T) {
+	o := &options{}
+	v := func(_ context.Context) error {
+		t.Log("AfterStop...")
+		return nil
+	}
+	AfterStop(v)(o)
+}
diff --git a/selector/node/ewma/node_test.go b/selector/node/ewma/node_test.go
index feac09f2..d930495c 100644
--- a/selector/node/ewma/node_test.go
+++ b/selector/node/ewma/node_test.go
@@ -2,6 +2,7 @@ package ewma
 
 import (
 	"context"
+	"net"
 	"reflect"
 	"testing"
 	"time"
@@ -100,11 +101,15 @@ func TestDirectErrorHandler(t *testing.T) {
 			Endpoints: []string{"http://127.0.0.1:9090"},
 			Metadata:  map[string]string{"weight": "10"},
 		}))
-
+	errs := []error{
+		context.DeadlineExceeded,
+		context.Canceled,
+		net.ErrClosed,
+	}
 	for i := 0; i < 5; i++ {
 		var err error
 		if i != 0 {
-			err = context.DeadlineExceeded
+			err = errs[i%len(errs)]
 		}
 		done := wn.Pick()
 		if done == nil {
diff --git a/selector/p2c/p2c_test.go b/selector/p2c/p2c_test.go
index f23412b7..c8206361 100644
--- a/selector/p2c/p2c_test.go
+++ b/selector/p2c/p2c_test.go
@@ -70,7 +70,7 @@ func TestWrr3(t *testing.T) {
 		t.Errorf("count1(%v) >= int64(4500),", count1)
 	}
 	if count2 <= int64(1500) {
-		t.Errorf("count2(%v) <= int64(1500)", count1)
+		t.Errorf("count2(%v) <= int64(1500)", count2)
 	}
 	if count2 >= int64(4500) {
 		t.Errorf("count2(%v) >= int64(4500),", count2)
diff --git a/transport/http/binding/bind_test.go b/transport/http/binding/bind_test.go
index 20aadba7..6cd8b6d5 100644
--- a/transport/http/binding/bind_test.go
+++ b/transport/http/binding/bind_test.go
@@ -96,7 +96,7 @@ func TestBindForm(t *testing.T) {
 		{
 			name: "error not nil",
 			args: args{
-				req:    &http.Request{Method: "POST"},
+				req:    &http.Request{Method: http.MethodPost},
 				target: &p1,
 			},
 			wantErr: true,
@@ -106,7 +106,7 @@ func TestBindForm(t *testing.T) {
 			name: "error is nil",
 			args: args{
 				req: &http.Request{
-					Method: "POST",
+					Method: http.MethodPost,
 					Header: http.Header{"Content-Type": {"application/x-www-form-urlencoded; param=value"}},
 					Body:   io.NopCloser(strings.NewReader("name=kratos&url=https://go-kratos.dev/")),
 				},
@@ -119,7 +119,7 @@ func TestBindForm(t *testing.T) {
 			name: "error BadRequest",
 			args: args{
 				req: &http.Request{
-					Method: "POST",
+					Method: http.MethodPost,
 					Header: http.Header{"Content-Type": {"application/x-www-form-urlencoded; param=value"}},
 					Body:   io.NopCloser(strings.NewReader("age=a")),
 				},
diff --git a/transport/http/client_test.go b/transport/http/client_test.go
index ab8031dd..9a0dd782 100644
--- a/transport/http/client_test.go
+++ b/transport/http/client_test.go
@@ -9,6 +9,7 @@ import (
 	"fmt"
 	"io"
 	"log"
+	"net/http"
 	nethttp "net/http"
 	"reflect"
 	"strconv"
@@ -348,18 +349,18 @@ func TestNewClient(t *testing.T) {
 		t.Error(err)
 	}
 
-	err = client.Invoke(context.Background(), "POST", "/go", map[string]string{"name": "kratos"}, nil, EmptyCallOption{}, &mockCallOption{})
+	err = client.Invoke(context.Background(), http.MethodPost, "/go", map[string]string{"name": "kratos"}, nil, EmptyCallOption{}, &mockCallOption{})
 	if err == nil {
 		t.Error("err should not be equal to nil")
 	}
-	err = client.Invoke(context.Background(), "POST", "/go", map[string]string{"name": "kratos"}, nil, EmptyCallOption{}, &mockCallOption{needErr: true})
+	err = client.Invoke(context.Background(), http.MethodPost, "/go", map[string]string{"name": "kratos"}, nil, EmptyCallOption{}, &mockCallOption{needErr: true})
 	if err == nil {
 		t.Error("err should be equal to callOption err")
 	}
 	client.opts.encoder = func(ctx context.Context, contentType string, in interface{}) (body []byte, err error) {
 		return nil, errors.New("mock test encoder error")
 	}
-	err = client.Invoke(context.Background(), "POST", "/go", map[string]string{"name": "kratos"}, nil, EmptyCallOption{})
+	err = client.Invoke(context.Background(), http.MethodPost, "/go", map[string]string{"name": "kratos"}, nil, EmptyCallOption{})
 	if err == nil {
 		t.Error("err should be equal to encoder error")
 	}
diff --git a/transport/http/context_test.go b/transport/http/context_test.go
index b440e9df..6cae1b9a 100644
--- a/transport/http/context_test.go
+++ b/transport/http/context_test.go
@@ -12,9 +12,11 @@ import (
 	"time"
 )
 
+var testRouter = &Router{srv: NewServer()}
+
 func TestContextHeader(t *testing.T) {
 	w := wrapper{
-		router: nil,
+		router: testRouter,
 		req:    &http.Request{Header: map[string][]string{"name": {"kratos"}}},
 		res:    nil,
 		w:      responseWriter{},
@@ -27,8 +29,8 @@ func TestContextHeader(t *testing.T) {
 
 func TestContextForm(t *testing.T) {
 	w := wrapper{
-		router: nil,
-		req:    &http.Request{Header: map[string][]string{"name": {"kratos"}}, Method: "POST"},
+		router: testRouter,
+		req:    &http.Request{Header: map[string][]string{"name": {"kratos"}}, Method: http.MethodPost},
 		res:    nil,
 		w:      responseWriter{},
 	}
@@ -38,7 +40,7 @@ func TestContextForm(t *testing.T) {
 	}
 
 	w = wrapper{
-		router: nil,
+		router: testRouter,
 		req:    &http.Request{Form: map[string][]string{"name": {"kratos"}}},
 		res:    nil,
 		w:      responseWriter{},
@@ -51,8 +53,8 @@ func TestContextForm(t *testing.T) {
 
 func TestContextQuery(t *testing.T) {
 	w := wrapper{
-		router: nil,
-		req:    &http.Request{URL: &url.URL{Scheme: "https", Host: "github.com", Path: "go-kratos/kratos", RawQuery: "page=1"}, Method: "POST"},
+		router: testRouter,
+		req:    &http.Request{URL: &url.URL{Scheme: "https", Host: "github.com", Path: "go-kratos/kratos", RawQuery: "page=1"}, Method: http.MethodPost},
 		res:    nil,
 		w:      responseWriter{},
 	}
@@ -63,9 +65,9 @@ func TestContextQuery(t *testing.T) {
 }
 
 func TestContextRequest(t *testing.T) {
-	req := &http.Request{Method: "POST"}
+	req := &http.Request{Method: http.MethodPost}
 	w := wrapper{
-		router: nil,
+		router: testRouter,
 		req:    req,
 		res:    nil,
 		w:      responseWriter{},
@@ -80,7 +82,7 @@ func TestContextResponse(t *testing.T) {
 	res := httptest.NewRecorder()
 	w := wrapper{
 		router: &Router{srv: &Server{enc: DefaultResponseEncoder}},
-		req:    &http.Request{Method: "POST"},
+		req:    &http.Request{Method: http.MethodPost},
 		res:    res,
 		w:      responseWriter{200, res},
 	}
@@ -100,7 +102,7 @@ func TestContextResponse(t *testing.T) {
 
 func TestContextBindQuery(t *testing.T) {
 	w := wrapper{
-		router: nil,
+		router: testRouter,
 		req:    &http.Request{URL: &url.URL{Scheme: "https", Host: "go-kratos-dev", RawQuery: "page=2"}},
 		res:    nil,
 		w:      responseWriter{},
@@ -120,7 +122,7 @@ func TestContextBindQuery(t *testing.T) {
 
 func TestContextBindForm(t *testing.T) {
 	w := wrapper{
-		router: nil,
+		router: testRouter,
 		req:    &http.Request{URL: &url.URL{Scheme: "https", Host: "go-kratos-dev"}, Form: map[string][]string{"page": {"2"}}},
 		res:    nil,
 		w:      responseWriter{},
@@ -141,7 +143,7 @@ func TestContextBindForm(t *testing.T) {
 func TestContextResponseReturn(t *testing.T) {
 	writer := httptest.NewRecorder()
 	w := wrapper{
-		router: nil,
+		router: testRouter,
 		req:    nil,
 		res:    writer,
 		w:      responseWriter{},
@@ -171,10 +173,10 @@ func TestContextResponseReturn(t *testing.T) {
 func TestContextCtx(t *testing.T) {
 	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
 	defer cancel()
-	req := &http.Request{Method: "POST"}
+	req := &http.Request{Method: http.MethodPost}
 	req = req.WithContext(ctx)
 	w := wrapper{
-		router: &Router{srv: &Server{enc: DefaultResponseEncoder}},
+		router: testRouter,
 		req:    req,
 		res:    nil,
 		w:      responseWriter{},
diff --git a/transport/http/redirect_test.go b/transport/http/redirect_test.go
index b98bf4f0..879966a4 100644
--- a/transport/http/redirect_test.go
+++ b/transport/http/redirect_test.go
@@ -1,6 +1,7 @@
 package http
 
 import (
+	"net/http"
 	"net/http/httptest"
 	"testing"
 )
@@ -10,7 +11,7 @@ func TestRedirect(t *testing.T) {
 		redirectURL  = "/redirect"
 		redirectCode = 302
 	)
-	r := httptest.NewRequest("POST", "/test", nil)
+	r := httptest.NewRequest(http.MethodPost, "/test", nil)
 	w := httptest.NewRecorder()
 	_ = DefaultResponseEncoder(w, r, NewRedirect(redirectURL, redirectCode))
 
diff --git a/transport/http/router_test.go b/transport/http/router_test.go
index ad37831d..747ebf05 100644
--- a/transport/http/router_test.go
+++ b/transport/http/router_test.go
@@ -136,7 +136,7 @@ func testRoute(t *testing.T, srv *Server) {
 		t.Fatalf("got %s want bar", u.Name)
 	}
 	// PUT
-	req, _ := http.NewRequest("PUT", base+"/users", strings.NewReader(`{"name":"bar"}`))
+	req, _ := http.NewRequest(http.MethodPut, base+"/users", strings.NewReader(`{"name":"bar"}`))
 	req.Header.Set("Content-Type", appJSONStr)
 	resp, err = http.DefaultClient.Do(req)
 	if err != nil {
@@ -157,7 +157,7 @@ func testRoute(t *testing.T, srv *Server) {
 		t.Fatalf("got %s want bar", u.Name)
 	}
 	// OPTIONS
-	req, _ = http.NewRequest("OPTIONS", base+"/users", nil)
+	req, _ = http.NewRequest(http.MethodOptions, base+"/users", nil)
 	resp, err = http.DefaultClient.Do(req)
 	if err != nil {
 		t.Fatal(err)
@@ -166,7 +166,7 @@ func testRoute(t *testing.T, srv *Server) {
 	if resp.StatusCode != 200 {
 		t.Fatalf("code: %d", resp.StatusCode)
 	}
-	if resp.Header.Get("Access-Control-Allow-Methods") != "OPTIONS" {
+	if resp.Header.Get("Access-Control-Allow-Methods") != http.MethodOptions {
 		t.Fatal("cors failed")
 	}
 }
diff --git a/transport/http/server_test.go b/transport/http/server_test.go
index 0d4be88b..22865fc3 100644
--- a/transport/http/server_test.go
+++ b/transport/http/server_test.go
@@ -117,8 +117,8 @@ func testAccept(t *testing.T, srv *Server) {
 		path        string
 		contentType string
 	}{
-		{"GET", "/errors/cause", "application/json"},
-		{"GET", "/errors/cause", "application/proto"},
+		{http.MethodGet, "/errors/cause", "application/json"},
+		{http.MethodGet, "/errors/cause", "application/proto"},
 	}
 	e, err := srv.Endpoint()
 	if err != nil {
@@ -154,7 +154,7 @@ func testHeader(t *testing.T, srv *Server) {
 		t.Errorf("expected nil got %v", err)
 	}
 	reqURL := fmt.Sprintf(e.String() + "/index")
-	req, err := http.NewRequest("GET", reqURL, nil)
+	req, err := http.NewRequest(http.MethodGet, reqURL, nil)
 	if err != nil {
 		t.Errorf("expected nil got %v", err)
 	}
@@ -172,21 +172,21 @@ func testClient(t *testing.T, srv *Server) {
 		path   string
 		code   int
 	}{
-		{"GET", "/index", http.StatusOK},
-		{"PUT", "/index", http.StatusOK},
-		{"POST", "/index", http.StatusOK},
-		{"PATCH", "/index", http.StatusOK},
-		{"DELETE", "/index", http.StatusOK},
+		{http.MethodGet, "/index", http.StatusOK},
+		{http.MethodPut, "/index", http.StatusOK},
+		{http.MethodPost, "/index", http.StatusOK},
+		{http.MethodPatch, "/index", http.StatusOK},
+		{http.MethodDelete, "/index", http.StatusOK},
 
-		{"GET", "/index/1", http.StatusOK},
-		{"PUT", "/index/1", http.StatusOK},
-		{"POST", "/index/1", http.StatusOK},
-		{"PATCH", "/index/1", http.StatusOK},
-		{"DELETE", "/index/1", http.StatusOK},
+		{http.MethodGet, "/index/1", http.StatusOK},
+		{http.MethodPut, "/index/1", http.StatusOK},
+		{http.MethodPost, "/index/1", http.StatusOK},
+		{http.MethodPatch, "/index/1", http.StatusOK},
+		{http.MethodDelete, "/index/1", http.StatusOK},
 
-		{"GET", "/index/notfound", http.StatusNotFound},
-		{"GET", "/errors/cause", http.StatusBadRequest},
-		{"GET", "/test/prefix/123111", http.StatusOK},
+		{http.MethodGet, "/index/notfound", http.StatusNotFound},
+		{http.MethodGet, "/errors/cause", http.StatusBadRequest},
+		{http.MethodGet, "/test/prefix/123111", http.StatusOK},
 	}
 	e, err := srv.Endpoint()
 	if err != nil {
@@ -273,7 +273,7 @@ func BenchmarkServer(b *testing.B) {
 	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
 		var res testData
-		err := client.Invoke(context.Background(), "POST", "/index", nil, &res)
+		err := client.Invoke(context.Background(), http.MethodPost, "/index", nil, &res)
 		if err != nil {
 			b.Errorf("expected nil got %v", err)
 		}
@@ -316,8 +316,8 @@ func TestRequestDecoder(t *testing.T) {
 	o := &Server{}
 	v := func(*http.Request, interface{}) error { return nil }
 	RequestDecoder(v)(o)
-	if o.dec == nil {
-		t.Errorf("expected nil got %v", o.dec)
+	if o.decBody == nil {
+		t.Errorf("expected nil got %v", o.decBody)
 	}
 }