mirror of
https://github.com/hashicorp/terraform.git
synced 2026-06-09 08:58:34 -04:00
rpcapi: Emit top-level tracing spans for requests
rpcapi is a normal gRPC server once it's running, so if the overall Terraform CLI process has been configured to export telemetry then this will emit a span for each incoming gRPC request. In later commits we'll hopefully add further telemetry downstream to cover interesting child spans such as running Terraform Core operations, but this is at least enough to observe which requests a client is making and what their outcomes were.
This commit is contained in:
parent
a246e05036
commit
e8e20a2b0a
7 changed files with 376 additions and 32 deletions
21
go.mod
21
go.mod
|
|
@ -1,7 +1,7 @@
|
|||
module github.com/hashicorp/terraform
|
||||
|
||||
require (
|
||||
cloud.google.com/go/kms v1.12.1
|
||||
cloud.google.com/go/kms v1.15.0
|
||||
cloud.google.com/go/storage v1.30.1
|
||||
github.com/Azure/azure-sdk-for-go v59.2.0+incompatible
|
||||
github.com/Azure/go-autorest/autorest v0.11.27
|
||||
|
|
@ -32,7 +32,7 @@ require (
|
|||
github.com/go-test/deep v1.0.3
|
||||
github.com/golang/mock v1.6.0
|
||||
github.com/google/go-cmp v0.6.0
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/google/uuid v1.3.1
|
||||
github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.40
|
||||
github.com/hashicorp/consul/api v1.13.0
|
||||
github.com/hashicorp/consul/sdk v0.8.0
|
||||
|
|
@ -46,6 +46,7 @@ require (
|
|||
github.com/hashicorp/go-multierror v1.1.1
|
||||
github.com/hashicorp/go-plugin v1.4.3
|
||||
github.com/hashicorp/go-retryablehttp v0.7.4
|
||||
github.com/hashicorp/go-slug v0.12.2
|
||||
github.com/hashicorp/go-tfe v1.34.0
|
||||
github.com/hashicorp/go-uuid v1.0.3
|
||||
github.com/hashicorp/go-version v1.6.0
|
||||
|
|
@ -87,6 +88,7 @@ require (
|
|||
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b
|
||||
github.com/zclconf/go-cty-yaml v1.0.3
|
||||
go.opentelemetry.io/contrib/exporters/autoexport v0.45.0
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0
|
||||
go.opentelemetry.io/otel v1.20.0
|
||||
go.opentelemetry.io/otel/sdk v1.20.0
|
||||
go.opentelemetry.io/otel/trace v1.20.0
|
||||
|
|
@ -94,15 +96,15 @@ require (
|
|||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9
|
||||
golang.org/x/mod v0.12.0
|
||||
golang.org/x/net v0.17.0
|
||||
golang.org/x/oauth2 v0.10.0
|
||||
golang.org/x/oauth2 v0.11.0
|
||||
golang.org/x/sys v0.14.0
|
||||
golang.org/x/term v0.13.0
|
||||
golang.org/x/text v0.14.0
|
||||
golang.org/x/tools v0.13.0
|
||||
golang.org/x/tools/cmd/cover v0.1.0-deprecated
|
||||
google.golang.org/api v0.126.0
|
||||
google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98
|
||||
google.golang.org/grpc v1.58.3
|
||||
google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d
|
||||
google.golang.org/grpc v1.59.0
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0
|
||||
google.golang.org/protobuf v1.31.0
|
||||
honnef.co/go/tools v0.5.0-0.dev.0.20230826160118-ad5ca31ff221
|
||||
|
|
@ -113,8 +115,8 @@ require (
|
|||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.110.4 // indirect
|
||||
cloud.google.com/go/compute v1.21.0 // indirect
|
||||
cloud.google.com/go v0.110.7 // indirect
|
||||
cloud.google.com/go/compute v1.23.0 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||
cloud.google.com/go/iam v1.1.1 // indirect
|
||||
github.com/AlecAivazis/survey/v2 v2.3.6 // indirect
|
||||
|
|
@ -200,7 +202,6 @@ require (
|
|||
github.com/hashicorp/go-msgpack v0.5.4 // indirect
|
||||
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
|
||||
github.com/hashicorp/go-safetemp v1.0.0 // indirect
|
||||
github.com/hashicorp/go-slug v0.12.2 // indirect
|
||||
github.com/hashicorp/golang-lru v0.5.1 // indirect
|
||||
github.com/hashicorp/serf v0.9.6 // indirect
|
||||
github.com/hashicorp/terraform-plugin-log v0.9.0 // indirect
|
||||
|
|
@ -261,8 +262,8 @@ require (
|
|||
golang.org/x/time v0.3.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/ini.v1 v1.66.2 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
|
|
|
|||
45
go.sum
45
go.sum
|
|
@ -32,8 +32,8 @@ cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w9
|
|||
cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc=
|
||||
cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU=
|
||||
cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA=
|
||||
cloud.google.com/go v0.110.4 h1:1JYyxKMN9hd5dR2MYTPWkGUgcoxVVhg0LKNKEo0qvmk=
|
||||
cloud.google.com/go v0.110.4/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI=
|
||||
cloud.google.com/go v0.110.7 h1:rJyC7nWRg2jWGZ4wSJ5nY65GTdYJkg0cd/uXb+ACI6o=
|
||||
cloud.google.com/go v0.110.7/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI=
|
||||
cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw=
|
||||
cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY=
|
||||
cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI=
|
||||
|
|
@ -70,8 +70,8 @@ cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz
|
|||
cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU=
|
||||
cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U=
|
||||
cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU=
|
||||
cloud.google.com/go/compute v1.21.0 h1:JNBsyXVoOoNJtTQcnEY5uYpZIbeCTYIeDe0Xh1bySMk=
|
||||
cloud.google.com/go/compute v1.21.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
|
||||
cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY=
|
||||
cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
|
||||
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
|
||||
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
|
||||
cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I=
|
||||
|
|
@ -113,8 +113,8 @@ cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp
|
|||
cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc=
|
||||
cloud.google.com/go/iam v1.1.1 h1:lW7fzj15aVIXYHREOqjRBV9PsH0Z6u8Y46a1YGvQP4Y=
|
||||
cloud.google.com/go/iam v1.1.1/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU=
|
||||
cloud.google.com/go/kms v1.12.1 h1:xZmZuwy2cwzsocmKDOPu4BL7umg8QXagQx6fKVmf45U=
|
||||
cloud.google.com/go/kms v1.12.1/go.mod h1:c9J991h5DTl+kg7gi3MYomh12YEENGrf48ee/N/2CDM=
|
||||
cloud.google.com/go/kms v1.15.0 h1:xYl5WEaSekKYN5gGRyhjvZKM22GVBBCzegGNVPy+aIs=
|
||||
cloud.google.com/go/kms v1.15.0/go.mod h1:c9J991h5DTl+kg7gi3MYomh12YEENGrf48ee/N/2CDM=
|
||||
cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic=
|
||||
cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI=
|
||||
cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8=
|
||||
|
|
@ -425,6 +425,8 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH
|
|||
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k=
|
||||
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d h1:t5Wuyh53qYyg9eqn4BbnlIT+vmhyww0TatL+zT3uWgI=
|
||||
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
|
|
@ -461,6 +463,8 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m
|
|||
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
||||
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||
|
|
@ -522,8 +526,8 @@ github.com/golang-jwt/jwt/v4 v4.4.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w
|
|||
github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs=
|
||||
github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE=
|
||||
github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ=
|
||||
github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo=
|
||||
github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
|
|
@ -619,8 +623,9 @@ github.com/google/s2a-go v0.1.4 h1:1kZ/sQM3srePvKs3tXAvQzo66XfcReoqFpIpIccE7Oc=
|
|||
github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
|
||||
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg=
|
||||
|
|
@ -1082,6 +1087,8 @@ go.opentelemetry.io/contrib/exporters/autoexport v0.45.0 h1:KU3hwb3O+fc2F15lltmD
|
|||
go.opentelemetry.io/contrib/exporters/autoexport v0.45.0/go.mod h1:9hFI4YY6Ehe9enzw9qGlKAjJGQAtEo75Ysrb3byOZtI=
|
||||
go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.46.0 h1:qmQcwJOEOfNvVOD8H7bVAEipp+6UtnDK3qHGCcjwB9o=
|
||||
go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.46.0/go.mod h1:d1FGIeeryqx0a2Oa5oQrK1Ug85AGfFUx+nMtoAwJ4VI=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0 h1:PzIubN4/sjByhDRHLviCjJuweBXWFZWhghjg7cS28+M=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0/go.mod h1:Ct6zzQEuGK3WpJs2n4dn+wfJYzd/+hNnxMRTWjGn30M=
|
||||
go.opentelemetry.io/otel v1.20.0 h1:vsb/ggIY+hUjD/zCAQHpzTmndPqv/ml2ArbsbfBYTAc=
|
||||
go.opentelemetry.io/otel v1.20.0/go.mod h1:oUIGj3D77RwJdM6PPZImDpSZGDvkD9fhesHny69JFrs=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U=
|
||||
|
|
@ -1262,8 +1269,8 @@ golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri
|
|||
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
|
||||
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
|
||||
golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A=
|
||||
golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
|
||||
golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
|
||||
golang.org/x/oauth2 v0.11.0 h1:vPL4xzxBM4niKCW6g9whtaWVXTJf1U5e4aZxxFx/gbU=
|
||||
golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
|
@ -1644,12 +1651,12 @@ google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqw
|
|||
google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM=
|
||||
google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM=
|
||||
google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s=
|
||||
google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 h1:Z0hjGZePRE0ZBWotvtrwxFNrNE9CUAGtplaDK5NNI/g=
|
||||
google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98/go.mod h1:S7mY02OqCJTD0E1OiQy1F72PWFB4bZJ87cAtLPYgDR0=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 h1:FmF5cCW94Ij59cfpoLiwTgodWmm60eEV0CjlsVg2fuw=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM=
|
||||
google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d h1:VBu5YqKPv6XiJ199exd8Br+Aetz+o08F+PLMnwJQHAY=
|
||||
google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d h1:DoPTO70H+bcDXcd39vOqb2viZxgqeBeSGtZ55yZU4/Q=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M=
|
||||
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
|
|
@ -1688,8 +1695,8 @@ google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACu
|
|||
google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
|
||||
google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
|
||||
google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
|
||||
google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ=
|
||||
google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0=
|
||||
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/cmd/protoc-gen-go-grpc v1.1.0 h1:M1YKkFIboKNieVO5DLUEVzQfGwJD30Nv2jfUgzb5UcE=
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
"net"
|
||||
"testing"
|
||||
|
||||
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/test/bufconn"
|
||||
)
|
||||
|
|
@ -19,7 +20,10 @@ import (
|
|||
// server end of this fake connection.
|
||||
func grpcClientForTesting(ctx context.Context, t *testing.T, registerServices func(srv *grpc.Server)) (conn grpc.ClientConnInterface, close func()) {
|
||||
fakeListener := bufconn.Listen(1024 /* buffer size */)
|
||||
srv := grpc.NewServer()
|
||||
srv := grpc.NewServer(
|
||||
grpc.UnaryInterceptor(otelgrpc.UnaryServerInterceptor()),
|
||||
grpc.StreamInterceptor(otelgrpc.StreamServerInterceptor()),
|
||||
)
|
||||
|
||||
// Caller gets an opportunity to register specific services before
|
||||
// we actually start "serving".
|
||||
|
|
@ -40,6 +44,8 @@ func grpcClientForTesting(ctx context.Context, t *testing.T, registerServices fu
|
|||
ctx, "testfake",
|
||||
grpc.WithContextDialer(fakeDialer),
|
||||
grpc.WithInsecure(),
|
||||
grpc.WithUnaryInterceptor(otelgrpc.UnaryClientInterceptor()),
|
||||
grpc.WithStreamInterceptor(otelgrpc.StreamClientInterceptor()),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to connect to the fake server: %s", err)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import (
|
|||
"os"
|
||||
|
||||
"github.com/hashicorp/go-plugin"
|
||||
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
|
|
@ -34,7 +35,12 @@ func ServePlugin(ctx context.Context, opts ServerOpts) error {
|
|||
},
|
||||
},
|
||||
GRPCServer: func(opts []grpc.ServerOption) *grpc.Server {
|
||||
server := grpc.NewServer(opts...)
|
||||
fullOpts := []grpc.ServerOption{
|
||||
grpc.UnaryInterceptor(otelgrpc.UnaryServerInterceptor()),
|
||||
grpc.StreamInterceptor(otelgrpc.StreamServerInterceptor()),
|
||||
}
|
||||
fullOpts = append(fullOpts, opts...)
|
||||
server := grpc.NewServer(fullOpts...)
|
||||
// We'll also monitor the given context for cancellation
|
||||
// and terminate the server gracefully if we get cancelled.
|
||||
go func() {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
"sync"
|
||||
|
||||
"github.com/hashicorp/terraform/internal/rpcapi/terraform1"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
|
@ -39,7 +40,13 @@ func (s *setupServer) Handshake(ctx context.Context, req *terraform1.Handshake_R
|
|||
return nil, status.Error(codes.FailedPrecondition, "handshake already completed")
|
||||
}
|
||||
|
||||
serverCaps, err := s.initOthers(ctx, req.Capabilities)
|
||||
var serverCaps *terraform1.ServerCapabilities
|
||||
var err error
|
||||
{
|
||||
ctx, span := tracer.Start(ctx, "initialize RPC services")
|
||||
serverCaps, err = s.initOthers(ctx, req.Capabilities)
|
||||
span.End()
|
||||
}
|
||||
s.initOthers = nil // cannot handshake again
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
20
internal/rpcapi/telemetry.go
Normal file
20
internal/rpcapi/telemetry.go
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
package rpcapi
|
||||
|
||||
import (
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
// tracer is the OpenTelemetry tracer to use for tracing for code in this
|
||||
// package.
|
||||
//
|
||||
// When creating tracing spans in gRPC service functions, always use the
|
||||
// a [context.Context] descended from the one passed in to the service
|
||||
// function so that the spans can attach to the automatically-generated
|
||||
// server request span and, if the client is also using OpenTelemetry,
|
||||
// to the client's request span.
|
||||
var tracer trace.Tracer
|
||||
|
||||
func init() {
|
||||
tracer = otel.Tracer("github.com/hashicorp/terraform/internal/rpcapi")
|
||||
}
|
||||
297
internal/rpcapi/telemetry_test.go
Normal file
297
internal/rpcapi/telemetry_test.go
Normal file
|
|
@ -0,0 +1,297 @@
|
|||
package rpcapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/hashicorp/terraform/internal/rpcapi/terraform1"
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
"go.opentelemetry.io/otel/propagation"
|
||||
"go.opentelemetry.io/otel/sdk/instrumentation"
|
||||
"go.opentelemetry.io/otel/sdk/resource"
|
||||
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
||||
"go.opentelemetry.io/otel/sdk/trace/tracetest"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.17.0"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// initTelemetryForTest configures OpenTelemetry to collect spans into a
|
||||
// local in-memory buffer and returns an object that provides access to that
|
||||
// buffer.
|
||||
//
|
||||
// The OpenTelemetry tracer provider is a global cross-cutting concern shared
|
||||
// throughout the program, so it isn't valid to use this function in any test
|
||||
// that calls t.Parallel, or in subtests of a parent test that has already
|
||||
// used this function.
|
||||
func initTelemetryForTest(t *testing.T, providerOptions ...sdktrace.TracerProviderOption) *tracetest.InMemoryExporter {
|
||||
t.Helper()
|
||||
|
||||
exp := tracetest.NewInMemoryExporter()
|
||||
sp := sdktrace.NewSimpleSpanProcessor(exp)
|
||||
providerOptions = append(
|
||||
[]sdktrace.TracerProviderOption{
|
||||
sdktrace.WithSpanProcessor(sp),
|
||||
},
|
||||
providerOptions...,
|
||||
)
|
||||
provider := sdktrace.NewTracerProvider(providerOptions...)
|
||||
otel.SetTracerProvider(provider)
|
||||
|
||||
pgtr := propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{})
|
||||
otel.SetTextMapPropagator(pgtr)
|
||||
|
||||
// We'll automatically shut down the provider at the end of the test run,
|
||||
// because otherwise a subsequent test which runs something that generates
|
||||
// telemetry _without_ calling initTelemetryForTest (which is optional)
|
||||
// could end up appending irrelevant spans to an earlier test's exporter.
|
||||
t.Cleanup(func() {
|
||||
provider.Shutdown(context.Background())
|
||||
otel.SetTracerProvider(nil)
|
||||
otel.SetTextMapPropagator(nil)
|
||||
})
|
||||
|
||||
t.Log("OpenTelemetry initialized")
|
||||
return exp
|
||||
}
|
||||
|
||||
// findTestTelemetrySpan tests each of the spans that have been reported to the
|
||||
// given [tracetest.InMemoryExporter] with the given predicate function and
|
||||
// returns the first one for which the predicate matches.
|
||||
//
|
||||
// If the predicate returns false for all spans then this function will fail
|
||||
// the test using the given [testing.T].
|
||||
func findTestTelemetrySpan(t *testing.T, exp *tracetest.InMemoryExporter, predicate func(tracetest.SpanStub) bool) tracetest.SpanStub {
|
||||
for _, span := range exp.GetSpans() {
|
||||
if predicate(span) {
|
||||
return span
|
||||
}
|
||||
}
|
||||
t.Fatal("no spans matched the predicate")
|
||||
return tracetest.SpanStub{}
|
||||
}
|
||||
|
||||
// findTestTelemetrySpans tests each of the spans that have been reported to the
|
||||
// given [tracetest.InMemoryExporter] with the given predicate function and
|
||||
// returns only those for which the predicate matches.
|
||||
//
|
||||
// If no spans match at all then the result is a zero-length slice. If you are
|
||||
// expecting to find exactly one matching span then [findTestTelemetrySpan]
|
||||
// (singular) might be more convenient.
|
||||
func findTestTelemetrySpans(t *testing.T, exp *tracetest.InMemoryExporter, predicate func(tracetest.SpanStub) bool) tracetest.SpanStubs {
|
||||
var ret tracetest.SpanStubs
|
||||
for _, span := range exp.GetSpans() {
|
||||
if predicate(span) {
|
||||
ret = append(ret, span)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// overwriteTestSpanTimestamps overwrites the timestamps in all of the given
|
||||
// spans to be exactly the given fakeTime, as a way to avoid considering exact
|
||||
// timestamps when comparing actual spans with desired spans.
|
||||
//
|
||||
// This function overwrites both the start and end times of the spans themselves
|
||||
// and also the timestamps of any events associated with the spans.
|
||||
func overwriteTestSpanTimestamps(spans tracetest.SpanStubs, fakeTime time.Time) {
|
||||
for i := range spans {
|
||||
spans[i].StartTime = fakeTime
|
||||
spans[i].EndTime = fakeTime
|
||||
for j := range spans[i].Events {
|
||||
spans[i].Events[j].Time = fakeTime
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func fixedTraceID(n uint32) trace.TraceID {
|
||||
return trace.TraceID{
|
||||
0xfe, 0xed, 0xfa, 0xce,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
uint8(n >> 24), uint8(n >> 16), uint8(n >> 8), uint8(n >> 0),
|
||||
}
|
||||
}
|
||||
|
||||
func fixedSpanID(n uint32) trace.SpanID {
|
||||
return trace.SpanID{
|
||||
0xfa, 0xce, 0xfe, 0xed,
|
||||
uint8(n >> 24), uint8(n >> 16), uint8(n >> 8), uint8(n >> 0),
|
||||
}
|
||||
}
|
||||
|
||||
func TestTelemetryInTests(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
testResource := resource.NewWithAttributes(
|
||||
semconv.SchemaURL,
|
||||
semconv.ServiceNameKey.String("telemetry test"),
|
||||
semconv.ServiceVersionKey.String("1.2.3"),
|
||||
)
|
||||
|
||||
telemetry := initTelemetryForTest(t,
|
||||
sdktrace.WithResource(testResource),
|
||||
)
|
||||
|
||||
var parentSpanContext, childSpanContext trace.SpanContext
|
||||
|
||||
tracer := otel.Tracer("test thingy")
|
||||
{
|
||||
ctx, parentSpan := tracer.Start(ctx, "parent span")
|
||||
parentSpanContext = parentSpan.SpanContext()
|
||||
{
|
||||
_, childSpan := tracer.Start(ctx, "child span")
|
||||
childSpanContext = childSpan.SpanContext()
|
||||
childSpan.AddEvent("did something totally hilarious")
|
||||
childSpan.SetStatus(codes.Error, "it went wrong")
|
||||
childSpan.End()
|
||||
}
|
||||
parentSpan.End()
|
||||
}
|
||||
|
||||
gotSpans := telemetry.GetSpans()
|
||||
|
||||
// The spans contain real timestamps that make them annoying to compare,
|
||||
// so we'll just replace those with fixed timestamps so we can easily
|
||||
// compare everything else.
|
||||
fakeTime := time.Now()
|
||||
overwriteTestSpanTimestamps(gotSpans, fakeTime)
|
||||
|
||||
wantSpans := tracetest.SpanStubs{
|
||||
// These are ordered by the calls to Span.End above, so child should
|
||||
// always appear first. (That's a detail of this in-memory-only
|
||||
// exporter, not a general guarantee about OpenTracing.)
|
||||
{
|
||||
Name: "child span",
|
||||
SpanContext: childSpanContext,
|
||||
Parent: parentSpanContext,
|
||||
SpanKind: trace.SpanKindInternal,
|
||||
StartTime: fakeTime,
|
||||
EndTime: fakeTime,
|
||||
Events: []sdktrace.Event{
|
||||
{
|
||||
Name: "did something totally hilarious",
|
||||
Time: fakeTime,
|
||||
},
|
||||
},
|
||||
Status: sdktrace.Status{
|
||||
Code: codes.Error,
|
||||
Description: "it went wrong",
|
||||
},
|
||||
Resource: testResource,
|
||||
InstrumentationLibrary: instrumentation.Scope{
|
||||
Name: "test thingy",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "parent span",
|
||||
SpanContext: parentSpanContext,
|
||||
SpanKind: trace.SpanKindInternal,
|
||||
StartTime: fakeTime,
|
||||
EndTime: fakeTime,
|
||||
ChildSpanCount: 1,
|
||||
Resource: testResource,
|
||||
InstrumentationLibrary: instrumentation.Scope{
|
||||
Name: "test thingy",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(wantSpans, gotSpans); diff != "" {
|
||||
t.Errorf("wrong spans\n%s", diff)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTelemetryInTestsGRPC(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
testResource := resource.NewWithAttributes(
|
||||
semconv.SchemaURL,
|
||||
semconv.ServiceNameKey.String("TestTelemetryInTestsGRPC"),
|
||||
)
|
||||
telemetry := initTelemetryForTest(t,
|
||||
sdktrace.WithResource(testResource),
|
||||
)
|
||||
|
||||
client, close := grpcClientForTesting(ctx, t, func(srv *grpc.Server) {
|
||||
setup := &setupServer{
|
||||
initOthers: func(ctx context.Context, cc *terraform1.ClientCapabilities) (*terraform1.ServerCapabilities, error) {
|
||||
return &terraform1.ServerCapabilities{}, nil
|
||||
},
|
||||
}
|
||||
terraform1.RegisterSetupServer(srv, setup)
|
||||
})
|
||||
defer close()
|
||||
setupClient := terraform1.NewSetupClient(client)
|
||||
|
||||
{
|
||||
ctx, span := otel.Tracer("TestTelemetryInTestsGRPC").Start(ctx, "root")
|
||||
_, err := setupClient.Handshake(ctx, &terraform1.Handshake_Request{
|
||||
Capabilities: &terraform1.ClientCapabilities{},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
span.End()
|
||||
}
|
||||
|
||||
clientSpan := findTestTelemetrySpan(t, telemetry, func(ss tracetest.SpanStub) bool {
|
||||
return ss.SpanKind == trace.SpanKindClient
|
||||
})
|
||||
serverSpan := findTestTelemetrySpan(t, telemetry, func(ss tracetest.SpanStub) bool {
|
||||
return ss.SpanKind == trace.SpanKindServer
|
||||
})
|
||||
t.Run("client span", func(t *testing.T) {
|
||||
span := clientSpan
|
||||
t.Logf("client span: %s", spew.Sdump(span))
|
||||
if got, want := span.Name, "terraform1.Setup/Handshake"; got != want {
|
||||
t.Errorf("wrong name\ngot: %s\nwant: %s", got, want)
|
||||
}
|
||||
attrs := otelAttributesMap(span.Attributes)
|
||||
if got, want := attrs["rpc.system"], "grpc"; got != want {
|
||||
t.Errorf("wrong rpc.system\ngot: %s\nwant: %s", got, want)
|
||||
}
|
||||
if got, want := attrs["rpc.service"], "terraform1.Setup"; got != want {
|
||||
t.Errorf("wrong rpc.service\ngot: %s\nwant: %s", got, want)
|
||||
}
|
||||
if got, want := attrs["rpc.method"], "Handshake"; got != want {
|
||||
t.Errorf("wrong rpc.method\ngot: %s\nwant: %s", got, want)
|
||||
}
|
||||
})
|
||||
t.Run("server span", func(t *testing.T) {
|
||||
span := serverSpan
|
||||
t.Logf("server span: %s", spew.Sdump(span))
|
||||
if got, want := span.Name, "terraform1.Setup/Handshake"; got != want {
|
||||
t.Errorf("wrong name\ngot: %s\nwant: %s", got, want)
|
||||
}
|
||||
if got, want := span.Parent.SpanID(), clientSpan.SpanContext.SpanID(); got != want {
|
||||
t.Errorf("server span is not a child of the client span\nclient span ID: %s\nserver span parent ID: %s", want, got)
|
||||
}
|
||||
if got, want := serverSpan.SpanContext.TraceID(), clientSpan.SpanContext.TraceID(); got != want {
|
||||
t.Errorf("server span belongs to different trace than client span\nclient trace ID: %s\nserver trace ID: %s", want, got)
|
||||
}
|
||||
attrs := otelAttributesMap(span.Attributes)
|
||||
if got, want := attrs["rpc.system"], "grpc"; got != want {
|
||||
t.Errorf("wrong rpc.system\ngot: %s\nwant: %s", got, want)
|
||||
}
|
||||
if got, want := attrs["rpc.service"], "terraform1.Setup"; got != want {
|
||||
t.Errorf("wrong rpc.service\ngot: %s\nwant: %s", got, want)
|
||||
}
|
||||
if got, want := attrs["rpc.method"], "Handshake"; got != want {
|
||||
t.Errorf("wrong rpc.method\ngot: %s\nwant: %s", got, want)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func otelAttributesMap(kvs []attribute.KeyValue) map[string]any {
|
||||
ret := make(map[string]any, len(kvs))
|
||||
for _, kv := range kvs {
|
||||
ret[string(kv.Key)] = kv.Value.AsInterface()
|
||||
}
|
||||
return ret
|
||||
}
|
||||
Loading…
Reference in a new issue