Repository: go-kratos/kratos
Pull request #1485 (2021-09-15 14:59:20)

feat: add selector and filters examples
feat: add selector and filters examples

codecov-commenter: # [Codecov](https://codecov.io/gh/go-kratos/kratos/pull/1485?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos) Report
> Merging [#1485](https://codecov.io/gh/go-kratos/kratos/pull/1485?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos) (ff9369d) into [main](https://codecov.io/gh/go-kratos/kratos/commit/53563ab498cc157d74e2178f89c613fd9c4ac74c?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos) (53563ab) will **decrease** coverage by `0.76%`.
> The diff coverage is `38.09%`.

> :exclamation: Current head ff9369d differs from pull request most recent head f56fcea. Consider uploading reports for the commit f56fcea to get more accurate results
[![Impacted file tree graph](https://codecov.io/gh/go-kratos/kratos/pull/1485/graphs/tree.svg?width=650&height=150&src=pr&token=XwnmBTz78x&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos)](https://codecov.io/gh/go-kratos/kratos/pull/1485?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos)

```diff
@@            Coverage Diff             @@
##             main    #1485      +/-   ##
==========================================
- Coverage   66.65%   65.89%   -0.77%     
==========================================
  Files          66       67       +1     
  Lines        3038     3099      +61     
==========================================
+ Hits         2025     2042      +17     
- Misses        841      885      +44     
  Partials      172      172              
```


| [Impacted Files](https://codecov.io/gh/go-kratos/kratos/pull/1485?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos) | Coverage Δ | |
|---|---|---|
| [transport/grpc/transport.go](https://codecov.io/gh/go-kratos/kratos/pull/1485/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos#diff-dHJhbnNwb3J0L2dycGMvdHJhbnNwb3J0Lmdv) | `91.66% <0.00%> (-8.34%)` | :arrow_down: |
| [transport/grpc/balancer.go](https://codecov.io/gh/go-kratos/kratos/pull/1485/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos#diff-dHJhbnNwb3J0L2dycGMvYmFsYW5jZXIuZ28=) | `25.49% <16.66%> (ø)` | |
| [transport/grpc/client.go](https://codecov.io/gh/go-kratos/kratos/pull/1485/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos#diff-dHJhbnNwb3J0L2dycGMvY2xpZW50Lmdv) | `76.92% <50.00%> (-5.94%)` | :arrow_down: |
| [transport/http/client.go](https://codecov.io/gh/go-kratos/kratos/pull/1485/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos#diff-dHJhbnNwb3J0L2h0dHAvY2xpZW50Lmdv) | `66.11% <100.00%> (ø)` | |
| [internal/context/context.go](https://codecov.io/gh/go-kratos/kratos/pull/1485/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos#diff-aW50ZXJuYWwvY29udGV4dC9jb250ZXh0Lmdv) | `100.00% <0.00%> (+2.98%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/go-kratos/kratos/pull/1485?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/go-kratos/kratos/pull/1485?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos). Last update [53563ab...f56fcea](https://codecov.io/gh/go-kratos/kratos/pull/1485?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos).


Patch:
diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml
index 0e5e2684..ae4f7da6 100644
--- a/.github/workflows/go.yml
+++ b/.github/workflows/go.yml
@@ -32,7 +32,7 @@ jobs:
       - name: Set up Go
         uses: actions/setup-go@v2
         with:
-          go-version: 1.16
+          go-version: 1.17
 
       - name: Build
         run: go build ./...
diff --git a/app.go b/app.go
index 10a43dbc..2a11f845 100644
--- a/app.go
+++ b/app.go
@@ -116,7 +116,7 @@ func (a *App) Run() error {
 			case <-c:
 				err := a.Stop()
 				if err != nil {
-					a.opts.logger.Errorf("failed to app stop: %v", err)
+					a.opts.logger.Errorf("failed to stop app: %v", err)
 				}
 			}
 		}
diff --git a/contrib/config/apollo/go.sum b/contrib/config/apollo/go.sum
index ce82d2a9..8c689ca0 100644
--- a/contrib/config/apollo/go.sum
+++ b/contrib/config/apollo/go.sum
@@ -228,9 +228,9 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
 go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
 go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
 go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
-go.opentelemetry.io/otel v1.0.0-RC3/go.mod h1:Ka5j3ua8tZs4Rkq4Ex3hwgBgOchyPVq5S6P2lz//nKQ=
-go.opentelemetry.io/otel/sdk v1.0.0-RC3/go.mod h1:78H6hyg2fka0NYT9fqGuFLvly2yCxiBXDJAgLKo/2Us=
-go.opentelemetry.io/otel/trace v1.0.0-RC3/go.mod h1:VUt2TUYd8S2/ZRX09ZDFZQwn2RqfMB5MzO17jBojGxo=
+go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg=
+go.opentelemetry.io/otel/sdk v1.0.0/go.mod h1:PCrDHlSy5x1kjezSdL37PhbFUMjrsLRshJ2zCzeXwbM=
+go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs=
 go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
 go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
diff --git a/contrib/config/etcd/go.sum b/contrib/config/etcd/go.sum
index cb51fdbf..15ea82d7 100644
--- a/contrib/config/etcd/go.sum
+++ b/contrib/config/etcd/go.sum
@@ -155,9 +155,9 @@ go.etcd.io/etcd/client/pkg/v3 v3.5.0 h1:2aQv6F436YnN7I4VbI8PPYrBhu+SmrTaADcf8Mi/
 go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
 go.etcd.io/etcd/client/v3 v3.5.0 h1:62Eh0XOro+rDwkrypAGDfgmNh5Joq+z+W9HZdlXMzek=
 go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0=
-go.opentelemetry.io/otel v1.0.0-RC3/go.mod h1:Ka5j3ua8tZs4Rkq4Ex3hwgBgOchyPVq5S6P2lz//nKQ=
-go.opentelemetry.io/otel/sdk v1.0.0-RC3/go.mod h1:78H6hyg2fka0NYT9fqGuFLvly2yCxiBXDJAgLKo/2Us=
-go.opentelemetry.io/otel/trace v1.0.0-RC3/go.mod h1:VUt2TUYd8S2/ZRX09ZDFZQwn2RqfMB5MzO17jBojGxo=
+go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg=
+go.opentelemetry.io/otel/sdk v1.0.0/go.mod h1:PCrDHlSy5x1kjezSdL37PhbFUMjrsLRshJ2zCzeXwbM=
+go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs=
 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=
diff --git a/contrib/config/kubernetes/go.sum b/contrib/config/kubernetes/go.sum
index 8f86af0a..6380942a 100644
--- a/contrib/config/kubernetes/go.sum
+++ b/contrib/config/kubernetes/go.sum
@@ -208,9 +208,9 @@ go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
 go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
 go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
 go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
-go.opentelemetry.io/otel v1.0.0-RC3/go.mod h1:Ka5j3ua8tZs4Rkq4Ex3hwgBgOchyPVq5S6P2lz//nKQ=
-go.opentelemetry.io/otel/sdk v1.0.0-RC3/go.mod h1:78H6hyg2fka0NYT9fqGuFLvly2yCxiBXDJAgLKo/2Us=
-go.opentelemetry.io/otel/trace v1.0.0-RC3/go.mod h1:VUt2TUYd8S2/ZRX09ZDFZQwn2RqfMB5MzO17jBojGxo=
+go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg=
+go.opentelemetry.io/otel/sdk v1.0.0/go.mod h1:PCrDHlSy5x1kjezSdL37PhbFUMjrsLRshJ2zCzeXwbM=
+go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs=
 go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
 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=
diff --git a/contrib/config/nacos/go.sum b/contrib/config/nacos/go.sum
index 16fcff98..6c4d253f 100644
--- a/contrib/config/nacos/go.sum
+++ b/contrib/config/nacos/go.sum
@@ -121,9 +121,9 @@ github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ
 github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8=
 github.com/toolkits/concurrent v0.0.0-20150624120057-a4371d70e3e3/go.mod h1:QDlpd3qS71vYtakd2hmdpqhJ9nwv6mD6A30bQ1BPBFE=
 github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
-go.opentelemetry.io/otel v1.0.0-RC3/go.mod h1:Ka5j3ua8tZs4Rkq4Ex3hwgBgOchyPVq5S6P2lz//nKQ=
-go.opentelemetry.io/otel/sdk v1.0.0-RC3/go.mod h1:78H6hyg2fka0NYT9fqGuFLvly2yCxiBXDJAgLKo/2Us=
-go.opentelemetry.io/otel/trace v1.0.0-RC3/go.mod h1:VUt2TUYd8S2/ZRX09ZDFZQwn2RqfMB5MzO17jBojGxo=
+go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg=
+go.opentelemetry.io/otel/sdk v1.0.0/go.mod h1:PCrDHlSy5x1kjezSdL37PhbFUMjrsLRshJ2zCzeXwbM=
+go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs=
 go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
 go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk=
 go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
diff --git a/contrib/log/fluent/go.sum b/contrib/log/fluent/go.sum
index 2c06201d..f9a2fbed 100644
--- a/contrib/log/fluent/go.sum
+++ b/contrib/log/fluent/go.sum
@@ -74,9 +74,9 @@ github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcy
 github.com/ttacon/chalk v0.0.0-20160626202418-22c06c80ed31/go.mod h1:onvgF043R+lC5RZ8IT9rBXDaEDnpnw/Cl+HFiw+v/7Q=
 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.opentelemetry.io/otel v1.0.0-RC3/go.mod h1:Ka5j3ua8tZs4Rkq4Ex3hwgBgOchyPVq5S6P2lz//nKQ=
-go.opentelemetry.io/otel/sdk v1.0.0-RC3/go.mod h1:78H6hyg2fka0NYT9fqGuFLvly2yCxiBXDJAgLKo/2Us=
-go.opentelemetry.io/otel/trace v1.0.0-RC3/go.mod h1:VUt2TUYd8S2/ZRX09ZDFZQwn2RqfMB5MzO17jBojGxo=
+go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg=
+go.opentelemetry.io/otel/sdk v1.0.0/go.mod h1:PCrDHlSy5x1kjezSdL37PhbFUMjrsLRshJ2zCzeXwbM=
+go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs=
 go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
diff --git a/contrib/log/zap/go.sum b/contrib/log/zap/go.sum
index 1e9c2864..2dacc46d 100644
--- a/contrib/log/zap/go.sum
+++ b/contrib/log/zap/go.sum
@@ -74,9 +74,9 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
 github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs=
 github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8=
 github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
-go.opentelemetry.io/otel v1.0.0-RC3/go.mod h1:Ka5j3ua8tZs4Rkq4Ex3hwgBgOchyPVq5S6P2lz//nKQ=
-go.opentelemetry.io/otel/sdk v1.0.0-RC3/go.mod h1:78H6hyg2fka0NYT9fqGuFLvly2yCxiBXDJAgLKo/2Us=
-go.opentelemetry.io/otel/trace v1.0.0-RC3/go.mod h1:VUt2TUYd8S2/ZRX09ZDFZQwn2RqfMB5MzO17jBojGxo=
+go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg=
+go.opentelemetry.io/otel/sdk v1.0.0/go.mod h1:PCrDHlSy5x1kjezSdL37PhbFUMjrsLRshJ2zCzeXwbM=
+go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs=
 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=
diff --git a/contrib/metrics/datadog/go.sum b/contrib/metrics/datadog/go.sum
index 43aa9496..9aaa5cbc 100644
--- a/contrib/metrics/datadog/go.sum
+++ b/contrib/metrics/datadog/go.sum
@@ -71,9 +71,9 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
 github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs=
 github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8=
 github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
-go.opentelemetry.io/otel v1.0.0-RC3/go.mod h1:Ka5j3ua8tZs4Rkq4Ex3hwgBgOchyPVq5S6P2lz//nKQ=
-go.opentelemetry.io/otel/sdk v1.0.0-RC3/go.mod h1:78H6hyg2fka0NYT9fqGuFLvly2yCxiBXDJAgLKo/2Us=
-go.opentelemetry.io/otel/trace v1.0.0-RC3/go.mod h1:VUt2TUYd8S2/ZRX09ZDFZQwn2RqfMB5MzO17jBojGxo=
+go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg=
+go.opentelemetry.io/otel/sdk v1.0.0/go.mod h1:PCrDHlSy5x1kjezSdL37PhbFUMjrsLRshJ2zCzeXwbM=
+go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs=
 go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
diff --git a/contrib/metrics/prometheus/go.sum b/contrib/metrics/prometheus/go.sum
index 9fb7ab9b..1198ff71 100644
--- a/contrib/metrics/prometheus/go.sum
+++ b/contrib/metrics/prometheus/go.sum
@@ -295,9 +295,9 @@ go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mI
 go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
 go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
 go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
-go.opentelemetry.io/otel v1.0.0-RC3/go.mod h1:Ka5j3ua8tZs4Rkq4Ex3hwgBgOchyPVq5S6P2lz//nKQ=
-go.opentelemetry.io/otel/sdk v1.0.0-RC3/go.mod h1:78H6hyg2fka0NYT9fqGuFLvly2yCxiBXDJAgLKo/2Us=
-go.opentelemetry.io/otel/trace v1.0.0-RC3/go.mod h1:VUt2TUYd8S2/ZRX09ZDFZQwn2RqfMB5MzO17jBojGxo=
+go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg=
+go.opentelemetry.io/otel/sdk v1.0.0/go.mod h1:PCrDHlSy5x1kjezSdL37PhbFUMjrsLRshJ2zCzeXwbM=
+go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs=
 go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
 go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
diff --git a/contrib/registry/consul/go.sum b/contrib/registry/consul/go.sum
index 6ab46362..9a37e7b2 100644
--- a/contrib/registry/consul/go.sum
+++ b/contrib/registry/consul/go.sum
@@ -145,9 +145,9 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
 github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs=
 github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8=
 github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
-go.opentelemetry.io/otel v1.0.0-RC3/go.mod h1:Ka5j3ua8tZs4Rkq4Ex3hwgBgOchyPVq5S6P2lz//nKQ=
-go.opentelemetry.io/otel/sdk v1.0.0-RC3/go.mod h1:78H6hyg2fka0NYT9fqGuFLvly2yCxiBXDJAgLKo/2Us=
-go.opentelemetry.io/otel/trace v1.0.0-RC3/go.mod h1:VUt2TUYd8S2/ZRX09ZDFZQwn2RqfMB5MzO17jBojGxo=
+go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg=
+go.opentelemetry.io/otel/sdk v1.0.0/go.mod h1:PCrDHlSy5x1kjezSdL37PhbFUMjrsLRshJ2zCzeXwbM=
+go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs=
 go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
 golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
diff --git a/contrib/registry/etcd/go.sum b/contrib/registry/etcd/go.sum
index d116c083..4fca9338 100644
--- a/contrib/registry/etcd/go.sum
+++ b/contrib/registry/etcd/go.sum
@@ -154,9 +154,9 @@ go.etcd.io/etcd/client/pkg/v3 v3.5.0 h1:2aQv6F436YnN7I4VbI8PPYrBhu+SmrTaADcf8Mi/
 go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
 go.etcd.io/etcd/client/v3 v3.5.0 h1:62Eh0XOro+rDwkrypAGDfgmNh5Joq+z+W9HZdlXMzek=
 go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0=
-go.opentelemetry.io/otel v1.0.0-RC3/go.mod h1:Ka5j3ua8tZs4Rkq4Ex3hwgBgOchyPVq5S6P2lz//nKQ=
-go.opentelemetry.io/otel/sdk v1.0.0-RC3/go.mod h1:78H6hyg2fka0NYT9fqGuFLvly2yCxiBXDJAgLKo/2Us=
-go.opentelemetry.io/otel/trace v1.0.0-RC3/go.mod h1:VUt2TUYd8S2/ZRX09ZDFZQwn2RqfMB5MzO17jBojGxo=
+go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg=
+go.opentelemetry.io/otel/sdk v1.0.0/go.mod h1:PCrDHlSy5x1kjezSdL37PhbFUMjrsLRshJ2zCzeXwbM=
+go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs=
 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=
diff --git a/contrib/registry/kubernetes/go.sum b/contrib/registry/kubernetes/go.sum
index 90796a19..daec28e0 100644
--- a/contrib/registry/kubernetes/go.sum
+++ b/contrib/registry/kubernetes/go.sum
@@ -208,9 +208,9 @@ go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
 go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
 go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
 go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
-go.opentelemetry.io/otel v1.0.0-RC3/go.mod h1:Ka5j3ua8tZs4Rkq4Ex3hwgBgOchyPVq5S6P2lz//nKQ=
-go.opentelemetry.io/otel/sdk v1.0.0-RC3/go.mod h1:78H6hyg2fka0NYT9fqGuFLvly2yCxiBXDJAgLKo/2Us=
-go.opentelemetry.io/otel/trace v1.0.0-RC3/go.mod h1:VUt2TUYd8S2/ZRX09ZDFZQwn2RqfMB5MzO17jBojGxo=
+go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg=
+go.opentelemetry.io/otel/sdk v1.0.0/go.mod h1:PCrDHlSy5x1kjezSdL37PhbFUMjrsLRshJ2zCzeXwbM=
+go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs=
 go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
 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=
diff --git a/contrib/registry/nacos/go.sum b/contrib/registry/nacos/go.sum
index 73a543be..ad8e5810 100644
--- a/contrib/registry/nacos/go.sum
+++ b/contrib/registry/nacos/go.sum
@@ -112,9 +112,9 @@ github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcy
 github.com/toolkits/concurrent v0.0.0-20150624120057-a4371d70e3e3 h1:kF/7m/ZU+0D4Jj5eZ41Zm3IH/J8OElK1Qtd7tVKAwLk=
 github.com/toolkits/concurrent v0.0.0-20150624120057-a4371d70e3e3/go.mod h1:QDlpd3qS71vYtakd2hmdpqhJ9nwv6mD6A30bQ1BPBFE=
 github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
-go.opentelemetry.io/otel v1.0.0-RC3/go.mod h1:Ka5j3ua8tZs4Rkq4Ex3hwgBgOchyPVq5S6P2lz//nKQ=
-go.opentelemetry.io/otel/sdk v1.0.0-RC3/go.mod h1:78H6hyg2fka0NYT9fqGuFLvly2yCxiBXDJAgLKo/2Us=
-go.opentelemetry.io/otel/trace v1.0.0-RC3/go.mod h1:VUt2TUYd8S2/ZRX09ZDFZQwn2RqfMB5MzO17jBojGxo=
+go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg=
+go.opentelemetry.io/otel/sdk v1.0.0/go.mod h1:PCrDHlSy5x1kjezSdL37PhbFUMjrsLRshJ2zCzeXwbM=
+go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs=
 go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
 go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk=
 go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
diff --git a/contrib/registry/zookeeper/go.sum b/contrib/registry/zookeeper/go.sum
index 16cfd778..c351f5ce 100644
--- a/contrib/registry/zookeeper/go.sum
+++ b/contrib/registry/zookeeper/go.sum
@@ -61,9 +61,9 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
 github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs=
 github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8=
 github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
-go.opentelemetry.io/otel v1.0.0-RC3/go.mod h1:Ka5j3ua8tZs4Rkq4Ex3hwgBgOchyPVq5S6P2lz//nKQ=
-go.opentelemetry.io/otel/sdk v1.0.0-RC3/go.mod h1:78H6hyg2fka0NYT9fqGuFLvly2yCxiBXDJAgLKo/2Us=
-go.opentelemetry.io/otel/trace v1.0.0-RC3/go.mod h1:VUt2TUYd8S2/ZRX09ZDFZQwn2RqfMB5MzO17jBojGxo=
+go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg=
+go.opentelemetry.io/otel/sdk v1.0.0/go.mod h1:PCrDHlSy5x1kjezSdL37PhbFUMjrsLRshJ2zCzeXwbM=
+go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs=
 go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
diff --git a/examples/go.mod b/examples/go.mod
index c06bd991..fdabf685 100644
--- a/examples/go.mod
+++ b/examples/go.mod
@@ -34,10 +34,10 @@ require (
 	github.com/sirupsen/logrus v1.8.1
 	github.com/stretchr/testify v1.7.0
 	go.etcd.io/etcd/client/v3 v3.5.0
-	go.opentelemetry.io/otel v1.0.0-RC3
-	go.opentelemetry.io/otel/exporters/jaeger v1.0.0-RC3
-	go.opentelemetry.io/otel/sdk v1.0.0-RC3
-	go.opentelemetry.io/otel/trace v1.0.0-RC3
+	go.opentelemetry.io/otel v1.0.0
+	go.opentelemetry.io/otel/exporters/jaeger v1.0.0
+	go.opentelemetry.io/otel/sdk v1.0.0
+	go.opentelemetry.io/otel/trace v1.0.0
 	go.uber.org/zap v1.19.0
 	golang.org/x/text v0.3.7
 	google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2
diff --git a/examples/go.sum b/examples/go.sum
index 9f08ce86..d8065206 100644
--- a/examples/go.sum
+++ b/examples/go.sum
@@ -669,17 +669,17 @@ go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
 go.opentelemetry.io/otel v0.13.0/go.mod h1:dlSNewoRYikTkotEnxdmuBHgzT+k/idJSfDv/FxEnOY=
 go.opentelemetry.io/otel v0.16.0/go.mod h1:e4GKElweB8W2gWUqbghw0B8t5MCTccc9212eNHnOHwA=
 go.opentelemetry.io/otel v0.17.0/go.mod h1:Oqtdxmf7UtEvL037ohlgnaYa1h7GtMh0NcSd9eqkC9s=
-go.opentelemetry.io/otel v1.0.0-RC3 h1:kvwiyEkiUT/JaadXzVLI/R1wDO934A7r3Bs2wEe6wqA=
-go.opentelemetry.io/otel v1.0.0-RC3/go.mod h1:Ka5j3ua8tZs4Rkq4Ex3hwgBgOchyPVq5S6P2lz//nKQ=
-go.opentelemetry.io/otel/exporters/jaeger v1.0.0-RC3 h1:pKXuRvOc+5NgM0vv05PVIUetreuM57mcC6QQAKkcqZA=
-go.opentelemetry.io/otel/exporters/jaeger v1.0.0-RC3/go.mod h1:UbP19Xlhk9tcRZ+A3PfvyN5ld4X4YrSnzXaYzx1yNLc=
+go.opentelemetry.io/otel v1.0.0 h1:qTTn6x71GVBvoafHK/yaRUmFzI4LcONZD0/kXxl5PHI=
+go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg=
+go.opentelemetry.io/otel/exporters/jaeger v1.0.0 h1:cLhx8llHw02h5JTqGqaRbYn+QVKHmrzD9vEbKnSPk5U=
+go.opentelemetry.io/otel/exporters/jaeger v1.0.0/go.mod h1:q10N1AolE1JjqKrFJK2tYw0iZpmX+HBaXBtuCzRnBGQ=
 go.opentelemetry.io/otel/metric v0.17.0/go.mod h1:hUz9lH1rNXyEwWAhIWCMFWKhYtpASgSnObJFnU26dJ0=
 go.opentelemetry.io/otel/oteltest v0.17.0/go.mod h1:JT/LGFxPwpN+nlsTiinSYjdIx3hZIGqHCpChcIZmdoE=
-go.opentelemetry.io/otel/sdk v1.0.0-RC3 h1:iRMkET+EmJUn5mW0hJzygBraXRmrUwzbOtNvTCh/oKs=
-go.opentelemetry.io/otel/sdk v1.0.0-RC3/go.mod h1:78H6hyg2fka0NYT9fqGuFLvly2yCxiBXDJAgLKo/2Us=
+go.opentelemetry.io/otel/sdk v1.0.0 h1:BNPMYUONPNbLneMttKSjQhOTlFLOD9U22HNG1KrIN2Y=
+go.opentelemetry.io/otel/sdk v1.0.0/go.mod h1:PCrDHlSy5x1kjezSdL37PhbFUMjrsLRshJ2zCzeXwbM=
 go.opentelemetry.io/otel/trace v0.17.0/go.mod h1:bIujpqg6ZL6xUTubIUgziI1jSaUPthmabA/ygf/6Cfg=
-go.opentelemetry.io/otel/trace v1.0.0-RC3 h1:9F0ayEvlxv8BmNmPbU005WK7hC+7KbOazCPZjNa1yME=
-go.opentelemetry.io/otel/trace v1.0.0-RC3/go.mod h1:VUt2TUYd8S2/ZRX09ZDFZQwn2RqfMB5MzO17jBojGxo=
+go.opentelemetry.io/otel/trace v1.0.0 h1:TSBr8GTEtKevYMG/2d21M989r5WJYVimhTHBKVEZuh4=
+go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs=
 go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
 go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
diff --git a/examples/selector/client/main.go b/examples/selector/client/main.go
new file mode 100644
index 00000000..3641c632
--- /dev/null
+++ b/examples/selector/client/main.go
@@ -0,0 +1,82 @@
+package main
+
+import (
+	"context"
+	"log"
+	"time"
+
+	"github.com/go-kratos/kratos/contrib/registry/consul/v2"
+	"github.com/go-kratos/kratos/examples/helloworld/helloworld"
+	"github.com/go-kratos/kratos/v2/middleware/recovery"
+	"github.com/go-kratos/kratos/v2/selector/filter"
+	"github.com/go-kratos/kratos/v2/selector/p2c"
+	"github.com/go-kratos/kratos/v2/selector/wrr"
+	"github.com/go-kratos/kratos/v2/transport/grpc"
+	"github.com/go-kratos/kratos/v2/transport/http"
+	"github.com/hashicorp/consul/api"
+)
+
+func main() {
+	consulCli, err := api.NewClient(api.DefaultConfig())
+	if err != nil {
+		panic(err)
+	}
+	r := consul.New(consulCli)
+
+	// new grpc client
+	conn, err := grpc.DialInsecure(
+		context.Background(),
+		grpc.WithEndpoint("discovery:///helloworld"),
+		grpc.WithDiscovery(r),
+		// 由于gRPC框架的限制只能使用全局balancer+filter的方式来实现selector
+		// 这里使用weighted round robin算法的balancer+静态version=1.0.0的Filter
+		grpc.WithBalancerName(wrr.Name),
+		grpc.WithSelectFilter(filter.Version("1.0.0")),
+	)
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer conn.Close()
+	gClient := helloworld.NewGreeterClient(conn)
+
+	// new http client
+	hConn, err := http.NewClient(
+		context.Background(),
+		http.WithMiddleware(
+			recovery.Recovery(),
+		),
+		http.WithEndpoint("discovery:///helloworld"),
+		http.WithDiscovery(r),
+		// 这里使用p2c算法的balancer+静态version=2.0.0的Filter组成一个selector
+		http.WithSelector(
+			p2c.New(p2c.WithFilter(filter.Version("2.0.0"))),
+		),
+	)
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer hConn.Close()
+	hClient := helloworld.NewGreeterHTTPClient(hConn)
+
+	for {
+		time.Sleep(time.Second)
+		callGRPC(gClient)
+		callHTTP(hClient)
+	}
+}
+
+func callGRPC(client helloworld.GreeterClient) {
+	reply, err := client.SayHello(context.Background(), &helloworld.HelloRequest{Name: "kratos"})
+	if err != nil {
+		log.Fatal(err)
+	}
+	log.Printf("[grpc] SayHello %+v\n", reply)
+}
+
+func callHTTP(client helloworld.GreeterHTTPClient) {
+	reply, err := client.SayHello(context.Background(), &helloworld.HelloRequest{Name: "kratos"})
+	if err != nil {
+		log.Fatal(err)
+	}
+	log.Printf("[http] SayHello %s\n", reply.Message)
+}
diff --git a/examples/selector/server/main.go b/examples/selector/server/main.go
new file mode 100644
index 00000000..247bdc4c
--- /dev/null
+++ b/examples/selector/server/main.go
@@ -0,0 +1,79 @@
+package main
+
+import (
+	"context"
+	"fmt"
+	"os"
+
+	"github.com/go-kratos/kratos/contrib/registry/consul/v2"
+	"github.com/go-kratos/kratos/examples/helloworld/helloworld"
+	"github.com/go-kratos/kratos/v2"
+	"github.com/go-kratos/kratos/v2/log"
+	"github.com/go-kratos/kratos/v2/middleware/logging"
+	"github.com/go-kratos/kratos/v2/middleware/recovery"
+	"github.com/go-kratos/kratos/v2/transport/grpc"
+	"github.com/go-kratos/kratos/v2/transport/http"
+	"github.com/hashicorp/consul/api"
+)
+
+// server is used to implement helloworld.GreeterServer.
+type server struct {
+	helloworld.UnimplementedGreeterServer
+}
+
+// SayHello implements helloworld.GreeterServer
+func (s *server) SayHello(ctx context.Context, in *helloworld.HelloRequest) (*helloworld.HelloReply, error) {
+	return &helloworld.HelloReply{Message: fmt.Sprintf("Welcome %+v!", in.Name)}, nil
+}
+
+func main() {
+	logger := log.NewStdLogger(os.Stdout)
+
+	consulClient, err := api.NewClient(api.DefaultConfig())
+	if err != nil {
+		log.NewHelper(logger).Fatal(err)
+	}
+	go runServer("1.0.0", logger, consulClient, 8000)
+	go runServer("1.0.0", logger, consulClient, 8010)
+
+	runServer("2.0.0", logger, consulClient, 8020)
+}
+
+func runServer(version string, logger log.Logger, client *api.Client, port int) {
+	logger = log.With(logger, "version", version, "port:", port)
+	log := log.NewHelper(logger)
+
+	httpSrv := http.NewServer(
+		http.Address(fmt.Sprintf(":%d", port)),
+		http.Middleware(
+			recovery.Recovery(),
+			logging.Server(logger),
+		),
+	)
+	grpcSrv := grpc.NewServer(
+		grpc.Address(fmt.Sprintf(":%d", port+1000)),
+		grpc.Middleware(
+			recovery.Recovery(),
+			logging.Server(logger),
+		),
+	)
+
+	s := &server{}
+	helloworld.RegisterGreeterServer(grpcSrv, s)
+	helloworld.RegisterGreeterHTTPServer(httpSrv, s)
+
+	r := consul.New(client)
+	app := kratos.New(
+		kratos.Name("helloworld"),
+		kratos.Server(
+			grpcSrv,
+			httpSrv,
+		),
+		kratos.Version(version),
+		kratos.Registrar(r),
+	)
+
+	if err := app.Run(); err != nil {
+		log.Fatal(err)
+	}
+}
diff --git a/go.mod b/go.mod
index 758f2f8e..2be0b165 100644
--- a/go.mod
+++ b/go.mod
@@ -11,9 +11,9 @@ require (
 	github.com/gorilla/mux v1.8.0
 	github.com/imdario/mergo v0.3.12
 	github.com/stretchr/testify v1.7.0
-	go.opentelemetry.io/otel v1.0.0-RC3
-	go.opentelemetry.io/otel/sdk v1.0.0-RC3
-	go.opentelemetry.io/otel/trace v1.0.0-RC3
+	go.opentelemetry.io/otel v1.0.0
+	go.opentelemetry.io/otel/sdk v1.0.0
+	go.opentelemetry.io/otel/trace v1.0.0
 	golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
 	google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67
 	google.golang.org/grpc v1.39.1
diff --git a/go.sum b/go.sum
index 54ec3788..51155df6 100644
--- a/go.sum
+++ b/go.sum
@@ -77,12 +77,12 @@ github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ
 github.com/tklauser/numcpus v0.3.0 h1:ILuRUQBtssgnxw0XXIjKUC56fgnOrFoQQ/4+DeU2biQ=
 github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8=
 github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
-go.opentelemetry.io/otel v1.0.0-RC3 h1:kvwiyEkiUT/JaadXzVLI/R1wDO934A7r3Bs2wEe6wqA=
-go.opentelemetry.io/otel v1.0.0-RC3/go.mod h1:Ka5j3ua8tZs4Rkq4Ex3hwgBgOchyPVq5S6P2lz//nKQ=
-go.opentelemetry.io/otel/sdk v1.0.0-RC3 h1:iRMkET+EmJUn5mW0hJzygBraXRmrUwzbOtNvTCh/oKs=
-go.opentelemetry.io/otel/sdk v1.0.0-RC3/go.mod h1:78H6hyg2fka0NYT9fqGuFLvly2yCxiBXDJAgLKo/2Us=
-go.opentelemetry.io/otel/trace v1.0.0-RC3 h1:9F0ayEvlxv8BmNmPbU005WK7hC+7KbOazCPZjNa1yME=
-go.opentelemetry.io/otel/trace v1.0.0-RC3/go.mod h1:VUt2TUYd8S2/ZRX09ZDFZQwn2RqfMB5MzO17jBojGxo=
+go.opentelemetry.io/otel v1.0.0 h1:qTTn6x71GVBvoafHK/yaRUmFzI4LcONZD0/kXxl5PHI=
+go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg=
+go.opentelemetry.io/otel/sdk v1.0.0 h1:BNPMYUONPNbLneMttKSjQhOTlFLOD9U22HNG1KrIN2Y=
+go.opentelemetry.io/otel/sdk v1.0.0/go.mod h1:PCrDHlSy5x1kjezSdL37PhbFUMjrsLRshJ2zCzeXwbM=
+go.opentelemetry.io/otel/trace v1.0.0 h1:TSBr8GTEtKevYMG/2d21M989r5WJYVimhTHBKVEZuh4=
+go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs=
 go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
diff --git a/log/README.md b/log/README.md
index 3d785e33..8f4f70e1 100644
--- a/log/README.md
+++ b/log/README.md
@@ -24,7 +24,7 @@ helper.Infow("key", "value")
 
 // filter
 log := log.NewHelper(log.NewFilter(logger,
-	log.FilterLevel(LevelInfo),
+	log.FilterLevel(log.LevelInfo),
 	log.FilterKey("foo"),
 	log.FilterValue("bar"),
 	log.FilterFunc(customFilter),
diff --git a/selector/default.go b/selector/default.go
index 63a19bb4..25698e71 100644
--- a/selector/default.go
+++ b/selector/default.go
@@ -9,6 +9,7 @@ import (
 type Default struct {
 	NodeBuilder WeightedNodeBuilder
 	Balancer    Balancer
+	Filters     []Filter
 
 	lk            sync.RWMutex
 	weightedNodes []Node
@@ -19,6 +20,10 @@ func (d *Default) Select(ctx context.Context, opts ...SelectOption) (selected No
 	d.lk.RLock()
 	weightedNodes := d.weightedNodes
 	d.lk.RUnlock()
+
+	for _, f := range d.Filters {
+		weightedNodes = f(ctx, weightedNodes)
+	}
 	var options SelectOptions
 	for _, o := range opts {
 		o(&options)
diff --git a/selector/p2c/p2c.go b/selector/p2c/p2c.go
index 88cd3a7b..817bccd1 100644
--- a/selector/p2c/p2c.go
+++ b/selector/p2c/p2c.go
@@ -18,13 +18,33 @@ const (
 
 var _ selector.Balancer = &Balancer{}
 
+// WithFilter with select filters
+func WithFilter(filters ...selector.Filter) Option {
+	return func(o *options) {
+		o.filters = filters
+	}
+}
+
+// Option is random builder option.
+type Option func(o *options)
+
+// options is random builder options
+type options struct {
+	filters []selector.Filter
+}
+
 // New creates a p2c selector.
-func New() selector.Selector {
+func New(opts ...Option) selector.Selector {
+	var option options
+	for _, opt := range opts {
+		opt(&option)
+	}
 	return &selector.Default{
 		NodeBuilder: &ewma.Builder{},
 		Balancer: &Balancer{
 			r: rand.New(rand.NewSource(time.Now().UnixNano())),
 		},
+		Filters: option.filters,
 	}
 }
 
diff --git a/selector/random/random.go b/selector/random/random.go
index 30e33d4d..14a194df 100644
--- a/selector/random/random.go
+++ b/selector/random/random.go
@@ -8,21 +8,42 @@ import (
 	"github.com/go-kratos/kratos/v2/selector/node/direct"
 )
 
-var (
-	_ selector.Balancer = &Balancer{}
-
-	// Name is balancer name
+const (
+	// Name is random balancer name
 	Name = "random"
 )
 
+var _ selector.Balancer = &Balancer{} // Name is balancer name
+
+// WithFilter with select filters
+func WithFilter(filters ...selector.Filter) Option {
+	return func(o *options) {
+		o.filters = filters
+	}
+}
+
+// Option is random builder option.
+type Option func(o *options)
+
+// options is random builder options
+type options struct {
+	filters []selector.Filter
+}
+
 // Balancer is a random balancer.
 type Balancer struct{}
 
 // New random a selector.
-func New() selector.Selector {
+func New(opts ...Option) selector.Selector {
+	var option options
+	for _, opt := range opts {
+		opt(&option)
+	}
+
 	return &selector.Default{
 		Balancer:    &Balancer{},
 		NodeBuilder: &direct.Builder{},
+		Filters:     option.filters,
 	}
 }
 
diff --git a/selector/wrr/wrr.go b/selector/wrr/wrr.go
new file mode 100644
index 00000000..e5898daf
--- /dev/null
+++ b/selector/wrr/wrr.go
@@ -0,0 +1,82 @@
+package wrr
+
+import (
+	"context"
+	"sync"
+
+	"github.com/go-kratos/kratos/v2/selector"
+	"github.com/go-kratos/kratos/v2/selector/node/direct"
+)
+
+const (
+	// Name is wrr balancer name
+	Name = "wrr"
+)
+
+var _ selector.Balancer = &Balancer{} // Name is balancer name
+
+// WithFilter with select filters
+func WithFilter(filters ...selector.Filter) Option {
+	return func(o *options) {
+		o.filters = filters
+	}
+}
+
+// Option is random builder option.
+type Option func(o *options)
+
+// options is random builder options
+type options struct {
+	filters []selector.Filter
+}
+
+// Balancer is a random balancer.
+type Balancer struct {
+	mu            sync.Mutex
+	currentWeight map[string]float64
+}
+
+// New random a selector.
+func New(opts ...Option) selector.Selector {
+	var option options
+	for _, opt := range opts {
+		opt(&option)
+	}
+
+	return &selector.Default{
+		Balancer: &Balancer{
+			currentWeight: make(map[string]float64),
+		},
+		NodeBuilder: &direct.Builder{},
+		Filters:     option.filters,
+	}
+}
+
+// Pick pick a weighted node.
+func (p *Balancer) Pick(_ context.Context, nodes []selector.WeightedNode) (selector.WeightedNode, selector.DoneFunc, error) {
+	if len(nodes) == 0 {
+		return nil, nil, selector.ErrNoAvailable
+	}
+	var totalWeight float64
+	var selected selector.WeightedNode
+	var selectWeight float64
+
+	// nginx wrr load balancing algorithm: http://blog.csdn.net/zhangskd/article/details/50194069
+	p.mu.Lock()
+	for _, node := range nodes {
+		totalWeight += node.Weight()
+		cwt := p.currentWeight[node.Address()]
+		// current += effectiveWeight
+		cwt += node.Weight()
+		p.currentWeight[node.Address()] = cwt
+		if selected == nil || selectWeight < cwt {
+			selectWeight = cwt
+			selected = node
+		}
+	}
+	p.currentWeight[selected.Address()] = selectWeight - totalWeight
+	p.mu.Unlock()
+
+	d := selected.Pick()
+	return selected, d, nil
+}
diff --git a/transport/grpc/balancer/balancer.go b/transport/grpc/balancer.go
similarity index 85%
rename from transport/grpc/balancer/balancer.go
rename to transport/grpc/balancer.go
index 573f9b7a..3814742f 100644
--- a/transport/grpc/balancer/balancer.go
+++ b/transport/grpc/balancer.go
@@ -1,4 +1,4 @@
-package balancer
+package grpc
 
 import (
 	"sync"
@@ -8,6 +8,8 @@ import (
 	"github.com/go-kratos/kratos/v2/selector/node"
 	"github.com/go-kratos/kratos/v2/selector/p2c"
 	"github.com/go-kratos/kratos/v2/selector/random"
+	"github.com/go-kratos/kratos/v2/selector/wrr"
+	"github.com/go-kratos/kratos/v2/transport"
 
 	gBalancer "google.golang.org/grpc/balancer"
 	"google.golang.org/grpc/balancer/base"
@@ -24,6 +26,7 @@ var (
 func init() {
 	// inject global grpc balancer
 	SetGlobalBalancer(random.Name, random.New())
+	SetGlobalBalancer(wrr.Name, wrr.New())
 	SetGlobalBalancer(p2c.Name, p2c.New())
 }
 
@@ -74,7 +77,14 @@ type Picker struct {
 
 // Pick pick instances.
 func (p *Picker) Pick(info gBalancer.PickInfo) (gBalancer.PickResult, error) {
-	n, done, err := p.selector.Select(info.Ctx)
+	var filters []selector.Filter
+	if tr, ok := transport.FromClientContext(info.Ctx); ok {
+		if gtr, ok := tr.(*Transport); ok {
+			filters = gtr.Filters()
+		}
+	}
+
+	n, done, err := p.selector.Select(info.Ctx, selector.WithFilter(filters...))
 	if err != nil {
 		return gBalancer.PickResult{}, err
 	}
diff --git a/transport/grpc/client.go b/transport/grpc/client.go
index fa33c707..dd1a614b 100644
--- a/transport/grpc/client.go
+++ b/transport/grpc/client.go
@@ -8,14 +8,13 @@ import (
 
 	"github.com/go-kratos/kratos/v2/middleware"
 	"github.com/go-kratos/kratos/v2/registry"
-	"github.com/go-kratos/kratos/v2/selector/random"
+	"github.com/go-kratos/kratos/v2/selector"
+	"github.com/go-kratos/kratos/v2/selector/wrr"
 	"github.com/go-kratos/kratos/v2/transport"
 	"github.com/go-kratos/kratos/v2/transport/grpc/resolver/discovery"
 
 	// init resolver
 	_ "github.com/go-kratos/kratos/v2/transport/grpc/resolver/direct"
-	// init balancer
-	_ "github.com/go-kratos/kratos/v2/transport/grpc/balancer"
 
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/credentials"
@@ -74,15 +73,31 @@ func WithOptions(opts ...grpc.DialOption) ClientOption {
 	}
 }
 
+// WithBalancerName with balancer name
+func WithBalancerName(name string) ClientOption {
+	return func(o *clientOptions) {
+		o.balancerName = name
+	}
+}
+
+// WithSelectFilter with select filters
+func WithSelectFilter(filters ...selector.Filter) ClientOption {
+	return func(o *clientOptions) {
+		o.filters = filters
+	}
+}
+
 // clientOptions is gRPC Client
 type clientOptions struct {
-	endpoint   string
-	tlsConf    *tls.Config
-	timeout    time.Duration
-	discovery  registry.Discovery
-	middleware []middleware.Middleware
-	ints       []grpc.UnaryClientInterceptor
-	grpcOpts   []grpc.DialOption
+	endpoint     string
+	tlsConf      *tls.Config
+	timeout      time.Duration
+	discovery    registry.Discovery
+	middleware   []middleware.Middleware
+	ints         []grpc.UnaryClientInterceptor
+	grpcOpts     []grpc.DialOption
+	balancerName string
+	filters      []selector.Filter
 }
 
 // Dial returns a GRPC connection.
@@ -97,19 +112,20 @@ func DialInsecure(ctx context.Context, opts ...ClientOption) (*grpc.ClientConn,
 
 func dial(ctx context.Context, insecure bool, opts ...ClientOption) (*grpc.ClientConn, error) {
 	options := clientOptions{
-		timeout: 2000 * time.Millisecond,
+		timeout:      2000 * time.Millisecond,
+		balancerName: wrr.Name,
 	}
 	for _, o := range opts {
 		o(&options)
 	}
 	ints := []grpc.UnaryClientInterceptor{
-		unaryClientInterceptor(options.middleware, options.timeout),
+		unaryClientInterceptor(options.middleware, options.timeout, options.filters),
 	}
 	if len(options.ints) > 0 {
 		ints = append(ints, options.ints...)
 	}
 	grpcOpts := []grpc.DialOption{
-		grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s"}`, random.Name)),
+		grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s"}`, options.balancerName)),
 		grpc.WithChainUnaryInterceptor(ints...),
 	}
 	if options.discovery != nil {
@@ -127,12 +143,13 @@ func dial(ctx context.Context, insecure bool, opts ...ClientOption) (*grpc.Clien
 	return grpc.DialContext(ctx, options.endpoint, grpcOpts...)
 }
 
-func unaryClientInterceptor(ms []middleware.Middleware, timeout time.Duration) grpc.UnaryClientInterceptor {
+func unaryClientInterceptor(ms []middleware.Middleware, timeout time.Duration, filters []selector.Filter) grpc.UnaryClientInterceptor {
 	return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
 		ctx = transport.NewClientContext(ctx, &Transport{
 			endpoint:  cc.Target(),
 			operation: method,
 			reqHeader: headerCarrier{},
+			filters:   filters,
 		})
 		if timeout > 0 {
 			var cancel context.CancelFunc
diff --git a/transport/grpc/transport.go b/transport/grpc/transport.go
index 3f07e744..eb8c5127 100644
--- a/transport/grpc/transport.go
+++ b/transport/grpc/transport.go
@@ -1,6 +1,7 @@
 package grpc
 
 import (
+	"github.com/go-kratos/kratos/v2/selector"
 	"github.com/go-kratos/kratos/v2/transport"
 	"google.golang.org/grpc/metadata"
 )
@@ -13,6 +14,7 @@ type Transport struct {
 	operation   string
 	reqHeader   headerCarrier
 	replyHeader headerCarrier
+	filters     []selector.Filter
 }
 
 // Kind returns the transport kind.
@@ -40,6 +42,11 @@ func (tr *Transport) ReplyHeader() transport.Header {
 	return tr.replyHeader
 }
 
+// Filters returns the client select filters.
+func (tr *Transport) Filters() []selector.Filter {
+	return tr.filters
+}
+
 type headerCarrier metadata.MD
 
 // Get returns the value associated with the passed key.
diff --git a/transport/http/calloption.go b/transport/http/calloption.go
index f6851895..7b0ed82d 100644
--- a/transport/http/calloption.go
+++ b/transport/http/calloption.go
@@ -2,8 +2,6 @@ package http
 
 import (
 	"net/http"
-
-	"github.com/go-kratos/kratos/v2/selector"
 )
 
 // CallOption configures a Call before it starts or extracts information from
@@ -22,7 +20,6 @@ type callInfo struct {
 	contentType  string
 	operation    string
 	pathTemplate string
-	filters      []selector.Filter
 }
 
 // EmptyCallOption does not alter the Call configuration.
@@ -93,22 +90,6 @@ func (o PathTemplateCallOption) before(c *callInfo) error {
 	return nil
 }
 
-// SelectFilter is http select filter
-func SelectFilter(filters ...selector.Filter) CallOption {
-	return SelectFilterCallOption{filters: filters}
-}
-
-// SelectFilterCallOption is set call select filters
-type SelectFilterCallOption struct {
-	EmptyCallOption
-	filters []selector.Filter
-}
-
-func (o SelectFilterCallOption) before(c *callInfo) error {
-	c.filters = o.filters
-	return nil
-}
-
 // Header returns a CallOptions that retrieves the http response header
 // from server reply.
 func Header(header *http.Header) CallOption {
diff --git a/transport/http/client.go b/transport/http/client.go
index 14dc9a3b..fcd29d2c 100644
--- a/transport/http/client.go
+++ b/transport/http/client.go
@@ -17,7 +17,7 @@ import (
 	"github.com/go-kratos/kratos/v2/middleware"
 	"github.com/go-kratos/kratos/v2/registry"
 	"github.com/go-kratos/kratos/v2/selector"
-	"github.com/go-kratos/kratos/v2/selector/random"
+	"github.com/go-kratos/kratos/v2/selector/wrr"
 	"github.com/go-kratos/kratos/v2/transport"
 )
 
@@ -152,7 +152,7 @@ func NewClient(ctx context.Context, opts ...ClientOption) (*Client, error) {
 		decoder:      DefaultResponseDecoder,
 		errorDecoder: DefaultErrorDecoder,
 		transport:    http.DefaultTransport,
-		selector:     random.New(),
+		selector:     wrr.New(),
 	}
 	for _, o := range opts {
 		o(&options)
@@ -238,7 +238,7 @@ func (client *Client) invoke(ctx context.Context, req *http.Request, args interf
 				err  error
 				node selector.Node
 			)
-			if node, done, err = client.opts.selector.Select(ctx, selector.WithFilter(c.filters...)); err != nil {
+			if node, done, err = client.opts.selector.Select(ctx); err != nil {
 				return nil, errors.ServiceUnavailable("NODE_NOT_FOUND", err.Error())
 			}
 			if client.insecure {
diff --git a/transport/http/server.go b/transport/http/server.go
index 15dc0b57..da8a29fe 100644
--- a/transport/http/server.go
+++ b/transport/http/server.go
@@ -91,13 +91,6 @@ func ErrorEncoder(en EncodeErrorFunc) ServerOption {
 	}
 }
 
-// Endpoint with server endpoint.
-func Endpoint(endpoint *url.URL) ServerOption {
-	return func(o *Server) {
-		o.endpoint = endpoint
-	}
-}
-
 // TLSConfig with TLS config.
 func TLSConfig(c *tls.Config) ServerOption {
 	return func(o *Server) {
@@ -227,9 +220,6 @@ func (s *Server) filter() mux.MiddlewareFunc {
 //   http://127.0.0.1:8000?isSecure=false
 func (s *Server) Endpoint() (*url.URL, error) {
 	s.once.Do(func() {
-		if s.endpoint != nil {
-			return
-		}
 		lis, err := net.Listen(s.network, s.address)
 		if err != nil {
 			s.err = err


Test patch:
diff --git a/config/env/env_test.go b/config/env/env_test.go
index 0ddb7c93..6ccf76d7 100644
--- a/config/env/env_test.go
+++ b/config/env/env_test.go
@@ -55,9 +55,7 @@ func TestEnvWithPrefix(t *testing.T) {
 	}
 
 	for k, v := range envs {
-		if err := os.Setenv(k, v); err != nil {
-			t.Fatal(err)
-		}
+		t.Setenv(k, v)
 	}
 
 	c := config.New(config.WithSource(
@@ -163,9 +161,7 @@ func TestEnvWithoutPrefix(t *testing.T) {
 	}
 
 	for k, v := range envs {
-		if err := os.Setenv(k, v); err != nil {
-			t.Fatal(err)
-		}
+		t.Setenv(k, v)
 	}
 
 	c := config.New(config.WithSource(
diff --git a/middleware/tracing/span_test.go b/middleware/tracing/span_test.go
new file mode 100644
index 00000000..c930154f
--- /dev/null
+++ b/middleware/tracing/span_test.go
@@ -0,0 +1,158 @@
+package tracing
+
+import (
+	"reflect"
+	"testing"
+
+	"go.opentelemetry.io/otel/attribute"
+	semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
+)
+
+func Test_parseFullMethod(t *testing.T) {
+	tests := []struct {
+		name       string
+		fullMethod string
+		want       string
+		wantAttr   []attribute.KeyValue
+	}{
+		{
+			name:       "/foo.bar/hello",
+			fullMethod: "/foo.bar/hello",
+			want:       "foo.bar/hello",
+			wantAttr: []attribute.KeyValue{
+				semconv.RPCServiceKey.String("foo.bar"),
+				semconv.RPCMethodKey.String("hello"),
+			},
+		},
+		{
+			name:       "/foo.bar/hello/world",
+			fullMethod: "/foo.bar/hello/world",
+			want:       "foo.bar/hello/world",
+			wantAttr: []attribute.KeyValue{
+				semconv.RPCServiceKey.String("foo.bar"),
+				semconv.RPCMethodKey.String("hello/world"),
+			},
+		},
+		{
+			name:       "/hello",
+			fullMethod: "/hello",
+			want:       "hello",
+			wantAttr:   []attribute.KeyValue{attribute.Key("rpc.operation").String("/hello")},
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got, got1 := parseFullMethod(tt.fullMethod)
+			if got != tt.want {
+				t.Errorf("parseFullMethod() got = %v, want %v", got, tt.want)
+			}
+			if !reflect.DeepEqual(got1, tt.wantAttr) {
+				t.Errorf("parseFullMethod() got1 = %v, want %v", got1, tt.wantAttr)
+			}
+		})
+	}
+}
+
+func Test_peerAttr(t *testing.T) {
+	tests := []struct {
+		name string
+		addr string
+		want []attribute.KeyValue
+	}{
+		{
+			name: "nil addr",
+			addr: ":8080",
+			want: []attribute.KeyValue{
+				semconv.NetPeerIPKey.String("127.0.0.1"),
+				semconv.NetPeerPortKey.String("8080"),
+			},
+		},
+		{
+			name: "normal addr without port",
+			addr: "192.168.0.1",
+			want: []attribute.KeyValue(nil),
+		},
+		{
+			name: "normal addr with port",
+			addr: "192.168.0.1:8080",
+			want: []attribute.KeyValue{
+				semconv.NetPeerIPKey.String("192.168.0.1"),
+				semconv.NetPeerPortKey.String("8080"),
+			},
+		},
+		{
+			name: "dns addr",
+			addr: "foo:8080",
+			want: []attribute.KeyValue{
+				semconv.NetPeerIPKey.String("foo"),
+				semconv.NetPeerPortKey.String("8080"),
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if got := peerAttr(tt.addr); !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("peerAttr() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func Test_parseTarget(t *testing.T) {
+	tests := []struct {
+		name        string
+		endpoint    string
+		wantAddress string
+		wantErr     bool
+	}{
+		{
+			name:        "http",
+			endpoint:    "http://foo.bar:8080",
+			wantAddress: "http://foo.bar:8080",
+			wantErr:     false,
+		},
+		{
+			name:        "http",
+			endpoint:    "http://127.0.0.1:8080",
+			wantAddress: "http://127.0.0.1:8080",
+			wantErr:     false,
+		},
+		{
+			name:        "without protocol",
+			endpoint:    "foo.bar:8080",
+			wantAddress: "foo.bar:8080",
+			wantErr:     false,
+		},
+		{
+			name:        "grpc",
+			endpoint:    "grpc://foo.bar",
+			wantAddress: "grpc://foo.bar",
+			wantErr:     false,
+		},
+		{
+			name:        "with path",
+			endpoint:    "/foo",
+			wantAddress: "foo",
+			wantErr:     false,
+		},
+		{
+			name:        "with path",
+			endpoint:    "http://127.0.0.1/hello",
+			wantAddress: "hello",
+			wantErr:     false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			gotAddress, err := parseTarget(tt.endpoint)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("parseTarget() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if gotAddress != tt.wantAddress {
+				t.Errorf("parseTarget() = %v, want %v", gotAddress, tt.wantAddress)
+			}
+		})
+	}
+}
diff --git a/middleware/tracing/tracing_test.go b/middleware/tracing/tracing_test.go
index 40ada4da..7593d1d3 100644
--- a/middleware/tracing/tracing_test.go
+++ b/middleware/tracing/tracing_test.go
@@ -3,15 +3,18 @@ package tracing
 import (
 	"context"
 	"net/http"
+	"os"
 	"testing"
 
+	"github.com/go-kratos/kratos/v2/log"
 	"github.com/go-kratos/kratos/v2/transport"
+	"github.com/stretchr/testify/assert"
 	"go.opentelemetry.io/otel/propagation"
 	tracesdk "go.opentelemetry.io/otel/sdk/trace"
 	"go.opentelemetry.io/otel/trace"
 )
 
-var _ transport.Transporter = &Transport{}
+var _ transport.Transporter = &mockTransport{}
 
 type headerCarrier http.Header
 
@@ -34,25 +37,25 @@ func (hc headerCarrier) Keys() []string {
 	return keys
 }
 
-type Transport struct {
+type mockTransport struct {
 	kind      transport.Kind
 	endpoint  string
 	operation string
 	header    headerCarrier
 }
 
-func (tr *Transport) Kind() transport.Kind            { return tr.kind }
-func (tr *Transport) Endpoint() string                { return tr.endpoint }
-func (tr *Transport) Operation() string               { return tr.operation }
-func (tr *Transport) RequestHeader() transport.Header { return tr.header }
-func (tr *Transport) ReplyHeader() transport.Header   { return tr.header }
+func (tr *mockTransport) Kind() transport.Kind            { return tr.kind }
+func (tr *mockTransport) Endpoint() string                { return tr.endpoint }
+func (tr *mockTransport) Operation() string               { return tr.operation }
+func (tr *mockTransport) RequestHeader() transport.Header { return tr.header }
+func (tr *mockTransport) ReplyHeader() transport.Header   { return tr.header }
 
-func TestTracing(t *testing.T) {
+func TestTracer(t *testing.T) {
 	carrier := headerCarrier{}
 	tp := tracesdk.NewTracerProvider(tracesdk.WithSampler(tracesdk.TraceIDRatioBased(0)))
 
 	// caller use Inject
-	tracer := NewTracer(
+	cliTracer := NewTracer(
 		trace.SpanKindClient,
 		WithTracerProvider(tp),
 		WithPropagator(
@@ -60,17 +63,17 @@ func TestTracing(t *testing.T) {
 		),
 	)
 
-	ts := &Transport{kind: transport.KindHTTP, header: carrier}
+	ts := &mockTransport{kind: transport.KindHTTP, header: carrier}
 
-	ctx, aboveSpan := tracer.Start(transport.NewClientContext(context.Background(), ts), ts.Operation(), ts.RequestHeader())
-	defer tracer.End(ctx, aboveSpan, nil, nil)
+	ctx, aboveSpan := cliTracer.Start(transport.NewClientContext(context.Background(), ts), ts.Operation(), ts.RequestHeader())
+	defer cliTracer.End(ctx, aboveSpan, nil, nil)
 
 	// server use Extract fetch traceInfo from carrier
-	tracer = NewTracer(trace.SpanKindServer, WithPropagator(propagation.NewCompositeTextMapPropagator(propagation.Baggage{}, propagation.TraceContext{})))
-	ts = &Transport{kind: transport.KindHTTP, header: carrier}
+	svrTracer := NewTracer(trace.SpanKindServer, WithPropagator(propagation.NewCompositeTextMapPropagator(propagation.Baggage{}, propagation.TraceContext{})))
+	ts = &mockTransport{kind: transport.KindHTTP, header: carrier}
 
-	ctx, span := tracer.Start(transport.NewServerContext(ctx, ts), ts.Operation(), ts.RequestHeader())
-	defer tracer.End(ctx, span, nil, nil)
+	ctx, span := svrTracer.Start(transport.NewServerContext(ctx, ts), ts.Operation(), ts.RequestHeader())
+	defer svrTracer.End(ctx, span, nil, nil)
 
 	if aboveSpan.SpanContext().TraceID() != span.SpanContext().TraceID() {
 		t.Fatalf("TraceID failed to deliver")
@@ -80,3 +83,110 @@ func TestTracing(t *testing.T) {
 		t.Fatalf("traceHeader failed to deliver")
 	}
 }
+
+func TestServer(t *testing.T) {
+	tr := &mockTransport{
+		kind:      transport.KindHTTP,
+		endpoint:  "server:2233",
+		operation: "/test.server/hello",
+		header:    headerCarrier{},
+	}
+
+	tracer := NewTracer(
+		trace.SpanKindClient,
+		WithTracerProvider(tracesdk.NewTracerProvider()),
+	)
+
+	logger := log.NewStdLogger(os.Stdout)
+	logger = log.With(logger, "span_id", SpanID())
+	logger = log.With(logger, "trace_id", TraceID())
+
+	var (
+		childSpanID  string
+		childTraceID string
+	)
+	next := func(ctx context.Context, req interface{}) (interface{}, error) {
+		_ = log.WithContext(ctx, logger).Log(log.LevelInfo,
+			"kind", "server",
+		)
+		childSpanID = SpanID()(ctx).(string)
+		childTraceID = TraceID()(ctx).(string)
+		return req.(string) + "https://go-kratos.dev", nil
+	}
+
+	var ctx context.Context
+	ctx, span := tracer.Start(
+		transport.NewServerContext(context.Background(), tr),
+		tr.Operation(),
+		tr.RequestHeader(),
+	)
+
+	_, err := Server(
+		WithTracerProvider(tracesdk.NewTracerProvider()),
+		WithPropagator(propagation.NewCompositeTextMapPropagator(propagation.Baggage{}, propagation.TraceContext{})),
+	)(next)(ctx, "test server: ")
+
+	span.End()
+	assert.NoError(t, err)
+	assert.NotEmpty(t, childSpanID)
+	assert.NotEqual(t, span.SpanContext().SpanID().String(), childSpanID)
+	assert.Equal(t, span.SpanContext().TraceID().String(), childTraceID)
+
+	_, err = Server(
+		WithTracerProvider(tracesdk.NewTracerProvider()),
+		WithPropagator(propagation.NewCompositeTextMapPropagator(propagation.Baggage{}, propagation.TraceContext{})),
+	)(next)(context.Background(), "test server: ")
+
+	assert.NoError(t, err)
+	assert.Empty(t, childSpanID)
+	assert.Empty(t, childTraceID)
+}
+
+func TestClient(t *testing.T) {
+	tr := &mockTransport{
+		kind:      transport.KindHTTP,
+		endpoint:  "server:2233",
+		operation: "/test.server/hello",
+		header:    headerCarrier{},
+	}
+
+	tracer := NewTracer(
+		trace.SpanKindClient,
+		WithTracerProvider(tracesdk.NewTracerProvider()),
+	)
+
+	logger := log.NewStdLogger(os.Stdout)
+	logger = log.With(logger, "span_id", SpanID())
+	logger = log.With(logger, "trace_id", TraceID())
+
+	var (
+		childSpanID  string
+		childTraceID string
+	)
+	next := func(ctx context.Context, req interface{}) (interface{}, error) {
+		_ = log.WithContext(ctx, logger).Log(log.LevelInfo,
+			"kind", "client",
+		)
+		childSpanID = SpanID()(ctx).(string)
+		childTraceID = TraceID()(ctx).(string)
+		return req.(string) + "https://go-kratos.dev", nil
+	}
+
+	var ctx context.Context
+	ctx, span := tracer.Start(
+		transport.NewClientContext(context.Background(), tr),
+		tr.Operation(),
+		tr.RequestHeader(),
+	)
+
+	_, err := Client(
+		WithTracerProvider(tracesdk.NewTracerProvider()),
+		WithPropagator(propagation.NewCompositeTextMapPropagator(propagation.Baggage{}, propagation.TraceContext{})),
+	)(next)(ctx, "test client: ")
+
+	span.End()
+	assert.NoError(t, err)
+	assert.NotEmpty(t, childSpanID)
+	assert.NotEqual(t, span.SpanContext().SpanID().String(), childSpanID)
+	assert.Equal(t, span.SpanContext().TraceID().String(), childTraceID)
+}
diff --git a/transport/grpc/client_test.go b/transport/grpc/client_test.go
index f18b6183..f618d9bf 100644
--- a/transport/grpc/client_test.go
+++ b/transport/grpc/client_test.go
@@ -68,7 +68,7 @@ func EmptyMiddleware() middleware.Middleware {
 }
 
 func TestUnaryClientInterceptor(t *testing.T) {
-	f := unaryClientInterceptor([]middleware.Middleware{EmptyMiddleware()}, time.Duration(100))
+	f := unaryClientInterceptor([]middleware.Middleware{EmptyMiddleware()}, time.Duration(100), nil)
 	req := &struct{}{}
 	resp := &struct{}{}
 
diff --git a/transport/http/resolver_test.go b/transport/http/resolver_test.go
index 11598237..8818ce41 100644
--- a/transport/http/resolver_test.go
+++ b/transport/http/resolver_test.go
@@ -3,7 +3,10 @@ package http
 import (
 	"context"
 	"errors"
+	"fmt"
+	"strconv"
 	"testing"
+	"time"
 
 	"github.com/go-kratos/kratos/v2/registry"
 	"github.com/go-kratos/kratos/v2/selector"
@@ -36,23 +39,26 @@ type mockRebalancer struct{}
 
 func (m *mockRebalancer) Apply(nodes []selector.Node) {}
 
-type mockDiscoverys struct{}
+type mockDiscoverys struct {
+	isSecure bool
+}
 
-func (*mockDiscoverys) GetService(ctx context.Context, serviceName string) ([]*registry.ServiceInstance, error) {
+func (d *mockDiscoverys) GetService(ctx context.Context, serviceName string) ([]*registry.ServiceInstance, error) {
 	return nil, nil
 }
 
-func (*mockDiscoverys) Watch(ctx context.Context, serviceName string) (registry.Watcher, error) {
-	return &mockWatch{}, nil
+func (d *mockDiscoverys) Watch(ctx context.Context, serviceName string) (registry.Watcher, error) {
+	return &mockWatch{isSecure: d.isSecure}, nil
 }
 
 type mockWatch struct {
-	count int
+	isSecure bool
+	count    int
 }
 
 func (m *mockWatch) Next() ([]*registry.ServiceInstance, error) {
-	if m.count == 0 {
-		m.count++
+	m.count++
+	if m.count == 1 {
 		return nil, errors.New("mock test error")
 	}
 	instance := &registry.ServiceInstance{
@@ -60,7 +66,10 @@ func (m *mockWatch) Next() ([]*registry.ServiceInstance, error) {
 		Name:      "kratos",
 		Version:   "v1",
 		Metadata:  map[string]string{},
-		Endpoints: []string{},
+		Endpoints: []string{fmt.Sprintf("http://127.0.0.1:9001?isSecure=%s", strconv.FormatBool(m.isSecure))},
+	}
+	if m.count > 3 {
+		time.Sleep(time.Millisecond * 500)
 	}
 	return []*registry.ServiceInstance{instance}, nil
 }
@@ -73,10 +82,10 @@ func TestResolver(t *testing.T) {
 	ta := &Target{
 		Scheme:    "http",
 		Authority: "",
-		Endpoint:  "http://127.0.0.1:9001",
+		Endpoint:  "discovery://helloworld",
 	}
-	_, err := newResolver(context.Background(), &mockDiscoverys{}, ta, &mockRebalancer{}, false, false)
+	_, err := newResolver(context.Background(), &mockDiscoverys{true}, ta, &mockRebalancer{}, false, false)
 	assert.Nil(t, err)
-	_, err = newResolver(context.Background(), &mockDiscoverys{}, ta, &mockRebalancer{}, true, false)
+	_, err = newResolver(context.Background(), &mockDiscoverys{false}, ta, &mockRebalancer{}, true, true)
 	assert.Nil(t, err)
 }
diff --git a/transport/http/server_test.go b/transport/http/server_test.go
index 69a2ceb0..5be44e8a 100644
--- a/transport/http/server_test.go
+++ b/transport/http/server_test.go
@@ -7,7 +7,6 @@ import (
 	"fmt"
 	"io/ioutil"
 	"net/http"
-	"net/url"
 	"strings"
 	"testing"
 	"time"
@@ -201,15 +200,6 @@ func TestLogger(t *testing.T) {
 	// todo
 }
 
-func TestEndpoint(t *testing.T) {
-	u, err := url.Parse("http://hello/world")
-	assert.NoError(t, err)
-	o := &Server{}
-	Endpoint(u)(o)
-	assert.Equal(t, "hello", o.endpoint.Host)
-	assert.Equal(t, "http", o.endpoint.Scheme)
-}
-
 func TestMiddleware(t *testing.T) {
 	o := &Server{}
 	v := []middleware.Middleware{