mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-11-21 14:44:00 +00:00
vendor: run make vendor-update
This commit is contained in:
parent
1a5cdb4790
commit
7df8d19831
63 changed files with 3276 additions and 1443 deletions
19
go.mod
19
go.mod
|
@ -4,7 +4,7 @@ go 1.20
|
|||
|
||||
require (
|
||||
cloud.google.com/go/storage v1.35.1
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0
|
||||
github.com/VictoriaMetrics/fastcache v1.12.2
|
||||
|
||||
|
@ -36,7 +36,7 @@ require (
|
|||
golang.org/x/net v0.19.0
|
||||
golang.org/x/oauth2 v0.15.0
|
||||
golang.org/x/sys v0.15.0
|
||||
google.golang.org/api v0.153.0
|
||||
google.golang.org/api v0.154.0
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
)
|
||||
|
||||
|
@ -50,7 +50,7 @@ require (
|
|||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.0 // indirect
|
||||
github.com/VividCortex/ewma v1.2.0 // indirect
|
||||
github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 // indirect
|
||||
github.com/aws/aws-sdk-go v1.48.16 // indirect
|
||||
github.com/aws/aws-sdk-go v1.49.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.16.12 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.10 // indirect
|
||||
|
@ -80,7 +80,7 @@ require (
|
|||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/google/s2a-go v0.1.7 // indirect
|
||||
github.com/google/uuid v1.4.0 // indirect
|
||||
github.com/google/uuid v1.5.0 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
|
||||
github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
|
@ -110,7 +110,8 @@ require (
|
|||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/collector/pdata v1.0.0 // indirect
|
||||
go.opentelemetry.io/collector/semconv v0.90.1 // indirect
|
||||
go.opentelemetry.io/collector/semconv v0.91.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 // indirect
|
||||
go.opentelemetry.io/otel v1.21.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.21.0 // indirect
|
||||
|
@ -125,10 +126,10 @@ require (
|
|||
golang.org/x/time v0.5.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
|
||||
google.golang.org/appengine v1.6.8 // indirect
|
||||
google.golang.org/genproto v0.0.0-20231127180814-3a041ad873d4 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231127180814-3a041ad873d4 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4 // indirect
|
||||
google.golang.org/grpc v1.59.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231212172506-995d672761c0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 // indirect
|
||||
google.golang.org/grpc v1.60.0 // indirect
|
||||
google.golang.org/protobuf v1.31.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
|
38
go.sum
38
go.sum
|
@ -41,8 +41,8 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9
|
|||
cloud.google.com/go/storage v1.35.1 h1:B59ahL//eDfx2IIKFBeT5Atm9wnNmj3+8xG/W4WB//w=
|
||||
cloud.google.com/go/storage v1.35.1/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0 h1:fb8kj/Dh4CSwgsOzHeZY4Xh68cFVbzXx+ONXGMY//4w=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0/go.mod h1:uReU2sSxZExRPBAg3qKzmAucSi51+SP1OhohieR821Q=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1 h1:lGlwhPtrX6EVml1hO0ivjkUxsSyl4dsiw9qcA1k/3IQ=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1/go.mod h1:RKUqNu35KJYcVG/fqTRqmuXJZYNhYkBrnC/hX7yGbTA=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 h1:BMAjVKJM0U/CYF27gA0ZMmXGkOcvfFtD0oHVZ1TIPRI=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0/go.mod h1:1fXstnBMas5kzG+S3q8UoJcmyU6nUeunJcMDHcRYHhs=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1 h1:6oNBlSdi1QqM1PNW7FPA6xOGA5UNsXnkaYZz9vdPGhA=
|
||||
|
@ -82,8 +82,8 @@ github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu
|
|||
github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA=
|
||||
github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
|
||||
github.com/aws/aws-sdk-go v1.48.16 h1:mcj2/9J/MJ55Dov+ocMevhR8Jv6jW/fAxbrn4a1JFc8=
|
||||
github.com/aws/aws-sdk-go v1.48.16/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
|
||||
github.com/aws/aws-sdk-go v1.49.1 h1:Dsamcd8d/nNb3A+bZ0ucfGl0vGZsW5wlRW0vhoYGoeQ=
|
||||
github.com/aws/aws-sdk-go v1.49.1/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
|
||||
github.com/aws/aws-sdk-go-v2 v1.24.0 h1:890+mqQ+hTpNuw0gGP6/4akolQkSToDJgHfQE7AwGuk=
|
||||
github.com/aws/aws-sdk-go-v2 v1.24.0/go.mod h1:LNh45Br1YAkEKaAqvmE1m8FUx6a5b/V0oAKV7of29b4=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.4 h1:OCs21ST2LrepDfD3lwlQiOqIGp6JiEUqG84GzTDoyJs=
|
||||
|
@ -262,8 +262,8 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4
|
|||
github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
|
||||
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
|
||||
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
|
||||
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
|
@ -456,8 +456,10 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
|||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/collector/pdata v1.0.0 h1:ECP2jnLztewsHmL1opL8BeMtWVc7/oSlKNhfY9jP8ec=
|
||||
go.opentelemetry.io/collector/pdata v1.0.0/go.mod h1:TsDFgs4JLNG7t6x9D8kGswXUz4mme+MyNChHx8zSF6k=
|
||||
go.opentelemetry.io/collector/semconv v0.90.1 h1:2fkQZbefQBbIcNb9Rk1mRcWlFZgQOk7CpST1e1BK8eg=
|
||||
go.opentelemetry.io/collector/semconv v0.90.1/go.mod h1:j/8THcqVxFna1FpvA2zYIsUperEtOaRaqoLYIN4doWw=
|
||||
go.opentelemetry.io/collector/semconv v0.91.0 h1:TRd+yDDfKQl+aNtS24wmEbJp1/QE/xAFV9SB5zWGxpE=
|
||||
go.opentelemetry.io/collector/semconv v0.91.0/go.mod h1:j/8THcqVxFna1FpvA2zYIsUperEtOaRaqoLYIN4doWw=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 h1:SpGay3w+nEwMpfVnbqOLH5gY52/foP8RE8UzTZ1pdSE=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo=
|
||||
go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc=
|
||||
|
@ -706,8 +708,8 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M
|
|||
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
||||
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
||||
google.golang.org/api v0.153.0 h1:N1AwGhielyKFaUqH07/ZSIQR3uNPcV7NVw0vj+j4iR4=
|
||||
google.golang.org/api v0.153.0/go.mod h1:3qNJX5eOmhiWYc67jRA/3GsDw97UFb5ivv7Y2PrriAY=
|
||||
google.golang.org/api v0.154.0 h1:X7QkVKZBskztmpPKWQXgjJRPA2dJYrL6r+sYPRLj050=
|
||||
google.golang.org/api v0.154.0/go.mod h1:qhSMkM85hgqiokIYsrRyKxrjfBeIhgl4Z2JmeRkYylc=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
|
@ -745,12 +747,12 @@ 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-20231127180814-3a041ad873d4 h1:W12Pwm4urIbRdGhMEg2NM9O3TWKjNcxQhs46V0ypf/k=
|
||||
google.golang.org/genproto v0.0.0-20231127180814-3a041ad873d4/go.mod h1:5RBcpGRxr25RbDzY5w+dmaqpSEvl8Gwl1x2CICf60ic=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231127180814-3a041ad873d4 h1:ZcOkrmX74HbKFYnpPY8Qsw93fC29TbJXspYKaBkSXDQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231127180814-3a041ad873d4/go.mod h1:k2dtGpRrbsSyKcNPKKI5sstZkrNCZwpU/ns96JoHbGg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4 h1:DC7wcm+i+P1rN3Ff07vL+OndGg5OhNddHyTA+ocPqYE=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4/go.mod h1:eJVxU6o+4G1PSczBr85xmyvSNYAKvAYgkub40YGomFM=
|
||||
google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 h1:YJ5pD9rF8o9Qtta0Cmy9rdBwkSjrTCT6XTiUQVOtIos=
|
||||
google.golang.org/genproto v0.0.0-20231212172506-995d672761c0/go.mod h1:l/k7rMz0vFTBPy+tFSGvXEd3z+BcoG1k7EHbqm+YBsY=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231212172506-995d672761c0 h1:s1w3X6gQxwrLEpxnLd/qXTVLgQE2yXwaOaoa6IlY/+o=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231212172506-995d672761c0/go.mod h1:CAny0tYF+0/9rmDB9fahA9YLzX3+AEVl1qXbv5hhj6c=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 h1:/jFB8jK5R3Sq3i/lmeZO0cATSzFfZaJq1J2Euan3XKU=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0/go.mod h1:FUoWkonphQm3RhTS+kOEhF8h0iDpm4tdXolVCeZ9KKA=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
|
@ -764,8 +766,8 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji
|
|||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
|
||||
google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
|
||||
google.golang.org/grpc v1.60.0 h1:6FQAR0kM31P6MRdeluor2w2gPaS4SVNrD/DNTxrQ15k=
|
||||
google.golang.org/grpc v1.60.0/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM=
|
||||
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=
|
||||
|
|
10
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/CHANGELOG.md
generated
vendored
10
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/CHANGELOG.md
generated
vendored
|
@ -1,5 +1,15 @@
|
|||
# Release History
|
||||
|
||||
## 1.9.1 (2023-12-11)
|
||||
|
||||
### Bugs Fixed
|
||||
|
||||
* The `retry-after-ms` and `x-ms-retry-after-ms` headers weren't being checked during retries.
|
||||
|
||||
### Other Changes
|
||||
|
||||
* Update dependencies.
|
||||
|
||||
## 1.9.0 (2023-11-06)
|
||||
|
||||
### Breaking Changes
|
||||
|
|
4
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go
generated
vendored
4
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go
generated
vendored
|
@ -22,11 +22,13 @@ const (
|
|||
HeaderLocation = "Location"
|
||||
HeaderOperationLocation = "Operation-Location"
|
||||
HeaderRetryAfter = "Retry-After"
|
||||
HeaderRetryAfterMS = "Retry-After-Ms"
|
||||
HeaderUserAgent = "User-Agent"
|
||||
HeaderWWWAuthenticate = "WWW-Authenticate"
|
||||
HeaderXMSClientRequestID = "x-ms-client-request-id"
|
||||
HeaderXMSRequestID = "x-ms-request-id"
|
||||
HeaderXMSErrorCode = "x-ms-error-code"
|
||||
HeaderXMSRetryAfterMS = "x-ms-retry-after-ms"
|
||||
)
|
||||
|
||||
const BearerTokenPrefix = "Bearer "
|
||||
|
@ -38,5 +40,5 @@ const (
|
|||
Module = "azcore"
|
||||
|
||||
// Version is the semantic version (see http://semver.org) of this module.
|
||||
Version = "v1.9.0"
|
||||
Version = "v1.9.1"
|
||||
)
|
||||
|
|
62
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/shared.go
generated
vendored
62
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/shared.go
generated
vendored
|
@ -44,22 +44,64 @@ func Delay(ctx context.Context, delay time.Duration) error {
|
|||
}
|
||||
}
|
||||
|
||||
// RetryAfter returns non-zero if the response contains a Retry-After header value.
|
||||
// RetryAfter returns non-zero if the response contains one of the headers with a "retry after" value.
|
||||
// Headers are checked in the following order: retry-after-ms, x-ms-retry-after-ms, retry-after
|
||||
func RetryAfter(resp *http.Response) time.Duration {
|
||||
if resp == nil {
|
||||
return 0
|
||||
}
|
||||
ra := resp.Header.Get(HeaderRetryAfter)
|
||||
if ra == "" {
|
||||
return 0
|
||||
|
||||
type retryData struct {
|
||||
header string
|
||||
units time.Duration
|
||||
|
||||
// custom is used when the regular algorithm failed and is optional.
|
||||
// the returned duration is used verbatim (units is not applied).
|
||||
custom func(string) time.Duration
|
||||
}
|
||||
// retry-after values are expressed in either number of
|
||||
// seconds or an HTTP-date indicating when to try again
|
||||
if retryAfter, _ := strconv.Atoi(ra); retryAfter > 0 {
|
||||
return time.Duration(retryAfter) * time.Second
|
||||
} else if t, err := time.Parse(time.RFC1123, ra); err == nil {
|
||||
return time.Until(t)
|
||||
|
||||
nop := func(string) time.Duration { return 0 }
|
||||
|
||||
// the headers are listed in order of preference
|
||||
retries := []retryData{
|
||||
{
|
||||
header: HeaderRetryAfterMS,
|
||||
units: time.Millisecond,
|
||||
custom: nop,
|
||||
},
|
||||
{
|
||||
header: HeaderXMSRetryAfterMS,
|
||||
units: time.Millisecond,
|
||||
custom: nop,
|
||||
},
|
||||
{
|
||||
header: HeaderRetryAfter,
|
||||
units: time.Second,
|
||||
|
||||
// retry-after values are expressed in either number of
|
||||
// seconds or an HTTP-date indicating when to try again
|
||||
custom: func(ra string) time.Duration {
|
||||
t, err := time.Parse(time.RFC1123, ra)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return time.Until(t)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, retry := range retries {
|
||||
v := resp.Header.Get(retry.header)
|
||||
if v == "" {
|
||||
continue
|
||||
}
|
||||
if retryAfter, _ := strconv.Atoi(v); retryAfter > 0 {
|
||||
return time.Duration(retryAfter) * retry.units
|
||||
} else if d := retry.custom(v); d > 0 {
|
||||
return d
|
||||
}
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
|
|
3
vendor/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go
generated
vendored
3
vendor/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go
generated
vendored
|
@ -5028,6 +5028,9 @@ var awsPartition = partition{
|
|||
endpointKey{
|
||||
Region: "eu-west-3",
|
||||
}: endpoint{},
|
||||
endpointKey{
|
||||
Region: "il-central-1",
|
||||
}: endpoint{},
|
||||
endpointKey{
|
||||
Region: "me-south-1",
|
||||
}: endpoint{},
|
||||
|
|
2
vendor/github.com/aws/aws-sdk-go/aws/version.go
generated
vendored
2
vendor/github.com/aws/aws-sdk-go/aws/version.go
generated
vendored
|
@ -5,4 +5,4 @@ package aws
|
|||
const SDKName = "aws-sdk-go"
|
||||
|
||||
// SDKVersion is the version of this SDK
|
||||
const SDKVersion = "1.48.16"
|
||||
const SDKVersion = "1.49.1"
|
||||
|
|
7
vendor/github.com/google/uuid/CHANGELOG.md
generated
vendored
7
vendor/github.com/google/uuid/CHANGELOG.md
generated
vendored
|
@ -1,5 +1,12 @@
|
|||
# Changelog
|
||||
|
||||
## [1.5.0](https://github.com/google/uuid/compare/v1.4.0...v1.5.0) (2023-12-12)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Validate UUID without creating new UUID ([#141](https://github.com/google/uuid/issues/141)) ([9ee7366](https://github.com/google/uuid/commit/9ee7366e66c9ad96bab89139418a713dc584ae29))
|
||||
|
||||
## [1.4.0](https://github.com/google/uuid/compare/v1.3.1...v1.4.0) (2023-10-26)
|
||||
|
||||
|
||||
|
|
21
vendor/github.com/google/uuid/time.go
generated
vendored
21
vendor/github.com/google/uuid/time.go
generated
vendored
|
@ -108,12 +108,23 @@ func setClockSequence(seq int) {
|
|||
}
|
||||
|
||||
// Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in
|
||||
// uuid. The time is only defined for version 1 and 2 UUIDs.
|
||||
// uuid. The time is only defined for version 1, 2, 6 and 7 UUIDs.
|
||||
func (uuid UUID) Time() Time {
|
||||
time := int64(binary.BigEndian.Uint32(uuid[0:4]))
|
||||
time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32
|
||||
time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48
|
||||
return Time(time)
|
||||
var t Time
|
||||
switch uuid.Version() {
|
||||
case 6:
|
||||
time := binary.BigEndian.Uint64(uuid[:8]) // Ignore uuid[6] version b0110
|
||||
t = Time(time)
|
||||
case 7:
|
||||
time := binary.BigEndian.Uint64(uuid[:8])
|
||||
t = Time((time>>16)*10000 + g1582ns100)
|
||||
default: // forward compatible
|
||||
time := int64(binary.BigEndian.Uint32(uuid[0:4]))
|
||||
time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32
|
||||
time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48
|
||||
t = Time(time)
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// ClockSequence returns the clock sequence encoded in uuid.
|
||||
|
|
53
vendor/github.com/google/uuid/uuid.go
generated
vendored
53
vendor/github.com/google/uuid/uuid.go
generated
vendored
|
@ -186,6 +186,59 @@ func Must(uuid UUID, err error) UUID {
|
|||
return uuid
|
||||
}
|
||||
|
||||
// Validate returns an error if s is not a properly formatted UUID in one of the following formats:
|
||||
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
// {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
|
||||
// It returns an error if the format is invalid, otherwise nil.
|
||||
func Validate(s string) error {
|
||||
switch len(s) {
|
||||
// Standard UUID format
|
||||
case 36:
|
||||
|
||||
// UUID with "urn:uuid:" prefix
|
||||
case 36 + 9:
|
||||
if !strings.EqualFold(s[:9], "urn:uuid:") {
|
||||
return fmt.Errorf("invalid urn prefix: %q", s[:9])
|
||||
}
|
||||
s = s[9:]
|
||||
|
||||
// UUID enclosed in braces
|
||||
case 36 + 2:
|
||||
if s[0] != '{' || s[len(s)-1] != '}' {
|
||||
return fmt.Errorf("invalid bracketed UUID format")
|
||||
}
|
||||
s = s[1 : len(s)-1]
|
||||
|
||||
// UUID without hyphens
|
||||
case 32:
|
||||
for i := 0; i < len(s); i += 2 {
|
||||
_, ok := xtob(s[i], s[i+1])
|
||||
if !ok {
|
||||
return errors.New("invalid UUID format")
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
return invalidLengthError{len(s)}
|
||||
}
|
||||
|
||||
// Check for standard UUID format
|
||||
if len(s) == 36 {
|
||||
if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
|
||||
return errors.New("invalid UUID format")
|
||||
}
|
||||
for _, x := range []int{0, 2, 4, 6, 9, 11, 14, 16, 19, 21, 24, 26, 28, 30, 32, 34} {
|
||||
if _, ok := xtob(s[x], s[x+1]); !ok {
|
||||
return errors.New("invalid UUID format")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||
// , or "" if uuid is invalid.
|
||||
func (uuid UUID) String() string {
|
||||
|
|
56
vendor/github.com/google/uuid/version6.go
generated
vendored
Normal file
56
vendor/github.com/google/uuid/version6.go
generated
vendored
Normal file
|
@ -0,0 +1,56 @@
|
|||
// Copyright 2023 Google Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package uuid
|
||||
|
||||
import "encoding/binary"
|
||||
|
||||
// UUID version 6 is a field-compatible version of UUIDv1, reordered for improved DB locality.
|
||||
// It is expected that UUIDv6 will primarily be used in contexts where there are existing v1 UUIDs.
|
||||
// Systems that do not involve legacy UUIDv1 SHOULD consider using UUIDv7 instead.
|
||||
//
|
||||
// see https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-03#uuidv6
|
||||
//
|
||||
// NewV6 returns a Version 6 UUID based on the current NodeID and clock
|
||||
// sequence, and the current time. If the NodeID has not been set by SetNodeID
|
||||
// or SetNodeInterface then it will be set automatically. If the NodeID cannot
|
||||
// be set NewV6 set NodeID is random bits automatically . If clock sequence has not been set by
|
||||
// SetClockSequence then it will be set automatically. If GetTime fails to
|
||||
// return the current NewV6 returns Nil and an error.
|
||||
func NewV6() (UUID, error) {
|
||||
var uuid UUID
|
||||
now, seq, err := GetTime()
|
||||
if err != nil {
|
||||
return uuid, err
|
||||
}
|
||||
|
||||
/*
|
||||
0 1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| time_high |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| time_mid | time_low_and_version |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|clk_seq_hi_res | clk_seq_low | node (0-1) |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| node (2-5) |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
binary.BigEndian.PutUint64(uuid[0:], uint64(now))
|
||||
binary.BigEndian.PutUint16(uuid[8:], seq)
|
||||
|
||||
uuid[6] = 0x60 | (uuid[6] & 0x0F)
|
||||
uuid[8] = 0x80 | (uuid[8] & 0x3F)
|
||||
|
||||
nodeMu.Lock()
|
||||
if nodeID == zeroID {
|
||||
setNodeInterface("")
|
||||
}
|
||||
copy(uuid[10:], nodeID[:])
|
||||
nodeMu.Unlock()
|
||||
|
||||
return uuid, nil
|
||||
}
|
75
vendor/github.com/google/uuid/version7.go
generated
vendored
Normal file
75
vendor/github.com/google/uuid/version7.go
generated
vendored
Normal file
|
@ -0,0 +1,75 @@
|
|||
// Copyright 2023 Google Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package uuid
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// UUID version 7 features a time-ordered value field derived from the widely
|
||||
// implemented and well known Unix Epoch timestamp source,
|
||||
// the number of milliseconds seconds since midnight 1 Jan 1970 UTC, leap seconds excluded.
|
||||
// As well as improved entropy characteristics over versions 1 or 6.
|
||||
//
|
||||
// see https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-03#name-uuid-version-7
|
||||
//
|
||||
// Implementations SHOULD utilize UUID version 7 over UUID version 1 and 6 if possible.
|
||||
//
|
||||
// NewV7 returns a Version 7 UUID based on the current time(Unix Epoch).
|
||||
// Uses the randomness pool if it was enabled with EnableRandPool.
|
||||
// On error, NewV7 returns Nil and an error
|
||||
func NewV7() (UUID, error) {
|
||||
uuid, err := NewRandom()
|
||||
if err != nil {
|
||||
return uuid, err
|
||||
}
|
||||
makeV7(uuid[:])
|
||||
return uuid, nil
|
||||
}
|
||||
|
||||
// NewV7FromReader returns a Version 7 UUID based on the current time(Unix Epoch).
|
||||
// it use NewRandomFromReader fill random bits.
|
||||
// On error, NewV7FromReader returns Nil and an error.
|
||||
func NewV7FromReader(r io.Reader) (UUID, error) {
|
||||
uuid, err := NewRandomFromReader(r)
|
||||
if err != nil {
|
||||
return uuid, err
|
||||
}
|
||||
|
||||
makeV7(uuid[:])
|
||||
return uuid, nil
|
||||
}
|
||||
|
||||
// makeV7 fill 48 bits time (uuid[0] - uuid[5]), set version b0111 (uuid[6])
|
||||
// uuid[8] already has the right version number (Variant is 10)
|
||||
// see function NewV7 and NewV7FromReader
|
||||
func makeV7(uuid []byte) {
|
||||
/*
|
||||
0 1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| unix_ts_ms |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| unix_ts_ms | ver | rand_a |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|var| rand_b |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| rand_b |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
_ = uuid[15] // bounds check
|
||||
|
||||
t := timeNow().UnixMilli()
|
||||
|
||||
uuid[0] = byte(t >> 40)
|
||||
uuid[1] = byte(t >> 32)
|
||||
uuid[2] = byte(t >> 24)
|
||||
uuid[3] = byte(t >> 16)
|
||||
uuid[4] = byte(t >> 8)
|
||||
uuid[5] = byte(t)
|
||||
|
||||
uuid[6] = 0x70 | (uuid[6] & 0x0F)
|
||||
// uuid[8] has already has right version
|
||||
}
|
201
vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/LICENSE
generated
vendored
Normal file
201
vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
229
vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/config.go
generated
vendored
Normal file
229
vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/config.go
generated
vendored
Normal file
|
@ -0,0 +1,229 @@
|
|||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package otelgrpc // import "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
|
||||
|
||||
import (
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
"go.opentelemetry.io/otel/propagation"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.17.0"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
const (
|
||||
// ScopeName is the instrumentation scope name.
|
||||
ScopeName = "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
|
||||
// GRPCStatusCodeKey is convention for numeric status code of a gRPC request.
|
||||
GRPCStatusCodeKey = attribute.Key("rpc.grpc.status_code")
|
||||
)
|
||||
|
||||
// Filter is a predicate used to determine whether a given request in
|
||||
// interceptor info should be traced. A Filter must return true if
|
||||
// the request should be traced.
|
||||
type Filter func(*InterceptorInfo) bool
|
||||
|
||||
// config is a group of options for this instrumentation.
|
||||
type config struct {
|
||||
Filter Filter
|
||||
Propagators propagation.TextMapPropagator
|
||||
TracerProvider trace.TracerProvider
|
||||
MeterProvider metric.MeterProvider
|
||||
SpanStartOptions []trace.SpanStartOption
|
||||
|
||||
ReceivedEvent bool
|
||||
SentEvent bool
|
||||
|
||||
tracer trace.Tracer
|
||||
meter metric.Meter
|
||||
|
||||
rpcDuration metric.Float64Histogram
|
||||
rpcRequestSize metric.Int64Histogram
|
||||
rpcResponseSize metric.Int64Histogram
|
||||
rpcRequestsPerRPC metric.Int64Histogram
|
||||
rpcResponsesPerRPC metric.Int64Histogram
|
||||
}
|
||||
|
||||
// Option applies an option value for a config.
|
||||
type Option interface {
|
||||
apply(*config)
|
||||
}
|
||||
|
||||
// newConfig returns a config configured with all the passed Options.
|
||||
func newConfig(opts []Option, role string) *config {
|
||||
c := &config{
|
||||
Propagators: otel.GetTextMapPropagator(),
|
||||
TracerProvider: otel.GetTracerProvider(),
|
||||
MeterProvider: otel.GetMeterProvider(),
|
||||
}
|
||||
for _, o := range opts {
|
||||
o.apply(c)
|
||||
}
|
||||
|
||||
c.tracer = c.TracerProvider.Tracer(
|
||||
ScopeName,
|
||||
trace.WithInstrumentationVersion(SemVersion()),
|
||||
)
|
||||
|
||||
c.meter = c.MeterProvider.Meter(
|
||||
ScopeName,
|
||||
metric.WithInstrumentationVersion(Version()),
|
||||
metric.WithSchemaURL(semconv.SchemaURL),
|
||||
)
|
||||
|
||||
var err error
|
||||
c.rpcDuration, err = c.meter.Float64Histogram("rpc."+role+".duration",
|
||||
metric.WithDescription("Measures the duration of inbound RPC."),
|
||||
metric.WithUnit("ms"))
|
||||
if err != nil {
|
||||
otel.Handle(err)
|
||||
}
|
||||
|
||||
c.rpcRequestSize, err = c.meter.Int64Histogram("rpc."+role+".request.size",
|
||||
metric.WithDescription("Measures size of RPC request messages (uncompressed)."),
|
||||
metric.WithUnit("By"))
|
||||
if err != nil {
|
||||
otel.Handle(err)
|
||||
}
|
||||
|
||||
c.rpcResponseSize, err = c.meter.Int64Histogram("rpc."+role+".response.size",
|
||||
metric.WithDescription("Measures size of RPC response messages (uncompressed)."),
|
||||
metric.WithUnit("By"))
|
||||
if err != nil {
|
||||
otel.Handle(err)
|
||||
}
|
||||
|
||||
c.rpcRequestsPerRPC, err = c.meter.Int64Histogram("rpc."+role+".requests_per_rpc",
|
||||
metric.WithDescription("Measures the number of messages received per RPC. Should be 1 for all non-streaming RPCs."),
|
||||
metric.WithUnit("{count}"))
|
||||
if err != nil {
|
||||
otel.Handle(err)
|
||||
}
|
||||
|
||||
c.rpcResponsesPerRPC, err = c.meter.Int64Histogram("rpc."+role+".responses_per_rpc",
|
||||
metric.WithDescription("Measures the number of messages received per RPC. Should be 1 for all non-streaming RPCs."),
|
||||
metric.WithUnit("{count}"))
|
||||
if err != nil {
|
||||
otel.Handle(err)
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
type propagatorsOption struct{ p propagation.TextMapPropagator }
|
||||
|
||||
func (o propagatorsOption) apply(c *config) {
|
||||
if o.p != nil {
|
||||
c.Propagators = o.p
|
||||
}
|
||||
}
|
||||
|
||||
// WithPropagators returns an Option to use the Propagators when extracting
|
||||
// and injecting trace context from requests.
|
||||
func WithPropagators(p propagation.TextMapPropagator) Option {
|
||||
return propagatorsOption{p: p}
|
||||
}
|
||||
|
||||
type tracerProviderOption struct{ tp trace.TracerProvider }
|
||||
|
||||
func (o tracerProviderOption) apply(c *config) {
|
||||
if o.tp != nil {
|
||||
c.TracerProvider = o.tp
|
||||
}
|
||||
}
|
||||
|
||||
// WithInterceptorFilter returns an Option to use the request filter.
|
||||
//
|
||||
// Deprecated: Use stats handlers instead.
|
||||
func WithInterceptorFilter(f Filter) Option {
|
||||
return interceptorFilterOption{f: f}
|
||||
}
|
||||
|
||||
type interceptorFilterOption struct {
|
||||
f Filter
|
||||
}
|
||||
|
||||
func (o interceptorFilterOption) apply(c *config) {
|
||||
if o.f != nil {
|
||||
c.Filter = o.f
|
||||
}
|
||||
}
|
||||
|
||||
// WithTracerProvider returns an Option to use the TracerProvider when
|
||||
// creating a Tracer.
|
||||
func WithTracerProvider(tp trace.TracerProvider) Option {
|
||||
return tracerProviderOption{tp: tp}
|
||||
}
|
||||
|
||||
type meterProviderOption struct{ mp metric.MeterProvider }
|
||||
|
||||
func (o meterProviderOption) apply(c *config) {
|
||||
if o.mp != nil {
|
||||
c.MeterProvider = o.mp
|
||||
}
|
||||
}
|
||||
|
||||
// WithMeterProvider returns an Option to use the MeterProvider when
|
||||
// creating a Meter. If this option is not provide the global MeterProvider will be used.
|
||||
func WithMeterProvider(mp metric.MeterProvider) Option {
|
||||
return meterProviderOption{mp: mp}
|
||||
}
|
||||
|
||||
// Event type that can be recorded, see WithMessageEvents.
|
||||
type Event int
|
||||
|
||||
// Different types of events that can be recorded, see WithMessageEvents.
|
||||
const (
|
||||
ReceivedEvents Event = iota
|
||||
SentEvents
|
||||
)
|
||||
|
||||
type messageEventsProviderOption struct {
|
||||
events []Event
|
||||
}
|
||||
|
||||
func (m messageEventsProviderOption) apply(c *config) {
|
||||
for _, e := range m.events {
|
||||
switch e {
|
||||
case ReceivedEvents:
|
||||
c.ReceivedEvent = true
|
||||
case SentEvents:
|
||||
c.SentEvent = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithMessageEvents configures the Handler to record the specified events
|
||||
// (span.AddEvent) on spans. By default only summary attributes are added at the
|
||||
// end of the request.
|
||||
//
|
||||
// Valid events are:
|
||||
// - ReceivedEvents: Record the number of bytes read after every gRPC read operation.
|
||||
// - SentEvents: Record the number of bytes written after every gRPC write operation.
|
||||
func WithMessageEvents(events ...Event) Option {
|
||||
return messageEventsProviderOption{events: events}
|
||||
}
|
||||
|
||||
type spanStartOption struct{ opts []trace.SpanStartOption }
|
||||
|
||||
func (o spanStartOption) apply(c *config) {
|
||||
c.SpanStartOptions = append(c.SpanStartOptions, o.opts...)
|
||||
}
|
||||
|
||||
// WithSpanOptions configures an additional set of
|
||||
// trace.SpanOptions, which are applied to each new span.
|
||||
func WithSpanOptions(opts ...trace.SpanStartOption) Option {
|
||||
return spanStartOption{opts}
|
||||
}
|
22
vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/doc.go
generated
vendored
Normal file
22
vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/*
|
||||
Package otelgrpc is the instrumentation library for [google.golang.org/grpc].
|
||||
|
||||
Use [NewClientHandler] with [grpc.WithStatsHandler] to instrument a gRPC client.
|
||||
|
||||
Use [NewServerHandler] with [grpc.StatsHandler] to instrument a gRPC server.
|
||||
*/
|
||||
package otelgrpc // import "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
|
540
vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/interceptor.go
generated
vendored
Normal file
540
vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/interceptor.go
generated
vendored
Normal file
|
@ -0,0 +1,540 @@
|
|||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package otelgrpc // import "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
|
||||
|
||||
// gRPC tracing middleware
|
||||
// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/rpc.md
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
grpc_codes "google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/peer"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/internal"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.17.0"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
type messageType attribute.KeyValue
|
||||
|
||||
// Event adds an event of the messageType to the span associated with the
|
||||
// passed context with a message id.
|
||||
func (m messageType) Event(ctx context.Context, id int, _ interface{}) {
|
||||
span := trace.SpanFromContext(ctx)
|
||||
if !span.IsRecording() {
|
||||
return
|
||||
}
|
||||
span.AddEvent("message", trace.WithAttributes(
|
||||
attribute.KeyValue(m),
|
||||
RPCMessageIDKey.Int(id),
|
||||
))
|
||||
}
|
||||
|
||||
var (
|
||||
messageSent = messageType(RPCMessageTypeSent)
|
||||
messageReceived = messageType(RPCMessageTypeReceived)
|
||||
)
|
||||
|
||||
// UnaryClientInterceptor returns a grpc.UnaryClientInterceptor suitable
|
||||
// for use in a grpc.Dial call.
|
||||
//
|
||||
// Deprecated: Use [NewClientHandler] instead.
|
||||
func UnaryClientInterceptor(opts ...Option) grpc.UnaryClientInterceptor {
|
||||
cfg := newConfig(opts, "client")
|
||||
tracer := cfg.TracerProvider.Tracer(
|
||||
ScopeName,
|
||||
trace.WithInstrumentationVersion(Version()),
|
||||
)
|
||||
|
||||
return func(
|
||||
ctx context.Context,
|
||||
method string,
|
||||
req, reply interface{},
|
||||
cc *grpc.ClientConn,
|
||||
invoker grpc.UnaryInvoker,
|
||||
callOpts ...grpc.CallOption,
|
||||
) error {
|
||||
i := &InterceptorInfo{
|
||||
Method: method,
|
||||
Type: UnaryClient,
|
||||
}
|
||||
if cfg.Filter != nil && !cfg.Filter(i) {
|
||||
return invoker(ctx, method, req, reply, cc, callOpts...)
|
||||
}
|
||||
|
||||
name, attr, _ := telemetryAttributes(method, cc.Target())
|
||||
|
||||
startOpts := append([]trace.SpanStartOption{
|
||||
trace.WithSpanKind(trace.SpanKindClient),
|
||||
trace.WithAttributes(attr...),
|
||||
},
|
||||
cfg.SpanStartOptions...,
|
||||
)
|
||||
|
||||
ctx, span := tracer.Start(
|
||||
ctx,
|
||||
name,
|
||||
startOpts...,
|
||||
)
|
||||
defer span.End()
|
||||
|
||||
ctx = inject(ctx, cfg.Propagators)
|
||||
|
||||
if cfg.SentEvent {
|
||||
messageSent.Event(ctx, 1, req)
|
||||
}
|
||||
|
||||
err := invoker(ctx, method, req, reply, cc, callOpts...)
|
||||
|
||||
if cfg.ReceivedEvent {
|
||||
messageReceived.Event(ctx, 1, reply)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
s, _ := status.FromError(err)
|
||||
span.SetStatus(codes.Error, s.Message())
|
||||
span.SetAttributes(statusCodeAttr(s.Code()))
|
||||
} else {
|
||||
span.SetAttributes(statusCodeAttr(grpc_codes.OK))
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// clientStream wraps around the embedded grpc.ClientStream, and intercepts the RecvMsg and
|
||||
// SendMsg method call.
|
||||
type clientStream struct {
|
||||
grpc.ClientStream
|
||||
desc *grpc.StreamDesc
|
||||
|
||||
span trace.Span
|
||||
|
||||
receivedEvent bool
|
||||
sentEvent bool
|
||||
|
||||
receivedMessageID int
|
||||
sentMessageID int
|
||||
}
|
||||
|
||||
var _ = proto.Marshal
|
||||
|
||||
func (w *clientStream) RecvMsg(m interface{}) error {
|
||||
err := w.ClientStream.RecvMsg(m)
|
||||
|
||||
if err == nil && !w.desc.ServerStreams {
|
||||
w.endSpan(nil)
|
||||
} else if err == io.EOF {
|
||||
w.endSpan(nil)
|
||||
} else if err != nil {
|
||||
w.endSpan(err)
|
||||
} else {
|
||||
w.receivedMessageID++
|
||||
|
||||
if w.receivedEvent {
|
||||
messageReceived.Event(w.Context(), w.receivedMessageID, m)
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (w *clientStream) SendMsg(m interface{}) error {
|
||||
err := w.ClientStream.SendMsg(m)
|
||||
|
||||
w.sentMessageID++
|
||||
|
||||
if w.sentEvent {
|
||||
messageSent.Event(w.Context(), w.sentMessageID, m)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
w.endSpan(err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (w *clientStream) Header() (metadata.MD, error) {
|
||||
md, err := w.ClientStream.Header()
|
||||
if err != nil {
|
||||
w.endSpan(err)
|
||||
}
|
||||
|
||||
return md, err
|
||||
}
|
||||
|
||||
func (w *clientStream) CloseSend() error {
|
||||
err := w.ClientStream.CloseSend()
|
||||
if err != nil {
|
||||
w.endSpan(err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func wrapClientStream(ctx context.Context, s grpc.ClientStream, desc *grpc.StreamDesc, span trace.Span, cfg *config) *clientStream {
|
||||
return &clientStream{
|
||||
ClientStream: s,
|
||||
span: span,
|
||||
desc: desc,
|
||||
receivedEvent: cfg.ReceivedEvent,
|
||||
sentEvent: cfg.SentEvent,
|
||||
}
|
||||
}
|
||||
|
||||
func (w *clientStream) endSpan(err error) {
|
||||
if err != nil {
|
||||
s, _ := status.FromError(err)
|
||||
w.span.SetStatus(codes.Error, s.Message())
|
||||
w.span.SetAttributes(statusCodeAttr(s.Code()))
|
||||
} else {
|
||||
w.span.SetAttributes(statusCodeAttr(grpc_codes.OK))
|
||||
}
|
||||
|
||||
w.span.End()
|
||||
}
|
||||
|
||||
// StreamClientInterceptor returns a grpc.StreamClientInterceptor suitable
|
||||
// for use in a grpc.Dial call.
|
||||
//
|
||||
// Deprecated: Use [NewClientHandler] instead.
|
||||
func StreamClientInterceptor(opts ...Option) grpc.StreamClientInterceptor {
|
||||
cfg := newConfig(opts, "client")
|
||||
tracer := cfg.TracerProvider.Tracer(
|
||||
ScopeName,
|
||||
trace.WithInstrumentationVersion(Version()),
|
||||
)
|
||||
|
||||
return func(
|
||||
ctx context.Context,
|
||||
desc *grpc.StreamDesc,
|
||||
cc *grpc.ClientConn,
|
||||
method string,
|
||||
streamer grpc.Streamer,
|
||||
callOpts ...grpc.CallOption,
|
||||
) (grpc.ClientStream, error) {
|
||||
i := &InterceptorInfo{
|
||||
Method: method,
|
||||
Type: StreamClient,
|
||||
}
|
||||
if cfg.Filter != nil && !cfg.Filter(i) {
|
||||
return streamer(ctx, desc, cc, method, callOpts...)
|
||||
}
|
||||
|
||||
name, attr, _ := telemetryAttributes(method, cc.Target())
|
||||
|
||||
startOpts := append([]trace.SpanStartOption{
|
||||
trace.WithSpanKind(trace.SpanKindClient),
|
||||
trace.WithAttributes(attr...),
|
||||
},
|
||||
cfg.SpanStartOptions...,
|
||||
)
|
||||
|
||||
ctx, span := tracer.Start(
|
||||
ctx,
|
||||
name,
|
||||
startOpts...,
|
||||
)
|
||||
|
||||
ctx = inject(ctx, cfg.Propagators)
|
||||
|
||||
s, err := streamer(ctx, desc, cc, method, callOpts...)
|
||||
if err != nil {
|
||||
grpcStatus, _ := status.FromError(err)
|
||||
span.SetStatus(codes.Error, grpcStatus.Message())
|
||||
span.SetAttributes(statusCodeAttr(grpcStatus.Code()))
|
||||
span.End()
|
||||
return s, err
|
||||
}
|
||||
stream := wrapClientStream(ctx, s, desc, span, cfg)
|
||||
return stream, nil
|
||||
}
|
||||
}
|
||||
|
||||
// UnaryServerInterceptor returns a grpc.UnaryServerInterceptor suitable
|
||||
// for use in a grpc.NewServer call.
|
||||
//
|
||||
// Deprecated: Use [NewServerHandler] instead.
|
||||
func UnaryServerInterceptor(opts ...Option) grpc.UnaryServerInterceptor {
|
||||
cfg := newConfig(opts, "server")
|
||||
tracer := cfg.TracerProvider.Tracer(
|
||||
ScopeName,
|
||||
trace.WithInstrumentationVersion(Version()),
|
||||
)
|
||||
|
||||
return func(
|
||||
ctx context.Context,
|
||||
req interface{},
|
||||
info *grpc.UnaryServerInfo,
|
||||
handler grpc.UnaryHandler,
|
||||
) (interface{}, error) {
|
||||
i := &InterceptorInfo{
|
||||
UnaryServerInfo: info,
|
||||
Type: UnaryServer,
|
||||
}
|
||||
if cfg.Filter != nil && !cfg.Filter(i) {
|
||||
return handler(ctx, req)
|
||||
}
|
||||
|
||||
ctx = extract(ctx, cfg.Propagators)
|
||||
name, attr, metricAttrs := telemetryAttributes(info.FullMethod, peerFromCtx(ctx))
|
||||
|
||||
startOpts := append([]trace.SpanStartOption{
|
||||
trace.WithSpanKind(trace.SpanKindServer),
|
||||
trace.WithAttributes(attr...),
|
||||
},
|
||||
cfg.SpanStartOptions...,
|
||||
)
|
||||
|
||||
ctx, span := tracer.Start(
|
||||
trace.ContextWithRemoteSpanContext(ctx, trace.SpanContextFromContext(ctx)),
|
||||
name,
|
||||
startOpts...,
|
||||
)
|
||||
defer span.End()
|
||||
|
||||
if cfg.ReceivedEvent {
|
||||
messageReceived.Event(ctx, 1, req)
|
||||
}
|
||||
|
||||
before := time.Now()
|
||||
|
||||
resp, err := handler(ctx, req)
|
||||
|
||||
s, _ := status.FromError(err)
|
||||
if err != nil {
|
||||
statusCode, msg := serverStatus(s)
|
||||
span.SetStatus(statusCode, msg)
|
||||
if cfg.SentEvent {
|
||||
messageSent.Event(ctx, 1, s.Proto())
|
||||
}
|
||||
} else {
|
||||
if cfg.SentEvent {
|
||||
messageSent.Event(ctx, 1, resp)
|
||||
}
|
||||
}
|
||||
grpcStatusCodeAttr := statusCodeAttr(s.Code())
|
||||
span.SetAttributes(grpcStatusCodeAttr)
|
||||
|
||||
// Use floating point division here for higher precision (instead of Millisecond method).
|
||||
elapsedTime := float64(time.Since(before)) / float64(time.Millisecond)
|
||||
|
||||
metricAttrs = append(metricAttrs, grpcStatusCodeAttr)
|
||||
cfg.rpcDuration.Record(ctx, elapsedTime, metric.WithAttributes(metricAttrs...))
|
||||
|
||||
return resp, err
|
||||
}
|
||||
}
|
||||
|
||||
// serverStream wraps around the embedded grpc.ServerStream, and intercepts the RecvMsg and
|
||||
// SendMsg method call.
|
||||
type serverStream struct {
|
||||
grpc.ServerStream
|
||||
ctx context.Context
|
||||
|
||||
receivedMessageID int
|
||||
sentMessageID int
|
||||
|
||||
receivedEvent bool
|
||||
sentEvent bool
|
||||
}
|
||||
|
||||
func (w *serverStream) Context() context.Context {
|
||||
return w.ctx
|
||||
}
|
||||
|
||||
func (w *serverStream) RecvMsg(m interface{}) error {
|
||||
err := w.ServerStream.RecvMsg(m)
|
||||
|
||||
if err == nil {
|
||||
w.receivedMessageID++
|
||||
if w.receivedEvent {
|
||||
messageReceived.Event(w.Context(), w.receivedMessageID, m)
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (w *serverStream) SendMsg(m interface{}) error {
|
||||
err := w.ServerStream.SendMsg(m)
|
||||
|
||||
w.sentMessageID++
|
||||
if w.sentEvent {
|
||||
messageSent.Event(w.Context(), w.sentMessageID, m)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func wrapServerStream(ctx context.Context, ss grpc.ServerStream, cfg *config) *serverStream {
|
||||
return &serverStream{
|
||||
ServerStream: ss,
|
||||
ctx: ctx,
|
||||
receivedEvent: cfg.ReceivedEvent,
|
||||
sentEvent: cfg.SentEvent,
|
||||
}
|
||||
}
|
||||
|
||||
// StreamServerInterceptor returns a grpc.StreamServerInterceptor suitable
|
||||
// for use in a grpc.NewServer call.
|
||||
//
|
||||
// Deprecated: Use [NewServerHandler] instead.
|
||||
func StreamServerInterceptor(opts ...Option) grpc.StreamServerInterceptor {
|
||||
cfg := newConfig(opts, "server")
|
||||
tracer := cfg.TracerProvider.Tracer(
|
||||
ScopeName,
|
||||
trace.WithInstrumentationVersion(Version()),
|
||||
)
|
||||
|
||||
return func(
|
||||
srv interface{},
|
||||
ss grpc.ServerStream,
|
||||
info *grpc.StreamServerInfo,
|
||||
handler grpc.StreamHandler,
|
||||
) error {
|
||||
ctx := ss.Context()
|
||||
i := &InterceptorInfo{
|
||||
StreamServerInfo: info,
|
||||
Type: StreamServer,
|
||||
}
|
||||
if cfg.Filter != nil && !cfg.Filter(i) {
|
||||
return handler(srv, wrapServerStream(ctx, ss, cfg))
|
||||
}
|
||||
|
||||
ctx = extract(ctx, cfg.Propagators)
|
||||
name, attr, _ := telemetryAttributes(info.FullMethod, peerFromCtx(ctx))
|
||||
|
||||
startOpts := append([]trace.SpanStartOption{
|
||||
trace.WithSpanKind(trace.SpanKindServer),
|
||||
trace.WithAttributes(attr...),
|
||||
},
|
||||
cfg.SpanStartOptions...,
|
||||
)
|
||||
|
||||
ctx, span := tracer.Start(
|
||||
trace.ContextWithRemoteSpanContext(ctx, trace.SpanContextFromContext(ctx)),
|
||||
name,
|
||||
startOpts...,
|
||||
)
|
||||
defer span.End()
|
||||
|
||||
err := handler(srv, wrapServerStream(ctx, ss, cfg))
|
||||
if err != nil {
|
||||
s, _ := status.FromError(err)
|
||||
statusCode, msg := serverStatus(s)
|
||||
span.SetStatus(statusCode, msg)
|
||||
span.SetAttributes(statusCodeAttr(s.Code()))
|
||||
} else {
|
||||
span.SetAttributes(statusCodeAttr(grpc_codes.OK))
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// telemetryAttributes returns a span name and span and metric attributes from
|
||||
// the gRPC method and peer address.
|
||||
func telemetryAttributes(fullMethod, peerAddress string) (string, []attribute.KeyValue, []attribute.KeyValue) {
|
||||
name, methodAttrs := internal.ParseFullMethod(fullMethod)
|
||||
peerAttrs := peerAttr(peerAddress)
|
||||
|
||||
attrs := make([]attribute.KeyValue, 0, 1+len(methodAttrs)+len(peerAttrs))
|
||||
attrs = append(attrs, RPCSystemGRPC)
|
||||
attrs = append(attrs, methodAttrs...)
|
||||
metricAttrs := attrs[:1+len(methodAttrs)]
|
||||
attrs = append(attrs, peerAttrs...)
|
||||
return name, attrs, metricAttrs
|
||||
}
|
||||
|
||||
// peerAttr returns attributes about the peer address.
|
||||
func peerAttr(addr string) []attribute.KeyValue {
|
||||
host, p, err := net.SplitHostPort(addr)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if host == "" {
|
||||
host = "127.0.0.1"
|
||||
}
|
||||
port, err := strconv.Atoi(p)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var attr []attribute.KeyValue
|
||||
if ip := net.ParseIP(host); ip != nil {
|
||||
attr = []attribute.KeyValue{
|
||||
semconv.NetSockPeerAddr(host),
|
||||
semconv.NetSockPeerPort(port),
|
||||
}
|
||||
} else {
|
||||
attr = []attribute.KeyValue{
|
||||
semconv.NetPeerName(host),
|
||||
semconv.NetPeerPort(port),
|
||||
}
|
||||
}
|
||||
|
||||
return attr
|
||||
}
|
||||
|
||||
// peerFromCtx returns a peer address from a context, if one exists.
|
||||
func peerFromCtx(ctx context.Context) string {
|
||||
p, ok := peer.FromContext(ctx)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return p.Addr.String()
|
||||
}
|
||||
|
||||
// statusCodeAttr returns status code attribute based on given gRPC code.
|
||||
func statusCodeAttr(c grpc_codes.Code) attribute.KeyValue {
|
||||
return GRPCStatusCodeKey.Int64(int64(c))
|
||||
}
|
||||
|
||||
// serverStatus returns a span status code and message for a given gRPC
|
||||
// status code. It maps specific gRPC status codes to a corresponding span
|
||||
// status code and message. This function is intended for use on the server
|
||||
// side of a gRPC connection.
|
||||
//
|
||||
// If the gRPC status code is Unknown, DeadlineExceeded, Unimplemented,
|
||||
// Internal, Unavailable, or DataLoss, it returns a span status code of Error
|
||||
// and the message from the gRPC status. Otherwise, it returns a span status
|
||||
// code of Unset and an empty message.
|
||||
func serverStatus(grpcStatus *status.Status) (codes.Code, string) {
|
||||
switch grpcStatus.Code() {
|
||||
case grpc_codes.Unknown,
|
||||
grpc_codes.DeadlineExceeded,
|
||||
grpc_codes.Unimplemented,
|
||||
grpc_codes.Internal,
|
||||
grpc_codes.Unavailable,
|
||||
grpc_codes.DataLoss:
|
||||
return codes.Error, grpcStatus.Message()
|
||||
default:
|
||||
return codes.Unset, ""
|
||||
}
|
||||
}
|
50
vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/interceptorinfo.go
generated
vendored
Normal file
50
vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/interceptorinfo.go
generated
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package otelgrpc // import "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
|
||||
|
||||
import (
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// InterceptorType is the flag to define which gRPC interceptor
|
||||
// the InterceptorInfo object is.
|
||||
type InterceptorType uint8
|
||||
|
||||
const (
|
||||
// UndefinedInterceptor is the type for the interceptor information that is not
|
||||
// well initialized or categorized to other types.
|
||||
UndefinedInterceptor InterceptorType = iota
|
||||
// UnaryClient is the type for grpc.UnaryClient interceptor.
|
||||
UnaryClient
|
||||
// StreamClient is the type for grpc.StreamClient interceptor.
|
||||
StreamClient
|
||||
// UnaryServer is the type for grpc.UnaryServer interceptor.
|
||||
UnaryServer
|
||||
// StreamServer is the type for grpc.StreamServer interceptor.
|
||||
StreamServer
|
||||
)
|
||||
|
||||
// InterceptorInfo is the union of some arguments to four types of
|
||||
// gRPC interceptors.
|
||||
type InterceptorInfo struct {
|
||||
// Method is method name registered to UnaryClient and StreamClient
|
||||
Method string
|
||||
// UnaryServerInfo is the metadata for UnaryServer
|
||||
UnaryServerInfo *grpc.UnaryServerInfo
|
||||
// StreamServerInfo if the metadata for StreamServer
|
||||
StreamServerInfo *grpc.StreamServerInfo
|
||||
// Type is the type for interceptor
|
||||
Type InterceptorType
|
||||
}
|
51
vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/internal/parse.go
generated
vendored
Normal file
51
vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/internal/parse.go
generated
vendored
Normal file
|
@ -0,0 +1,51 @@
|
|||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package internal // import "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/internal"
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.17.0"
|
||||
)
|
||||
|
||||
// ParseFullMethod returns a span name following the OpenTelemetry semantic
|
||||
// conventions as well as all applicable span attribute.KeyValue attributes based
|
||||
// on a gRPC's FullMethod.
|
||||
//
|
||||
// Parsing is consistent with grpc-go implementation:
|
||||
// https://github.com/grpc/grpc-go/blob/v1.57.0/internal/grpcutil/method.go#L26-L39
|
||||
func ParseFullMethod(fullMethod string) (string, []attribute.KeyValue) {
|
||||
if !strings.HasPrefix(fullMethod, "/") {
|
||||
// Invalid format, does not follow `/package.service/method`.
|
||||
return fullMethod, nil
|
||||
}
|
||||
name := fullMethod[1:]
|
||||
pos := strings.LastIndex(name, "/")
|
||||
if pos < 0 {
|
||||
// Invalid format, does not follow `/package.service/method`.
|
||||
return name, nil
|
||||
}
|
||||
service, method := name[:pos], name[pos+1:]
|
||||
|
||||
var attrs []attribute.KeyValue
|
||||
if service != "" {
|
||||
attrs = append(attrs, semconv.RPCService(service))
|
||||
}
|
||||
if method != "" {
|
||||
attrs = append(attrs, semconv.RPCMethod(method))
|
||||
}
|
||||
return name, attrs
|
||||
}
|
98
vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/metadata_supplier.go
generated
vendored
Normal file
98
vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/metadata_supplier.go
generated
vendored
Normal file
|
@ -0,0 +1,98 @@
|
|||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package otelgrpc // import "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"google.golang.org/grpc/metadata"
|
||||
|
||||
"go.opentelemetry.io/otel/baggage"
|
||||
"go.opentelemetry.io/otel/propagation"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
type metadataSupplier struct {
|
||||
metadata *metadata.MD
|
||||
}
|
||||
|
||||
// assert that metadataSupplier implements the TextMapCarrier interface.
|
||||
var _ propagation.TextMapCarrier = &metadataSupplier{}
|
||||
|
||||
func (s *metadataSupplier) Get(key string) string {
|
||||
values := s.metadata.Get(key)
|
||||
if len(values) == 0 {
|
||||
return ""
|
||||
}
|
||||
return values[0]
|
||||
}
|
||||
|
||||
func (s *metadataSupplier) Set(key string, value string) {
|
||||
s.metadata.Set(key, value)
|
||||
}
|
||||
|
||||
func (s *metadataSupplier) Keys() []string {
|
||||
out := make([]string, 0, len(*s.metadata))
|
||||
for key := range *s.metadata {
|
||||
out = append(out, key)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// Inject injects correlation context and span context into the gRPC
|
||||
// metadata object. This function is meant to be used on outgoing
|
||||
// requests.
|
||||
// Deprecated: Unnecessary public func.
|
||||
func Inject(ctx context.Context, md *metadata.MD, opts ...Option) {
|
||||
c := newConfig(opts, "")
|
||||
c.Propagators.Inject(ctx, &metadataSupplier{
|
||||
metadata: md,
|
||||
})
|
||||
}
|
||||
|
||||
func inject(ctx context.Context, propagators propagation.TextMapPropagator) context.Context {
|
||||
md, ok := metadata.FromOutgoingContext(ctx)
|
||||
if !ok {
|
||||
md = metadata.MD{}
|
||||
}
|
||||
propagators.Inject(ctx, &metadataSupplier{
|
||||
metadata: &md,
|
||||
})
|
||||
return metadata.NewOutgoingContext(ctx, md)
|
||||
}
|
||||
|
||||
// Extract returns the correlation context and span context that
|
||||
// another service encoded in the gRPC metadata object with Inject.
|
||||
// This function is meant to be used on incoming requests.
|
||||
// Deprecated: Unnecessary public func.
|
||||
func Extract(ctx context.Context, md *metadata.MD, opts ...Option) (baggage.Baggage, trace.SpanContext) {
|
||||
c := newConfig(opts, "")
|
||||
ctx = c.Propagators.Extract(ctx, &metadataSupplier{
|
||||
metadata: md,
|
||||
})
|
||||
|
||||
return baggage.FromContext(ctx), trace.SpanContextFromContext(ctx)
|
||||
}
|
||||
|
||||
func extract(ctx context.Context, propagators propagation.TextMapPropagator) context.Context {
|
||||
md, ok := metadata.FromIncomingContext(ctx)
|
||||
if !ok {
|
||||
md = metadata.MD{}
|
||||
}
|
||||
|
||||
return propagators.Extract(ctx, &metadataSupplier{
|
||||
metadata: &md,
|
||||
})
|
||||
}
|
52
vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/semconv.go
generated
vendored
Normal file
52
vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/semconv.go
generated
vendored
Normal file
|
@ -0,0 +1,52 @@
|
|||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package otelgrpc // import "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
|
||||
|
||||
import (
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.17.0"
|
||||
)
|
||||
|
||||
// Semantic conventions for attribute keys for gRPC.
|
||||
const (
|
||||
// Name of message transmitted or received.
|
||||
RPCNameKey = attribute.Key("name")
|
||||
|
||||
// Type of message transmitted or received.
|
||||
RPCMessageTypeKey = attribute.Key("message.type")
|
||||
|
||||
// Identifier of message transmitted or received.
|
||||
RPCMessageIDKey = attribute.Key("message.id")
|
||||
|
||||
// The compressed size of the message transmitted or received in bytes.
|
||||
RPCMessageCompressedSizeKey = attribute.Key("message.compressed_size")
|
||||
|
||||
// The uncompressed size of the message transmitted or received in
|
||||
// bytes.
|
||||
RPCMessageUncompressedSizeKey = attribute.Key("message.uncompressed_size")
|
||||
)
|
||||
|
||||
// Semantic conventions for common RPC attributes.
|
||||
var (
|
||||
// Semantic convention for gRPC as the remoting system.
|
||||
RPCSystemGRPC = semconv.RPCSystemGRPC
|
||||
|
||||
// Semantic convention for a message named message.
|
||||
RPCNameMessage = RPCNameKey.String("message")
|
||||
|
||||
// Semantic conventions for RPC message types.
|
||||
RPCMessageTypeSent = RPCMessageTypeKey.String("SENT")
|
||||
RPCMessageTypeReceived = RPCMessageTypeKey.String("RECEIVED")
|
||||
)
|
238
vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/stats_handler.go
generated
vendored
Normal file
238
vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/stats_handler.go
generated
vendored
Normal file
|
@ -0,0 +1,238 @@
|
|||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package otelgrpc // import "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
grpc_codes "google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/stats"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/internal"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.17.0"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
type gRPCContextKey struct{}
|
||||
|
||||
type gRPCContext struct {
|
||||
messagesReceived int64
|
||||
messagesSent int64
|
||||
metricAttrs []attribute.KeyValue
|
||||
}
|
||||
|
||||
type serverHandler struct {
|
||||
*config
|
||||
}
|
||||
|
||||
// NewServerHandler creates a stats.Handler for gRPC server.
|
||||
func NewServerHandler(opts ...Option) stats.Handler {
|
||||
h := &serverHandler{
|
||||
config: newConfig(opts, "server"),
|
||||
}
|
||||
|
||||
return h
|
||||
}
|
||||
|
||||
// TagConn can attach some information to the given context.
|
||||
func (h *serverHandler) TagConn(ctx context.Context, info *stats.ConnTagInfo) context.Context {
|
||||
span := trace.SpanFromContext(ctx)
|
||||
attrs := peerAttr(peerFromCtx(ctx))
|
||||
span.SetAttributes(attrs...)
|
||||
return ctx
|
||||
}
|
||||
|
||||
// HandleConn processes the Conn stats.
|
||||
func (h *serverHandler) HandleConn(ctx context.Context, info stats.ConnStats) {
|
||||
}
|
||||
|
||||
// TagRPC can attach some information to the given context.
|
||||
func (h *serverHandler) TagRPC(ctx context.Context, info *stats.RPCTagInfo) context.Context {
|
||||
ctx = extract(ctx, h.config.Propagators)
|
||||
|
||||
name, attrs := internal.ParseFullMethod(info.FullMethodName)
|
||||
attrs = append(attrs, RPCSystemGRPC)
|
||||
ctx, _ = h.tracer.Start(
|
||||
trace.ContextWithRemoteSpanContext(ctx, trace.SpanContextFromContext(ctx)),
|
||||
name,
|
||||
trace.WithSpanKind(trace.SpanKindServer),
|
||||
trace.WithAttributes(attrs...),
|
||||
)
|
||||
|
||||
gctx := gRPCContext{
|
||||
metricAttrs: attrs,
|
||||
}
|
||||
return context.WithValue(ctx, gRPCContextKey{}, &gctx)
|
||||
}
|
||||
|
||||
// HandleRPC processes the RPC stats.
|
||||
func (h *serverHandler) HandleRPC(ctx context.Context, rs stats.RPCStats) {
|
||||
h.handleRPC(ctx, rs)
|
||||
}
|
||||
|
||||
type clientHandler struct {
|
||||
*config
|
||||
}
|
||||
|
||||
// NewClientHandler creates a stats.Handler for gRPC client.
|
||||
func NewClientHandler(opts ...Option) stats.Handler {
|
||||
h := &clientHandler{
|
||||
config: newConfig(opts, "client"),
|
||||
}
|
||||
|
||||
return h
|
||||
}
|
||||
|
||||
// TagRPC can attach some information to the given context.
|
||||
func (h *clientHandler) TagRPC(ctx context.Context, info *stats.RPCTagInfo) context.Context {
|
||||
name, attrs := internal.ParseFullMethod(info.FullMethodName)
|
||||
attrs = append(attrs, RPCSystemGRPC)
|
||||
ctx, _ = h.tracer.Start(
|
||||
ctx,
|
||||
name,
|
||||
trace.WithSpanKind(trace.SpanKindClient),
|
||||
trace.WithAttributes(attrs...),
|
||||
)
|
||||
|
||||
gctx := gRPCContext{
|
||||
metricAttrs: attrs,
|
||||
}
|
||||
|
||||
return inject(context.WithValue(ctx, gRPCContextKey{}, &gctx), h.config.Propagators)
|
||||
}
|
||||
|
||||
// HandleRPC processes the RPC stats.
|
||||
func (h *clientHandler) HandleRPC(ctx context.Context, rs stats.RPCStats) {
|
||||
h.handleRPC(ctx, rs)
|
||||
}
|
||||
|
||||
// TagConn can attach some information to the given context.
|
||||
func (h *clientHandler) TagConn(ctx context.Context, cti *stats.ConnTagInfo) context.Context {
|
||||
span := trace.SpanFromContext(ctx)
|
||||
attrs := peerAttr(cti.RemoteAddr.String())
|
||||
span.SetAttributes(attrs...)
|
||||
return ctx
|
||||
}
|
||||
|
||||
// HandleConn processes the Conn stats.
|
||||
func (h *clientHandler) HandleConn(context.Context, stats.ConnStats) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
func (c *config) handleRPC(ctx context.Context, rs stats.RPCStats) {
|
||||
span := trace.SpanFromContext(ctx)
|
||||
gctx, _ := ctx.Value(gRPCContextKey{}).(*gRPCContext)
|
||||
var messageId int64
|
||||
metricAttrs := make([]attribute.KeyValue, 0, len(gctx.metricAttrs)+1)
|
||||
metricAttrs = append(metricAttrs, gctx.metricAttrs...)
|
||||
wctx := withoutCancel(ctx)
|
||||
|
||||
switch rs := rs.(type) {
|
||||
case *stats.Begin:
|
||||
case *stats.InPayload:
|
||||
if gctx != nil {
|
||||
messageId = atomic.AddInt64(&gctx.messagesReceived, 1)
|
||||
c.rpcRequestSize.Record(wctx, int64(rs.Length), metric.WithAttributes(metricAttrs...))
|
||||
}
|
||||
|
||||
if c.ReceivedEvent {
|
||||
span.AddEvent("message",
|
||||
trace.WithAttributes(
|
||||
semconv.MessageTypeReceived,
|
||||
semconv.MessageIDKey.Int64(messageId),
|
||||
semconv.MessageCompressedSizeKey.Int(rs.CompressedLength),
|
||||
semconv.MessageUncompressedSizeKey.Int(rs.Length),
|
||||
),
|
||||
)
|
||||
}
|
||||
case *stats.OutPayload:
|
||||
if gctx != nil {
|
||||
messageId = atomic.AddInt64(&gctx.messagesSent, 1)
|
||||
c.rpcResponseSize.Record(wctx, int64(rs.Length), metric.WithAttributes(metricAttrs...))
|
||||
}
|
||||
|
||||
if c.SentEvent {
|
||||
span.AddEvent("message",
|
||||
trace.WithAttributes(
|
||||
semconv.MessageTypeSent,
|
||||
semconv.MessageIDKey.Int64(messageId),
|
||||
semconv.MessageCompressedSizeKey.Int(rs.CompressedLength),
|
||||
semconv.MessageUncompressedSizeKey.Int(rs.Length),
|
||||
),
|
||||
)
|
||||
}
|
||||
case *stats.OutTrailer:
|
||||
case *stats.End:
|
||||
var rpcStatusAttr attribute.KeyValue
|
||||
|
||||
if rs.Error != nil {
|
||||
s, _ := status.FromError(rs.Error)
|
||||
span.SetStatus(codes.Error, s.Message())
|
||||
rpcStatusAttr = semconv.RPCGRPCStatusCodeKey.Int(int(s.Code()))
|
||||
} else {
|
||||
rpcStatusAttr = semconv.RPCGRPCStatusCodeKey.Int(int(grpc_codes.OK))
|
||||
}
|
||||
span.SetAttributes(rpcStatusAttr)
|
||||
span.End()
|
||||
|
||||
metricAttrs = append(metricAttrs, rpcStatusAttr)
|
||||
|
||||
// Use floating point division here for higher precision (instead of Millisecond method).
|
||||
elapsedTime := float64(rs.EndTime.Sub(rs.BeginTime)) / float64(time.Millisecond)
|
||||
|
||||
c.rpcDuration.Record(wctx, elapsedTime, metric.WithAttributes(metricAttrs...))
|
||||
c.rpcRequestsPerRPC.Record(wctx, atomic.LoadInt64(&gctx.messagesReceived), metric.WithAttributes(metricAttrs...))
|
||||
c.rpcResponsesPerRPC.Record(wctx, atomic.LoadInt64(&gctx.messagesSent), metric.WithAttributes(metricAttrs...))
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func withoutCancel(parent context.Context) context.Context {
|
||||
if parent == nil {
|
||||
panic("cannot create context from nil parent")
|
||||
}
|
||||
return withoutCancelCtx{parent}
|
||||
}
|
||||
|
||||
type withoutCancelCtx struct {
|
||||
c context.Context
|
||||
}
|
||||
|
||||
func (withoutCancelCtx) Deadline() (deadline time.Time, ok bool) {
|
||||
return
|
||||
}
|
||||
|
||||
func (withoutCancelCtx) Done() <-chan struct{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (withoutCancelCtx) Err() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w withoutCancelCtx) Value(key any) any {
|
||||
return w.c.Value(key)
|
||||
}
|
||||
|
||||
func (w withoutCancelCtx) String() string {
|
||||
return "withoutCancel"
|
||||
}
|
28
vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/version.go
generated
vendored
Normal file
28
vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/version.go
generated
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package otelgrpc // import "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
|
||||
|
||||
// Version is the current release version of the gRPC instrumentation.
|
||||
func Version() string {
|
||||
return "0.46.1"
|
||||
// This string is updated by the pre_release.sh script during release
|
||||
}
|
||||
|
||||
// SemVersion is the semantic version to be supplied to tracer/meter creation.
|
||||
//
|
||||
// Deprecated: Use [Version] instead.
|
||||
func SemVersion() string {
|
||||
return Version()
|
||||
}
|
2
vendor/google.golang.org/api/internal/version.go
generated
vendored
2
vendor/google.golang.org/api/internal/version.go
generated
vendored
|
@ -5,4 +5,4 @@
|
|||
package internal
|
||||
|
||||
// Version is the current tagged release of the library.
|
||||
const Version = "0.153.0"
|
||||
const Version = "0.154.0"
|
||||
|
|
11
vendor/google.golang.org/api/storage/v1/storage-api.json
generated
vendored
11
vendor/google.golang.org/api/storage/v1/storage-api.json
generated
vendored
|
@ -26,7 +26,14 @@
|
|||
"description": "Stores and retrieves potentially large, immutable data objects.",
|
||||
"discoveryVersion": "v1",
|
||||
"documentationLink": "https://developers.google.com/storage/docs/json_api/",
|
||||
"etag": "\"38383938373230313033363637363637353533\"",
|
||||
"endpoints": [
|
||||
{
|
||||
"description": "Regional Endpoint",
|
||||
"endpointUrl": "https://storage.me-central2.rep.googleapis.com/",
|
||||
"location": "me-central2"
|
||||
}
|
||||
],
|
||||
"etag": "\"3131373432363238303039393730353234383930\"",
|
||||
"icons": {
|
||||
"x16": "https://www.google.com/images/icons/product/cloud_storage-16.png",
|
||||
"x32": "https://www.google.com/images/icons/product/cloud_storage-32.png"
|
||||
|
@ -3799,7 +3806,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"revision": "20231117",
|
||||
"revision": "20231202",
|
||||
"rootUrl": "https://storage.googleapis.com/",
|
||||
"schemas": {
|
||||
"AnywhereCache": {
|
||||
|
|
14
vendor/google.golang.org/api/transport/grpc/dial.go
generated
vendored
14
vendor/google.golang.org/api/transport/grpc/dial.go
generated
vendored
|
@ -18,6 +18,7 @@ import (
|
|||
|
||||
"cloud.google.com/go/compute/metadata"
|
||||
"go.opencensus.io/plugin/ocgrpc"
|
||||
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
|
||||
"golang.org/x/oauth2"
|
||||
"golang.org/x/time/rate"
|
||||
"google.golang.org/api/internal"
|
||||
|
@ -43,6 +44,9 @@ var timeoutDialerOption grpc.DialOption
|
|||
// Log rate limiter
|
||||
var logRateLimiter = rate.Sometimes{Interval: 1 * time.Second}
|
||||
|
||||
// Assign to var for unit test replacement
|
||||
var dialContext = grpc.DialContext
|
||||
|
||||
// Dial returns a GRPC connection for use communicating with a Google cloud
|
||||
// service, configured with the given ClientOptions.
|
||||
func Dial(ctx context.Context, opts ...option.ClientOption) (*grpc.ClientConn, error) {
|
||||
|
@ -195,12 +199,13 @@ func dial(ctx context.Context, insecure bool, o *internal.DialSettings) (*grpc.C
|
|||
// gRPC stats handler.
|
||||
// This assumes that gRPC options are processed in order, left to right.
|
||||
grpcOpts = addOCStatsHandler(grpcOpts, o)
|
||||
grpcOpts = addOpenTelemetryStatsHandler(grpcOpts, o)
|
||||
grpcOpts = append(grpcOpts, o.GRPCDialOpts...)
|
||||
if o.UserAgent != "" {
|
||||
grpcOpts = append(grpcOpts, grpc.WithUserAgent(o.UserAgent))
|
||||
}
|
||||
|
||||
return grpc.DialContext(ctx, endpoint, grpcOpts...)
|
||||
return dialContext(ctx, endpoint, grpcOpts...)
|
||||
}
|
||||
|
||||
func addOCStatsHandler(opts []grpc.DialOption, settings *internal.DialSettings) []grpc.DialOption {
|
||||
|
@ -210,6 +215,13 @@ func addOCStatsHandler(opts []grpc.DialOption, settings *internal.DialSettings)
|
|||
return append(opts, grpc.WithStatsHandler(&ocgrpc.ClientHandler{}))
|
||||
}
|
||||
|
||||
func addOpenTelemetryStatsHandler(opts []grpc.DialOption, settings *internal.DialSettings) []grpc.DialOption {
|
||||
if settings.TelemetryDisabled {
|
||||
return opts
|
||||
}
|
||||
return append(opts, grpc.WithStatsHandler(otelgrpc.NewClientHandler()))
|
||||
}
|
||||
|
||||
// grpcTokenSource supplies PerRPCCredentials from an oauth.TokenSource.
|
||||
type grpcTokenSource struct {
|
||||
oauth.TokenSource
|
||||
|
|
11
vendor/google.golang.org/api/transport/http/dial.go
generated
vendored
11
vendor/google.golang.org/api/transport/http/dial.go
generated
vendored
|
@ -16,6 +16,7 @@ import (
|
|||
"time"
|
||||
|
||||
"go.opencensus.io/plugin/ochttp"
|
||||
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/oauth2"
|
||||
"google.golang.org/api/googleapi/transport"
|
||||
|
@ -69,6 +70,9 @@ func newTransport(ctx context.Context, base http.RoundTripper, settings *interna
|
|||
requestReason: settings.RequestReason,
|
||||
}
|
||||
var trans http.RoundTripper = paramTransport
|
||||
// Give OpenTelemetry precedence over OpenCensus in case user configuration
|
||||
// causes both to write the same header (`X-Cloud-Trace-Context`).
|
||||
trans = addOpenTelemetryTransport(trans, settings)
|
||||
trans = addOCTransport(trans, settings)
|
||||
switch {
|
||||
case settings.NoAuth:
|
||||
|
@ -203,6 +207,13 @@ func fallbackBaseTransport() *http.Transport {
|
|||
}
|
||||
}
|
||||
|
||||
func addOpenTelemetryTransport(trans http.RoundTripper, settings *internal.DialSettings) http.RoundTripper {
|
||||
if settings.TelemetryDisabled {
|
||||
return trans
|
||||
}
|
||||
return otelhttp.NewTransport(trans)
|
||||
}
|
||||
|
||||
func addOCTransport(trans http.RoundTripper, settings *internal.DialSettings) http.RoundTripper {
|
||||
if settings.TelemetryDisabled {
|
||||
return trans
|
||||
|
|
|
@ -32,21 +32,13 @@ import (
|
|||
"google.golang.org/grpc/resolver"
|
||||
)
|
||||
|
||||
type ccbMode int
|
||||
|
||||
const (
|
||||
ccbModeActive = iota
|
||||
ccbModeIdle
|
||||
ccbModeClosed
|
||||
ccbModeExitingIdle
|
||||
)
|
||||
|
||||
// ccBalancerWrapper sits between the ClientConn and the Balancer.
|
||||
//
|
||||
// ccBalancerWrapper implements methods corresponding to the ones on the
|
||||
// balancer.Balancer interface. The ClientConn is free to call these methods
|
||||
// concurrently and the ccBalancerWrapper ensures that calls from the ClientConn
|
||||
// to the Balancer happen synchronously and in order.
|
||||
// to the Balancer happen in order by performing them in the serializer, without
|
||||
// any mutexes held.
|
||||
//
|
||||
// ccBalancerWrapper also implements the balancer.ClientConn interface and is
|
||||
// passed to the Balancer implementations. It invokes unexported methods on the
|
||||
|
@ -57,87 +49,75 @@ const (
|
|||
type ccBalancerWrapper struct {
|
||||
// The following fields are initialized when the wrapper is created and are
|
||||
// read-only afterwards, and therefore can be accessed without a mutex.
|
||||
cc *ClientConn
|
||||
opts balancer.BuildOptions
|
||||
cc *ClientConn
|
||||
opts balancer.BuildOptions
|
||||
serializer *grpcsync.CallbackSerializer
|
||||
serializerCancel context.CancelFunc
|
||||
|
||||
// Outgoing (gRPC --> balancer) calls are guaranteed to execute in a
|
||||
// mutually exclusive manner as they are scheduled in the serializer. Fields
|
||||
// accessed *only* in these serializer callbacks, can therefore be accessed
|
||||
// without a mutex.
|
||||
balancer *gracefulswitch.Balancer
|
||||
// The following fields are only accessed within the serializer or during
|
||||
// initialization.
|
||||
curBalancerName string
|
||||
balancer *gracefulswitch.Balancer
|
||||
|
||||
// mu guards access to the below fields. Access to the serializer and its
|
||||
// cancel function needs to be mutex protected because they are overwritten
|
||||
// when the wrapper exits idle mode.
|
||||
mu sync.Mutex
|
||||
serializer *grpcsync.CallbackSerializer // To serialize all outoing calls.
|
||||
serializerCancel context.CancelFunc // To close the seralizer at close/enterIdle time.
|
||||
mode ccbMode // Tracks the current mode of the wrapper.
|
||||
// The following field is protected by mu. Caller must take cc.mu before
|
||||
// taking mu.
|
||||
mu sync.Mutex
|
||||
closed bool
|
||||
}
|
||||
|
||||
// newCCBalancerWrapper creates a new balancer wrapper. The underlying balancer
|
||||
// is not created until the switchTo() method is invoked.
|
||||
func newCCBalancerWrapper(cc *ClientConn, bopts balancer.BuildOptions) *ccBalancerWrapper {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
// newCCBalancerWrapper creates a new balancer wrapper in idle state. The
|
||||
// underlying balancer is not created until the switchTo() method is invoked.
|
||||
func newCCBalancerWrapper(cc *ClientConn) *ccBalancerWrapper {
|
||||
ctx, cancel := context.WithCancel(cc.ctx)
|
||||
ccb := &ccBalancerWrapper{
|
||||
cc: cc,
|
||||
opts: bopts,
|
||||
cc: cc,
|
||||
opts: balancer.BuildOptions{
|
||||
DialCreds: cc.dopts.copts.TransportCredentials,
|
||||
CredsBundle: cc.dopts.copts.CredsBundle,
|
||||
Dialer: cc.dopts.copts.Dialer,
|
||||
Authority: cc.authority,
|
||||
CustomUserAgent: cc.dopts.copts.UserAgent,
|
||||
ChannelzParentID: cc.channelzID,
|
||||
Target: cc.parsedTarget,
|
||||
},
|
||||
serializer: grpcsync.NewCallbackSerializer(ctx),
|
||||
serializerCancel: cancel,
|
||||
}
|
||||
ccb.balancer = gracefulswitch.NewBalancer(ccb, bopts)
|
||||
ccb.balancer = gracefulswitch.NewBalancer(ccb, ccb.opts)
|
||||
return ccb
|
||||
}
|
||||
|
||||
// updateClientConnState is invoked by grpc to push a ClientConnState update to
|
||||
// the underlying balancer.
|
||||
// the underlying balancer. This is always executed from the serializer, so
|
||||
// it is safe to call into the balancer here.
|
||||
func (ccb *ccBalancerWrapper) updateClientConnState(ccs *balancer.ClientConnState) error {
|
||||
ccb.mu.Lock()
|
||||
errCh := make(chan error, 1)
|
||||
// Here and everywhere else where Schedule() is called, it is done with the
|
||||
// lock held. But the lock guards only the scheduling part. The actual
|
||||
// callback is called asynchronously without the lock being held.
|
||||
ok := ccb.serializer.Schedule(func(_ context.Context) {
|
||||
errCh <- ccb.balancer.UpdateClientConnState(*ccs)
|
||||
errCh := make(chan error)
|
||||
ok := ccb.serializer.Schedule(func(ctx context.Context) {
|
||||
defer close(errCh)
|
||||
if ctx.Err() != nil || ccb.balancer == nil {
|
||||
return
|
||||
}
|
||||
err := ccb.balancer.UpdateClientConnState(*ccs)
|
||||
if logger.V(2) && err != nil {
|
||||
logger.Infof("error from balancer.UpdateClientConnState: %v", err)
|
||||
}
|
||||
errCh <- err
|
||||
})
|
||||
if !ok {
|
||||
// If we are unable to schedule a function with the serializer, it
|
||||
// indicates that it has been closed. A serializer is only closed when
|
||||
// the wrapper is closed or is in idle.
|
||||
ccb.mu.Unlock()
|
||||
return fmt.Errorf("grpc: cannot send state update to a closed or idle balancer")
|
||||
return nil
|
||||
}
|
||||
ccb.mu.Unlock()
|
||||
|
||||
// We get here only if the above call to Schedule succeeds, in which case it
|
||||
// is guaranteed that the scheduled function will run. Therefore it is safe
|
||||
// to block on this channel.
|
||||
err := <-errCh
|
||||
if logger.V(2) && err != nil {
|
||||
logger.Infof("error from balancer.UpdateClientConnState: %v", err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// updateSubConnState is invoked by grpc to push a subConn state update to the
|
||||
// underlying balancer.
|
||||
func (ccb *ccBalancerWrapper) updateSubConnState(sc balancer.SubConn, s connectivity.State, err error) {
|
||||
ccb.mu.Lock()
|
||||
ccb.serializer.Schedule(func(_ context.Context) {
|
||||
// Even though it is optional for balancers, gracefulswitch ensures
|
||||
// opts.StateListener is set, so this cannot ever be nil.
|
||||
sc.(*acBalancerWrapper).stateListener(balancer.SubConnState{ConnectivityState: s, ConnectionError: err})
|
||||
})
|
||||
ccb.mu.Unlock()
|
||||
return <-errCh
|
||||
}
|
||||
|
||||
// resolverError is invoked by grpc to push a resolver error to the underlying
|
||||
// balancer. The call to the balancer is executed from the serializer.
|
||||
func (ccb *ccBalancerWrapper) resolverError(err error) {
|
||||
ccb.mu.Lock()
|
||||
ccb.serializer.Schedule(func(_ context.Context) {
|
||||
ccb.serializer.Schedule(func(ctx context.Context) {
|
||||
if ctx.Err() != nil || ccb.balancer == nil {
|
||||
return
|
||||
}
|
||||
ccb.balancer.ResolverError(err)
|
||||
})
|
||||
ccb.mu.Unlock()
|
||||
}
|
||||
|
||||
// switchTo is invoked by grpc to instruct the balancer wrapper to switch to the
|
||||
|
@ -151,8 +131,10 @@ func (ccb *ccBalancerWrapper) resolverError(err error) {
|
|||
// the ccBalancerWrapper keeps track of the current LB policy name, and skips
|
||||
// the graceful balancer switching process if the name does not change.
|
||||
func (ccb *ccBalancerWrapper) switchTo(name string) {
|
||||
ccb.mu.Lock()
|
||||
ccb.serializer.Schedule(func(_ context.Context) {
|
||||
ccb.serializer.Schedule(func(ctx context.Context) {
|
||||
if ctx.Err() != nil || ccb.balancer == nil {
|
||||
return
|
||||
}
|
||||
// TODO: Other languages use case-sensitive balancer registries. We should
|
||||
// switch as well. See: https://github.com/grpc/grpc-go/issues/5288.
|
||||
if strings.EqualFold(ccb.curBalancerName, name) {
|
||||
|
@ -160,7 +142,6 @@ func (ccb *ccBalancerWrapper) switchTo(name string) {
|
|||
}
|
||||
ccb.buildLoadBalancingPolicy(name)
|
||||
})
|
||||
ccb.mu.Unlock()
|
||||
}
|
||||
|
||||
// buildLoadBalancingPolicy performs the following:
|
||||
|
@ -187,115 +168,49 @@ func (ccb *ccBalancerWrapper) buildLoadBalancingPolicy(name string) {
|
|||
ccb.curBalancerName = builder.Name()
|
||||
}
|
||||
|
||||
// close initiates async shutdown of the wrapper. cc.mu must be held when
|
||||
// calling this function. To determine the wrapper has finished shutting down,
|
||||
// the channel should block on ccb.serializer.Done() without cc.mu held.
|
||||
func (ccb *ccBalancerWrapper) close() {
|
||||
channelz.Info(logger, ccb.cc.channelzID, "ccBalancerWrapper: closing")
|
||||
ccb.closeBalancer(ccbModeClosed)
|
||||
}
|
||||
|
||||
// enterIdleMode is invoked by grpc when the channel enters idle mode upon
|
||||
// expiry of idle_timeout. This call blocks until the balancer is closed.
|
||||
func (ccb *ccBalancerWrapper) enterIdleMode() {
|
||||
channelz.Info(logger, ccb.cc.channelzID, "ccBalancerWrapper: entering idle mode")
|
||||
ccb.closeBalancer(ccbModeIdle)
|
||||
}
|
||||
|
||||
// closeBalancer is invoked when the channel is being closed or when it enters
|
||||
// idle mode upon expiry of idle_timeout.
|
||||
func (ccb *ccBalancerWrapper) closeBalancer(m ccbMode) {
|
||||
ccb.mu.Lock()
|
||||
if ccb.mode == ccbModeClosed || ccb.mode == ccbModeIdle {
|
||||
ccb.mu.Unlock()
|
||||
return
|
||||
}
|
||||
|
||||
ccb.mode = m
|
||||
done := ccb.serializer.Done()
|
||||
b := ccb.balancer
|
||||
ok := ccb.serializer.Schedule(func(_ context.Context) {
|
||||
// Close the serializer to ensure that no more calls from gRPC are sent
|
||||
// to the balancer.
|
||||
ccb.serializerCancel()
|
||||
// Empty the current balancer name because we don't have a balancer
|
||||
// anymore and also so that we act on the next call to switchTo by
|
||||
// creating a new balancer specified by the new resolver.
|
||||
ccb.curBalancerName = ""
|
||||
})
|
||||
if !ok {
|
||||
ccb.mu.Unlock()
|
||||
return
|
||||
}
|
||||
ccb.closed = true
|
||||
ccb.mu.Unlock()
|
||||
|
||||
// Give enqueued callbacks a chance to finish before closing the balancer.
|
||||
<-done
|
||||
b.Close()
|
||||
}
|
||||
|
||||
// exitIdleMode is invoked by grpc when the channel exits idle mode either
|
||||
// because of an RPC or because of an invocation of the Connect() API. This
|
||||
// recreates the balancer that was closed previously when entering idle mode.
|
||||
//
|
||||
// If the channel is not in idle mode, we know for a fact that we are here as a
|
||||
// result of the user calling the Connect() method on the ClientConn. In this
|
||||
// case, we can simply forward the call to the underlying balancer, instructing
|
||||
// it to reconnect to the backends.
|
||||
func (ccb *ccBalancerWrapper) exitIdleMode() {
|
||||
ccb.mu.Lock()
|
||||
if ccb.mode == ccbModeClosed {
|
||||
// Request to exit idle is a no-op when wrapper is already closed.
|
||||
ccb.mu.Unlock()
|
||||
return
|
||||
}
|
||||
|
||||
if ccb.mode == ccbModeIdle {
|
||||
// Recreate the serializer which was closed when we entered idle.
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
ccb.serializer = grpcsync.NewCallbackSerializer(ctx)
|
||||
ccb.serializerCancel = cancel
|
||||
}
|
||||
|
||||
// The ClientConn guarantees that mutual exclusion between close() and
|
||||
// exitIdleMode(), and since we just created a new serializer, we can be
|
||||
// sure that the below function will be scheduled.
|
||||
done := make(chan struct{})
|
||||
ccb.serializer.Schedule(func(_ context.Context) {
|
||||
defer close(done)
|
||||
|
||||
ccb.mu.Lock()
|
||||
defer ccb.mu.Unlock()
|
||||
|
||||
if ccb.mode != ccbModeIdle {
|
||||
ccb.balancer.ExitIdle()
|
||||
channelz.Info(logger, ccb.cc.channelzID, "ccBalancerWrapper: closing")
|
||||
ccb.serializer.Schedule(func(context.Context) {
|
||||
if ccb.balancer == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Gracefulswitch balancer does not support a switchTo operation after
|
||||
// being closed. Hence we need to create a new one here.
|
||||
ccb.balancer = gracefulswitch.NewBalancer(ccb, ccb.opts)
|
||||
ccb.mode = ccbModeActive
|
||||
channelz.Info(logger, ccb.cc.channelzID, "ccBalancerWrapper: exiting idle mode")
|
||||
|
||||
ccb.balancer.Close()
|
||||
ccb.balancer = nil
|
||||
})
|
||||
ccb.mu.Unlock()
|
||||
|
||||
<-done
|
||||
ccb.serializerCancel()
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) isIdleOrClosed() bool {
|
||||
ccb.mu.Lock()
|
||||
defer ccb.mu.Unlock()
|
||||
return ccb.mode == ccbModeIdle || ccb.mode == ccbModeClosed
|
||||
// exitIdle invokes the balancer's exitIdle method in the serializer.
|
||||
func (ccb *ccBalancerWrapper) exitIdle() {
|
||||
ccb.serializer.Schedule(func(ctx context.Context) {
|
||||
if ctx.Err() != nil || ccb.balancer == nil {
|
||||
return
|
||||
}
|
||||
ccb.balancer.ExitIdle()
|
||||
})
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) NewSubConn(addrs []resolver.Address, opts balancer.NewSubConnOptions) (balancer.SubConn, error) {
|
||||
if ccb.isIdleOrClosed() {
|
||||
return nil, fmt.Errorf("grpc: cannot create SubConn when balancer is closed or idle")
|
||||
ccb.cc.mu.Lock()
|
||||
defer ccb.cc.mu.Unlock()
|
||||
|
||||
ccb.mu.Lock()
|
||||
if ccb.closed {
|
||||
ccb.mu.Unlock()
|
||||
return nil, fmt.Errorf("balancer is being closed; no new SubConns allowed")
|
||||
}
|
||||
ccb.mu.Unlock()
|
||||
|
||||
if len(addrs) == 0 {
|
||||
return nil, fmt.Errorf("grpc: cannot create SubConn with empty address list")
|
||||
}
|
||||
ac, err := ccb.cc.newAddrConn(addrs, opts)
|
||||
ac, err := ccb.cc.newAddrConnLocked(addrs, opts)
|
||||
if err != nil {
|
||||
channelz.Warningf(logger, ccb.cc.channelzID, "acBalancerWrapper: NewSubConn: failed to newAddrConn: %v", err)
|
||||
return nil, err
|
||||
|
@ -316,10 +231,6 @@ func (ccb *ccBalancerWrapper) RemoveSubConn(sc balancer.SubConn) {
|
|||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) UpdateAddresses(sc balancer.SubConn, addrs []resolver.Address) {
|
||||
if ccb.isIdleOrClosed() {
|
||||
return
|
||||
}
|
||||
|
||||
acbw, ok := sc.(*acBalancerWrapper)
|
||||
if !ok {
|
||||
return
|
||||
|
@ -328,25 +239,39 @@ func (ccb *ccBalancerWrapper) UpdateAddresses(sc balancer.SubConn, addrs []resol
|
|||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) UpdateState(s balancer.State) {
|
||||
if ccb.isIdleOrClosed() {
|
||||
ccb.cc.mu.Lock()
|
||||
defer ccb.cc.mu.Unlock()
|
||||
|
||||
ccb.mu.Lock()
|
||||
if ccb.closed {
|
||||
ccb.mu.Unlock()
|
||||
return
|
||||
}
|
||||
|
||||
ccb.mu.Unlock()
|
||||
// Update picker before updating state. Even though the ordering here does
|
||||
// not matter, it can lead to multiple calls of Pick in the common start-up
|
||||
// case where we wait for ready and then perform an RPC. If the picker is
|
||||
// updated later, we could call the "connecting" picker when the state is
|
||||
// updated, and then call the "ready" picker after the picker gets updated.
|
||||
ccb.cc.blockingpicker.updatePicker(s.Picker)
|
||||
|
||||
// Note that there is no need to check if the balancer wrapper was closed,
|
||||
// as we know the graceful switch LB policy will not call cc if it has been
|
||||
// closed.
|
||||
ccb.cc.pickerWrapper.updatePicker(s.Picker)
|
||||
ccb.cc.csMgr.updateState(s.ConnectivityState)
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) ResolveNow(o resolver.ResolveNowOptions) {
|
||||
if ccb.isIdleOrClosed() {
|
||||
ccb.cc.mu.RLock()
|
||||
defer ccb.cc.mu.RUnlock()
|
||||
|
||||
ccb.mu.Lock()
|
||||
if ccb.closed {
|
||||
ccb.mu.Unlock()
|
||||
return
|
||||
}
|
||||
|
||||
ccb.cc.resolveNow(o)
|
||||
ccb.mu.Unlock()
|
||||
ccb.cc.resolveNowLocked(o)
|
||||
}
|
||||
|
||||
func (ccb *ccBalancerWrapper) Target() string {
|
||||
|
@ -364,6 +289,20 @@ type acBalancerWrapper struct {
|
|||
producers map[balancer.ProducerBuilder]*refCountedProducer
|
||||
}
|
||||
|
||||
// updateState is invoked by grpc to push a subConn state update to the
|
||||
// underlying balancer.
|
||||
func (acbw *acBalancerWrapper) updateState(s connectivity.State, err error) {
|
||||
acbw.ccb.serializer.Schedule(func(ctx context.Context) {
|
||||
if ctx.Err() != nil || acbw.ccb.balancer == nil {
|
||||
return
|
||||
}
|
||||
// Even though it is optional for balancers, gracefulswitch ensures
|
||||
// opts.StateListener is set, so this cannot ever be nil.
|
||||
// TODO: delete this comment when UpdateSubConnState is removed.
|
||||
acbw.stateListener(balancer.SubConnState{ConnectivityState: s, ConnectionError: err})
|
||||
})
|
||||
}
|
||||
|
||||
func (acbw *acBalancerWrapper) String() string {
|
||||
return fmt.Sprintf("SubConn(id:%d)", acbw.ac.channelzID.Int())
|
||||
}
|
||||
|
@ -377,20 +316,7 @@ func (acbw *acBalancerWrapper) Connect() {
|
|||
}
|
||||
|
||||
func (acbw *acBalancerWrapper) Shutdown() {
|
||||
ccb := acbw.ccb
|
||||
if ccb.isIdleOrClosed() {
|
||||
// It it safe to ignore this call when the balancer is closed or in idle
|
||||
// because the ClientConn takes care of closing the connections.
|
||||
//
|
||||
// Not returning early from here when the balancer is closed or in idle
|
||||
// leads to a deadlock though, because of the following sequence of
|
||||
// calls when holding cc.mu:
|
||||
// cc.exitIdleMode --> ccb.enterIdleMode --> gsw.Close -->
|
||||
// ccb.RemoveAddrConn --> cc.removeAddrConn
|
||||
return
|
||||
}
|
||||
|
||||
ccb.cc.removeAddrConn(acbw.ac, errConnDrain)
|
||||
acbw.ccb.cc.removeAddrConn(acbw.ac, errConnDrain)
|
||||
}
|
||||
|
||||
// NewStream begins a streaming RPC on the addrConn. If the addrConn is not
|
500
vendor/google.golang.org/grpc/clientconn.go
generated
vendored
500
vendor/google.golang.org/grpc/clientconn.go
generated
vendored
|
@ -33,9 +33,7 @@ import (
|
|||
"google.golang.org/grpc/balancer/base"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/connectivity"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/internal"
|
||||
"google.golang.org/grpc/internal/backoff"
|
||||
"google.golang.org/grpc/internal/channelz"
|
||||
"google.golang.org/grpc/internal/grpcsync"
|
||||
"google.golang.org/grpc/internal/idle"
|
||||
|
@ -48,9 +46,9 @@ import (
|
|||
"google.golang.org/grpc/status"
|
||||
|
||||
_ "google.golang.org/grpc/balancer/roundrobin" // To register roundrobin.
|
||||
_ "google.golang.org/grpc/internal/resolver/dns" // To register dns resolver.
|
||||
_ "google.golang.org/grpc/internal/resolver/passthrough" // To register passthrough resolver.
|
||||
_ "google.golang.org/grpc/internal/resolver/unix" // To register unix resolver.
|
||||
_ "google.golang.org/grpc/resolver/dns" // To register dns resolver.
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -119,23 +117,8 @@ func (dcs *defaultConfigSelector) SelectConfig(rpcInfo iresolver.RPCInfo) (*ires
|
|||
}, nil
|
||||
}
|
||||
|
||||
// DialContext creates a client connection to the given target. By default, it's
|
||||
// a non-blocking dial (the function won't wait for connections to be
|
||||
// established, and connecting happens in the background). To make it a blocking
|
||||
// dial, use WithBlock() dial option.
|
||||
//
|
||||
// In the non-blocking case, the ctx does not act against the connection. It
|
||||
// only controls the setup steps.
|
||||
//
|
||||
// In the blocking case, ctx can be used to cancel or expire the pending
|
||||
// connection. Once this function returns, the cancellation and expiration of
|
||||
// ctx will be noop. Users should call ClientConn.Close to terminate all the
|
||||
// pending operations after this function returns.
|
||||
//
|
||||
// The target name syntax is defined in
|
||||
// https://github.com/grpc/grpc/blob/master/doc/naming.md.
|
||||
// e.g. to use dns resolver, a "dns:///" prefix should be applied to the target.
|
||||
func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *ClientConn, err error) {
|
||||
// newClient returns a new client in idle mode.
|
||||
func newClient(target string, opts ...DialOption) (conn *ClientConn, err error) {
|
||||
cc := &ClientConn{
|
||||
target: target,
|
||||
conns: make(map[*addrConn]struct{}),
|
||||
|
@ -143,23 +126,11 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
|
|||
czData: new(channelzData),
|
||||
}
|
||||
|
||||
// We start the channel off in idle mode, but kick it out of idle at the end
|
||||
// of this method, instead of waiting for the first RPC. Other gRPC
|
||||
// implementations do wait for the first RPC to kick the channel out of
|
||||
// idle. But doing so would be a major behavior change for our users who are
|
||||
// used to seeing the channel active after Dial.
|
||||
//
|
||||
// Taking this approach of kicking it out of idle at the end of this method
|
||||
// allows us to share the code between channel creation and exiting idle
|
||||
// mode. This will also make it easy for us to switch to starting the
|
||||
// channel off in idle, if at all we ever get to do that.
|
||||
cc.idlenessState = ccIdlenessStateIdle
|
||||
|
||||
cc.retryThrottler.Store((*retryThrottler)(nil))
|
||||
cc.safeConfigSelector.UpdateConfigSelector(&defaultConfigSelector{nil})
|
||||
cc.ctx, cc.cancel = context.WithCancel(context.Background())
|
||||
cc.exitIdleCond = sync.NewCond(&cc.mu)
|
||||
|
||||
// Apply dial options.
|
||||
disableGlobalOpts := false
|
||||
for _, opt := range opts {
|
||||
if _, ok := opt.(*disableGlobalDialOptions); ok {
|
||||
|
@ -177,21 +148,9 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
|
|||
for _, opt := range opts {
|
||||
opt.apply(&cc.dopts)
|
||||
}
|
||||
|
||||
chainUnaryClientInterceptors(cc)
|
||||
chainStreamClientInterceptors(cc)
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
cc.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
// Register ClientConn with channelz.
|
||||
cc.channelzRegistration(target)
|
||||
|
||||
cc.csMgr = newConnectivityStateManager(cc.ctx, cc.channelzID)
|
||||
|
||||
if err := cc.validateTransportCredentials(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -205,10 +164,80 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
|
|||
}
|
||||
cc.mkp = cc.dopts.copts.KeepaliveParams
|
||||
|
||||
if cc.dopts.copts.UserAgent != "" {
|
||||
cc.dopts.copts.UserAgent += " " + grpcUA
|
||||
} else {
|
||||
cc.dopts.copts.UserAgent = grpcUA
|
||||
// Register ClientConn with channelz.
|
||||
cc.channelzRegistration(target)
|
||||
|
||||
// TODO: Ideally it should be impossible to error from this function after
|
||||
// channelz registration. This will require removing some channelz logs
|
||||
// from the following functions that can error. Errors can be returned to
|
||||
// the user, and successful logs can be emitted here, after the checks have
|
||||
// passed and channelz is subsequently registered.
|
||||
|
||||
// Determine the resolver to use.
|
||||
if err := cc.parseTargetAndFindResolver(); err != nil {
|
||||
channelz.RemoveEntry(cc.channelzID)
|
||||
return nil, err
|
||||
}
|
||||
if err = cc.determineAuthority(); err != nil {
|
||||
channelz.RemoveEntry(cc.channelzID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cc.csMgr = newConnectivityStateManager(cc.ctx, cc.channelzID)
|
||||
cc.pickerWrapper = newPickerWrapper(cc.dopts.copts.StatsHandlers)
|
||||
|
||||
cc.initIdleStateLocked() // Safe to call without the lock, since nothing else has a reference to cc.
|
||||
cc.idlenessMgr = idle.NewManager((*idler)(cc), cc.dopts.idleTimeout)
|
||||
return cc, nil
|
||||
}
|
||||
|
||||
// DialContext creates a client connection to the given target. By default, it's
|
||||
// a non-blocking dial (the function won't wait for connections to be
|
||||
// established, and connecting happens in the background). To make it a blocking
|
||||
// dial, use WithBlock() dial option.
|
||||
//
|
||||
// In the non-blocking case, the ctx does not act against the connection. It
|
||||
// only controls the setup steps.
|
||||
//
|
||||
// In the blocking case, ctx can be used to cancel or expire the pending
|
||||
// connection. Once this function returns, the cancellation and expiration of
|
||||
// ctx will be noop. Users should call ClientConn.Close to terminate all the
|
||||
// pending operations after this function returns.
|
||||
//
|
||||
// The target name syntax is defined in
|
||||
// https://github.com/grpc/grpc/blob/master/doc/naming.md.
|
||||
// e.g. to use dns resolver, a "dns:///" prefix should be applied to the target.
|
||||
func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *ClientConn, err error) {
|
||||
cc, err := newClient(target, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// We start the channel off in idle mode, but kick it out of idle now,
|
||||
// instead of waiting for the first RPC. Other gRPC implementations do wait
|
||||
// for the first RPC to kick the channel out of idle. But doing so would be
|
||||
// a major behavior change for our users who are used to seeing the channel
|
||||
// active after Dial.
|
||||
//
|
||||
// Taking this approach of kicking it out of idle at the end of this method
|
||||
// allows us to share the code between channel creation and exiting idle
|
||||
// mode. This will also make it easy for us to switch to starting the
|
||||
// channel off in idle, i.e. by making newClient exported.
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
cc.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
// This creates the name resolver, load balancer, etc.
|
||||
if err := cc.idlenessMgr.ExitIdleMode(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Return now for non-blocking dials.
|
||||
if !cc.dopts.block {
|
||||
return cc, nil
|
||||
}
|
||||
|
||||
if cc.dopts.timeout > 0 {
|
||||
|
@ -231,49 +260,6 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
|
|||
}
|
||||
}()
|
||||
|
||||
if cc.dopts.bs == nil {
|
||||
cc.dopts.bs = backoff.DefaultExponential
|
||||
}
|
||||
|
||||
// Determine the resolver to use.
|
||||
if err := cc.parseTargetAndFindResolver(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = cc.determineAuthority(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cc.dopts.scChan != nil {
|
||||
// Blocking wait for the initial service config.
|
||||
select {
|
||||
case sc, ok := <-cc.dopts.scChan:
|
||||
if ok {
|
||||
cc.sc = &sc
|
||||
cc.safeConfigSelector.UpdateConfigSelector(&defaultConfigSelector{&sc})
|
||||
}
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
}
|
||||
if cc.dopts.scChan != nil {
|
||||
go cc.scWatcher()
|
||||
}
|
||||
|
||||
// This creates the name resolver, load balancer, blocking picker etc.
|
||||
if err := cc.exitIdleMode(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Configure idleness support with configured idle timeout or default idle
|
||||
// timeout duration. Idleness can be explicitly disabled by the user, by
|
||||
// setting the dial option to 0.
|
||||
cc.idlenessMgr = idle.NewManager(idle.ManagerOptions{Enforcer: (*idler)(cc), Timeout: cc.dopts.idleTimeout, Logger: logger})
|
||||
|
||||
// Return early for non-blocking dials.
|
||||
if !cc.dopts.block {
|
||||
return cc, nil
|
||||
}
|
||||
|
||||
// A blocking dial blocks until the clientConn is ready.
|
||||
for {
|
||||
s := cc.GetState()
|
||||
|
@ -320,8 +306,8 @@ func (cc *ClientConn) addTraceEvent(msg string) {
|
|||
|
||||
type idler ClientConn
|
||||
|
||||
func (i *idler) EnterIdleMode() error {
|
||||
return (*ClientConn)(i).enterIdleMode()
|
||||
func (i *idler) EnterIdleMode() {
|
||||
(*ClientConn)(i).enterIdleMode()
|
||||
}
|
||||
|
||||
func (i *idler) ExitIdleMode() error {
|
||||
|
@ -329,117 +315,71 @@ func (i *idler) ExitIdleMode() error {
|
|||
}
|
||||
|
||||
// exitIdleMode moves the channel out of idle mode by recreating the name
|
||||
// resolver and load balancer.
|
||||
func (cc *ClientConn) exitIdleMode() error {
|
||||
// resolver and load balancer. This should never be called directly; use
|
||||
// cc.idlenessMgr.ExitIdleMode instead.
|
||||
func (cc *ClientConn) exitIdleMode() (err error) {
|
||||
cc.mu.Lock()
|
||||
if cc.conns == nil {
|
||||
cc.mu.Unlock()
|
||||
return errConnClosing
|
||||
}
|
||||
if cc.idlenessState != ccIdlenessStateIdle {
|
||||
channelz.Infof(logger, cc.channelzID, "ClientConn asked to exit idle mode, current mode is %v", cc.idlenessState)
|
||||
cc.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
defer func() {
|
||||
// When Close() and exitIdleMode() race against each other, one of the
|
||||
// following two can happen:
|
||||
// - Close() wins the race and runs first. exitIdleMode() runs after, and
|
||||
// sees that the ClientConn is already closed and hence returns early.
|
||||
// - exitIdleMode() wins the race and runs first and recreates the balancer
|
||||
// and releases the lock before recreating the resolver. If Close() runs
|
||||
// in this window, it will wait for exitIdleMode to complete.
|
||||
//
|
||||
// We achieve this synchronization using the below condition variable.
|
||||
cc.mu.Lock()
|
||||
cc.idlenessState = ccIdlenessStateActive
|
||||
cc.exitIdleCond.Signal()
|
||||
cc.mu.Unlock()
|
||||
}()
|
||||
|
||||
cc.idlenessState = ccIdlenessStateExitingIdle
|
||||
exitedIdle := false
|
||||
if cc.blockingpicker == nil {
|
||||
cc.blockingpicker = newPickerWrapper(cc.dopts.copts.StatsHandlers)
|
||||
} else {
|
||||
cc.blockingpicker.exitIdleMode()
|
||||
exitedIdle = true
|
||||
}
|
||||
|
||||
var credsClone credentials.TransportCredentials
|
||||
if creds := cc.dopts.copts.TransportCredentials; creds != nil {
|
||||
credsClone = creds.Clone()
|
||||
}
|
||||
if cc.balancerWrapper == nil {
|
||||
cc.balancerWrapper = newCCBalancerWrapper(cc, balancer.BuildOptions{
|
||||
DialCreds: credsClone,
|
||||
CredsBundle: cc.dopts.copts.CredsBundle,
|
||||
Dialer: cc.dopts.copts.Dialer,
|
||||
Authority: cc.authority,
|
||||
CustomUserAgent: cc.dopts.copts.UserAgent,
|
||||
ChannelzParentID: cc.channelzID,
|
||||
Target: cc.parsedTarget,
|
||||
})
|
||||
} else {
|
||||
cc.balancerWrapper.exitIdleMode()
|
||||
}
|
||||
cc.firstResolveEvent = grpcsync.NewEvent()
|
||||
cc.mu.Unlock()
|
||||
|
||||
// This needs to be called without cc.mu because this builds a new resolver
|
||||
// which might update state or report error inline which needs to be handled
|
||||
// by cc.updateResolverState() which also grabs cc.mu.
|
||||
if err := cc.initResolverWrapper(credsClone); err != nil {
|
||||
// which might update state or report error inline, which would then need to
|
||||
// acquire cc.mu.
|
||||
if err := cc.resolverWrapper.start(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if exitedIdle {
|
||||
cc.addTraceEvent("exiting idle mode")
|
||||
}
|
||||
cc.addTraceEvent("exiting idle mode")
|
||||
return nil
|
||||
}
|
||||
|
||||
// enterIdleMode puts the channel in idle mode, and as part of it shuts down the
|
||||
// name resolver, load balancer and any subchannels.
|
||||
func (cc *ClientConn) enterIdleMode() error {
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
|
||||
if cc.conns == nil {
|
||||
return ErrClientConnClosing
|
||||
}
|
||||
if cc.idlenessState != ccIdlenessStateActive {
|
||||
channelz.Warningf(logger, cc.channelzID, "ClientConn asked to enter idle mode, current mode is %v", cc.idlenessState)
|
||||
return nil
|
||||
}
|
||||
|
||||
// initIdleStateLocked initializes common state to how it should be while idle.
|
||||
func (cc *ClientConn) initIdleStateLocked() {
|
||||
cc.resolverWrapper = newCCResolverWrapper(cc)
|
||||
cc.balancerWrapper = newCCBalancerWrapper(cc)
|
||||
cc.firstResolveEvent = grpcsync.NewEvent()
|
||||
// cc.conns == nil is a proxy for the ClientConn being closed. So, instead
|
||||
// of setting it to nil here, we recreate the map. This also means that we
|
||||
// don't have to do this when exiting idle mode.
|
||||
conns := cc.conns
|
||||
cc.conns = make(map[*addrConn]struct{})
|
||||
}
|
||||
|
||||
// TODO: Currently, we close the resolver wrapper upon entering idle mode
|
||||
// and create a new one upon exiting idle mode. This means that the
|
||||
// `cc.resolverWrapper` field would be overwritten everytime we exit idle
|
||||
// mode. While this means that we need to hold `cc.mu` when accessing
|
||||
// `cc.resolverWrapper`, it makes the code simpler in the wrapper. We should
|
||||
// try to do the same for the balancer and picker wrappers too.
|
||||
cc.resolverWrapper.close()
|
||||
cc.blockingpicker.enterIdleMode()
|
||||
cc.balancerWrapper.enterIdleMode()
|
||||
// enterIdleMode puts the channel in idle mode, and as part of it shuts down the
|
||||
// name resolver, load balancer, and any subchannels. This should never be
|
||||
// called directly; use cc.idlenessMgr.EnterIdleMode instead.
|
||||
func (cc *ClientConn) enterIdleMode() {
|
||||
cc.mu.Lock()
|
||||
|
||||
if cc.conns == nil {
|
||||
cc.mu.Unlock()
|
||||
return
|
||||
}
|
||||
|
||||
conns := cc.conns
|
||||
|
||||
rWrapper := cc.resolverWrapper
|
||||
rWrapper.close()
|
||||
cc.pickerWrapper.reset()
|
||||
bWrapper := cc.balancerWrapper
|
||||
bWrapper.close()
|
||||
cc.csMgr.updateState(connectivity.Idle)
|
||||
cc.idlenessState = ccIdlenessStateIdle
|
||||
cc.addTraceEvent("entering idle mode")
|
||||
|
||||
go func() {
|
||||
for ac := range conns {
|
||||
ac.tearDown(errConnIdling)
|
||||
}
|
||||
}()
|
||||
cc.initIdleStateLocked()
|
||||
|
||||
return nil
|
||||
cc.mu.Unlock()
|
||||
|
||||
// Block until the name resolver and LB policy are closed.
|
||||
<-rWrapper.serializer.Done()
|
||||
<-bWrapper.serializer.Done()
|
||||
|
||||
// Close all subchannels after the LB policy is closed.
|
||||
for ac := range conns {
|
||||
ac.tearDown(errConnIdling)
|
||||
}
|
||||
}
|
||||
|
||||
// validateTransportCredentials performs a series of checks on the configured
|
||||
|
@ -649,66 +589,35 @@ type ClientConn struct {
|
|||
dopts dialOptions // Default and user specified dial options.
|
||||
channelzID *channelz.Identifier // Channelz identifier for the channel.
|
||||
resolverBuilder resolver.Builder // See parseTargetAndFindResolver().
|
||||
balancerWrapper *ccBalancerWrapper // Uses gracefulswitch.balancer underneath.
|
||||
idlenessMgr idle.Manager
|
||||
idlenessMgr *idle.Manager
|
||||
|
||||
// The following provide their own synchronization, and therefore don't
|
||||
// require cc.mu to be held to access them.
|
||||
csMgr *connectivityStateManager
|
||||
blockingpicker *pickerWrapper
|
||||
pickerWrapper *pickerWrapper
|
||||
safeConfigSelector iresolver.SafeConfigSelector
|
||||
czData *channelzData
|
||||
retryThrottler atomic.Value // Updated from service config.
|
||||
|
||||
// firstResolveEvent is used to track whether the name resolver sent us at
|
||||
// least one update. RPCs block on this event.
|
||||
firstResolveEvent *grpcsync.Event
|
||||
|
||||
// mu protects the following fields.
|
||||
// TODO: split mu so the same mutex isn't used for everything.
|
||||
mu sync.RWMutex
|
||||
resolverWrapper *ccResolverWrapper // Initialized in Dial; cleared in Close.
|
||||
resolverWrapper *ccResolverWrapper // Always recreated whenever entering idle to simplify Close.
|
||||
balancerWrapper *ccBalancerWrapper // Always recreated whenever entering idle to simplify Close.
|
||||
sc *ServiceConfig // Latest service config received from the resolver.
|
||||
conns map[*addrConn]struct{} // Set to nil on close.
|
||||
mkp keepalive.ClientParameters // May be updated upon receipt of a GoAway.
|
||||
idlenessState ccIdlenessState // Tracks idleness state of the channel.
|
||||
exitIdleCond *sync.Cond // Signalled when channel exits idle.
|
||||
// firstResolveEvent is used to track whether the name resolver sent us at
|
||||
// least one update. RPCs block on this event. May be accessed without mu
|
||||
// if we know we cannot be asked to enter idle mode while accessing it (e.g.
|
||||
// when the idle manager has already been closed, or if we are already
|
||||
// entering idle mode).
|
||||
firstResolveEvent *grpcsync.Event
|
||||
|
||||
lceMu sync.Mutex // protects lastConnectionError
|
||||
lastConnectionError error
|
||||
}
|
||||
|
||||
// ccIdlenessState tracks the idleness state of the channel.
|
||||
//
|
||||
// Channels start off in `active` and move to `idle` after a period of
|
||||
// inactivity. When moving back to `active` upon an incoming RPC, they
|
||||
// transition through `exiting_idle`. This state is useful for synchronization
|
||||
// with Close().
|
||||
//
|
||||
// This state tracking is mostly for self-protection. The idlenessManager is
|
||||
// expected to keep track of the state as well, and is expected not to call into
|
||||
// the ClientConn unnecessarily.
|
||||
type ccIdlenessState int8
|
||||
|
||||
const (
|
||||
ccIdlenessStateActive ccIdlenessState = iota
|
||||
ccIdlenessStateIdle
|
||||
ccIdlenessStateExitingIdle
|
||||
)
|
||||
|
||||
func (s ccIdlenessState) String() string {
|
||||
switch s {
|
||||
case ccIdlenessStateActive:
|
||||
return "active"
|
||||
case ccIdlenessStateIdle:
|
||||
return "idle"
|
||||
case ccIdlenessStateExitingIdle:
|
||||
return "exitingIdle"
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
// WaitForStateChange waits until the connectivity.State of ClientConn changes from sourceState or
|
||||
// ctx expires. A true value is returned in former case and false in latter.
|
||||
//
|
||||
|
@ -748,29 +657,15 @@ func (cc *ClientConn) GetState() connectivity.State {
|
|||
// Notice: This API is EXPERIMENTAL and may be changed or removed in a later
|
||||
// release.
|
||||
func (cc *ClientConn) Connect() {
|
||||
cc.exitIdleMode()
|
||||
if err := cc.idlenessMgr.ExitIdleMode(); err != nil {
|
||||
cc.addTraceEvent(err.Error())
|
||||
return
|
||||
}
|
||||
// If the ClientConn was not in idle mode, we need to call ExitIdle on the
|
||||
// LB policy so that connections can be created.
|
||||
cc.balancerWrapper.exitIdleMode()
|
||||
}
|
||||
|
||||
func (cc *ClientConn) scWatcher() {
|
||||
for {
|
||||
select {
|
||||
case sc, ok := <-cc.dopts.scChan:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
cc.mu.Lock()
|
||||
// TODO: load balance policy runtime change is ignored.
|
||||
// We may revisit this decision in the future.
|
||||
cc.sc = &sc
|
||||
cc.safeConfigSelector.UpdateConfigSelector(&defaultConfigSelector{&sc})
|
||||
cc.mu.Unlock()
|
||||
case <-cc.ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
cc.mu.Lock()
|
||||
cc.balancerWrapper.exitIdle()
|
||||
cc.mu.Unlock()
|
||||
}
|
||||
|
||||
// waitForResolvedAddrs blocks until the resolver has provided addresses or the
|
||||
|
@ -804,11 +699,11 @@ func init() {
|
|||
internal.SubscribeToConnectivityStateChanges = func(cc *ClientConn, s grpcsync.Subscriber) func() {
|
||||
return cc.csMgr.pubSub.Subscribe(s)
|
||||
}
|
||||
internal.EnterIdleModeForTesting = func(cc *ClientConn) error {
|
||||
return cc.enterIdleMode()
|
||||
internal.EnterIdleModeForTesting = func(cc *ClientConn) {
|
||||
cc.idlenessMgr.EnterIdleModeForTesting()
|
||||
}
|
||||
internal.ExitIdleModeForTesting = func(cc *ClientConn) error {
|
||||
return cc.exitIdleMode()
|
||||
return cc.idlenessMgr.ExitIdleMode()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -824,9 +719,8 @@ func (cc *ClientConn) maybeApplyDefaultServiceConfig(addrs []resolver.Address) {
|
|||
}
|
||||
}
|
||||
|
||||
func (cc *ClientConn) updateResolverState(s resolver.State, err error) error {
|
||||
func (cc *ClientConn) updateResolverStateAndUnlock(s resolver.State, err error) error {
|
||||
defer cc.firstResolveEvent.Fire()
|
||||
cc.mu.Lock()
|
||||
// Check if the ClientConn is already closed. Some fields (e.g.
|
||||
// balancerWrapper) are set to nil when closing the ClientConn, and could
|
||||
// cause nil pointer panic if we don't have this check.
|
||||
|
@ -872,7 +766,7 @@ func (cc *ClientConn) updateResolverState(s resolver.State, err error) error {
|
|||
if cc.sc == nil {
|
||||
// Apply the failing LB only if we haven't received valid service config
|
||||
// from the name resolver in the past.
|
||||
cc.applyFailingLB(s.ServiceConfig)
|
||||
cc.applyFailingLBLocked(s.ServiceConfig)
|
||||
cc.mu.Unlock()
|
||||
return ret
|
||||
}
|
||||
|
@ -894,15 +788,13 @@ func (cc *ClientConn) updateResolverState(s resolver.State, err error) error {
|
|||
return ret
|
||||
}
|
||||
|
||||
// applyFailingLB is akin to configuring an LB policy on the channel which
|
||||
// applyFailingLBLocked is akin to configuring an LB policy on the channel which
|
||||
// always fails RPCs. Here, an actual LB policy is not configured, but an always
|
||||
// erroring picker is configured, which returns errors with information about
|
||||
// what was invalid in the received service config. A config selector with no
|
||||
// service config is configured, and the connectivity state of the channel is
|
||||
// set to TransientFailure.
|
||||
//
|
||||
// Caller must hold cc.mu.
|
||||
func (cc *ClientConn) applyFailingLB(sc *serviceconfig.ParseResult) {
|
||||
func (cc *ClientConn) applyFailingLBLocked(sc *serviceconfig.ParseResult) {
|
||||
var err error
|
||||
if sc.Err != nil {
|
||||
err = status.Errorf(codes.Unavailable, "error parsing service config: %v", sc.Err)
|
||||
|
@ -910,14 +802,10 @@ func (cc *ClientConn) applyFailingLB(sc *serviceconfig.ParseResult) {
|
|||
err = status.Errorf(codes.Unavailable, "illegal service config type: %T", sc.Config)
|
||||
}
|
||||
cc.safeConfigSelector.UpdateConfigSelector(&defaultConfigSelector{nil})
|
||||
cc.blockingpicker.updatePicker(base.NewErrPicker(err))
|
||||
cc.pickerWrapper.updatePicker(base.NewErrPicker(err))
|
||||
cc.csMgr.updateState(connectivity.TransientFailure)
|
||||
}
|
||||
|
||||
func (cc *ClientConn) handleSubConnStateChange(sc balancer.SubConn, s connectivity.State, err error) {
|
||||
cc.balancerWrapper.updateSubConnState(sc, s, err)
|
||||
}
|
||||
|
||||
// Makes a copy of the input addresses slice and clears out the balancer
|
||||
// attributes field. Addresses are passed during subconn creation and address
|
||||
// update operations. In both cases, we will clear the balancer attributes by
|
||||
|
@ -932,10 +820,14 @@ func copyAddressesWithoutBalancerAttributes(in []resolver.Address) []resolver.Ad
|
|||
return out
|
||||
}
|
||||
|
||||
// newAddrConn creates an addrConn for addrs and adds it to cc.conns.
|
||||
// newAddrConnLocked creates an addrConn for addrs and adds it to cc.conns.
|
||||
//
|
||||
// Caller needs to make sure len(addrs) > 0.
|
||||
func (cc *ClientConn) newAddrConn(addrs []resolver.Address, opts balancer.NewSubConnOptions) (*addrConn, error) {
|
||||
func (cc *ClientConn) newAddrConnLocked(addrs []resolver.Address, opts balancer.NewSubConnOptions) (*addrConn, error) {
|
||||
if cc.conns == nil {
|
||||
return nil, ErrClientConnClosing
|
||||
}
|
||||
|
||||
ac := &addrConn{
|
||||
state: connectivity.Idle,
|
||||
cc: cc,
|
||||
|
@ -947,12 +839,6 @@ func (cc *ClientConn) newAddrConn(addrs []resolver.Address, opts balancer.NewSub
|
|||
stateChan: make(chan struct{}),
|
||||
}
|
||||
ac.ctx, ac.cancel = context.WithCancel(cc.ctx)
|
||||
// Track ac in cc. This needs to be done before any getTransport(...) is called.
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
if cc.conns == nil {
|
||||
return nil, ErrClientConnClosing
|
||||
}
|
||||
|
||||
var err error
|
||||
ac.channelzID, err = channelz.RegisterSubChannel(ac, cc.channelzID, "")
|
||||
|
@ -968,6 +854,7 @@ func (cc *ClientConn) newAddrConn(addrs []resolver.Address, opts balancer.NewSub
|
|||
},
|
||||
})
|
||||
|
||||
// Track ac in cc. This needs to be done before any getTransport(...) is called.
|
||||
cc.conns[ac] = struct{}{}
|
||||
return ac, nil
|
||||
}
|
||||
|
@ -1174,7 +1061,7 @@ func (cc *ClientConn) healthCheckConfig() *healthCheckConfig {
|
|||
}
|
||||
|
||||
func (cc *ClientConn) getTransport(ctx context.Context, failfast bool, method string) (transport.ClientTransport, balancer.PickResult, error) {
|
||||
return cc.blockingpicker.pick(ctx, failfast, balancer.PickInfo{
|
||||
return cc.pickerWrapper.pick(ctx, failfast, balancer.PickInfo{
|
||||
Ctx: ctx,
|
||||
FullMethodName: method,
|
||||
})
|
||||
|
@ -1216,12 +1103,12 @@ func (cc *ClientConn) applyServiceConfigAndBalancer(sc *ServiceConfig, configSel
|
|||
|
||||
func (cc *ClientConn) resolveNow(o resolver.ResolveNowOptions) {
|
||||
cc.mu.RLock()
|
||||
r := cc.resolverWrapper
|
||||
cc.resolverWrapper.resolveNow(o)
|
||||
cc.mu.RUnlock()
|
||||
if r == nil {
|
||||
return
|
||||
}
|
||||
go r.resolveNow(o)
|
||||
}
|
||||
|
||||
func (cc *ClientConn) resolveNowLocked(o resolver.ResolveNowOptions) {
|
||||
cc.resolverWrapper.resolveNow(o)
|
||||
}
|
||||
|
||||
// ResetConnectBackoff wakes up all subchannels in transient failure and causes
|
||||
|
@ -1253,40 +1140,32 @@ func (cc *ClientConn) Close() error {
|
|||
<-cc.csMgr.pubSub.Done()
|
||||
}()
|
||||
|
||||
// Prevent calls to enter/exit idle immediately, and ensure we are not
|
||||
// currently entering/exiting idle mode.
|
||||
cc.idlenessMgr.Close()
|
||||
|
||||
cc.mu.Lock()
|
||||
if cc.conns == nil {
|
||||
cc.mu.Unlock()
|
||||
return ErrClientConnClosing
|
||||
}
|
||||
|
||||
for cc.idlenessState == ccIdlenessStateExitingIdle {
|
||||
cc.exitIdleCond.Wait()
|
||||
}
|
||||
|
||||
conns := cc.conns
|
||||
cc.conns = nil
|
||||
cc.csMgr.updateState(connectivity.Shutdown)
|
||||
|
||||
pWrapper := cc.blockingpicker
|
||||
rWrapper := cc.resolverWrapper
|
||||
bWrapper := cc.balancerWrapper
|
||||
idlenessMgr := cc.idlenessMgr
|
||||
// We can safely unlock and continue to access all fields now as
|
||||
// cc.conns==nil, preventing any further operations on cc.
|
||||
cc.mu.Unlock()
|
||||
|
||||
cc.resolverWrapper.close()
|
||||
// The order of closing matters here since the balancer wrapper assumes the
|
||||
// picker is closed before it is closed.
|
||||
if pWrapper != nil {
|
||||
pWrapper.close()
|
||||
}
|
||||
if bWrapper != nil {
|
||||
bWrapper.close()
|
||||
}
|
||||
if rWrapper != nil {
|
||||
rWrapper.close()
|
||||
}
|
||||
if idlenessMgr != nil {
|
||||
idlenessMgr.Close()
|
||||
}
|
||||
cc.pickerWrapper.close()
|
||||
cc.balancerWrapper.close()
|
||||
|
||||
<-cc.resolverWrapper.serializer.Done()
|
||||
<-cc.balancerWrapper.serializer.Done()
|
||||
|
||||
for ac := range conns {
|
||||
ac.tearDown(ErrClientConnClosing)
|
||||
|
@ -1307,7 +1186,7 @@ type addrConn struct {
|
|||
|
||||
cc *ClientConn
|
||||
dopts dialOptions
|
||||
acbw balancer.SubConn
|
||||
acbw *acBalancerWrapper
|
||||
scopts balancer.NewSubConnOptions
|
||||
|
||||
// transport is set when there's a viable transport (note: ac state may not be READY as LB channel
|
||||
|
@ -1345,7 +1224,7 @@ func (ac *addrConn) updateConnectivityState(s connectivity.State, lastErr error)
|
|||
} else {
|
||||
channelz.Infof(logger, ac.channelzID, "Subchannel Connectivity change to %v, last error: %s", s, lastErr)
|
||||
}
|
||||
ac.cc.handleSubConnStateChange(ac.acbw, s, lastErr)
|
||||
ac.acbw.updateState(s, lastErr)
|
||||
}
|
||||
|
||||
// adjustParams updates parameters used to create transports upon
|
||||
|
@ -1849,7 +1728,7 @@ func (cc *ClientConn) parseTargetAndFindResolver() error {
|
|||
if err != nil {
|
||||
channelz.Infof(logger, cc.channelzID, "dial target %q parse failed: %v", cc.target, err)
|
||||
} else {
|
||||
channelz.Infof(logger, cc.channelzID, "parsed dial target is: %+v", parsedTarget)
|
||||
channelz.Infof(logger, cc.channelzID, "parsed dial target is: %#v", parsedTarget)
|
||||
rb = cc.getResolver(parsedTarget.URL.Scheme)
|
||||
if rb != nil {
|
||||
cc.parsedTarget = parsedTarget
|
||||
|
@ -2007,32 +1886,3 @@ func (cc *ClientConn) determineAuthority() error {
|
|||
channelz.Infof(logger, cc.channelzID, "Channel authority set to %q", cc.authority)
|
||||
return nil
|
||||
}
|
||||
|
||||
// initResolverWrapper creates a ccResolverWrapper, which builds the name
|
||||
// resolver. This method grabs the lock to assign the newly built resolver
|
||||
// wrapper to the cc.resolverWrapper field.
|
||||
func (cc *ClientConn) initResolverWrapper(creds credentials.TransportCredentials) error {
|
||||
rw, err := newCCResolverWrapper(cc, ccResolverWrapperOpts{
|
||||
target: cc.parsedTarget,
|
||||
builder: cc.resolverBuilder,
|
||||
bOpts: resolver.BuildOptions{
|
||||
DisableServiceConfig: cc.dopts.disableServiceConfig,
|
||||
DialCreds: creds,
|
||||
CredsBundle: cc.dopts.copts.CredsBundle,
|
||||
Dialer: cc.dopts.copts.Dialer,
|
||||
},
|
||||
channelzID: cc.channelzID,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to build resolver: %v", err)
|
||||
}
|
||||
// Resolver implementations may report state update or error inline when
|
||||
// built (or right after), and this is handled in cc.updateResolverState.
|
||||
// Also, an error from the resolver might lead to a re-resolution request
|
||||
// from the balancer, which is handled in resolveNow() where
|
||||
// `cc.resolverWrapper` is accessed. Hence, we need to hold the lock here.
|
||||
cc.mu.Lock()
|
||||
cc.resolverWrapper = rw
|
||||
cc.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
|
8
vendor/google.golang.org/grpc/codes/codes.go
generated
vendored
8
vendor/google.golang.org/grpc/codes/codes.go
generated
vendored
|
@ -25,7 +25,13 @@ import (
|
|||
"strconv"
|
||||
)
|
||||
|
||||
// A Code is an unsigned 32-bit error code as defined in the gRPC spec.
|
||||
// A Code is a status code defined according to the [gRPC documentation].
|
||||
//
|
||||
// Only the codes defined as consts in this package are valid codes. Do not use
|
||||
// other code values. Behavior of other codes is implementation-specific and
|
||||
// interoperability between implementations is not guaranteed.
|
||||
//
|
||||
// [gRPC documentation]: https://github.com/grpc/grpc/blob/master/doc/statuscodes.md
|
||||
type Code uint32
|
||||
|
||||
const (
|
||||
|
|
2
vendor/google.golang.org/grpc/credentials/alts/alts.go
generated
vendored
2
vendor/google.golang.org/grpc/credentials/alts/alts.go
generated
vendored
|
@ -43,7 +43,7 @@ import (
|
|||
const (
|
||||
// hypervisorHandshakerServiceAddress represents the default ALTS gRPC
|
||||
// handshaker service address in the hypervisor.
|
||||
hypervisorHandshakerServiceAddress = "metadata.google.internal.:8080"
|
||||
hypervisorHandshakerServiceAddress = "dns:///metadata.google.internal.:8080"
|
||||
// defaultTimeout specifies the server handshake timeout.
|
||||
defaultTimeout = 30.0 * time.Second
|
||||
// The following constants specify the minimum and maximum acceptable
|
||||
|
|
75
vendor/google.golang.org/grpc/credentials/tls.go
generated
vendored
75
vendor/google.golang.org/grpc/credentials/tls.go
generated
vendored
|
@ -44,10 +44,25 @@ func (t TLSInfo) AuthType() string {
|
|||
return "tls"
|
||||
}
|
||||
|
||||
// cipherSuiteLookup returns the string version of a TLS cipher suite ID.
|
||||
func cipherSuiteLookup(cipherSuiteID uint16) string {
|
||||
for _, s := range tls.CipherSuites() {
|
||||
if s.ID == cipherSuiteID {
|
||||
return s.Name
|
||||
}
|
||||
}
|
||||
for _, s := range tls.InsecureCipherSuites() {
|
||||
if s.ID == cipherSuiteID {
|
||||
return s.Name
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("unknown ID: %v", cipherSuiteID)
|
||||
}
|
||||
|
||||
// GetSecurityValue returns security info requested by channelz.
|
||||
func (t TLSInfo) GetSecurityValue() ChannelzSecurityValue {
|
||||
v := &TLSChannelzSecurityValue{
|
||||
StandardName: cipherSuiteLookup[t.State.CipherSuite],
|
||||
StandardName: cipherSuiteLookup(t.State.CipherSuite),
|
||||
}
|
||||
// Currently there's no way to get LocalCertificate info from tls package.
|
||||
if len(t.State.PeerCertificates) > 0 {
|
||||
|
@ -138,10 +153,39 @@ func (c *tlsCreds) OverrideServerName(serverNameOverride string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// The following cipher suites are forbidden for use with HTTP/2 by
|
||||
// https://datatracker.ietf.org/doc/html/rfc7540#appendix-A
|
||||
var tls12ForbiddenCipherSuites = map[uint16]struct{}{
|
||||
tls.TLS_RSA_WITH_AES_128_CBC_SHA: {},
|
||||
tls.TLS_RSA_WITH_AES_256_CBC_SHA: {},
|
||||
tls.TLS_RSA_WITH_AES_128_GCM_SHA256: {},
|
||||
tls.TLS_RSA_WITH_AES_256_GCM_SHA384: {},
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: {},
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: {},
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: {},
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: {},
|
||||
}
|
||||
|
||||
// NewTLS uses c to construct a TransportCredentials based on TLS.
|
||||
func NewTLS(c *tls.Config) TransportCredentials {
|
||||
tc := &tlsCreds{credinternal.CloneTLSConfig(c)}
|
||||
tc.config.NextProtos = credinternal.AppendH2ToNextProtos(tc.config.NextProtos)
|
||||
// If the user did not configure a MinVersion and did not configure a
|
||||
// MaxVersion < 1.2, use MinVersion=1.2, which is required by
|
||||
// https://datatracker.ietf.org/doc/html/rfc7540#section-9.2
|
||||
if tc.config.MinVersion == 0 && (tc.config.MaxVersion == 0 || tc.config.MaxVersion >= tls.VersionTLS12) {
|
||||
tc.config.MinVersion = tls.VersionTLS12
|
||||
}
|
||||
// If the user did not configure CipherSuites, use all "secure" cipher
|
||||
// suites reported by the TLS package, but remove some explicitly forbidden
|
||||
// by https://datatracker.ietf.org/doc/html/rfc7540#appendix-A
|
||||
if tc.config.CipherSuites == nil {
|
||||
for _, cs := range tls.CipherSuites() {
|
||||
if _, ok := tls12ForbiddenCipherSuites[cs.ID]; !ok {
|
||||
tc.config.CipherSuites = append(tc.config.CipherSuites, cs.ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
return tc
|
||||
}
|
||||
|
||||
|
@ -205,32 +249,3 @@ type TLSChannelzSecurityValue struct {
|
|||
LocalCertificate []byte
|
||||
RemoteCertificate []byte
|
||||
}
|
||||
|
||||
var cipherSuiteLookup = map[uint16]string{
|
||||
tls.TLS_RSA_WITH_RC4_128_SHA: "TLS_RSA_WITH_RC4_128_SHA",
|
||||
tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA: "TLS_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||
tls.TLS_RSA_WITH_AES_128_CBC_SHA: "TLS_RSA_WITH_AES_128_CBC_SHA",
|
||||
tls.TLS_RSA_WITH_AES_256_CBC_SHA: "TLS_RSA_WITH_AES_256_CBC_SHA",
|
||||
tls.TLS_RSA_WITH_AES_128_GCM_SHA256: "TLS_RSA_WITH_AES_128_GCM_SHA256",
|
||||
tls.TLS_RSA_WITH_AES_256_GCM_SHA384: "TLS_RSA_WITH_AES_256_GCM_SHA384",
|
||||
tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
|
||||
tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA: "TLS_ECDHE_RSA_WITH_RC4_128_SHA",
|
||||
tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
||||
tls.TLS_FALLBACK_SCSV: "TLS_FALLBACK_SCSV",
|
||||
tls.TLS_RSA_WITH_AES_128_CBC_SHA256: "TLS_RSA_WITH_AES_128_CBC_SHA256",
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
|
||||
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305: "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
|
||||
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305: "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
|
||||
tls.TLS_AES_128_GCM_SHA256: "TLS_AES_128_GCM_SHA256",
|
||||
tls.TLS_AES_256_GCM_SHA384: "TLS_AES_256_GCM_SHA384",
|
||||
tls.TLS_CHACHA20_POLY1305_SHA256: "TLS_CHACHA20_POLY1305_SHA256",
|
||||
}
|
||||
|
|
48
vendor/google.golang.org/grpc/dialoptions.go
generated
vendored
48
vendor/google.golang.org/grpc/dialoptions.go
generated
vendored
|
@ -46,6 +46,7 @@ func init() {
|
|||
internal.WithBinaryLogger = withBinaryLogger
|
||||
internal.JoinDialOptions = newJoinDialOption
|
||||
internal.DisableGlobalDialOptions = newDisableGlobalDialOptions
|
||||
internal.WithRecvBufferPool = withRecvBufferPool
|
||||
}
|
||||
|
||||
// dialOptions configure a Dial call. dialOptions are set by the DialOption
|
||||
|
@ -63,7 +64,6 @@ type dialOptions struct {
|
|||
block bool
|
||||
returnLastError bool
|
||||
timeout time.Duration
|
||||
scChan <-chan ServiceConfig
|
||||
authority string
|
||||
binaryLogger binarylog.Logger
|
||||
copts transport.ConnectOptions
|
||||
|
@ -250,19 +250,6 @@ func WithDecompressor(dc Decompressor) DialOption {
|
|||
})
|
||||
}
|
||||
|
||||
// WithServiceConfig returns a DialOption which has a channel to read the
|
||||
// service configuration.
|
||||
//
|
||||
// Deprecated: service config should be received through name resolver or via
|
||||
// WithDefaultServiceConfig, as specified at
|
||||
// https://github.com/grpc/grpc/blob/master/doc/service_config.md. Will be
|
||||
// removed in a future 1.x release.
|
||||
func WithServiceConfig(c <-chan ServiceConfig) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.scChan = c
|
||||
})
|
||||
}
|
||||
|
||||
// WithConnectParams configures the ClientConn to use the provided ConnectParams
|
||||
// for creating and maintaining connections to servers.
|
||||
//
|
||||
|
@ -413,6 +400,17 @@ func WithTimeout(d time.Duration) DialOption {
|
|||
// connections. If FailOnNonTempDialError() is set to true, and an error is
|
||||
// returned by f, gRPC checks the error's Temporary() method to decide if it
|
||||
// should try to reconnect to the network address.
|
||||
//
|
||||
// Note: All supported releases of Go (as of December 2023) override the OS
|
||||
// defaults for TCP keepalive time and interval to 15s. To enable TCP keepalive
|
||||
// with OS defaults for keepalive time and interval, use a net.Dialer that sets
|
||||
// the KeepAlive field to a negative value, and sets the SO_KEEPALIVE socket
|
||||
// option to true from the Control field. For a concrete example of how to do
|
||||
// this, see internal.NetDialerWithTCPKeepalive().
|
||||
//
|
||||
// For more information, please see [issue 23459] in the Go github repo.
|
||||
//
|
||||
// [issue 23459]: https://github.com/golang/go/issues/23459
|
||||
func WithContextDialer(f func(context.Context, string) (net.Conn, error)) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.Dialer = f
|
||||
|
@ -487,7 +485,7 @@ func FailOnNonTempDialError(f bool) DialOption {
|
|||
// the RPCs.
|
||||
func WithUserAgent(s string) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.copts.UserAgent = s
|
||||
o.copts.UserAgent = s + " " + grpcUA
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -637,14 +635,16 @@ func withHealthCheckFunc(f internal.HealthChecker) DialOption {
|
|||
|
||||
func defaultDialOptions() dialOptions {
|
||||
return dialOptions{
|
||||
healthCheckFunc: internal.HealthCheckFunc,
|
||||
copts: transport.ConnectOptions{
|
||||
WriteBufferSize: defaultWriteBufSize,
|
||||
ReadBufferSize: defaultReadBufSize,
|
||||
WriteBufferSize: defaultWriteBufSize,
|
||||
UseProxy: true,
|
||||
UserAgent: grpcUA,
|
||||
},
|
||||
recvBufferPool: nopBufferPool{},
|
||||
idleTimeout: 30 * time.Minute,
|
||||
bs: internalbackoff.DefaultExponential,
|
||||
healthCheckFunc: internal.HealthCheckFunc,
|
||||
idleTimeout: 30 * time.Minute,
|
||||
recvBufferPool: nopBufferPool{},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -705,11 +705,13 @@ func WithIdleTimeout(d time.Duration) DialOption {
|
|||
// options are used: WithStatsHandler, EnableTracing, or binary logging. In such
|
||||
// cases, the shared buffer pool will be ignored.
|
||||
//
|
||||
// # Experimental
|
||||
//
|
||||
// Notice: This API is EXPERIMENTAL and may be changed or removed in a
|
||||
// later release.
|
||||
// Deprecated: use experimental.WithRecvBufferPool instead. Will be deleted in
|
||||
// v1.60.0 or later.
|
||||
func WithRecvBufferPool(bufferPool SharedBufferPool) DialOption {
|
||||
return withRecvBufferPool(bufferPool)
|
||||
}
|
||||
|
||||
func withRecvBufferPool(bufferPool SharedBufferPool) DialOption {
|
||||
return newFuncDialOption(func(o *dialOptions) {
|
||||
o.recvBufferPool = bufferPool
|
||||
})
|
||||
|
|
41
vendor/google.golang.org/grpc/internal/buffer/unbounded.go
generated
vendored
41
vendor/google.golang.org/grpc/internal/buffer/unbounded.go
generated
vendored
|
@ -18,7 +18,10 @@
|
|||
// Package buffer provides an implementation of an unbounded buffer.
|
||||
package buffer
|
||||
|
||||
import "sync"
|
||||
import (
|
||||
"errors"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Unbounded is an implementation of an unbounded buffer which does not use
|
||||
// extra goroutines. This is typically used for passing updates from one entity
|
||||
|
@ -36,6 +39,7 @@ import "sync"
|
|||
type Unbounded struct {
|
||||
c chan any
|
||||
closed bool
|
||||
closing bool
|
||||
mu sync.Mutex
|
||||
backlog []any
|
||||
}
|
||||
|
@ -45,32 +49,32 @@ func NewUnbounded() *Unbounded {
|
|||
return &Unbounded{c: make(chan any, 1)}
|
||||
}
|
||||
|
||||
var errBufferClosed = errors.New("Put called on closed buffer.Unbounded")
|
||||
|
||||
// Put adds t to the unbounded buffer.
|
||||
func (b *Unbounded) Put(t any) {
|
||||
func (b *Unbounded) Put(t any) error {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
if b.closed {
|
||||
return
|
||||
if b.closing {
|
||||
return errBufferClosed
|
||||
}
|
||||
if len(b.backlog) == 0 {
|
||||
select {
|
||||
case b.c <- t:
|
||||
return
|
||||
return nil
|
||||
default:
|
||||
}
|
||||
}
|
||||
b.backlog = append(b.backlog, t)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Load sends the earliest buffered data, if any, onto the read channel
|
||||
// returned by Get(). Users are expected to call this every time they read a
|
||||
// Load sends the earliest buffered data, if any, onto the read channel returned
|
||||
// by Get(). Users are expected to call this every time they successfully read a
|
||||
// value from the read channel.
|
||||
func (b *Unbounded) Load() {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
if b.closed {
|
||||
return
|
||||
}
|
||||
if len(b.backlog) > 0 {
|
||||
select {
|
||||
case b.c <- b.backlog[0]:
|
||||
|
@ -78,6 +82,8 @@ func (b *Unbounded) Load() {
|
|||
b.backlog = b.backlog[1:]
|
||||
default:
|
||||
}
|
||||
} else if b.closing && !b.closed {
|
||||
close(b.c)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,18 +94,23 @@ func (b *Unbounded) Load() {
|
|||
// send the next buffered value onto the channel if there is any.
|
||||
//
|
||||
// If the unbounded buffer is closed, the read channel returned by this method
|
||||
// is closed.
|
||||
// is closed after all data is drained.
|
||||
func (b *Unbounded) Get() <-chan any {
|
||||
return b.c
|
||||
}
|
||||
|
||||
// Close closes the unbounded buffer.
|
||||
// Close closes the unbounded buffer. No subsequent data may be Put(), and the
|
||||
// channel returned from Get() will be closed after all the data is read and
|
||||
// Load() is called for the final time.
|
||||
func (b *Unbounded) Close() {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
if b.closed {
|
||||
if b.closing {
|
||||
return
|
||||
}
|
||||
b.closed = true
|
||||
close(b.c)
|
||||
b.closing = true
|
||||
if len(b.backlog) == 0 {
|
||||
b.closed = true
|
||||
close(b.c)
|
||||
}
|
||||
}
|
||||
|
|
7
vendor/google.golang.org/grpc/internal/channelz/funcs.go
generated
vendored
7
vendor/google.golang.org/grpc/internal/channelz/funcs.go
generated
vendored
|
@ -31,6 +31,7 @@ import (
|
|||
"time"
|
||||
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/internal"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -58,6 +59,12 @@ func TurnOn() {
|
|||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
internal.ChannelzTurnOffForTesting = func() {
|
||||
atomic.StoreInt32(&curState, 0)
|
||||
}
|
||||
}
|
||||
|
||||
// IsOn returns whether channelz data collection is on.
|
||||
func IsOn() bool {
|
||||
return atomic.LoadInt32(&curState) == 1
|
||||
|
|
3
vendor/google.golang.org/grpc/internal/envconfig/envconfig.go
generated
vendored
3
vendor/google.golang.org/grpc/internal/envconfig/envconfig.go
generated
vendored
|
@ -36,9 +36,6 @@ var (
|
|||
// "GRPC_RING_HASH_CAP". This does not override the default bounds
|
||||
// checking which NACKs configs specifying ring sizes > 8*1024*1024 (~8M).
|
||||
RingHashCap = uint64FromEnv("GRPC_RING_HASH_CAP", 4096, 1, 8*1024*1024)
|
||||
// PickFirstLBConfig is set if we should support configuration of the
|
||||
// pick_first LB policy.
|
||||
PickFirstLBConfig = boolFromEnv("GRPC_EXPERIMENTAL_PICKFIRST_LB_CONFIG", true)
|
||||
// LeastRequestLB is set if we should support the least_request_experimental
|
||||
// LB policy, which can be enabled by setting the environment variable
|
||||
// "GRPC_EXPERIMENTAL_ENABLE_LEAST_REQUEST" to "true".
|
||||
|
|
39
vendor/google.golang.org/grpc/internal/envconfig/xds.go
generated
vendored
39
vendor/google.golang.org/grpc/internal/envconfig/xds.go
generated
vendored
|
@ -50,46 +50,7 @@ var (
|
|||
//
|
||||
// When both bootstrap FileName and FileContent are set, FileName is used.
|
||||
XDSBootstrapFileContent = os.Getenv(XDSBootstrapFileContentEnv)
|
||||
// XDSRingHash indicates whether ring hash support is enabled, which can be
|
||||
// disabled by setting the environment variable
|
||||
// "GRPC_XDS_EXPERIMENTAL_ENABLE_RING_HASH" to "false".
|
||||
XDSRingHash = boolFromEnv("GRPC_XDS_EXPERIMENTAL_ENABLE_RING_HASH", true)
|
||||
// XDSClientSideSecurity is used to control processing of security
|
||||
// configuration on the client-side.
|
||||
//
|
||||
// Note that there is no env var protection for the server-side because we
|
||||
// have a brand new API on the server-side and users explicitly need to use
|
||||
// the new API to get security integration on the server.
|
||||
XDSClientSideSecurity = boolFromEnv("GRPC_XDS_EXPERIMENTAL_SECURITY_SUPPORT", true)
|
||||
// XDSAggregateAndDNS indicates whether processing of aggregated cluster and
|
||||
// DNS cluster is enabled, which can be disabled by setting the environment
|
||||
// variable "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER"
|
||||
// to "false".
|
||||
XDSAggregateAndDNS = boolFromEnv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER", true)
|
||||
|
||||
// XDSRBAC indicates whether xDS configured RBAC HTTP Filter is enabled,
|
||||
// which can be disabled by setting the environment variable
|
||||
// "GRPC_XDS_EXPERIMENTAL_RBAC" to "false".
|
||||
XDSRBAC = boolFromEnv("GRPC_XDS_EXPERIMENTAL_RBAC", true)
|
||||
// XDSOutlierDetection indicates whether outlier detection support is
|
||||
// enabled, which can be disabled by setting the environment variable
|
||||
// "GRPC_EXPERIMENTAL_ENABLE_OUTLIER_DETECTION" to "false".
|
||||
XDSOutlierDetection = boolFromEnv("GRPC_EXPERIMENTAL_ENABLE_OUTLIER_DETECTION", true)
|
||||
// XDSFederation indicates whether federation support is enabled, which can
|
||||
// be enabled by setting the environment variable
|
||||
// "GRPC_EXPERIMENTAL_XDS_FEDERATION" to "true".
|
||||
XDSFederation = boolFromEnv("GRPC_EXPERIMENTAL_XDS_FEDERATION", true)
|
||||
|
||||
// XDSRLS indicates whether processing of Cluster Specifier plugins and
|
||||
// support for the RLS CLuster Specifier is enabled, which can be disabled by
|
||||
// setting the environment variable "GRPC_EXPERIMENTAL_XDS_RLS_LB" to
|
||||
// "false".
|
||||
XDSRLS = boolFromEnv("GRPC_EXPERIMENTAL_XDS_RLS_LB", true)
|
||||
|
||||
// C2PResolverTestOnlyTrafficDirectorURI is the TD URI for testing.
|
||||
C2PResolverTestOnlyTrafficDirectorURI = os.Getenv("GRPC_TEST_ONLY_GOOGLE_C2P_RESOLVER_TRAFFIC_DIRECTOR_URI")
|
||||
// XDSCustomLBPolicy indicates whether Custom LB Policies are enabled, which
|
||||
// can be disabled by setting the environment variable
|
||||
// "GRPC_EXPERIMENTAL_XDS_CUSTOM_LB_CONFIG" to "false".
|
||||
XDSCustomLBPolicy = boolFromEnv("GRPC_EXPERIMENTAL_XDS_CUSTOM_LB_CONFIG", true)
|
||||
)
|
||||
|
|
28
vendor/google.golang.org/grpc/internal/experimental.go
generated
vendored
Normal file
28
vendor/google.golang.org/grpc/internal/experimental.go
generated
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright 2023 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package internal
|
||||
|
||||
var (
|
||||
// WithRecvBufferPool is implemented by the grpc package and returns a dial
|
||||
// option to configure a shared buffer pool for a grpc.ClientConn.
|
||||
WithRecvBufferPool any // func (grpc.SharedBufferPool) grpc.DialOption
|
||||
|
||||
// RecvBufferPool is implemented by the grpc package and returns a server
|
||||
// option to configure a shared buffer pool for a grpc.Server.
|
||||
RecvBufferPool any // func (grpc.SharedBufferPool) grpc.ServerOption
|
||||
)
|
51
vendor/google.golang.org/grpc/internal/grpcsync/callback_serializer.go
generated
vendored
51
vendor/google.golang.org/grpc/internal/grpcsync/callback_serializer.go
generated
vendored
|
@ -20,7 +20,6 @@ package grpcsync
|
|||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"google.golang.org/grpc/internal/buffer"
|
||||
)
|
||||
|
@ -38,8 +37,6 @@ type CallbackSerializer struct {
|
|||
done chan struct{}
|
||||
|
||||
callbacks *buffer.Unbounded
|
||||
closedMu sync.Mutex
|
||||
closed bool
|
||||
}
|
||||
|
||||
// NewCallbackSerializer returns a new CallbackSerializer instance. The provided
|
||||
|
@ -65,56 +62,34 @@ func NewCallbackSerializer(ctx context.Context) *CallbackSerializer {
|
|||
// callbacks to be executed by the serializer. It is not possible to add
|
||||
// callbacks once the context passed to NewCallbackSerializer is cancelled.
|
||||
func (cs *CallbackSerializer) Schedule(f func(ctx context.Context)) bool {
|
||||
cs.closedMu.Lock()
|
||||
defer cs.closedMu.Unlock()
|
||||
|
||||
if cs.closed {
|
||||
return false
|
||||
}
|
||||
cs.callbacks.Put(f)
|
||||
return true
|
||||
return cs.callbacks.Put(f) == nil
|
||||
}
|
||||
|
||||
func (cs *CallbackSerializer) run(ctx context.Context) {
|
||||
var backlog []func(context.Context)
|
||||
|
||||
defer close(cs.done)
|
||||
|
||||
// TODO: when Go 1.21 is the oldest supported version, this loop and Close
|
||||
// can be replaced with:
|
||||
//
|
||||
// context.AfterFunc(ctx, cs.callbacks.Close)
|
||||
for ctx.Err() == nil {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
// Do nothing here. Next iteration of the for loop will not happen,
|
||||
// since ctx.Err() would be non-nil.
|
||||
case callback, ok := <-cs.callbacks.Get():
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
case cb := <-cs.callbacks.Get():
|
||||
cs.callbacks.Load()
|
||||
callback.(func(ctx context.Context))(ctx)
|
||||
cb.(func(context.Context))(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch pending callbacks if any, and execute them before returning from
|
||||
// this method and closing cs.done.
|
||||
cs.closedMu.Lock()
|
||||
cs.closed = true
|
||||
backlog = cs.fetchPendingCallbacks()
|
||||
// Close the buffer to prevent new callbacks from being added.
|
||||
cs.callbacks.Close()
|
||||
cs.closedMu.Unlock()
|
||||
for _, b := range backlog {
|
||||
b(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
func (cs *CallbackSerializer) fetchPendingCallbacks() []func(context.Context) {
|
||||
var backlog []func(context.Context)
|
||||
for {
|
||||
select {
|
||||
case b := <-cs.callbacks.Get():
|
||||
backlog = append(backlog, b.(func(context.Context)))
|
||||
cs.callbacks.Load()
|
||||
default:
|
||||
return backlog
|
||||
}
|
||||
// Run all pending callbacks.
|
||||
for cb := range cs.callbacks.Get() {
|
||||
cs.callbacks.Load()
|
||||
cb.(func(context.Context))(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
177
vendor/google.golang.org/grpc/internal/idle/idle.go
generated
vendored
177
vendor/google.golang.org/grpc/internal/idle/idle.go
generated
vendored
|
@ -26,8 +26,6 @@ import (
|
|||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc/grpclog"
|
||||
)
|
||||
|
||||
// For overriding in unit tests.
|
||||
|
@ -39,27 +37,12 @@ var timeAfterFunc = func(d time.Duration, f func()) *time.Timer {
|
|||
// and exit from idle mode.
|
||||
type Enforcer interface {
|
||||
ExitIdleMode() error
|
||||
EnterIdleMode() error
|
||||
EnterIdleMode()
|
||||
}
|
||||
|
||||
// Manager defines the functionality required to track RPC activity on a
|
||||
// channel.
|
||||
type Manager interface {
|
||||
OnCallBegin() error
|
||||
OnCallEnd()
|
||||
Close()
|
||||
}
|
||||
|
||||
type noopManager struct{}
|
||||
|
||||
func (noopManager) OnCallBegin() error { return nil }
|
||||
func (noopManager) OnCallEnd() {}
|
||||
func (noopManager) Close() {}
|
||||
|
||||
// manager implements the Manager interface. It uses atomic operations to
|
||||
// synchronize access to shared state and a mutex to guarantee mutual exclusion
|
||||
// in a critical section.
|
||||
type manager struct {
|
||||
// Manager implements idleness detection and calls the configured Enforcer to
|
||||
// enter/exit idle mode when appropriate. Must be created by NewManager.
|
||||
type Manager struct {
|
||||
// State accessed atomically.
|
||||
lastCallEndTime int64 // Unix timestamp in nanos; time when the most recent RPC completed.
|
||||
activeCallsCount int32 // Count of active RPCs; -math.MaxInt32 means channel is idle or is trying to get there.
|
||||
|
@ -69,8 +52,7 @@ type manager struct {
|
|||
// Can be accessed without atomics or mutex since these are set at creation
|
||||
// time and read-only after that.
|
||||
enforcer Enforcer // Functionality provided by grpc.ClientConn.
|
||||
timeout int64 // Idle timeout duration nanos stored as an int64.
|
||||
logger grpclog.LoggerV2
|
||||
timeout time.Duration
|
||||
|
||||
// idleMu is used to guarantee mutual exclusion in two scenarios:
|
||||
// - Opposing intentions:
|
||||
|
@ -88,57 +70,48 @@ type manager struct {
|
|||
timer *time.Timer
|
||||
}
|
||||
|
||||
// ManagerOptions is a collection of options used by
|
||||
// NewManager.
|
||||
type ManagerOptions struct {
|
||||
Enforcer Enforcer
|
||||
Timeout time.Duration
|
||||
Logger grpclog.LoggerV2
|
||||
}
|
||||
|
||||
// NewManager creates a new idleness manager implementation for the
|
||||
// given idle timeout.
|
||||
func NewManager(opts ManagerOptions) Manager {
|
||||
if opts.Timeout == 0 {
|
||||
return noopManager{}
|
||||
// given idle timeout. It begins in idle mode.
|
||||
func NewManager(enforcer Enforcer, timeout time.Duration) *Manager {
|
||||
return &Manager{
|
||||
enforcer: enforcer,
|
||||
timeout: timeout,
|
||||
actuallyIdle: true,
|
||||
activeCallsCount: -math.MaxInt32,
|
||||
}
|
||||
|
||||
m := &manager{
|
||||
enforcer: opts.Enforcer,
|
||||
timeout: int64(opts.Timeout),
|
||||
logger: opts.Logger,
|
||||
}
|
||||
m.timer = timeAfterFunc(opts.Timeout, m.handleIdleTimeout)
|
||||
return m
|
||||
}
|
||||
|
||||
// resetIdleTimer resets the idle timer to the given duration. This method
|
||||
// should only be called from the timer callback.
|
||||
func (m *manager) resetIdleTimer(d time.Duration) {
|
||||
m.idleMu.Lock()
|
||||
defer m.idleMu.Unlock()
|
||||
|
||||
if m.timer == nil {
|
||||
// Only close sets timer to nil. We are done.
|
||||
// resetIdleTimerLocked resets the idle timer to the given duration. Called
|
||||
// when exiting idle mode or when the timer fires and we need to reset it.
|
||||
func (m *Manager) resetIdleTimerLocked(d time.Duration) {
|
||||
if m.isClosed() || m.timeout == 0 || m.actuallyIdle {
|
||||
return
|
||||
}
|
||||
|
||||
// It is safe to ignore the return value from Reset() because this method is
|
||||
// only ever called from the timer callback, which means the timer has
|
||||
// already fired.
|
||||
m.timer.Reset(d)
|
||||
// only ever called from the timer callback or when exiting idle mode.
|
||||
if m.timer != nil {
|
||||
m.timer.Stop()
|
||||
}
|
||||
m.timer = timeAfterFunc(d, m.handleIdleTimeout)
|
||||
}
|
||||
|
||||
func (m *Manager) resetIdleTimer(d time.Duration) {
|
||||
m.idleMu.Lock()
|
||||
defer m.idleMu.Unlock()
|
||||
m.resetIdleTimerLocked(d)
|
||||
}
|
||||
|
||||
// handleIdleTimeout is the timer callback that is invoked upon expiry of the
|
||||
// configured idle timeout. The channel is considered inactive if there are no
|
||||
// ongoing calls and no RPC activity since the last time the timer fired.
|
||||
func (m *manager) handleIdleTimeout() {
|
||||
func (m *Manager) handleIdleTimeout() {
|
||||
if m.isClosed() {
|
||||
return
|
||||
}
|
||||
|
||||
if atomic.LoadInt32(&m.activeCallsCount) > 0 {
|
||||
m.resetIdleTimer(time.Duration(m.timeout))
|
||||
m.resetIdleTimer(m.timeout)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -148,24 +121,12 @@ func (m *manager) handleIdleTimeout() {
|
|||
// Set the timer to fire after a duration of idle timeout, calculated
|
||||
// from the time the most recent RPC completed.
|
||||
atomic.StoreInt32(&m.activeSinceLastTimerCheck, 0)
|
||||
m.resetIdleTimer(time.Duration(atomic.LoadInt64(&m.lastCallEndTime) + m.timeout - time.Now().UnixNano()))
|
||||
m.resetIdleTimer(time.Duration(atomic.LoadInt64(&m.lastCallEndTime)-time.Now().UnixNano()) + m.timeout)
|
||||
return
|
||||
}
|
||||
|
||||
// This CAS operation is extremely likely to succeed given that there has
|
||||
// been no activity since the last time we were here. Setting the
|
||||
// activeCallsCount to -math.MaxInt32 indicates to OnCallBegin() that the
|
||||
// channel is either in idle mode or is trying to get there.
|
||||
if !atomic.CompareAndSwapInt32(&m.activeCallsCount, 0, -math.MaxInt32) {
|
||||
// This CAS operation can fail if an RPC started after we checked for
|
||||
// activity at the top of this method, or one was ongoing from before
|
||||
// the last time we were here. In both case, reset the timer and return.
|
||||
m.resetIdleTimer(time.Duration(m.timeout))
|
||||
return
|
||||
}
|
||||
|
||||
// Now that we've set the active calls count to -math.MaxInt32, it's time to
|
||||
// actually move to idle mode.
|
||||
// Now that we've checked that there has been no activity, attempt to enter
|
||||
// idle mode, which is very likely to succeed.
|
||||
if m.tryEnterIdleMode() {
|
||||
// Successfully entered idle mode. No timer needed until we exit idle.
|
||||
return
|
||||
|
@ -174,8 +135,7 @@ func (m *manager) handleIdleTimeout() {
|
|||
// Failed to enter idle mode due to a concurrent RPC that kept the channel
|
||||
// active, or because of an error from the channel. Undo the attempt to
|
||||
// enter idle, and reset the timer to try again later.
|
||||
atomic.AddInt32(&m.activeCallsCount, math.MaxInt32)
|
||||
m.resetIdleTimer(time.Duration(m.timeout))
|
||||
m.resetIdleTimer(m.timeout)
|
||||
}
|
||||
|
||||
// tryEnterIdleMode instructs the channel to enter idle mode. But before
|
||||
|
@ -185,36 +145,49 @@ func (m *manager) handleIdleTimeout() {
|
|||
// Return value indicates whether or not the channel moved to idle mode.
|
||||
//
|
||||
// Holds idleMu which ensures mutual exclusion with exitIdleMode.
|
||||
func (m *manager) tryEnterIdleMode() bool {
|
||||
func (m *Manager) tryEnterIdleMode() bool {
|
||||
// Setting the activeCallsCount to -math.MaxInt32 indicates to OnCallBegin()
|
||||
// that the channel is either in idle mode or is trying to get there.
|
||||
if !atomic.CompareAndSwapInt32(&m.activeCallsCount, 0, -math.MaxInt32) {
|
||||
// This CAS operation can fail if an RPC started after we checked for
|
||||
// activity in the timer handler, or one was ongoing from before the
|
||||
// last time the timer fired, or if a test is attempting to enter idle
|
||||
// mode without checking. In all cases, abort going into idle mode.
|
||||
return false
|
||||
}
|
||||
// N.B. if we fail to enter idle mode after this, we must re-add
|
||||
// math.MaxInt32 to m.activeCallsCount.
|
||||
|
||||
m.idleMu.Lock()
|
||||
defer m.idleMu.Unlock()
|
||||
|
||||
if atomic.LoadInt32(&m.activeCallsCount) != -math.MaxInt32 {
|
||||
// We raced and lost to a new RPC. Very rare, but stop entering idle.
|
||||
atomic.AddInt32(&m.activeCallsCount, math.MaxInt32)
|
||||
return false
|
||||
}
|
||||
if atomic.LoadInt32(&m.activeSinceLastTimerCheck) == 1 {
|
||||
// An very short RPC could have come in (and also finished) after we
|
||||
// A very short RPC could have come in (and also finished) after we
|
||||
// checked for calls count and activity in handleIdleTimeout(), but
|
||||
// before the CAS operation. So, we need to check for activity again.
|
||||
atomic.AddInt32(&m.activeCallsCount, math.MaxInt32)
|
||||
return false
|
||||
}
|
||||
|
||||
// No new RPCs have come in since we last set the active calls count value
|
||||
// -math.MaxInt32 in the timer callback. And since we have the lock, it is
|
||||
// safe to enter idle mode now.
|
||||
if err := m.enforcer.EnterIdleMode(); err != nil {
|
||||
m.logger.Errorf("Failed to enter idle mode: %v", err)
|
||||
return false
|
||||
}
|
||||
|
||||
// Successfully entered idle mode.
|
||||
// No new RPCs have come in since we set the active calls count value to
|
||||
// -math.MaxInt32. And since we have the lock, it is safe to enter idle mode
|
||||
// unconditionally now.
|
||||
m.enforcer.EnterIdleMode()
|
||||
m.actuallyIdle = true
|
||||
return true
|
||||
}
|
||||
|
||||
func (m *Manager) EnterIdleModeForTesting() {
|
||||
m.tryEnterIdleMode()
|
||||
}
|
||||
|
||||
// OnCallBegin is invoked at the start of every RPC.
|
||||
func (m *manager) OnCallBegin() error {
|
||||
func (m *Manager) OnCallBegin() error {
|
||||
if m.isClosed() {
|
||||
return nil
|
||||
}
|
||||
|
@ -227,7 +200,7 @@ func (m *manager) OnCallBegin() error {
|
|||
|
||||
// Channel is either in idle mode or is in the process of moving to idle
|
||||
// mode. Attempt to exit idle mode to allow this RPC.
|
||||
if err := m.exitIdleMode(); err != nil {
|
||||
if err := m.ExitIdleMode(); err != nil {
|
||||
// Undo the increment to calls count, and return an error causing the
|
||||
// RPC to fail.
|
||||
atomic.AddInt32(&m.activeCallsCount, -1)
|
||||
|
@ -238,28 +211,30 @@ func (m *manager) OnCallBegin() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// exitIdleMode instructs the channel to exit idle mode.
|
||||
//
|
||||
// Holds idleMu which ensures mutual exclusion with tryEnterIdleMode.
|
||||
func (m *manager) exitIdleMode() error {
|
||||
// ExitIdleMode instructs m to call the enforcer's ExitIdleMode and update m's
|
||||
// internal state.
|
||||
func (m *Manager) ExitIdleMode() error {
|
||||
// Holds idleMu which ensures mutual exclusion with tryEnterIdleMode.
|
||||
m.idleMu.Lock()
|
||||
defer m.idleMu.Unlock()
|
||||
|
||||
if !m.actuallyIdle {
|
||||
// This can happen in two scenarios:
|
||||
if m.isClosed() || !m.actuallyIdle {
|
||||
// This can happen in three scenarios:
|
||||
// - handleIdleTimeout() set the calls count to -math.MaxInt32 and called
|
||||
// tryEnterIdleMode(). But before the latter could grab the lock, an RPC
|
||||
// came in and OnCallBegin() noticed that the calls count is negative.
|
||||
// - Channel is in idle mode, and multiple new RPCs come in at the same
|
||||
// time, all of them notice a negative calls count in OnCallBegin and get
|
||||
// here. The first one to get the lock would got the channel to exit idle.
|
||||
// - Channel is not in idle mode, and the user calls Connect which calls
|
||||
// m.ExitIdleMode.
|
||||
//
|
||||
// Either way, nothing to do here.
|
||||
// In any case, there is nothing to do here.
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := m.enforcer.ExitIdleMode(); err != nil {
|
||||
return fmt.Errorf("channel failed to exit idle mode: %v", err)
|
||||
return fmt.Errorf("failed to exit idle mode: %w", err)
|
||||
}
|
||||
|
||||
// Undo the idle entry process. This also respects any new RPC attempts.
|
||||
|
@ -267,12 +242,12 @@ func (m *manager) exitIdleMode() error {
|
|||
m.actuallyIdle = false
|
||||
|
||||
// Start a new timer to fire after the configured idle timeout.
|
||||
m.timer = timeAfterFunc(time.Duration(m.timeout), m.handleIdleTimeout)
|
||||
m.resetIdleTimerLocked(m.timeout)
|
||||
return nil
|
||||
}
|
||||
|
||||
// OnCallEnd is invoked at the end of every RPC.
|
||||
func (m *manager) OnCallEnd() {
|
||||
func (m *Manager) OnCallEnd() {
|
||||
if m.isClosed() {
|
||||
return
|
||||
}
|
||||
|
@ -287,15 +262,17 @@ func (m *manager) OnCallEnd() {
|
|||
atomic.AddInt32(&m.activeCallsCount, -1)
|
||||
}
|
||||
|
||||
func (m *manager) isClosed() bool {
|
||||
func (m *Manager) isClosed() bool {
|
||||
return atomic.LoadInt32(&m.closed) == 1
|
||||
}
|
||||
|
||||
func (m *manager) Close() {
|
||||
func (m *Manager) Close() {
|
||||
atomic.StoreInt32(&m.closed, 1)
|
||||
|
||||
m.idleMu.Lock()
|
||||
m.timer.Stop()
|
||||
m.timer = nil
|
||||
if m.timer != nil {
|
||||
m.timer.Stop()
|
||||
m.timer = nil
|
||||
}
|
||||
m.idleMu.Unlock()
|
||||
}
|
||||
|
|
9
vendor/google.golang.org/grpc/internal/internal.go
generated
vendored
9
vendor/google.golang.org/grpc/internal/internal.go
generated
vendored
|
@ -73,6 +73,11 @@ var (
|
|||
// xDS-enabled server invokes this method on a grpc.Server when a particular
|
||||
// listener moves to "not-serving" mode.
|
||||
DrainServerTransports any // func(*grpc.Server, string)
|
||||
// IsRegisteredMethod returns whether the passed in method is registered as
|
||||
// a method on the server.
|
||||
IsRegisteredMethod any // func(*grpc.Server, string) bool
|
||||
// ServerFromContext returns the server from the context.
|
||||
ServerFromContext any // func(context.Context) *grpc.Server
|
||||
// AddGlobalServerOptions adds an array of ServerOption that will be
|
||||
// effective globally for newly created servers. The priority will be: 1.
|
||||
// user-provided; 2. this method; 3. default values.
|
||||
|
@ -177,10 +182,12 @@ var (
|
|||
GRPCResolverSchemeExtraMetadata string = "xds"
|
||||
|
||||
// EnterIdleModeForTesting gets the ClientConn to enter IDLE mode.
|
||||
EnterIdleModeForTesting any // func(*grpc.ClientConn) error
|
||||
EnterIdleModeForTesting any // func(*grpc.ClientConn)
|
||||
|
||||
// ExitIdleModeForTesting gets the ClientConn to exit IDLE mode.
|
||||
ExitIdleModeForTesting any // func(*grpc.ClientConn) error
|
||||
|
||||
ChannelzTurnOffForTesting func()
|
||||
)
|
||||
|
||||
// HealthChecker defines the signature of the client-side LB channel health checking function.
|
||||
|
|
69
vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go
generated
vendored
69
vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go
generated
vendored
|
@ -23,7 +23,6 @@ package dns
|
|||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
|
@ -37,6 +36,7 @@ import (
|
|||
"google.golang.org/grpc/internal/backoff"
|
||||
"google.golang.org/grpc/internal/envconfig"
|
||||
"google.golang.org/grpc/internal/grpcrand"
|
||||
"google.golang.org/grpc/internal/resolver/dns/internal"
|
||||
"google.golang.org/grpc/resolver"
|
||||
"google.golang.org/grpc/serviceconfig"
|
||||
)
|
||||
|
@ -47,15 +47,11 @@ var EnableSRVLookups = false
|
|||
|
||||
var logger = grpclog.Component("dns")
|
||||
|
||||
// Globals to stub out in tests. TODO: Perhaps these two can be combined into a
|
||||
// single variable for testing the resolver?
|
||||
var (
|
||||
newTimer = time.NewTimer
|
||||
newTimerDNSResRate = time.NewTimer
|
||||
)
|
||||
|
||||
func init() {
|
||||
resolver.Register(NewBuilder())
|
||||
internal.TimeAfterFunc = time.After
|
||||
internal.NewNetResolver = newNetResolver
|
||||
internal.AddressDialer = addressDialer
|
||||
}
|
||||
|
||||
const (
|
||||
|
@ -70,23 +66,6 @@ const (
|
|||
txtAttribute = "grpc_config="
|
||||
)
|
||||
|
||||
var (
|
||||
errMissingAddr = errors.New("dns resolver: missing address")
|
||||
|
||||
// Addresses ending with a colon that is supposed to be the separator
|
||||
// between host and port is not allowed. E.g. "::" is a valid address as
|
||||
// it is an IPv6 address (host only) and "[::]:" is invalid as it ends with
|
||||
// a colon as the host and port separator
|
||||
errEndsWithColon = errors.New("dns resolver: missing port after port-separator colon")
|
||||
)
|
||||
|
||||
var (
|
||||
defaultResolver netResolver = net.DefaultResolver
|
||||
// To prevent excessive re-resolution, we enforce a rate limit on DNS
|
||||
// resolution requests.
|
||||
minDNSResRate = 30 * time.Second
|
||||
)
|
||||
|
||||
var addressDialer = func(address string) func(context.Context, string, string) (net.Conn, error) {
|
||||
return func(ctx context.Context, network, _ string) (net.Conn, error) {
|
||||
var dialer net.Dialer
|
||||
|
@ -94,7 +73,11 @@ var addressDialer = func(address string) func(context.Context, string, string) (
|
|||
}
|
||||
}
|
||||
|
||||
var newNetResolver = func(authority string) (netResolver, error) {
|
||||
var newNetResolver = func(authority string) (internal.NetResolver, error) {
|
||||
if authority == "" {
|
||||
return net.DefaultResolver, nil
|
||||
}
|
||||
|
||||
host, port, err := parseTarget(authority, defaultDNSSvrPort)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -104,7 +87,7 @@ var newNetResolver = func(authority string) (netResolver, error) {
|
|||
|
||||
return &net.Resolver{
|
||||
PreferGo: true,
|
||||
Dial: addressDialer(authorityWithPort),
|
||||
Dial: internal.AddressDialer(authorityWithPort),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -142,13 +125,9 @@ func (b *dnsBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts
|
|||
disableServiceConfig: opts.DisableServiceConfig,
|
||||
}
|
||||
|
||||
if target.URL.Host == "" {
|
||||
d.resolver = defaultResolver
|
||||
} else {
|
||||
d.resolver, err = newNetResolver(target.URL.Host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
d.resolver, err = internal.NewNetResolver(target.URL.Host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
d.wg.Add(1)
|
||||
|
@ -161,12 +140,6 @@ func (b *dnsBuilder) Scheme() string {
|
|||
return "dns"
|
||||
}
|
||||
|
||||
type netResolver interface {
|
||||
LookupHost(ctx context.Context, host string) (addrs []string, err error)
|
||||
LookupSRV(ctx context.Context, service, proto, name string) (cname string, addrs []*net.SRV, err error)
|
||||
LookupTXT(ctx context.Context, name string) (txts []string, err error)
|
||||
}
|
||||
|
||||
// deadResolver is a resolver that does nothing.
|
||||
type deadResolver struct{}
|
||||
|
||||
|
@ -178,7 +151,7 @@ func (deadResolver) Close() {}
|
|||
type dnsResolver struct {
|
||||
host string
|
||||
port string
|
||||
resolver netResolver
|
||||
resolver internal.NetResolver
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
cc resolver.ClientConn
|
||||
|
@ -223,29 +196,27 @@ func (d *dnsResolver) watcher() {
|
|||
err = d.cc.UpdateState(*state)
|
||||
}
|
||||
|
||||
var timer *time.Timer
|
||||
var waitTime time.Duration
|
||||
if err == nil {
|
||||
// Success resolving, wait for the next ResolveNow. However, also wait 30
|
||||
// seconds at the very least to prevent constantly re-resolving.
|
||||
backoffIndex = 1
|
||||
timer = newTimerDNSResRate(minDNSResRate)
|
||||
waitTime = internal.MinResolutionRate
|
||||
select {
|
||||
case <-d.ctx.Done():
|
||||
timer.Stop()
|
||||
return
|
||||
case <-d.rn:
|
||||
}
|
||||
} else {
|
||||
// Poll on an error found in DNS Resolver or an error received from
|
||||
// ClientConn.
|
||||
timer = newTimer(backoff.DefaultExponential.Backoff(backoffIndex))
|
||||
waitTime = backoff.DefaultExponential.Backoff(backoffIndex)
|
||||
backoffIndex++
|
||||
}
|
||||
select {
|
||||
case <-d.ctx.Done():
|
||||
timer.Stop()
|
||||
return
|
||||
case <-timer.C:
|
||||
case <-internal.TimeAfterFunc(waitTime):
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -387,7 +358,7 @@ func formatIP(addr string) (addrIP string, ok bool) {
|
|||
// target: ":80" defaultPort: "443" returns host: "localhost", port: "80"
|
||||
func parseTarget(target, defaultPort string) (host, port string, err error) {
|
||||
if target == "" {
|
||||
return "", "", errMissingAddr
|
||||
return "", "", internal.ErrMissingAddr
|
||||
}
|
||||
if ip := net.ParseIP(target); ip != nil {
|
||||
// target is an IPv4 or IPv6(without brackets) address
|
||||
|
@ -397,7 +368,7 @@ func parseTarget(target, defaultPort string) (host, port string, err error) {
|
|||
if port == "" {
|
||||
// If the port field is empty (target ends with colon), e.g. "[::1]:",
|
||||
// this is an error.
|
||||
return "", "", errEndsWithColon
|
||||
return "", "", internal.ErrEndsWithColon
|
||||
}
|
||||
// target has port, i.e ipv4-host:port, [ipv6-host]:port, host-name:port
|
||||
if host == "" {
|
||||
|
|
70
vendor/google.golang.org/grpc/internal/resolver/dns/internal/internal.go
generated
vendored
Normal file
70
vendor/google.golang.org/grpc/internal/resolver/dns/internal/internal.go
generated
vendored
Normal file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2023 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package internal contains functionality internal to the dns resolver package.
|
||||
package internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
// NetResolver groups the methods on net.Resolver that are used by the DNS
|
||||
// resolver implementation. This allows the default net.Resolver instance to be
|
||||
// overidden from tests.
|
||||
type NetResolver interface {
|
||||
LookupHost(ctx context.Context, host string) (addrs []string, err error)
|
||||
LookupSRV(ctx context.Context, service, proto, name string) (cname string, addrs []*net.SRV, err error)
|
||||
LookupTXT(ctx context.Context, name string) (txts []string, err error)
|
||||
}
|
||||
|
||||
var (
|
||||
// ErrMissingAddr is the error returned when building a DNS resolver when
|
||||
// the provided target name is empty.
|
||||
ErrMissingAddr = errors.New("dns resolver: missing address")
|
||||
|
||||
// ErrEndsWithColon is the error returned when building a DNS resolver when
|
||||
// the provided target name ends with a colon that is supposed to be the
|
||||
// separator between host and port. E.g. "::" is a valid address as it is
|
||||
// an IPv6 address (host only) and "[::]:" is invalid as it ends with a
|
||||
// colon as the host and port separator
|
||||
ErrEndsWithColon = errors.New("dns resolver: missing port after port-separator colon")
|
||||
)
|
||||
|
||||
// The following vars are overridden from tests.
|
||||
var (
|
||||
// MinResolutionRate is the minimum rate at which re-resolutions are
|
||||
// allowed. This helps to prevent excessive re-resolution.
|
||||
MinResolutionRate = 30 * time.Second
|
||||
|
||||
// TimeAfterFunc is used by the DNS resolver to wait for the given duration
|
||||
// to elapse. In non-test code, this is implemented by time.After. In test
|
||||
// code, this can be used to control the amount of time the resolver is
|
||||
// blocked waiting for the duration to elapse.
|
||||
TimeAfterFunc func(time.Duration) <-chan time.Time
|
||||
|
||||
// NewNetResolver returns the net.Resolver instance for the given target.
|
||||
NewNetResolver func(string) (NetResolver, error)
|
||||
|
||||
// AddressDialer is the dialer used to dial the DNS server. It accepts the
|
||||
// Host portion of the URL corresponding to the user's dial target and
|
||||
// returns a dial function.
|
||||
AddressDialer func(address string) func(context.Context, string, string) (net.Conn, error)
|
||||
)
|
29
vendor/google.golang.org/grpc/internal/tcp_keepalive_nonunix.go
generated
vendored
Normal file
29
vendor/google.golang.org/grpc/internal/tcp_keepalive_nonunix.go
generated
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
//go:build !unix
|
||||
|
||||
/*
|
||||
* Copyright 2023 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"net"
|
||||
)
|
||||
|
||||
// NetDialerWithTCPKeepalive returns a vanilla net.Dialer on non-unix platforms.
|
||||
func NetDialerWithTCPKeepalive() *net.Dialer {
|
||||
return &net.Dialer{}
|
||||
}
|
54
vendor/google.golang.org/grpc/internal/tcp_keepalive_unix.go
generated
vendored
Normal file
54
vendor/google.golang.org/grpc/internal/tcp_keepalive_unix.go
generated
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
//go:build unix
|
||||
|
||||
/*
|
||||
* Copyright 2023 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"net"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// NetDialerWithTCPKeepalive returns a net.Dialer that enables TCP keepalives on
|
||||
// the underlying connection with OS default values for keepalive parameters.
|
||||
//
|
||||
// TODO: Once https://github.com/golang/go/issues/62254 lands, and the
|
||||
// appropriate Go version becomes less than our least supported Go version, we
|
||||
// should look into using the new API to make things more straightforward.
|
||||
func NetDialerWithTCPKeepalive() *net.Dialer {
|
||||
return &net.Dialer{
|
||||
// Setting a negative value here prevents the Go stdlib from overriding
|
||||
// the values of TCP keepalive time and interval. It also prevents the
|
||||
// Go stdlib from enabling TCP keepalives by default.
|
||||
KeepAlive: time.Duration(-1),
|
||||
// This method is called after the underlying network socket is created,
|
||||
// but before dialing the socket (or calling its connect() method). The
|
||||
// combination of unconditionally enabling TCP keepalives here, and
|
||||
// disabling the overriding of TCP keepalive parameters by setting the
|
||||
// KeepAlive field to a negative value above, results in OS defaults for
|
||||
// the TCP keealive interval and time parameters.
|
||||
Control: func(_, _ string, c syscall.RawConn) error {
|
||||
return c.Control(func(fd uintptr) {
|
||||
unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_KEEPALIVE, 1)
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
67
vendor/google.golang.org/grpc/internal/transport/handler_server.go
generated
vendored
67
vendor/google.golang.org/grpc/internal/transport/handler_server.go
generated
vendored
|
@ -75,11 +75,25 @@ func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request, stats []s
|
|||
return nil, errors.New(msg)
|
||||
}
|
||||
|
||||
var localAddr net.Addr
|
||||
if la := r.Context().Value(http.LocalAddrContextKey); la != nil {
|
||||
localAddr, _ = la.(net.Addr)
|
||||
}
|
||||
var authInfo credentials.AuthInfo
|
||||
if r.TLS != nil {
|
||||
authInfo = credentials.TLSInfo{State: *r.TLS, CommonAuthInfo: credentials.CommonAuthInfo{SecurityLevel: credentials.PrivacyAndIntegrity}}
|
||||
}
|
||||
p := peer.Peer{
|
||||
Addr: strAddr(r.RemoteAddr),
|
||||
LocalAddr: localAddr,
|
||||
AuthInfo: authInfo,
|
||||
}
|
||||
st := &serverHandlerTransport{
|
||||
rw: w,
|
||||
req: r,
|
||||
closedCh: make(chan struct{}),
|
||||
writes: make(chan func()),
|
||||
peer: p,
|
||||
contentType: contentType,
|
||||
contentSubtype: contentSubtype,
|
||||
stats: stats,
|
||||
|
@ -134,6 +148,8 @@ type serverHandlerTransport struct {
|
|||
|
||||
headerMD metadata.MD
|
||||
|
||||
peer peer.Peer
|
||||
|
||||
closeOnce sync.Once
|
||||
closedCh chan struct{} // closed on Close
|
||||
|
||||
|
@ -165,7 +181,13 @@ func (ht *serverHandlerTransport) Close(err error) {
|
|||
})
|
||||
}
|
||||
|
||||
func (ht *serverHandlerTransport) RemoteAddr() net.Addr { return strAddr(ht.req.RemoteAddr) }
|
||||
func (ht *serverHandlerTransport) Peer() *peer.Peer {
|
||||
return &peer.Peer{
|
||||
Addr: ht.peer.Addr,
|
||||
LocalAddr: ht.peer.LocalAddr,
|
||||
AuthInfo: ht.peer.AuthInfo,
|
||||
}
|
||||
}
|
||||
|
||||
// strAddr is a net.Addr backed by either a TCP "ip:port" string, or
|
||||
// the empty string if unknown.
|
||||
|
@ -347,10 +369,8 @@ func (ht *serverHandlerTransport) WriteHeader(s *Stream, md metadata.MD) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func (ht *serverHandlerTransport) HandleStreams(startStream func(*Stream)) {
|
||||
func (ht *serverHandlerTransport) HandleStreams(ctx context.Context, startStream func(*Stream)) {
|
||||
// With this transport type there will be exactly 1 stream: this HTTP request.
|
||||
|
||||
ctx := ht.req.Context()
|
||||
var cancel context.CancelFunc
|
||||
if ht.timeoutSet {
|
||||
ctx, cancel = context.WithTimeout(ctx, ht.timeout)
|
||||
|
@ -370,34 +390,19 @@ func (ht *serverHandlerTransport) HandleStreams(startStream func(*Stream)) {
|
|||
ht.Close(errors.New("request is done processing"))
|
||||
}()
|
||||
|
||||
req := ht.req
|
||||
|
||||
s := &Stream{
|
||||
id: 0, // irrelevant
|
||||
requestRead: func(int) {},
|
||||
cancel: cancel,
|
||||
buf: newRecvBuffer(),
|
||||
st: ht,
|
||||
method: req.URL.Path,
|
||||
recvCompress: req.Header.Get("grpc-encoding"),
|
||||
contentSubtype: ht.contentSubtype,
|
||||
}
|
||||
pr := &peer.Peer{
|
||||
Addr: ht.RemoteAddr(),
|
||||
}
|
||||
if req.TLS != nil {
|
||||
pr.AuthInfo = credentials.TLSInfo{State: *req.TLS, CommonAuthInfo: credentials.CommonAuthInfo{SecurityLevel: credentials.PrivacyAndIntegrity}}
|
||||
}
|
||||
ctx = metadata.NewIncomingContext(ctx, ht.headerMD)
|
||||
s.ctx = peer.NewContext(ctx, pr)
|
||||
for _, sh := range ht.stats {
|
||||
s.ctx = sh.TagRPC(s.ctx, &stats.RPCTagInfo{FullMethodName: s.method})
|
||||
inHeader := &stats.InHeader{
|
||||
FullMethod: s.method,
|
||||
RemoteAddr: ht.RemoteAddr(),
|
||||
Compression: s.recvCompress,
|
||||
}
|
||||
sh.HandleRPC(s.ctx, inHeader)
|
||||
req := ht.req
|
||||
s := &Stream{
|
||||
id: 0, // irrelevant
|
||||
ctx: ctx,
|
||||
requestRead: func(int) {},
|
||||
cancel: cancel,
|
||||
buf: newRecvBuffer(),
|
||||
st: ht,
|
||||
method: req.URL.Path,
|
||||
recvCompress: req.Header.Get("grpc-encoding"),
|
||||
contentSubtype: ht.contentSubtype,
|
||||
headerWireLength: 0, // won't have access to header wire length until golang/go#18997.
|
||||
}
|
||||
s.trReader = &transportReader{
|
||||
reader: &recvBufferReader{ctx: s.ctx, ctxDone: s.ctx.Done(), recv: s.buf, freeBuffer: func(*bytes.Buffer) {}},
|
||||
|
|
12
vendor/google.golang.org/grpc/internal/transport/http2_client.go
generated
vendored
12
vendor/google.golang.org/grpc/internal/transport/http2_client.go
generated
vendored
|
@ -36,6 +36,7 @@ import (
|
|||
"golang.org/x/net/http2/hpack"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/internal"
|
||||
"google.golang.org/grpc/internal/channelz"
|
||||
icredentials "google.golang.org/grpc/internal/credentials"
|
||||
"google.golang.org/grpc/internal/grpclog"
|
||||
|
@ -43,7 +44,7 @@ import (
|
|||
"google.golang.org/grpc/internal/grpcutil"
|
||||
imetadata "google.golang.org/grpc/internal/metadata"
|
||||
istatus "google.golang.org/grpc/internal/status"
|
||||
"google.golang.org/grpc/internal/syscall"
|
||||
isyscall "google.golang.org/grpc/internal/syscall"
|
||||
"google.golang.org/grpc/internal/transport/networktype"
|
||||
"google.golang.org/grpc/keepalive"
|
||||
"google.golang.org/grpc/metadata"
|
||||
|
@ -176,7 +177,7 @@ func dial(ctx context.Context, fn func(context.Context, string) (net.Conn, error
|
|||
if networkType == "tcp" && useProxy {
|
||||
return proxyDial(ctx, address, grpcUA)
|
||||
}
|
||||
return (&net.Dialer{}).DialContext(ctx, networkType, address)
|
||||
return internal.NetDialerWithTCPKeepalive().DialContext(ctx, networkType, address)
|
||||
}
|
||||
|
||||
func isTemporary(err error) bool {
|
||||
|
@ -262,7 +263,7 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
|
|||
}
|
||||
keepaliveEnabled := false
|
||||
if kp.Time != infinity {
|
||||
if err = syscall.SetTCPUserTimeout(conn, kp.Timeout); err != nil {
|
||||
if err = isyscall.SetTCPUserTimeout(conn, kp.Timeout); err != nil {
|
||||
return nil, connectionErrorf(false, err, "transport: failed to set TCP_USER_TIMEOUT: %v", err)
|
||||
}
|
||||
keepaliveEnabled = true
|
||||
|
@ -493,8 +494,9 @@ func (t *http2Client) newStream(ctx context.Context, callHdr *CallHdr) *Stream {
|
|||
|
||||
func (t *http2Client) getPeer() *peer.Peer {
|
||||
return &peer.Peer{
|
||||
Addr: t.remoteAddr,
|
||||
AuthInfo: t.authInfo, // Can be nil
|
||||
Addr: t.remoteAddr,
|
||||
AuthInfo: t.authInfo, // Can be nil
|
||||
LocalAddr: t.localAddr,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
107
vendor/google.golang.org/grpc/internal/transport/http2_server.go
generated
vendored
107
vendor/google.golang.org/grpc/internal/transport/http2_server.go
generated
vendored
|
@ -68,18 +68,15 @@ var serverConnectionCounter uint64
|
|||
|
||||
// http2Server implements the ServerTransport interface with HTTP2.
|
||||
type http2Server struct {
|
||||
lastRead int64 // Keep this field 64-bit aligned. Accessed atomically.
|
||||
ctx context.Context
|
||||
done chan struct{}
|
||||
conn net.Conn
|
||||
loopy *loopyWriter
|
||||
readerDone chan struct{} // sync point to enable testing.
|
||||
writerDone chan struct{} // sync point to enable testing.
|
||||
remoteAddr net.Addr
|
||||
localAddr net.Addr
|
||||
authInfo credentials.AuthInfo // auth info about the connection
|
||||
inTapHandle tap.ServerInHandle
|
||||
framer *framer
|
||||
lastRead int64 // Keep this field 64-bit aligned. Accessed atomically.
|
||||
done chan struct{}
|
||||
conn net.Conn
|
||||
loopy *loopyWriter
|
||||
readerDone chan struct{} // sync point to enable testing.
|
||||
loopyWriterDone chan struct{}
|
||||
peer peer.Peer
|
||||
inTapHandle tap.ServerInHandle
|
||||
framer *framer
|
||||
// The max number of concurrent streams.
|
||||
maxStreams uint32
|
||||
// controlBuf delivers all the control related tasks (e.g., window
|
||||
|
@ -243,16 +240,18 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
|
|||
}
|
||||
|
||||
done := make(chan struct{})
|
||||
peer := peer.Peer{
|
||||
Addr: conn.RemoteAddr(),
|
||||
LocalAddr: conn.LocalAddr(),
|
||||
AuthInfo: authInfo,
|
||||
}
|
||||
t := &http2Server{
|
||||
ctx: setConnection(context.Background(), rawConn),
|
||||
done: done,
|
||||
conn: conn,
|
||||
remoteAddr: conn.RemoteAddr(),
|
||||
localAddr: conn.LocalAddr(),
|
||||
authInfo: authInfo,
|
||||
peer: peer,
|
||||
framer: framer,
|
||||
readerDone: make(chan struct{}),
|
||||
writerDone: make(chan struct{}),
|
||||
loopyWriterDone: make(chan struct{}),
|
||||
maxStreams: config.MaxStreams,
|
||||
inTapHandle: config.InTapHandle,
|
||||
fc: &trInFlow{limit: uint32(icwz)},
|
||||
|
@ -267,8 +266,6 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
|
|||
bufferPool: newBufferPool(),
|
||||
}
|
||||
t.logger = prefixLoggerForServerTransport(t)
|
||||
// Add peer information to the http2server context.
|
||||
t.ctx = peer.NewContext(t.ctx, t.getPeer())
|
||||
|
||||
t.controlBuf = newControlBuffer(t.done)
|
||||
if dynamicWindow {
|
||||
|
@ -277,15 +274,7 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
|
|||
updateFlowControl: t.updateFlowControl,
|
||||
}
|
||||
}
|
||||
for _, sh := range t.stats {
|
||||
t.ctx = sh.TagConn(t.ctx, &stats.ConnTagInfo{
|
||||
RemoteAddr: t.remoteAddr,
|
||||
LocalAddr: t.localAddr,
|
||||
})
|
||||
connBegin := &stats.ConnBegin{}
|
||||
sh.HandleConn(t.ctx, connBegin)
|
||||
}
|
||||
t.channelzID, err = channelz.RegisterNormalSocket(t, config.ChannelzParentID, fmt.Sprintf("%s -> %s", t.remoteAddr, t.localAddr))
|
||||
t.channelzID, err = channelz.RegisterNormalSocket(t, config.ChannelzParentID, fmt.Sprintf("%s -> %s", t.peer.Addr, t.peer.LocalAddr))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -334,7 +323,7 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
|
|||
t.loopy = newLoopyWriter(serverSide, t.framer, t.controlBuf, t.bdpEst, t.conn, t.logger)
|
||||
t.loopy.ssGoAwayHandler = t.outgoingGoAwayHandler
|
||||
t.loopy.run()
|
||||
close(t.writerDone)
|
||||
close(t.loopyWriterDone)
|
||||
}()
|
||||
go t.keepalive()
|
||||
return t, nil
|
||||
|
@ -342,7 +331,7 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
|
|||
|
||||
// operateHeaders takes action on the decoded headers. Returns an error if fatal
|
||||
// error encountered and transport needs to close, otherwise returns nil.
|
||||
func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(*Stream)) error {
|
||||
func (t *http2Server) operateHeaders(ctx context.Context, frame *http2.MetaHeadersFrame, handle func(*Stream)) error {
|
||||
// Acquire max stream ID lock for entire duration
|
||||
t.maxStreamMu.Lock()
|
||||
defer t.maxStreamMu.Unlock()
|
||||
|
@ -369,10 +358,11 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
|
|||
|
||||
buf := newRecvBuffer()
|
||||
s := &Stream{
|
||||
id: streamID,
|
||||
st: t,
|
||||
buf: buf,
|
||||
fc: &inFlow{limit: uint32(t.initialWindowSize)},
|
||||
id: streamID,
|
||||
st: t,
|
||||
buf: buf,
|
||||
fc: &inFlow{limit: uint32(t.initialWindowSize)},
|
||||
headerWireLength: int(frame.Header().Length),
|
||||
}
|
||||
var (
|
||||
// if false, content-type was missing or invalid
|
||||
|
@ -511,9 +501,9 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
|
|||
s.state = streamReadDone
|
||||
}
|
||||
if timeoutSet {
|
||||
s.ctx, s.cancel = context.WithTimeout(t.ctx, timeout)
|
||||
s.ctx, s.cancel = context.WithTimeout(ctx, timeout)
|
||||
} else {
|
||||
s.ctx, s.cancel = context.WithCancel(t.ctx)
|
||||
s.ctx, s.cancel = context.WithCancel(ctx)
|
||||
}
|
||||
|
||||
// Attach the received metadata to the context.
|
||||
|
@ -592,18 +582,6 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
|
|||
s.requestRead = func(n int) {
|
||||
t.adjustWindow(s, uint32(n))
|
||||
}
|
||||
for _, sh := range t.stats {
|
||||
s.ctx = sh.TagRPC(s.ctx, &stats.RPCTagInfo{FullMethodName: s.method})
|
||||
inHeader := &stats.InHeader{
|
||||
FullMethod: s.method,
|
||||
RemoteAddr: t.remoteAddr,
|
||||
LocalAddr: t.localAddr,
|
||||
Compression: s.recvCompress,
|
||||
WireLength: int(frame.Header().Length),
|
||||
Header: mdata.Copy(),
|
||||
}
|
||||
sh.HandleRPC(s.ctx, inHeader)
|
||||
}
|
||||
s.ctxDone = s.ctx.Done()
|
||||
s.wq = newWriteQuota(defaultWriteQuota, s.ctxDone)
|
||||
s.trReader = &transportReader{
|
||||
|
@ -629,8 +607,11 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
|
|||
// HandleStreams receives incoming streams using the given handler. This is
|
||||
// typically run in a separate goroutine.
|
||||
// traceCtx attaches trace to ctx and returns the new context.
|
||||
func (t *http2Server) HandleStreams(handle func(*Stream)) {
|
||||
defer close(t.readerDone)
|
||||
func (t *http2Server) HandleStreams(ctx context.Context, handle func(*Stream)) {
|
||||
defer func() {
|
||||
<-t.loopyWriterDone
|
||||
close(t.readerDone)
|
||||
}()
|
||||
for {
|
||||
t.controlBuf.throttle()
|
||||
frame, err := t.framer.fr.ReadFrame()
|
||||
|
@ -664,7 +645,7 @@ func (t *http2Server) HandleStreams(handle func(*Stream)) {
|
|||
}
|
||||
switch frame := frame.(type) {
|
||||
case *http2.MetaHeadersFrame:
|
||||
if err := t.operateHeaders(frame, handle); err != nil {
|
||||
if err := t.operateHeaders(ctx, frame, handle); err != nil {
|
||||
t.Close(err)
|
||||
break
|
||||
}
|
||||
|
@ -1242,10 +1223,6 @@ func (t *http2Server) Close(err error) {
|
|||
for _, s := range streams {
|
||||
s.cancel()
|
||||
}
|
||||
for _, sh := range t.stats {
|
||||
connEnd := &stats.ConnEnd{}
|
||||
sh.HandleConn(t.ctx, connEnd)
|
||||
}
|
||||
}
|
||||
|
||||
// deleteStream deletes the stream s from transport's active streams.
|
||||
|
@ -1311,10 +1288,6 @@ func (t *http2Server) closeStream(s *Stream, rst bool, rstCode http2.ErrCode, eo
|
|||
})
|
||||
}
|
||||
|
||||
func (t *http2Server) RemoteAddr() net.Addr {
|
||||
return t.remoteAddr
|
||||
}
|
||||
|
||||
func (t *http2Server) Drain(debugData string) {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
|
@ -1397,11 +1370,11 @@ func (t *http2Server) ChannelzMetric() *channelz.SocketInternalMetric {
|
|||
LastMessageReceivedTimestamp: time.Unix(0, atomic.LoadInt64(&t.czData.lastMsgRecvTime)),
|
||||
LocalFlowControlWindow: int64(t.fc.getSize()),
|
||||
SocketOptions: channelz.GetSocketOption(t.conn),
|
||||
LocalAddr: t.localAddr,
|
||||
RemoteAddr: t.remoteAddr,
|
||||
LocalAddr: t.peer.LocalAddr,
|
||||
RemoteAddr: t.peer.Addr,
|
||||
// RemoteName :
|
||||
}
|
||||
if au, ok := t.authInfo.(credentials.ChannelzSecurityInfo); ok {
|
||||
if au, ok := t.peer.AuthInfo.(credentials.ChannelzSecurityInfo); ok {
|
||||
s.Security = au.GetSecurityValue()
|
||||
}
|
||||
s.RemoteFlowControlWindow = t.getOutFlowWindow()
|
||||
|
@ -1433,10 +1406,12 @@ func (t *http2Server) getOutFlowWindow() int64 {
|
|||
}
|
||||
}
|
||||
|
||||
func (t *http2Server) getPeer() *peer.Peer {
|
||||
// Peer returns the peer of the transport.
|
||||
func (t *http2Server) Peer() *peer.Peer {
|
||||
return &peer.Peer{
|
||||
Addr: t.remoteAddr,
|
||||
AuthInfo: t.authInfo, // Can be nil
|
||||
Addr: t.peer.Addr,
|
||||
LocalAddr: t.peer.LocalAddr,
|
||||
AuthInfo: t.peer.AuthInfo, // Can be nil
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1461,6 +1436,6 @@ func GetConnection(ctx context.Context) net.Conn {
|
|||
// SetConnection adds the connection to the context to be able to get
|
||||
// information about the destination ip and port for an incoming RPC. This also
|
||||
// allows any unary or streaming interceptors to see the connection.
|
||||
func setConnection(ctx context.Context, conn net.Conn) context.Context {
|
||||
func SetConnection(ctx context.Context, conn net.Conn) context.Context {
|
||||
return context.WithValue(ctx, connectionKey{}, conn)
|
||||
}
|
||||
|
|
14
vendor/google.golang.org/grpc/internal/transport/proxy.go
generated
vendored
14
vendor/google.golang.org/grpc/internal/transport/proxy.go
generated
vendored
|
@ -28,6 +28,8 @@ import (
|
|||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
|
||||
"google.golang.org/grpc/internal"
|
||||
)
|
||||
|
||||
const proxyAuthHeaderKey = "Proxy-Authorization"
|
||||
|
@ -112,7 +114,7 @@ func doHTTPConnectHandshake(ctx context.Context, conn net.Conn, backendAddr stri
|
|||
// proxyDial dials, connecting to a proxy first if necessary. Checks if a proxy
|
||||
// is necessary, dials, does the HTTP CONNECT handshake, and returns the
|
||||
// connection.
|
||||
func proxyDial(ctx context.Context, addr string, grpcUA string) (conn net.Conn, err error) {
|
||||
func proxyDial(ctx context.Context, addr string, grpcUA string) (net.Conn, error) {
|
||||
newAddr := addr
|
||||
proxyURL, err := mapAddress(addr)
|
||||
if err != nil {
|
||||
|
@ -122,15 +124,15 @@ func proxyDial(ctx context.Context, addr string, grpcUA string) (conn net.Conn,
|
|||
newAddr = proxyURL.Host
|
||||
}
|
||||
|
||||
conn, err = (&net.Dialer{}).DialContext(ctx, "tcp", newAddr)
|
||||
conn, err := internal.NetDialerWithTCPKeepalive().DialContext(ctx, "tcp", newAddr)
|
||||
if err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
if proxyURL != nil {
|
||||
if proxyURL == nil {
|
||||
// proxy is disabled if proxyURL is nil.
|
||||
conn, err = doHTTPConnectHandshake(ctx, conn, addr, proxyURL, grpcUA)
|
||||
return conn, err
|
||||
}
|
||||
return
|
||||
return doHTTPConnectHandshake(ctx, conn, addr, proxyURL, grpcUA)
|
||||
}
|
||||
|
||||
func sendHTTPRequest(ctx context.Context, req *http.Request, conn net.Conn) error {
|
||||
|
|
22
vendor/google.golang.org/grpc/internal/transport/transport.go
generated
vendored
22
vendor/google.golang.org/grpc/internal/transport/transport.go
generated
vendored
|
@ -37,6 +37,7 @@ import (
|
|||
"google.golang.org/grpc/internal/channelz"
|
||||
"google.golang.org/grpc/keepalive"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/peer"
|
||||
"google.golang.org/grpc/resolver"
|
||||
"google.golang.org/grpc/stats"
|
||||
"google.golang.org/grpc/status"
|
||||
|
@ -265,7 +266,8 @@ type Stream struct {
|
|||
// headerValid indicates whether a valid header was received. Only
|
||||
// meaningful after headerChan is closed (always call waitOnHeader() before
|
||||
// reading its value). Not valid on server side.
|
||||
headerValid bool
|
||||
headerValid bool
|
||||
headerWireLength int // Only set on server side.
|
||||
|
||||
// hdrMu protects header and trailer metadata on the server-side.
|
||||
hdrMu sync.Mutex
|
||||
|
@ -425,6 +427,12 @@ func (s *Stream) Context() context.Context {
|
|||
return s.ctx
|
||||
}
|
||||
|
||||
// SetContext sets the context of the stream. This will be deleted once the
|
||||
// stats handler callouts all move to gRPC layer.
|
||||
func (s *Stream) SetContext(ctx context.Context) {
|
||||
s.ctx = ctx
|
||||
}
|
||||
|
||||
// Method returns the method for the stream.
|
||||
func (s *Stream) Method() string {
|
||||
return s.method
|
||||
|
@ -437,6 +445,12 @@ func (s *Stream) Status() *status.Status {
|
|||
return s.status
|
||||
}
|
||||
|
||||
// HeaderWireLength returns the size of the headers of the stream as received
|
||||
// from the wire. Valid only on the server.
|
||||
func (s *Stream) HeaderWireLength() int {
|
||||
return s.headerWireLength
|
||||
}
|
||||
|
||||
// SetHeader sets the header metadata. This can be called multiple times.
|
||||
// Server side only.
|
||||
// This should not be called in parallel to other data writes.
|
||||
|
@ -698,7 +712,7 @@ type ClientTransport interface {
|
|||
// Write methods for a given Stream will be called serially.
|
||||
type ServerTransport interface {
|
||||
// HandleStreams receives incoming streams using the given handler.
|
||||
HandleStreams(func(*Stream))
|
||||
HandleStreams(context.Context, func(*Stream))
|
||||
|
||||
// WriteHeader sends the header metadata for the given stream.
|
||||
// WriteHeader may not be called on all streams.
|
||||
|
@ -717,8 +731,8 @@ type ServerTransport interface {
|
|||
// handlers will be terminated asynchronously.
|
||||
Close(err error)
|
||||
|
||||
// RemoteAddr returns the remote network address.
|
||||
RemoteAddr() net.Addr
|
||||
// Peer returns the peer of the server transport.
|
||||
Peer() *peer.Peer
|
||||
|
||||
// Drain notifies the client this ServerTransport stops accepting new RPCs.
|
||||
Drain(debugData string)
|
||||
|
|
18
vendor/google.golang.org/grpc/metadata/metadata.go
generated
vendored
18
vendor/google.golang.org/grpc/metadata/metadata.go
generated
vendored
|
@ -153,14 +153,16 @@ func Join(mds ...MD) MD {
|
|||
type mdIncomingKey struct{}
|
||||
type mdOutgoingKey struct{}
|
||||
|
||||
// NewIncomingContext creates a new context with incoming md attached.
|
||||
// NewIncomingContext creates a new context with incoming md attached. md must
|
||||
// not be modified after calling this function.
|
||||
func NewIncomingContext(ctx context.Context, md MD) context.Context {
|
||||
return context.WithValue(ctx, mdIncomingKey{}, md)
|
||||
}
|
||||
|
||||
// NewOutgoingContext creates a new context with outgoing md attached. If used
|
||||
// in conjunction with AppendToOutgoingContext, NewOutgoingContext will
|
||||
// overwrite any previously-appended metadata.
|
||||
// overwrite any previously-appended metadata. md must not be modified after
|
||||
// calling this function.
|
||||
func NewOutgoingContext(ctx context.Context, md MD) context.Context {
|
||||
return context.WithValue(ctx, mdOutgoingKey{}, rawMD{md: md})
|
||||
}
|
||||
|
@ -203,7 +205,8 @@ func FromIncomingContext(ctx context.Context) (MD, bool) {
|
|||
}
|
||||
|
||||
// ValueFromIncomingContext returns the metadata value corresponding to the metadata
|
||||
// key from the incoming metadata if it exists. Key must be lower-case.
|
||||
// key from the incoming metadata if it exists. Keys are matched in a case insensitive
|
||||
// manner.
|
||||
//
|
||||
// # Experimental
|
||||
//
|
||||
|
@ -219,17 +222,16 @@ func ValueFromIncomingContext(ctx context.Context, key string) []string {
|
|||
return copyOf(v)
|
||||
}
|
||||
for k, v := range md {
|
||||
// We need to manually convert all keys to lower case, because MD is a
|
||||
// map, and there's no guarantee that the MD attached to the context is
|
||||
// created using our helper functions.
|
||||
if strings.ToLower(k) == key {
|
||||
// Case insenitive comparison: MD is a map, and there's no guarantee
|
||||
// that the MD attached to the context is created using our helper
|
||||
// functions.
|
||||
if strings.EqualFold(k, key) {
|
||||
return copyOf(v)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// the returned slice must not be modified in place
|
||||
func copyOf(v []string) []string {
|
||||
vals := make([]string, len(v))
|
||||
copy(vals, v)
|
||||
|
|
2
vendor/google.golang.org/grpc/peer/peer.go
generated
vendored
2
vendor/google.golang.org/grpc/peer/peer.go
generated
vendored
|
@ -32,6 +32,8 @@ import (
|
|||
type Peer struct {
|
||||
// Addr is the peer address.
|
||||
Addr net.Addr
|
||||
// LocalAddr is the local address.
|
||||
LocalAddr net.Addr
|
||||
// AuthInfo is the authentication information of the transport.
|
||||
// It is nil if there is no transport security being used.
|
||||
AuthInfo credentials.AuthInfo
|
||||
|
|
21
vendor/google.golang.org/grpc/picker_wrapper.go
generated
vendored
21
vendor/google.golang.org/grpc/picker_wrapper.go
generated
vendored
|
@ -37,7 +37,6 @@ import (
|
|||
type pickerWrapper struct {
|
||||
mu sync.Mutex
|
||||
done bool
|
||||
idle bool
|
||||
blockingCh chan struct{}
|
||||
picker balancer.Picker
|
||||
statsHandlers []stats.Handler // to record blocking picker calls
|
||||
|
@ -53,11 +52,7 @@ func newPickerWrapper(statsHandlers []stats.Handler) *pickerWrapper {
|
|||
// updatePicker is called by UpdateBalancerState. It unblocks all blocked pick.
|
||||
func (pw *pickerWrapper) updatePicker(p balancer.Picker) {
|
||||
pw.mu.Lock()
|
||||
if pw.done || pw.idle {
|
||||
// There is a small window where a picker update from the LB policy can
|
||||
// race with the channel going to idle mode. If the picker is idle here,
|
||||
// it is because the channel asked it to do so, and therefore it is sage
|
||||
// to ignore the update from the LB policy.
|
||||
if pw.done {
|
||||
pw.mu.Unlock()
|
||||
return
|
||||
}
|
||||
|
@ -210,23 +205,15 @@ func (pw *pickerWrapper) close() {
|
|||
close(pw.blockingCh)
|
||||
}
|
||||
|
||||
func (pw *pickerWrapper) enterIdleMode() {
|
||||
pw.mu.Lock()
|
||||
defer pw.mu.Unlock()
|
||||
if pw.done {
|
||||
return
|
||||
}
|
||||
pw.idle = true
|
||||
}
|
||||
|
||||
func (pw *pickerWrapper) exitIdleMode() {
|
||||
// reset clears the pickerWrapper and prepares it for being used again when idle
|
||||
// mode is exited.
|
||||
func (pw *pickerWrapper) reset() {
|
||||
pw.mu.Lock()
|
||||
defer pw.mu.Unlock()
|
||||
if pw.done {
|
||||
return
|
||||
}
|
||||
pw.blockingCh = make(chan struct{})
|
||||
pw.idle = false
|
||||
}
|
||||
|
||||
// dropError is a wrapper error that indicates the LB policy wishes to drop the
|
||||
|
|
14
vendor/google.golang.org/grpc/pickfirst.go
generated
vendored
14
vendor/google.golang.org/grpc/pickfirst.go
generated
vendored
|
@ -25,7 +25,6 @@ import (
|
|||
|
||||
"google.golang.org/grpc/balancer"
|
||||
"google.golang.org/grpc/connectivity"
|
||||
"google.golang.org/grpc/internal/envconfig"
|
||||
internalgrpclog "google.golang.org/grpc/internal/grpclog"
|
||||
"google.golang.org/grpc/internal/grpcrand"
|
||||
"google.golang.org/grpc/internal/pretty"
|
||||
|
@ -65,19 +64,6 @@ type pfConfig struct {
|
|||
}
|
||||
|
||||
func (*pickfirstBuilder) ParseConfig(js json.RawMessage) (serviceconfig.LoadBalancingConfig, error) {
|
||||
if !envconfig.PickFirstLBConfig {
|
||||
// Prior to supporting loadbalancing configuration, the pick_first LB
|
||||
// policy did not implement the balancer.ConfigParser interface. This
|
||||
// meant that if a non-empty configuration was passed to it, the service
|
||||
// config unmarshaling code would throw a warning log, but would
|
||||
// continue using the pick_first LB policy. The code below ensures the
|
||||
// same behavior is retained if the env var is not set.
|
||||
if string(js) != "{}" {
|
||||
logger.Warningf("Ignoring non-empty balancer configuration %q for the pick_first LB policy", string(js))
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var cfg pfConfig
|
||||
if err := json.Unmarshal(js, &cfg); err != nil {
|
||||
return nil, fmt.Errorf("pickfirst: unable to unmarshal LB policy config: %s, error: %v", string(js), err)
|
||||
|
|
36
vendor/google.golang.org/grpc/resolver/dns/dns_resolver.go
generated
vendored
Normal file
36
vendor/google.golang.org/grpc/resolver/dns/dns_resolver.go
generated
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package dns implements a dns resolver to be installed as the default resolver
|
||||
// in grpc.
|
||||
//
|
||||
// Deprecated: this package is imported by grpc and should not need to be
|
||||
// imported directly by users.
|
||||
package dns
|
||||
|
||||
import (
|
||||
"google.golang.org/grpc/internal/resolver/dns"
|
||||
"google.golang.org/grpc/resolver"
|
||||
)
|
||||
|
||||
// NewBuilder creates a dnsBuilder which is used to factory DNS resolvers.
|
||||
//
|
||||
// Deprecated: import grpc and use resolver.Get("dns") instead.
|
||||
func NewBuilder() resolver.Builder {
|
||||
return dns.NewBuilder()
|
||||
}
|
15
vendor/google.golang.org/grpc/resolver/manual/manual.go
generated
vendored
15
vendor/google.golang.org/grpc/resolver/manual/manual.go
generated
vendored
|
@ -78,12 +78,12 @@ func (r *Resolver) InitialState(s resolver.State) {
|
|||
func (r *Resolver) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) {
|
||||
r.BuildCallback(target, cc, opts)
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
r.CC = cc
|
||||
if r.lastSeenState != nil {
|
||||
err := r.CC.UpdateState(*r.lastSeenState)
|
||||
go r.UpdateStateCallback(err)
|
||||
}
|
||||
r.mu.Unlock()
|
||||
return r, nil
|
||||
}
|
||||
|
||||
|
@ -105,15 +105,22 @@ func (r *Resolver) Close() {
|
|||
// UpdateState calls CC.UpdateState.
|
||||
func (r *Resolver) UpdateState(s resolver.State) {
|
||||
r.mu.Lock()
|
||||
err := r.CC.UpdateState(s)
|
||||
defer r.mu.Unlock()
|
||||
var err error
|
||||
if r.CC == nil {
|
||||
panic("cannot update state as grpc.Dial with resolver has not been called")
|
||||
}
|
||||
err = r.CC.UpdateState(s)
|
||||
r.lastSeenState = &s
|
||||
r.mu.Unlock()
|
||||
r.UpdateStateCallback(err)
|
||||
}
|
||||
|
||||
// ReportError calls CC.ReportError.
|
||||
func (r *Resolver) ReportError(err error) {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
if r.CC == nil {
|
||||
panic("cannot report error as grpc.Dial with resolver has not been called")
|
||||
}
|
||||
r.CC.ReportError(err)
|
||||
r.mu.Unlock()
|
||||
}
|
||||
|
|
113
vendor/google.golang.org/grpc/resolver/map.go
generated
vendored
113
vendor/google.golang.org/grpc/resolver/map.go
generated
vendored
|
@ -136,3 +136,116 @@ func (a *AddressMap) Values() []any {
|
|||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
type endpointNode struct {
|
||||
addrs map[string]struct{}
|
||||
}
|
||||
|
||||
// Equal returns whether the unordered set of addrs are the same between the
|
||||
// endpoint nodes.
|
||||
func (en *endpointNode) Equal(en2 *endpointNode) bool {
|
||||
if len(en.addrs) != len(en2.addrs) {
|
||||
return false
|
||||
}
|
||||
for addr := range en.addrs {
|
||||
if _, ok := en2.addrs[addr]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func toEndpointNode(endpoint Endpoint) endpointNode {
|
||||
en := make(map[string]struct{})
|
||||
for _, addr := range endpoint.Addresses {
|
||||
en[addr.Addr] = struct{}{}
|
||||
}
|
||||
return endpointNode{
|
||||
addrs: en,
|
||||
}
|
||||
}
|
||||
|
||||
// EndpointMap is a map of endpoints to arbitrary values keyed on only the
|
||||
// unordered set of address strings within an endpoint. This map is not thread
|
||||
// safe, thus it is unsafe to access concurrently. Must be created via
|
||||
// NewEndpointMap; do not construct directly.
|
||||
type EndpointMap struct {
|
||||
endpoints map[*endpointNode]any
|
||||
}
|
||||
|
||||
// NewEndpointMap creates a new EndpointMap.
|
||||
func NewEndpointMap() *EndpointMap {
|
||||
return &EndpointMap{
|
||||
endpoints: make(map[*endpointNode]any),
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns the value for the address in the map, if present.
|
||||
func (em *EndpointMap) Get(e Endpoint) (value any, ok bool) {
|
||||
en := toEndpointNode(e)
|
||||
if endpoint := em.find(en); endpoint != nil {
|
||||
return em.endpoints[endpoint], true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// Set updates or adds the value to the address in the map.
|
||||
func (em *EndpointMap) Set(e Endpoint, value any) {
|
||||
en := toEndpointNode(e)
|
||||
if endpoint := em.find(en); endpoint != nil {
|
||||
em.endpoints[endpoint] = value
|
||||
return
|
||||
}
|
||||
em.endpoints[&en] = value
|
||||
}
|
||||
|
||||
// Len returns the number of entries in the map.
|
||||
func (em *EndpointMap) Len() int {
|
||||
return len(em.endpoints)
|
||||
}
|
||||
|
||||
// Keys returns a slice of all current map keys, as endpoints specifying the
|
||||
// addresses present in the endpoint keys, in which uniqueness is determined by
|
||||
// the unordered set of addresses. Thus, endpoint information returned is not
|
||||
// the full endpoint data (drops duplicated addresses and attributes) but can be
|
||||
// used for EndpointMap accesses.
|
||||
func (em *EndpointMap) Keys() []Endpoint {
|
||||
ret := make([]Endpoint, 0, len(em.endpoints))
|
||||
for en := range em.endpoints {
|
||||
var endpoint Endpoint
|
||||
for addr := range en.addrs {
|
||||
endpoint.Addresses = append(endpoint.Addresses, Address{Addr: addr})
|
||||
}
|
||||
ret = append(ret, endpoint)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// Values returns a slice of all current map values.
|
||||
func (em *EndpointMap) Values() []any {
|
||||
ret := make([]any, 0, len(em.endpoints))
|
||||
for _, val := range em.endpoints {
|
||||
ret = append(ret, val)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// find returns a pointer to the endpoint node in em if the endpoint node is
|
||||
// already present. If not found, nil is returned. The comparisons are done on
|
||||
// the unordered set of addresses within an endpoint.
|
||||
func (em EndpointMap) find(e endpointNode) *endpointNode {
|
||||
for endpoint := range em.endpoints {
|
||||
if e.Equal(endpoint) {
|
||||
return endpoint
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Delete removes the specified endpoint from the map.
|
||||
func (em *EndpointMap) Delete(e Endpoint) {
|
||||
en := toEndpointNode(e)
|
||||
if entry := em.find(en); entry != nil {
|
||||
delete(em.endpoints, entry)
|
||||
}
|
||||
}
|
||||
|
|
10
vendor/google.golang.org/grpc/resolver/resolver.go
generated
vendored
10
vendor/google.golang.org/grpc/resolver/resolver.go
generated
vendored
|
@ -240,11 +240,6 @@ type ClientConn interface {
|
|||
//
|
||||
// Deprecated: Use UpdateState instead.
|
||||
NewAddress(addresses []Address)
|
||||
// NewServiceConfig is called by resolver to notify ClientConn a new
|
||||
// service config. The service config should be provided as a json string.
|
||||
//
|
||||
// Deprecated: Use UpdateState instead.
|
||||
NewServiceConfig(serviceConfig string)
|
||||
// ParseServiceConfig parses the provided service config and returns an
|
||||
// object that provides the parsed config.
|
||||
ParseServiceConfig(serviceConfigJSON string) *serviceconfig.ParseResult
|
||||
|
@ -286,6 +281,11 @@ func (t Target) Endpoint() string {
|
|||
return strings.TrimPrefix(endpoint, "/")
|
||||
}
|
||||
|
||||
// String returns a string representation of Target.
|
||||
func (t Target) String() string {
|
||||
return t.URL.String()
|
||||
}
|
||||
|
||||
// Builder creates a resolver that will be used to watch name resolution updates.
|
||||
type Builder interface {
|
||||
// Build creates a new resolver for the given target.
|
||||
|
|
247
vendor/google.golang.org/grpc/resolver_conn_wrapper.go
generated
vendored
247
vendor/google.golang.org/grpc/resolver_conn_wrapper.go
generated
vendored
|
@ -1,247 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"google.golang.org/grpc/balancer"
|
||||
"google.golang.org/grpc/internal/channelz"
|
||||
"google.golang.org/grpc/internal/grpcsync"
|
||||
"google.golang.org/grpc/internal/pretty"
|
||||
"google.golang.org/grpc/resolver"
|
||||
"google.golang.org/grpc/serviceconfig"
|
||||
)
|
||||
|
||||
// resolverStateUpdater wraps the single method used by ccResolverWrapper to
|
||||
// report a state update from the actual resolver implementation.
|
||||
type resolverStateUpdater interface {
|
||||
updateResolverState(s resolver.State, err error) error
|
||||
}
|
||||
|
||||
// ccResolverWrapper is a wrapper on top of cc for resolvers.
|
||||
// It implements resolver.ClientConn interface.
|
||||
type ccResolverWrapper struct {
|
||||
// The following fields are initialized when the wrapper is created and are
|
||||
// read-only afterwards, and therefore can be accessed without a mutex.
|
||||
cc resolverStateUpdater
|
||||
channelzID *channelz.Identifier
|
||||
ignoreServiceConfig bool
|
||||
opts ccResolverWrapperOpts
|
||||
serializer *grpcsync.CallbackSerializer // To serialize all incoming calls.
|
||||
serializerCancel context.CancelFunc // To close the serializer, accessed only from close().
|
||||
|
||||
// All incoming (resolver --> gRPC) calls are guaranteed to execute in a
|
||||
// mutually exclusive manner as they are scheduled on the serializer.
|
||||
// Fields accessed *only* in these serializer callbacks, can therefore be
|
||||
// accessed without a mutex.
|
||||
curState resolver.State
|
||||
|
||||
// mu guards access to the below fields.
|
||||
mu sync.Mutex
|
||||
closed bool
|
||||
resolver resolver.Resolver // Accessed only from outgoing calls.
|
||||
}
|
||||
|
||||
// ccResolverWrapperOpts wraps the arguments to be passed when creating a new
|
||||
// ccResolverWrapper.
|
||||
type ccResolverWrapperOpts struct {
|
||||
target resolver.Target // User specified dial target to resolve.
|
||||
builder resolver.Builder // Resolver builder to use.
|
||||
bOpts resolver.BuildOptions // Resolver build options to use.
|
||||
channelzID *channelz.Identifier // Channelz identifier for the channel.
|
||||
}
|
||||
|
||||
// newCCResolverWrapper uses the resolver.Builder to build a Resolver and
|
||||
// returns a ccResolverWrapper object which wraps the newly built resolver.
|
||||
func newCCResolverWrapper(cc resolverStateUpdater, opts ccResolverWrapperOpts) (*ccResolverWrapper, error) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
ccr := &ccResolverWrapper{
|
||||
cc: cc,
|
||||
channelzID: opts.channelzID,
|
||||
ignoreServiceConfig: opts.bOpts.DisableServiceConfig,
|
||||
opts: opts,
|
||||
serializer: grpcsync.NewCallbackSerializer(ctx),
|
||||
serializerCancel: cancel,
|
||||
}
|
||||
|
||||
// Cannot hold the lock at build time because the resolver can send an
|
||||
// update or error inline and these incoming calls grab the lock to schedule
|
||||
// a callback in the serializer.
|
||||
r, err := opts.builder.Build(opts.target, ccr, opts.bOpts)
|
||||
if err != nil {
|
||||
cancel()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Any error reported by the resolver at build time that leads to a
|
||||
// re-resolution request from the balancer is dropped by grpc until we
|
||||
// return from this function. So, we don't have to handle pending resolveNow
|
||||
// requests here.
|
||||
ccr.mu.Lock()
|
||||
ccr.resolver = r
|
||||
ccr.mu.Unlock()
|
||||
|
||||
return ccr, nil
|
||||
}
|
||||
|
||||
func (ccr *ccResolverWrapper) resolveNow(o resolver.ResolveNowOptions) {
|
||||
ccr.mu.Lock()
|
||||
defer ccr.mu.Unlock()
|
||||
|
||||
// ccr.resolver field is set only after the call to Build() returns. But in
|
||||
// the process of building, the resolver may send an error update which when
|
||||
// propagated to the balancer may result in a re-resolution request.
|
||||
if ccr.closed || ccr.resolver == nil {
|
||||
return
|
||||
}
|
||||
ccr.resolver.ResolveNow(o)
|
||||
}
|
||||
|
||||
func (ccr *ccResolverWrapper) close() {
|
||||
ccr.mu.Lock()
|
||||
if ccr.closed {
|
||||
ccr.mu.Unlock()
|
||||
return
|
||||
}
|
||||
|
||||
channelz.Info(logger, ccr.channelzID, "Closing the name resolver")
|
||||
|
||||
// Close the serializer to ensure that no more calls from the resolver are
|
||||
// handled, before actually closing the resolver.
|
||||
ccr.serializerCancel()
|
||||
ccr.closed = true
|
||||
r := ccr.resolver
|
||||
ccr.mu.Unlock()
|
||||
|
||||
// Give enqueued callbacks a chance to finish.
|
||||
<-ccr.serializer.Done()
|
||||
|
||||
// Spawn a goroutine to close the resolver (since it may block trying to
|
||||
// cleanup all allocated resources) and return early.
|
||||
go r.Close()
|
||||
}
|
||||
|
||||
// serializerScheduleLocked is a convenience method to schedule a function to be
|
||||
// run on the serializer while holding ccr.mu.
|
||||
func (ccr *ccResolverWrapper) serializerScheduleLocked(f func(context.Context)) {
|
||||
ccr.mu.Lock()
|
||||
ccr.serializer.Schedule(f)
|
||||
ccr.mu.Unlock()
|
||||
}
|
||||
|
||||
// UpdateState is called by resolver implementations to report new state to gRPC
|
||||
// which includes addresses and service config.
|
||||
func (ccr *ccResolverWrapper) UpdateState(s resolver.State) error {
|
||||
errCh := make(chan error, 1)
|
||||
if s.Endpoints == nil {
|
||||
s.Endpoints = make([]resolver.Endpoint, 0, len(s.Addresses))
|
||||
for _, a := range s.Addresses {
|
||||
ep := resolver.Endpoint{Addresses: []resolver.Address{a}, Attributes: a.BalancerAttributes}
|
||||
ep.Addresses[0].BalancerAttributes = nil
|
||||
s.Endpoints = append(s.Endpoints, ep)
|
||||
}
|
||||
}
|
||||
ok := ccr.serializer.Schedule(func(context.Context) {
|
||||
ccr.addChannelzTraceEvent(s)
|
||||
ccr.curState = s
|
||||
if err := ccr.cc.updateResolverState(ccr.curState, nil); err == balancer.ErrBadResolverState {
|
||||
errCh <- balancer.ErrBadResolverState
|
||||
return
|
||||
}
|
||||
errCh <- nil
|
||||
})
|
||||
if !ok {
|
||||
// The only time when Schedule() fail to add the callback to the
|
||||
// serializer is when the serializer is closed, and this happens only
|
||||
// when the resolver wrapper is closed.
|
||||
return nil
|
||||
}
|
||||
return <-errCh
|
||||
}
|
||||
|
||||
// ReportError is called by resolver implementations to report errors
|
||||
// encountered during name resolution to gRPC.
|
||||
func (ccr *ccResolverWrapper) ReportError(err error) {
|
||||
ccr.serializerScheduleLocked(func(_ context.Context) {
|
||||
channelz.Warningf(logger, ccr.channelzID, "ccResolverWrapper: reporting error to cc: %v", err)
|
||||
ccr.cc.updateResolverState(resolver.State{}, err)
|
||||
})
|
||||
}
|
||||
|
||||
// NewAddress is called by the resolver implementation to send addresses to
|
||||
// gRPC.
|
||||
func (ccr *ccResolverWrapper) NewAddress(addrs []resolver.Address) {
|
||||
ccr.serializerScheduleLocked(func(_ context.Context) {
|
||||
ccr.addChannelzTraceEvent(resolver.State{Addresses: addrs, ServiceConfig: ccr.curState.ServiceConfig})
|
||||
ccr.curState.Addresses = addrs
|
||||
ccr.cc.updateResolverState(ccr.curState, nil)
|
||||
})
|
||||
}
|
||||
|
||||
// NewServiceConfig is called by the resolver implementation to send service
|
||||
// configs to gRPC.
|
||||
func (ccr *ccResolverWrapper) NewServiceConfig(sc string) {
|
||||
ccr.serializerScheduleLocked(func(_ context.Context) {
|
||||
channelz.Infof(logger, ccr.channelzID, "ccResolverWrapper: got new service config: %s", sc)
|
||||
if ccr.ignoreServiceConfig {
|
||||
channelz.Info(logger, ccr.channelzID, "Service config lookups disabled; ignoring config")
|
||||
return
|
||||
}
|
||||
scpr := parseServiceConfig(sc)
|
||||
if scpr.Err != nil {
|
||||
channelz.Warningf(logger, ccr.channelzID, "ccResolverWrapper: error parsing service config: %v", scpr.Err)
|
||||
return
|
||||
}
|
||||
ccr.addChannelzTraceEvent(resolver.State{Addresses: ccr.curState.Addresses, ServiceConfig: scpr})
|
||||
ccr.curState.ServiceConfig = scpr
|
||||
ccr.cc.updateResolverState(ccr.curState, nil)
|
||||
})
|
||||
}
|
||||
|
||||
// ParseServiceConfig is called by resolver implementations to parse a JSON
|
||||
// representation of the service config.
|
||||
func (ccr *ccResolverWrapper) ParseServiceConfig(scJSON string) *serviceconfig.ParseResult {
|
||||
return parseServiceConfig(scJSON)
|
||||
}
|
||||
|
||||
// addChannelzTraceEvent adds a channelz trace event containing the new
|
||||
// state received from resolver implementations.
|
||||
func (ccr *ccResolverWrapper) addChannelzTraceEvent(s resolver.State) {
|
||||
var updates []string
|
||||
var oldSC, newSC *ServiceConfig
|
||||
var oldOK, newOK bool
|
||||
if ccr.curState.ServiceConfig != nil {
|
||||
oldSC, oldOK = ccr.curState.ServiceConfig.Config.(*ServiceConfig)
|
||||
}
|
||||
if s.ServiceConfig != nil {
|
||||
newSC, newOK = s.ServiceConfig.Config.(*ServiceConfig)
|
||||
}
|
||||
if oldOK != newOK || (oldOK && newOK && oldSC.rawJSONString != newSC.rawJSONString) {
|
||||
updates = append(updates, "service config updated")
|
||||
}
|
||||
if len(ccr.curState.Addresses) > 0 && len(s.Addresses) == 0 {
|
||||
updates = append(updates, "resolver returned an empty address list")
|
||||
} else if len(ccr.curState.Addresses) == 0 && len(s.Addresses) > 0 {
|
||||
updates = append(updates, "resolver returned new addresses")
|
||||
}
|
||||
channelz.Infof(logger, ccr.channelzID, "Resolver state updated: %s (%v)", pretty.ToJSON(s), strings.Join(updates, "; "))
|
||||
}
|
197
vendor/google.golang.org/grpc/resolver_wrapper.go
generated
vendored
Normal file
197
vendor/google.golang.org/grpc/resolver_wrapper.go
generated
vendored
Normal file
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"google.golang.org/grpc/internal/channelz"
|
||||
"google.golang.org/grpc/internal/grpcsync"
|
||||
"google.golang.org/grpc/internal/pretty"
|
||||
"google.golang.org/grpc/resolver"
|
||||
"google.golang.org/grpc/serviceconfig"
|
||||
)
|
||||
|
||||
// ccResolverWrapper is a wrapper on top of cc for resolvers.
|
||||
// It implements resolver.ClientConn interface.
|
||||
type ccResolverWrapper struct {
|
||||
// The following fields are initialized when the wrapper is created and are
|
||||
// read-only afterwards, and therefore can be accessed without a mutex.
|
||||
cc *ClientConn
|
||||
ignoreServiceConfig bool
|
||||
serializer *grpcsync.CallbackSerializer
|
||||
serializerCancel context.CancelFunc
|
||||
|
||||
resolver resolver.Resolver // only accessed within the serializer
|
||||
|
||||
// The following fields are protected by mu. Caller must take cc.mu before
|
||||
// taking mu.
|
||||
mu sync.Mutex
|
||||
curState resolver.State
|
||||
closed bool
|
||||
}
|
||||
|
||||
// newCCResolverWrapper initializes the ccResolverWrapper. It can only be used
|
||||
// after calling start, which builds the resolver.
|
||||
func newCCResolverWrapper(cc *ClientConn) *ccResolverWrapper {
|
||||
ctx, cancel := context.WithCancel(cc.ctx)
|
||||
return &ccResolverWrapper{
|
||||
cc: cc,
|
||||
ignoreServiceConfig: cc.dopts.disableServiceConfig,
|
||||
serializer: grpcsync.NewCallbackSerializer(ctx),
|
||||
serializerCancel: cancel,
|
||||
}
|
||||
}
|
||||
|
||||
// start builds the name resolver using the resolver.Builder in cc and returns
|
||||
// any error encountered. It must always be the first operation performed on
|
||||
// any newly created ccResolverWrapper, except that close may be called instead.
|
||||
func (ccr *ccResolverWrapper) start() error {
|
||||
errCh := make(chan error)
|
||||
ccr.serializer.Schedule(func(ctx context.Context) {
|
||||
if ctx.Err() != nil {
|
||||
return
|
||||
}
|
||||
opts := resolver.BuildOptions{
|
||||
DisableServiceConfig: ccr.cc.dopts.disableServiceConfig,
|
||||
DialCreds: ccr.cc.dopts.copts.TransportCredentials,
|
||||
CredsBundle: ccr.cc.dopts.copts.CredsBundle,
|
||||
Dialer: ccr.cc.dopts.copts.Dialer,
|
||||
}
|
||||
var err error
|
||||
ccr.resolver, err = ccr.cc.resolverBuilder.Build(ccr.cc.parsedTarget, ccr, opts)
|
||||
errCh <- err
|
||||
})
|
||||
return <-errCh
|
||||
}
|
||||
|
||||
func (ccr *ccResolverWrapper) resolveNow(o resolver.ResolveNowOptions) {
|
||||
ccr.serializer.Schedule(func(ctx context.Context) {
|
||||
if ctx.Err() != nil || ccr.resolver == nil {
|
||||
return
|
||||
}
|
||||
ccr.resolver.ResolveNow(o)
|
||||
})
|
||||
}
|
||||
|
||||
// close initiates async shutdown of the wrapper. To determine the wrapper has
|
||||
// finished shutting down, the channel should block on ccr.serializer.Done()
|
||||
// without cc.mu held.
|
||||
func (ccr *ccResolverWrapper) close() {
|
||||
channelz.Info(logger, ccr.cc.channelzID, "Closing the name resolver")
|
||||
ccr.mu.Lock()
|
||||
ccr.closed = true
|
||||
ccr.mu.Unlock()
|
||||
|
||||
ccr.serializer.Schedule(func(context.Context) {
|
||||
if ccr.resolver == nil {
|
||||
return
|
||||
}
|
||||
ccr.resolver.Close()
|
||||
ccr.resolver = nil
|
||||
})
|
||||
ccr.serializerCancel()
|
||||
}
|
||||
|
||||
// UpdateState is called by resolver implementations to report new state to gRPC
|
||||
// which includes addresses and service config.
|
||||
func (ccr *ccResolverWrapper) UpdateState(s resolver.State) error {
|
||||
ccr.cc.mu.Lock()
|
||||
ccr.mu.Lock()
|
||||
if ccr.closed {
|
||||
ccr.mu.Unlock()
|
||||
ccr.cc.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
if s.Endpoints == nil {
|
||||
s.Endpoints = make([]resolver.Endpoint, 0, len(s.Addresses))
|
||||
for _, a := range s.Addresses {
|
||||
ep := resolver.Endpoint{Addresses: []resolver.Address{a}, Attributes: a.BalancerAttributes}
|
||||
ep.Addresses[0].BalancerAttributes = nil
|
||||
s.Endpoints = append(s.Endpoints, ep)
|
||||
}
|
||||
}
|
||||
ccr.addChannelzTraceEvent(s)
|
||||
ccr.curState = s
|
||||
ccr.mu.Unlock()
|
||||
return ccr.cc.updateResolverStateAndUnlock(s, nil)
|
||||
}
|
||||
|
||||
// ReportError is called by resolver implementations to report errors
|
||||
// encountered during name resolution to gRPC.
|
||||
func (ccr *ccResolverWrapper) ReportError(err error) {
|
||||
ccr.cc.mu.Lock()
|
||||
ccr.mu.Lock()
|
||||
if ccr.closed {
|
||||
ccr.mu.Unlock()
|
||||
ccr.cc.mu.Unlock()
|
||||
return
|
||||
}
|
||||
ccr.mu.Unlock()
|
||||
channelz.Warningf(logger, ccr.cc.channelzID, "ccResolverWrapper: reporting error to cc: %v", err)
|
||||
ccr.cc.updateResolverStateAndUnlock(resolver.State{}, err)
|
||||
}
|
||||
|
||||
// NewAddress is called by the resolver implementation to send addresses to
|
||||
// gRPC.
|
||||
func (ccr *ccResolverWrapper) NewAddress(addrs []resolver.Address) {
|
||||
ccr.cc.mu.Lock()
|
||||
ccr.mu.Lock()
|
||||
if ccr.closed {
|
||||
ccr.mu.Unlock()
|
||||
ccr.cc.mu.Unlock()
|
||||
return
|
||||
}
|
||||
s := resolver.State{Addresses: addrs, ServiceConfig: ccr.curState.ServiceConfig}
|
||||
ccr.addChannelzTraceEvent(s)
|
||||
ccr.curState = s
|
||||
ccr.mu.Unlock()
|
||||
ccr.cc.updateResolverStateAndUnlock(s, nil)
|
||||
}
|
||||
|
||||
// ParseServiceConfig is called by resolver implementations to parse a JSON
|
||||
// representation of the service config.
|
||||
func (ccr *ccResolverWrapper) ParseServiceConfig(scJSON string) *serviceconfig.ParseResult {
|
||||
return parseServiceConfig(scJSON)
|
||||
}
|
||||
|
||||
// addChannelzTraceEvent adds a channelz trace event containing the new
|
||||
// state received from resolver implementations.
|
||||
func (ccr *ccResolverWrapper) addChannelzTraceEvent(s resolver.State) {
|
||||
var updates []string
|
||||
var oldSC, newSC *ServiceConfig
|
||||
var oldOK, newOK bool
|
||||
if ccr.curState.ServiceConfig != nil {
|
||||
oldSC, oldOK = ccr.curState.ServiceConfig.Config.(*ServiceConfig)
|
||||
}
|
||||
if s.ServiceConfig != nil {
|
||||
newSC, newOK = s.ServiceConfig.Config.(*ServiceConfig)
|
||||
}
|
||||
if oldOK != newOK || (oldOK && newOK && oldSC.rawJSONString != newSC.rawJSONString) {
|
||||
updates = append(updates, "service config updated")
|
||||
}
|
||||
if len(ccr.curState.Addresses) > 0 && len(s.Addresses) == 0 {
|
||||
updates = append(updates, "resolver returned an empty address list")
|
||||
} else if len(ccr.curState.Addresses) == 0 && len(s.Addresses) > 0 {
|
||||
updates = append(updates, "resolver returned new addresses")
|
||||
}
|
||||
channelz.Infof(logger, ccr.cc.channelzID, "Resolver state updated: %s (%v)", pretty.ToJSON(s), strings.Join(updates, "; "))
|
||||
}
|
221
vendor/google.golang.org/grpc/server.go
generated
vendored
221
vendor/google.golang.org/grpc/server.go
generated
vendored
|
@ -70,6 +70,10 @@ func init() {
|
|||
internal.GetServerCredentials = func(srv *Server) credentials.TransportCredentials {
|
||||
return srv.opts.creds
|
||||
}
|
||||
internal.IsRegisteredMethod = func(srv *Server, method string) bool {
|
||||
return srv.isRegisteredMethod(method)
|
||||
}
|
||||
internal.ServerFromContext = serverFromContext
|
||||
internal.DrainServerTransports = func(srv *Server, addr string) {
|
||||
srv.drainServerTransports(addr)
|
||||
}
|
||||
|
@ -81,6 +85,7 @@ func init() {
|
|||
}
|
||||
internal.BinaryLogger = binaryLogger
|
||||
internal.JoinServerOptions = newJoinServerOption
|
||||
internal.RecvBufferPool = recvBufferPool
|
||||
}
|
||||
|
||||
var statusOK = status.New(codes.OK, "")
|
||||
|
@ -578,11 +583,13 @@ func NumStreamWorkers(numServerWorkers uint32) ServerOption {
|
|||
// options are used: StatsHandler, EnableTracing, or binary logging. In such
|
||||
// cases, the shared buffer pool will be ignored.
|
||||
//
|
||||
// # Experimental
|
||||
//
|
||||
// Notice: This API is EXPERIMENTAL and may be changed or removed in a
|
||||
// later release.
|
||||
// Deprecated: use experimental.WithRecvBufferPool instead. Will be deleted in
|
||||
// v1.60.0 or later.
|
||||
func RecvBufferPool(bufferPool SharedBufferPool) ServerOption {
|
||||
return recvBufferPool(bufferPool)
|
||||
}
|
||||
|
||||
func recvBufferPool(bufferPool SharedBufferPool) ServerOption {
|
||||
return newFuncServerOption(func(o *serverOptions) {
|
||||
o.recvBufferPool = bufferPool
|
||||
})
|
||||
|
@ -806,6 +813,18 @@ func (l *listenSocket) Close() error {
|
|||
// Serve returns when lis.Accept fails with fatal errors. lis will be closed when
|
||||
// this method returns.
|
||||
// Serve will return a non-nil error unless Stop or GracefulStop is called.
|
||||
//
|
||||
// Note: All supported releases of Go (as of December 2023) override the OS
|
||||
// defaults for TCP keepalive time and interval to 15s. To enable TCP keepalive
|
||||
// with OS defaults for keepalive time and interval, callers need to do the
|
||||
// following two things:
|
||||
// - pass a net.Listener created by calling the Listen method on a
|
||||
// net.ListenConfig with the `KeepAlive` field set to a negative value. This
|
||||
// will result in the Go standard library not overriding OS defaults for TCP
|
||||
// keepalive interval and time. But this will also result in the Go standard
|
||||
// library not enabling TCP keepalives by default.
|
||||
// - override the Accept method on the passed in net.Listener and set the
|
||||
// SO_KEEPALIVE socket option to enable TCP keepalives, with OS defaults.
|
||||
func (s *Server) Serve(lis net.Listener) error {
|
||||
s.mu.Lock()
|
||||
s.printf("serving")
|
||||
|
@ -917,7 +936,7 @@ func (s *Server) handleRawConn(lisAddr string, rawConn net.Conn) {
|
|||
return
|
||||
}
|
||||
go func() {
|
||||
s.serveStreams(st)
|
||||
s.serveStreams(context.Background(), st, rawConn)
|
||||
s.removeConn(lisAddr, st)
|
||||
}()
|
||||
}
|
||||
|
@ -971,18 +990,29 @@ func (s *Server) newHTTP2Transport(c net.Conn) transport.ServerTransport {
|
|||
return st
|
||||
}
|
||||
|
||||
func (s *Server) serveStreams(st transport.ServerTransport) {
|
||||
defer st.Close(errors.New("finished serving streams for the server transport"))
|
||||
var wg sync.WaitGroup
|
||||
func (s *Server) serveStreams(ctx context.Context, st transport.ServerTransport, rawConn net.Conn) {
|
||||
ctx = transport.SetConnection(ctx, rawConn)
|
||||
ctx = peer.NewContext(ctx, st.Peer())
|
||||
for _, sh := range s.opts.statsHandlers {
|
||||
ctx = sh.TagConn(ctx, &stats.ConnTagInfo{
|
||||
RemoteAddr: st.Peer().Addr,
|
||||
LocalAddr: st.Peer().LocalAddr,
|
||||
})
|
||||
sh.HandleConn(ctx, &stats.ConnBegin{})
|
||||
}
|
||||
|
||||
defer func() {
|
||||
st.Close(errors.New("finished serving streams for the server transport"))
|
||||
for _, sh := range s.opts.statsHandlers {
|
||||
sh.HandleConn(ctx, &stats.ConnEnd{})
|
||||
}
|
||||
}()
|
||||
|
||||
streamQuota := newHandlerQuota(s.opts.maxConcurrentStreams)
|
||||
st.HandleStreams(func(stream *transport.Stream) {
|
||||
wg.Add(1)
|
||||
|
||||
st.HandleStreams(ctx, func(stream *transport.Stream) {
|
||||
streamQuota.acquire()
|
||||
f := func() {
|
||||
defer streamQuota.release()
|
||||
defer wg.Done()
|
||||
s.handleStream(st, stream)
|
||||
}
|
||||
|
||||
|
@ -996,7 +1026,6 @@ func (s *Server) serveStreams(st transport.ServerTransport) {
|
|||
}
|
||||
go f()
|
||||
})
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
var _ http.Handler = (*Server)(nil)
|
||||
|
@ -1040,7 +1069,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
defer s.removeConn(listenerAddressForServeHTTP, st)
|
||||
s.serveStreams(st)
|
||||
s.serveStreams(r.Context(), st, nil)
|
||||
}
|
||||
|
||||
func (s *Server) addConn(addr string, st transport.ServerTransport) bool {
|
||||
|
@ -1689,6 +1718,7 @@ func (s *Server) processStreamingRPC(ctx context.Context, t transport.ServerTran
|
|||
|
||||
func (s *Server) handleStream(t transport.ServerTransport, stream *transport.Stream) {
|
||||
ctx := stream.Context()
|
||||
ctx = contextWithServer(ctx, s)
|
||||
var ti *traceInfo
|
||||
if EnableTracing {
|
||||
tr := trace.New("grpc.Recv."+methodFamily(stream.Method()), stream.Method())
|
||||
|
@ -1697,7 +1727,7 @@ func (s *Server) handleStream(t transport.ServerTransport, stream *transport.Str
|
|||
tr: tr,
|
||||
firstLine: firstLine{
|
||||
client: false,
|
||||
remoteAddr: t.RemoteAddr(),
|
||||
remoteAddr: t.Peer().Addr,
|
||||
},
|
||||
}
|
||||
if dl, ok := ctx.Deadline(); ok {
|
||||
|
@ -1731,6 +1761,22 @@ func (s *Server) handleStream(t transport.ServerTransport, stream *transport.Str
|
|||
service := sm[:pos]
|
||||
method := sm[pos+1:]
|
||||
|
||||
md, _ := metadata.FromIncomingContext(ctx)
|
||||
for _, sh := range s.opts.statsHandlers {
|
||||
ctx = sh.TagRPC(ctx, &stats.RPCTagInfo{FullMethodName: stream.Method()})
|
||||
sh.HandleRPC(ctx, &stats.InHeader{
|
||||
FullMethod: stream.Method(),
|
||||
RemoteAddr: t.Peer().Addr,
|
||||
LocalAddr: t.Peer().LocalAddr,
|
||||
Compression: stream.RecvCompress(),
|
||||
WireLength: stream.HeaderWireLength(),
|
||||
Header: md,
|
||||
})
|
||||
}
|
||||
// To have calls in stream callouts work. Will delete once all stats handler
|
||||
// calls come from the gRPC layer.
|
||||
stream.SetContext(ctx)
|
||||
|
||||
srv, knownService := s.services[service]
|
||||
if knownService {
|
||||
if md, ok := srv.methods[method]; ok {
|
||||
|
@ -1820,62 +1866,64 @@ func ServerTransportStreamFromContext(ctx context.Context) ServerTransportStream
|
|||
// pending RPCs on the client side will get notified by connection
|
||||
// errors.
|
||||
func (s *Server) Stop() {
|
||||
s.quit.Fire()
|
||||
|
||||
defer func() {
|
||||
s.serveWG.Wait()
|
||||
s.done.Fire()
|
||||
}()
|
||||
|
||||
s.channelzRemoveOnce.Do(func() { channelz.RemoveEntry(s.channelzID) })
|
||||
|
||||
s.mu.Lock()
|
||||
listeners := s.lis
|
||||
s.lis = nil
|
||||
conns := s.conns
|
||||
s.conns = nil
|
||||
// interrupt GracefulStop if Stop and GracefulStop are called concurrently.
|
||||
s.cv.Broadcast()
|
||||
s.mu.Unlock()
|
||||
|
||||
for lis := range listeners {
|
||||
lis.Close()
|
||||
}
|
||||
for _, cs := range conns {
|
||||
for st := range cs {
|
||||
st.Close(errors.New("Server.Stop called"))
|
||||
}
|
||||
}
|
||||
if s.opts.numServerWorkers > 0 {
|
||||
s.stopServerWorkers()
|
||||
}
|
||||
|
||||
s.mu.Lock()
|
||||
if s.events != nil {
|
||||
s.events.Finish()
|
||||
s.events = nil
|
||||
}
|
||||
s.mu.Unlock()
|
||||
s.stop(false)
|
||||
}
|
||||
|
||||
// GracefulStop stops the gRPC server gracefully. It stops the server from
|
||||
// accepting new connections and RPCs and blocks until all the pending RPCs are
|
||||
// finished.
|
||||
func (s *Server) GracefulStop() {
|
||||
s.stop(true)
|
||||
}
|
||||
|
||||
func (s *Server) stop(graceful bool) {
|
||||
s.quit.Fire()
|
||||
defer s.done.Fire()
|
||||
|
||||
s.channelzRemoveOnce.Do(func() { channelz.RemoveEntry(s.channelzID) })
|
||||
|
||||
s.mu.Lock()
|
||||
if s.conns == nil {
|
||||
s.mu.Unlock()
|
||||
return
|
||||
s.closeListenersLocked()
|
||||
// Wait for serving threads to be ready to exit. Only then can we be sure no
|
||||
// new conns will be created.
|
||||
s.mu.Unlock()
|
||||
s.serveWG.Wait()
|
||||
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
if graceful {
|
||||
s.drainAllServerTransportsLocked()
|
||||
} else {
|
||||
s.closeServerTransportsLocked()
|
||||
}
|
||||
|
||||
for lis := range s.lis {
|
||||
lis.Close()
|
||||
if s.opts.numServerWorkers > 0 {
|
||||
s.stopServerWorkers()
|
||||
}
|
||||
s.lis = nil
|
||||
|
||||
for len(s.conns) != 0 {
|
||||
s.cv.Wait()
|
||||
}
|
||||
s.conns = nil
|
||||
|
||||
if s.events != nil {
|
||||
s.events.Finish()
|
||||
s.events = nil
|
||||
}
|
||||
}
|
||||
|
||||
// s.mu must be held by the caller.
|
||||
func (s *Server) closeServerTransportsLocked() {
|
||||
for _, conns := range s.conns {
|
||||
for st := range conns {
|
||||
st.Close(errors.New("Server.Stop called"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// s.mu must be held by the caller.
|
||||
func (s *Server) drainAllServerTransportsLocked() {
|
||||
if !s.drain {
|
||||
for _, conns := range s.conns {
|
||||
for st := range conns {
|
||||
|
@ -1884,22 +1932,14 @@ func (s *Server) GracefulStop() {
|
|||
}
|
||||
s.drain = true
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for serving threads to be ready to exit. Only then can we be sure no
|
||||
// new conns will be created.
|
||||
s.mu.Unlock()
|
||||
s.serveWG.Wait()
|
||||
s.mu.Lock()
|
||||
|
||||
for len(s.conns) != 0 {
|
||||
s.cv.Wait()
|
||||
// s.mu must be held by the caller.
|
||||
func (s *Server) closeListenersLocked() {
|
||||
for lis := range s.lis {
|
||||
lis.Close()
|
||||
}
|
||||
s.conns = nil
|
||||
if s.events != nil {
|
||||
s.events.Finish()
|
||||
s.events = nil
|
||||
}
|
||||
s.mu.Unlock()
|
||||
s.lis = nil
|
||||
}
|
||||
|
||||
// contentSubtype must be lowercase
|
||||
|
@ -1913,11 +1953,50 @@ func (s *Server) getCodec(contentSubtype string) baseCodec {
|
|||
}
|
||||
codec := encoding.GetCodec(contentSubtype)
|
||||
if codec == nil {
|
||||
logger.Warningf("Unsupported codec %q. Defaulting to %q for now. This will start to fail in future releases.", contentSubtype, proto.Name)
|
||||
return encoding.GetCodec(proto.Name)
|
||||
}
|
||||
return codec
|
||||
}
|
||||
|
||||
type serverKey struct{}
|
||||
|
||||
// serverFromContext gets the Server from the context.
|
||||
func serverFromContext(ctx context.Context) *Server {
|
||||
s, _ := ctx.Value(serverKey{}).(*Server)
|
||||
return s
|
||||
}
|
||||
|
||||
// contextWithServer sets the Server in the context.
|
||||
func contextWithServer(ctx context.Context, server *Server) context.Context {
|
||||
return context.WithValue(ctx, serverKey{}, server)
|
||||
}
|
||||
|
||||
// isRegisteredMethod returns whether the passed in method is registered as a
|
||||
// method on the server. /service/method and service/method will match if the
|
||||
// service and method are registered on the server.
|
||||
func (s *Server) isRegisteredMethod(serviceMethod string) bool {
|
||||
if serviceMethod != "" && serviceMethod[0] == '/' {
|
||||
serviceMethod = serviceMethod[1:]
|
||||
}
|
||||
pos := strings.LastIndex(serviceMethod, "/")
|
||||
if pos == -1 { // Invalid method name syntax.
|
||||
return false
|
||||
}
|
||||
service := serviceMethod[:pos]
|
||||
method := serviceMethod[pos+1:]
|
||||
srv, knownService := s.services[service]
|
||||
if knownService {
|
||||
if _, ok := srv.methods[method]; ok {
|
||||
return true
|
||||
}
|
||||
if _, ok := srv.streams[method]; ok {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// SetHeader sets the header metadata to be sent from the server to the client.
|
||||
// The context provided must be the context passed to the server's handler.
|
||||
//
|
||||
|
|
2
vendor/google.golang.org/grpc/version.go
generated
vendored
2
vendor/google.golang.org/grpc/version.go
generated
vendored
|
@ -19,4 +19,4 @@
|
|||
package grpc
|
||||
|
||||
// Version is the current grpc version.
|
||||
const Version = "1.59.0"
|
||||
const Version = "1.60.0"
|
||||
|
|
166
vendor/google.golang.org/grpc/vet.sh
generated
vendored
166
vendor/google.golang.org/grpc/vet.sh
generated
vendored
|
@ -35,7 +35,6 @@ if [[ "$1" = "-install" ]]; then
|
|||
# Install the pinned versions as defined in module tools.
|
||||
pushd ./test/tools
|
||||
go install \
|
||||
golang.org/x/lint/golint \
|
||||
golang.org/x/tools/cmd/goimports \
|
||||
honnef.co/go/tools/cmd/staticcheck \
|
||||
github.com/client9/misspell/cmd/misspell
|
||||
|
@ -77,12 +76,16 @@ fi
|
|||
not grep 'func Test[^(]' *_test.go
|
||||
not grep 'func Test[^(]' test/*.go
|
||||
|
||||
# - Check for typos in test function names
|
||||
git grep 'func (s) ' -- "*_test.go" | not grep -v 'func (s) Test'
|
||||
git grep 'func [A-Z]' -- "*_test.go" | not grep -v 'func Test\|Benchmark\|Example'
|
||||
|
||||
# - Do not import x/net/context.
|
||||
not git grep -l 'x/net/context' -- "*.go"
|
||||
|
||||
# - Do not import math/rand for real library code. Use internal/grpcrand for
|
||||
# thread safety.
|
||||
git grep -l '"math/rand"' -- "*.go" 2>&1 | not grep -v '^examples\|^stress\|grpcrand\|^benchmark\|wrr_test'
|
||||
git grep -l '"math/rand"' -- "*.go" 2>&1 | not grep -v '^examples\|^interop/stress\|grpcrand\|^benchmark\|wrr_test'
|
||||
|
||||
# - Do not use "interface{}"; use "any" instead.
|
||||
git grep -l 'interface{}' -- "*.go" 2>&1 | not grep -v '\.pb\.go\|protoc-gen-go-grpc'
|
||||
|
@ -94,15 +97,14 @@ git grep -l -e 'grpclog.I' --or -e 'grpclog.W' --or -e 'grpclog.E' --or -e 'grpc
|
|||
not git grep "\(import \|^\s*\)\"github.com/golang/protobuf/ptypes/" -- "*.go"
|
||||
|
||||
# - Ensure all usages of grpc_testing package are renamed when importing.
|
||||
not git grep "\(import \|^\s*\)\"google.golang.org/grpc/interop/grpc_testing" -- "*.go"
|
||||
not git grep "\(import \|^\s*\)\"google.golang.org/grpc/interop/grpc_testing" -- "*.go"
|
||||
|
||||
# - Ensure all xds proto imports are renamed to *pb or *grpc.
|
||||
git grep '"github.com/envoyproxy/go-control-plane/envoy' -- '*.go' ':(exclude)*.pb.go' | not grep -v 'pb "\|grpc "'
|
||||
|
||||
misspell -error .
|
||||
|
||||
# - gofmt, goimports, golint (with exceptions for generated code), go vet,
|
||||
# go mod tidy.
|
||||
# - gofmt, goimports, go vet, go mod tidy.
|
||||
# Perform these checks on each module inside gRPC.
|
||||
for MOD_FILE in $(find . -name 'go.mod'); do
|
||||
MOD_DIR=$(dirname ${MOD_FILE})
|
||||
|
@ -110,7 +112,6 @@ for MOD_FILE in $(find . -name 'go.mod'); do
|
|||
go vet -all ./... | fail_on_output
|
||||
gofmt -s -d -l . 2>&1 | fail_on_output
|
||||
goimports -l . 2>&1 | not grep -vE "\.pb\.go"
|
||||
golint ./... 2>&1 | not grep -vE "/grpc_testing_not_regenerate/.*\.pb\.go:"
|
||||
|
||||
go mod tidy -compat=1.19
|
||||
git status --porcelain 2>&1 | fail_on_output || \
|
||||
|
@ -119,94 +120,73 @@ for MOD_FILE in $(find . -name 'go.mod'); do
|
|||
done
|
||||
|
||||
# - Collection of static analysis checks
|
||||
#
|
||||
# TODO(dfawley): don't use deprecated functions in examples or first-party
|
||||
# plugins.
|
||||
# TODO(dfawley): enable ST1019 (duplicate imports) but allow for protobufs.
|
||||
SC_OUT="$(mktemp)"
|
||||
staticcheck -go 1.19 -checks 'inherit,-ST1015,-ST1019,-SA1019' ./... > "${SC_OUT}" || true
|
||||
# Error if anything other than deprecation warnings are printed.
|
||||
not grep -v "is deprecated:.*SA1019" "${SC_OUT}"
|
||||
# Only ignore the following deprecated types/fields/functions.
|
||||
not grep -Fv '.CredsBundle
|
||||
.HeaderMap
|
||||
.Metadata is deprecated: use Attributes
|
||||
.NewAddress
|
||||
.NewServiceConfig
|
||||
.Type is deprecated: use Attributes
|
||||
BuildVersion is deprecated
|
||||
balancer.ErrTransientFailure
|
||||
balancer.Picker
|
||||
extDesc.Filename is deprecated
|
||||
github.com/golang/protobuf/jsonpb is deprecated
|
||||
grpc.CallCustomCodec
|
||||
grpc.Code
|
||||
grpc.Compressor
|
||||
grpc.CustomCodec
|
||||
grpc.Decompressor
|
||||
grpc.MaxMsgSize
|
||||
grpc.MethodConfig
|
||||
grpc.NewGZIPCompressor
|
||||
grpc.NewGZIPDecompressor
|
||||
grpc.RPCCompressor
|
||||
grpc.RPCDecompressor
|
||||
grpc.ServiceConfig
|
||||
grpc.WithCompressor
|
||||
grpc.WithDecompressor
|
||||
grpc.WithDialer
|
||||
grpc.WithMaxMsgSize
|
||||
grpc.WithServiceConfig
|
||||
grpc.WithTimeout
|
||||
http.CloseNotifier
|
||||
info.SecurityVersion
|
||||
proto is deprecated
|
||||
proto.InternalMessageInfo is deprecated
|
||||
proto.EnumName is deprecated
|
||||
proto.ErrInternalBadWireType is deprecated
|
||||
proto.FileDescriptor is deprecated
|
||||
proto.Marshaler is deprecated
|
||||
proto.MessageType is deprecated
|
||||
proto.RegisterEnum is deprecated
|
||||
proto.RegisterFile is deprecated
|
||||
proto.RegisterType is deprecated
|
||||
proto.RegisterExtension is deprecated
|
||||
proto.RegisteredExtension is deprecated
|
||||
proto.RegisteredExtensions is deprecated
|
||||
proto.RegisterMapType is deprecated
|
||||
proto.Unmarshaler is deprecated
|
||||
staticcheck -go 1.19 -checks 'all' ./... > "${SC_OUT}" || true
|
||||
|
||||
# Error for anything other than checks that need exclusions.
|
||||
grep -v "(ST1000)" "${SC_OUT}" | grep -v "(SA1019)" | grep -v "(ST1003)" | not grep -v "(ST1019)\|\(other import of\)"
|
||||
|
||||
# Exclude underscore checks for generated code.
|
||||
grep "(ST1003)" "${SC_OUT}" | not grep -v '\(.pb.go:\)\|\(code_string_test.go:\)'
|
||||
|
||||
# Error for duplicate imports not including grpc protos.
|
||||
grep "(ST1019)\|\(other import of\)" "${SC_OUT}" | not grep -Fv 'XXXXX PleaseIgnoreUnused
|
||||
channelz/grpc_channelz_v1"
|
||||
go-control-plane/envoy
|
||||
grpclb/grpc_lb_v1"
|
||||
health/grpc_health_v1"
|
||||
interop/grpc_testing"
|
||||
orca/v3"
|
||||
proto/grpc_gcp"
|
||||
proto/grpc_lookup_v1"
|
||||
reflection/grpc_reflection_v1"
|
||||
reflection/grpc_reflection_v1alpha"
|
||||
XXXXX PleaseIgnoreUnused'
|
||||
|
||||
# Error for any package comments not in generated code.
|
||||
grep "(ST1000)" "${SC_OUT}" | not grep -v "\.pb\.go:"
|
||||
|
||||
# Only ignore the following deprecated types/fields/functions and exclude
|
||||
# generated code.
|
||||
grep "(SA1019)" "${SC_OUT}" | not grep -Fv 'XXXXX PleaseIgnoreUnused
|
||||
XXXXX Protobuf related deprecation errors:
|
||||
"github.com/golang/protobuf
|
||||
.pb.go:
|
||||
: ptypes.
|
||||
proto.RegisterType
|
||||
XXXXX gRPC internal usage deprecation errors:
|
||||
"google.golang.org/grpc
|
||||
: grpc.
|
||||
: v1alpha.
|
||||
: v1alphareflectionpb.
|
||||
BalancerAttributes is deprecated:
|
||||
CredsBundle is deprecated:
|
||||
Metadata is deprecated: use Attributes instead.
|
||||
NewSubConn is deprecated:
|
||||
OverrideServerName is deprecated:
|
||||
RemoveSubConn is deprecated:
|
||||
SecurityVersion is deprecated:
|
||||
Target is deprecated: Use the Target field in the BuildOptions instead.
|
||||
xxx_messageInfo_
|
||||
' "${SC_OUT}"
|
||||
|
||||
# - special golint on package comments.
|
||||
lint_package_comment_per_package() {
|
||||
# Number of files in this go package.
|
||||
fileCount=$(go list -f '{{len .GoFiles}}' $1)
|
||||
if [ ${fileCount} -eq 0 ]; then
|
||||
return 0
|
||||
fi
|
||||
# Number of package errors generated by golint.
|
||||
lintPackageCommentErrorsCount=$(golint --min_confidence 0 $1 | grep -c "should have a package comment")
|
||||
# golint complains about every file that's missing the package comment. If the
|
||||
# number of files for this package is greater than the number of errors, there's
|
||||
# at least one file with package comment, good. Otherwise, fail.
|
||||
if [ ${fileCount} -le ${lintPackageCommentErrorsCount} ]; then
|
||||
echo "Package $1 (with ${fileCount} files) is missing package comment"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
lint_package_comment() {
|
||||
set +ex
|
||||
|
||||
count=0
|
||||
for i in $(go list ./...); do
|
||||
lint_package_comment_per_package "$i"
|
||||
((count += $?))
|
||||
done
|
||||
|
||||
set -ex
|
||||
return $count
|
||||
}
|
||||
lint_package_comment
|
||||
UpdateAddresses is deprecated:
|
||||
UpdateSubConnState is deprecated:
|
||||
balancer.ErrTransientFailure is deprecated:
|
||||
grpc/reflection/v1alpha/reflection.proto
|
||||
XXXXX xDS deprecated fields we support
|
||||
.ExactMatch
|
||||
.PrefixMatch
|
||||
.SafeRegexMatch
|
||||
.SuffixMatch
|
||||
GetContainsMatch
|
||||
GetExactMatch
|
||||
GetMatchSubjectAltNames
|
||||
GetPrefixMatch
|
||||
GetSafeRegexMatch
|
||||
GetSuffixMatch
|
||||
GetTlsCertificateCertificateProviderInstance
|
||||
GetValidationContextCertificateProviderInstance
|
||||
XXXXX TODO: Remove the below deprecation usages:
|
||||
CloseNotifier
|
||||
Roots.Subjects
|
||||
XXXXX PleaseIgnoreUnused'
|
||||
|
||||
echo SUCCESS
|
||||
|
|
24
vendor/modules.txt
vendored
24
vendor/modules.txt
vendored
|
@ -20,7 +20,7 @@ cloud.google.com/go/storage
|
|||
cloud.google.com/go/storage/internal
|
||||
cloud.google.com/go/storage/internal/apiv2
|
||||
cloud.google.com/go/storage/internal/apiv2/storagepb
|
||||
# github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0
|
||||
# github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1
|
||||
## explicit; go 1.18
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud
|
||||
|
@ -110,7 +110,7 @@ github.com/VividCortex/ewma
|
|||
# github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9
|
||||
## explicit; go 1.15
|
||||
github.com/alecthomas/units
|
||||
# github.com/aws/aws-sdk-go v1.48.16
|
||||
# github.com/aws/aws-sdk-go v1.49.1
|
||||
## explicit; go 1.19
|
||||
github.com/aws/aws-sdk-go/aws
|
||||
github.com/aws/aws-sdk-go/aws/auth/bearer
|
||||
|
@ -372,7 +372,7 @@ github.com/google/s2a-go/internal/v2/remotesigner
|
|||
github.com/google/s2a-go/internal/v2/tlsconfigstore
|
||||
github.com/google/s2a-go/retry
|
||||
github.com/google/s2a-go/stream
|
||||
# github.com/google/uuid v1.4.0
|
||||
# github.com/google/uuid v1.5.0
|
||||
## explicit
|
||||
github.com/google/uuid
|
||||
# github.com/googleapis/enterprise-certificate-proxy v0.3.2
|
||||
|
@ -597,9 +597,13 @@ go.opentelemetry.io/collector/pdata/internal/otlp
|
|||
go.opentelemetry.io/collector/pdata/pcommon
|
||||
go.opentelemetry.io/collector/pdata/pmetric
|
||||
go.opentelemetry.io/collector/pdata/pmetric/pmetricotlp
|
||||
# go.opentelemetry.io/collector/semconv v0.90.1
|
||||
# go.opentelemetry.io/collector/semconv v0.91.0
|
||||
## explicit; go 1.20
|
||||
go.opentelemetry.io/collector/semconv/v1.6.1
|
||||
# go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1
|
||||
## explicit; go 1.20
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/internal
|
||||
# go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1
|
||||
## explicit; go 1.20
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp
|
||||
|
@ -693,7 +697,7 @@ golang.org/x/text/unicode/norm
|
|||
golang.org/x/time/rate
|
||||
# golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028
|
||||
## explicit; go 1.18
|
||||
# google.golang.org/api v0.153.0
|
||||
# google.golang.org/api v0.154.0
|
||||
## explicit; go 1.19
|
||||
google.golang.org/api/googleapi
|
||||
google.golang.org/api/googleapi/transport
|
||||
|
@ -723,21 +727,21 @@ google.golang.org/appengine/internal/modules
|
|||
google.golang.org/appengine/internal/remote_api
|
||||
google.golang.org/appengine/internal/urlfetch
|
||||
google.golang.org/appengine/urlfetch
|
||||
# google.golang.org/genproto v0.0.0-20231127180814-3a041ad873d4
|
||||
# google.golang.org/genproto v0.0.0-20231212172506-995d672761c0
|
||||
## explicit; go 1.19
|
||||
google.golang.org/genproto/googleapis/type/date
|
||||
google.golang.org/genproto/googleapis/type/expr
|
||||
google.golang.org/genproto/internal
|
||||
# google.golang.org/genproto/googleapis/api v0.0.0-20231127180814-3a041ad873d4
|
||||
# google.golang.org/genproto/googleapis/api v0.0.0-20231212172506-995d672761c0
|
||||
## explicit; go 1.19
|
||||
google.golang.org/genproto/googleapis/api
|
||||
google.golang.org/genproto/googleapis/api/annotations
|
||||
# google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4
|
||||
# google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0
|
||||
## explicit; go 1.19
|
||||
google.golang.org/genproto/googleapis/rpc/code
|
||||
google.golang.org/genproto/googleapis/rpc/errdetails
|
||||
google.golang.org/genproto/googleapis/rpc/status
|
||||
# google.golang.org/grpc v1.59.0
|
||||
# google.golang.org/grpc v1.60.0
|
||||
## explicit; go 1.19
|
||||
google.golang.org/grpc
|
||||
google.golang.org/grpc/attributes
|
||||
|
@ -785,6 +789,7 @@ google.golang.org/grpc/internal/metadata
|
|||
google.golang.org/grpc/internal/pretty
|
||||
google.golang.org/grpc/internal/resolver
|
||||
google.golang.org/grpc/internal/resolver/dns
|
||||
google.golang.org/grpc/internal/resolver/dns/internal
|
||||
google.golang.org/grpc/internal/resolver/passthrough
|
||||
google.golang.org/grpc/internal/resolver/unix
|
||||
google.golang.org/grpc/internal/serviceconfig
|
||||
|
@ -796,6 +801,7 @@ google.golang.org/grpc/keepalive
|
|||
google.golang.org/grpc/metadata
|
||||
google.golang.org/grpc/peer
|
||||
google.golang.org/grpc/resolver
|
||||
google.golang.org/grpc/resolver/dns
|
||||
google.golang.org/grpc/resolver/manual
|
||||
google.golang.org/grpc/serviceconfig
|
||||
google.golang.org/grpc/stats
|
||||
|
|
Loading…
Reference in a new issue