From aef62a99d922c9cd99d0ad40e5bf6b456e910205 Mon Sep 17 00:00:00 2001 From: Dmitry Savintsev Date: Wed, 9 Sep 2020 11:54:03 +0200 Subject: [PATCH 01/27] Remove pre-generated certificates from tests (#331) * test certs - cherry-pick PR325 on v2 * remove old test certificates * set CommonName to example.com --- .github/workflows/go.yaml | 4 +- grpctesting/certs/gen_cert.sh | 12 ----- grpctesting/certs/localhost.crt | 24 ---------- grpctesting/certs/localhost.go | 54 --------------------- grpctesting/certs/localhost.key | 27 ----------- grpctesting/interceptor_suite.go | 80 +++++++++++++++++++++++++------- 6 files changed, 66 insertions(+), 135 deletions(-) delete mode 100644 grpctesting/certs/gen_cert.sh delete mode 100644 grpctesting/certs/localhost.crt delete mode 100644 grpctesting/certs/localhost.go delete mode 100644 grpctesting/certs/localhost.key diff --git a/.github/workflows/go.yaml b/.github/workflows/go.yaml index e92d73989..127861bef 100644 --- a/.github/workflows/go.yaml +++ b/.github/workflows/go.yaml @@ -18,7 +18,7 @@ jobs: - name: Install Go uses: actions/setup-go@v2 with: - go-version: 1.14.x + go-version: 1.15.x - uses: actions/cache@v1 with: @@ -34,7 +34,7 @@ jobs: strategy: fail-fast: false matrix: - go: [ '1.12.x', '1.13.x', '1.14.x' ] + go: [ '1.12.x', '1.13.x', '1.14.x', '1.15.x' ] platform: [ubuntu-latest, macos-latest] steps: - name: Checkout code into the Go module directory. diff --git a/grpctesting/certs/gen_cert.sh b/grpctesting/certs/gen_cert.sh deleted file mode 100644 index a1105d07c..000000000 --- a/grpctesting/certs/gen_cert.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -# Regenerate the self-signed certificate for local host. - -openssl req -x509 -sha256 -nodes -newkey rsa:2048 -days 3650 -keyout localhost.key -out localhost.crt - -cat < localhost.go -package certs - -var LocalhostKey []byte = []byte(\`$(cat localhost.key)\`) - -var LocalhostCert []byte = []byte(\`$(cat localhost.crt)\`) -EOF diff --git a/grpctesting/certs/localhost.crt b/grpctesting/certs/localhost.crt deleted file mode 100644 index b4b1e3879..000000000 --- a/grpctesting/certs/localhost.crt +++ /dev/null @@ -1,24 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIECTCCAvGgAwIBAgIJAOizA5bposrzMA0GCSqGSIb3DQEBCwUAMGAxCzAJBgNV -BAYTAlVLMRMwEQYDVQQIEwpTb21lLVN0YXRlMQ8wDQYDVQQHEwZMb25kb24xFzAV -BgNVBAoTDkdycGMgRWNvc3lzdGVtMRIwEAYDVQQDEwlsb2NhbGhvc3QwHhcNMTcw -ODI1MDc0NTMyWhcNMjcwODIzMDc0NTMyWjBgMQswCQYDVQQGEwJVSzETMBEGA1UE -CBMKU29tZS1TdGF0ZTEPMA0GA1UEBxMGTG9uZG9uMRcwFQYDVQQKEw5HcnBjIEVj -b3N5c3RlbTESMBAGA1UEAxMJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOC -AQ8AMIIBCgKCAQEA2uDY9N8eGScSGAr/DIeFxyCrytqCkYvqVPYqrZv4VOZvyfak -Un7bW4q8zeNWwj64sU0al7Bz8KBmAM7raLnkvkZxmXUCls+Yw8BgXQr+1aDvYYd0 -JIVJvQqQd1oNXQeZs6GXfalCXh9mhHkJIHOm2ynk2GtS81NQik7ZMg+W3qygeK8O -40vbnYxqq2zkvub1dztxuApUzLmuXxLZRo+3faZZetNZ1eMCuqyqzibDRwcYhr3a -soC8d+6wWFobwV5AX7h7+qnS6mclESkN7FHMZT1r3OEvix012ry74xl79ploae8d -1dkR45C1DEaxwHYz7zJgP5IOXfKcv6KJhgEiYwIDAQABo4HFMIHCMB0GA1UdDgQW -BBRXiz6enaVw2tDnZ6/fEuW2USDSKjCBkgYDVR0jBIGKMIGHgBRXiz6enaVw2tDn -Z6/fEuW2USDSKqFkpGIwYDELMAkGA1UEBhMCVUsxEzARBgNVBAgTClNvbWUtU3Rh -dGUxDzANBgNVBAcTBkxvbmRvbjEXMBUGA1UEChMOR3JwYyBFY29zeXN0ZW0xEjAQ -BgNVBAMTCWxvY2FsaG9zdIIJAOizA5bposrzMAwGA1UdEwQFMAMBAf8wDQYJKoZI -hvcNAQELBQADggEBADFmrqug4HYCtcy2F61o53vXIJQ6SyGwPCE5gOq07tkEz2id -oKcb2qNF1Zh+lOQ9GkvMkfzop0a4nhW8ra28gEBwhESS/aGKc7/isZN4ZKyy9JvJ -taTmVgXGp8s0w5dCXqDf3YU3XpdF53J1R7dyEfey3nEjMPRj/Ebs7rmpfRzOI4cX -6SJWJ71ShXK/IZbSVfobTzRdmAlz7uiwp2OVveGqcpQk46wgVoduwrC2hCe4wI6y -Dlo/GLmyCVlIiPaNA32sw+lca02Z5EXcQutRov2R/lUfoUCS/gOjCD7hVZXSRo+9 -tFmGR8IuQDFseOW7CWTWqkiwu9F80HXmovboMKQ= ------END CERTIFICATE----- diff --git a/grpctesting/certs/localhost.go b/grpctesting/certs/localhost.go deleted file mode 100644 index 2f5458225..000000000 --- a/grpctesting/certs/localhost.go +++ /dev/null @@ -1,54 +0,0 @@ -package certs - -var LocalhostKey []byte = []byte(`-----BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEA2uDY9N8eGScSGAr/DIeFxyCrytqCkYvqVPYqrZv4VOZvyfak -Un7bW4q8zeNWwj64sU0al7Bz8KBmAM7raLnkvkZxmXUCls+Yw8BgXQr+1aDvYYd0 -JIVJvQqQd1oNXQeZs6GXfalCXh9mhHkJIHOm2ynk2GtS81NQik7ZMg+W3qygeK8O -40vbnYxqq2zkvub1dztxuApUzLmuXxLZRo+3faZZetNZ1eMCuqyqzibDRwcYhr3a -soC8d+6wWFobwV5AX7h7+qnS6mclESkN7FHMZT1r3OEvix012ry74xl79ploae8d -1dkR45C1DEaxwHYz7zJgP5IOXfKcv6KJhgEiYwIDAQABAoIBAEC/gQ63LhUsvKqG -HjrboFRussM4bqWVqUVm6Osgl46t+GXbY3LP+h4TZZTWaqTdnw88CuDSnwmQuXwF -uhfp3eP3vMUzmwd38+38a8U6anZRvF6yjkX7c/vLMz9LUWayx+IerEzNFEf5q/8G -Ow/xhmuQ8hSfcxNuEwZHGvM3L19BT852iXCh4uEJyR5G0e/5RI7f/bBieLo4exO9 -EO/vcxK+fcZk4XAwIa0UWdWfzk+lgTDfw0kG1fNm5QJgykGSpXw51GNrakcGsBX1 -ocu2DM6wIU7cb+orTmxRM4ra+NV4oiH63GVB79mnQtQ1PSwZv+v+tQdx/APu12MX -P23qfZECgYEA7T9NFbKQxMQxWc4YoMhtUNrURhRsgLtbkRLzzScfDhCAf576HQBe -vO3oPIF4b1i/SHQijLTjHuP32az1n9FJYakRTNUIYlKOPpRC8snULtvbhVUVoRXZ -iVnX6Nk5ISK5CpVQP9MDscbkmXejTSld4IK8y8f5eUV899rbfHq8prkCgYEA7C3Z -txJytRhwanUykG8fwF2KkJxWrgrUG6FyxQPt9hqIGbtG7naN0kucjcDmhywe5Luq -2DGxirEs08YpQKgyP+2o5+d6hCuAweA3HsZS4MdQO45IMubV1EEy/4mqODLxvGhr -0BQZ08px692iEUOQHmxbynIx8v7UwObbAncBg/sCgYANr/o9hzjM8Vi7iqVnGUkd -QhK/HEyKPMTyoLpKGriy8gbH1h8t7yiIE92zJ/EP03ntry2TGpiD3rkc6Nqe5s8q -ADwMR7odGhA00g7uvPAt5+dJUPhXe9A6GWHYgDfIjp1IXAbuN7ld11C2/e0A9aMB -4ekMhLQC6BxmnEzPaLFbmQKBgQCR1i4d0ZJrKNAhrISwky20Bw7NBPyxM5aOCT9p -UGfcE73+xZmjHimstWvSTE8NIL1i2E9CeEz9KzJXAoHunu2IdCRcLp+EhahYDy96 -HVSH4As2+0CxzcAz9J6dFFC7qxmCEaihMAhSsyttTcoJhwKzBo4XkDQvrBOLmgGa -oAmbiQKBgGacQ3nzSjlAfTqUKZc3wHKO2BNxSQfq7BejvGAR9bH/qUvB0Q7r7nb+ -98Epzx8K+om7BRh5cQc6QQIP4gUIi+K7IIaPLgoUwo3Uj+nq0m3cT+iWQKEwo6c3 -wtMi5c6K0MfzcMk0RVxcraL3isAV1zZMPsuAD5EzCsYF5a+opQNq ------END RSA PRIVATE KEY-----`) - -var LocalhostCert []byte = []byte(`-----BEGIN CERTIFICATE----- -MIIECTCCAvGgAwIBAgIJAOizA5bposrzMA0GCSqGSIb3DQEBCwUAMGAxCzAJBgNV -BAYTAlVLMRMwEQYDVQQIEwpTb21lLVN0YXRlMQ8wDQYDVQQHEwZMb25kb24xFzAV -BgNVBAoTDkdycGMgRWNvc3lzdGVtMRIwEAYDVQQDEwlsb2NhbGhvc3QwHhcNMTcw -ODI1MDc0NTMyWhcNMjcwODIzMDc0NTMyWjBgMQswCQYDVQQGEwJVSzETMBEGA1UE -CBMKU29tZS1TdGF0ZTEPMA0GA1UEBxMGTG9uZG9uMRcwFQYDVQQKEw5HcnBjIEVj -b3N5c3RlbTESMBAGA1UEAxMJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOC -AQ8AMIIBCgKCAQEA2uDY9N8eGScSGAr/DIeFxyCrytqCkYvqVPYqrZv4VOZvyfak -Un7bW4q8zeNWwj64sU0al7Bz8KBmAM7raLnkvkZxmXUCls+Yw8BgXQr+1aDvYYd0 -JIVJvQqQd1oNXQeZs6GXfalCXh9mhHkJIHOm2ynk2GtS81NQik7ZMg+W3qygeK8O -40vbnYxqq2zkvub1dztxuApUzLmuXxLZRo+3faZZetNZ1eMCuqyqzibDRwcYhr3a -soC8d+6wWFobwV5AX7h7+qnS6mclESkN7FHMZT1r3OEvix012ry74xl79ploae8d -1dkR45C1DEaxwHYz7zJgP5IOXfKcv6KJhgEiYwIDAQABo4HFMIHCMB0GA1UdDgQW -BBRXiz6enaVw2tDnZ6/fEuW2USDSKjCBkgYDVR0jBIGKMIGHgBRXiz6enaVw2tDn -Z6/fEuW2USDSKqFkpGIwYDELMAkGA1UEBhMCVUsxEzARBgNVBAgTClNvbWUtU3Rh -dGUxDzANBgNVBAcTBkxvbmRvbjEXMBUGA1UEChMOR3JwYyBFY29zeXN0ZW0xEjAQ -BgNVBAMTCWxvY2FsaG9zdIIJAOizA5bposrzMAwGA1UdEwQFMAMBAf8wDQYJKoZI -hvcNAQELBQADggEBADFmrqug4HYCtcy2F61o53vXIJQ6SyGwPCE5gOq07tkEz2id -oKcb2qNF1Zh+lOQ9GkvMkfzop0a4nhW8ra28gEBwhESS/aGKc7/isZN4ZKyy9JvJ -taTmVgXGp8s0w5dCXqDf3YU3XpdF53J1R7dyEfey3nEjMPRj/Ebs7rmpfRzOI4cX -6SJWJ71ShXK/IZbSVfobTzRdmAlz7uiwp2OVveGqcpQk46wgVoduwrC2hCe4wI6y -Dlo/GLmyCVlIiPaNA32sw+lca02Z5EXcQutRov2R/lUfoUCS/gOjCD7hVZXSRo+9 -tFmGR8IuQDFseOW7CWTWqkiwu9F80HXmovboMKQ= ------END CERTIFICATE-----`) diff --git a/grpctesting/certs/localhost.key b/grpctesting/certs/localhost.key deleted file mode 100644 index c9f365a25..000000000 --- a/grpctesting/certs/localhost.key +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEA2uDY9N8eGScSGAr/DIeFxyCrytqCkYvqVPYqrZv4VOZvyfak -Un7bW4q8zeNWwj64sU0al7Bz8KBmAM7raLnkvkZxmXUCls+Yw8BgXQr+1aDvYYd0 -JIVJvQqQd1oNXQeZs6GXfalCXh9mhHkJIHOm2ynk2GtS81NQik7ZMg+W3qygeK8O -40vbnYxqq2zkvub1dztxuApUzLmuXxLZRo+3faZZetNZ1eMCuqyqzibDRwcYhr3a -soC8d+6wWFobwV5AX7h7+qnS6mclESkN7FHMZT1r3OEvix012ry74xl79ploae8d -1dkR45C1DEaxwHYz7zJgP5IOXfKcv6KJhgEiYwIDAQABAoIBAEC/gQ63LhUsvKqG -HjrboFRussM4bqWVqUVm6Osgl46t+GXbY3LP+h4TZZTWaqTdnw88CuDSnwmQuXwF -uhfp3eP3vMUzmwd38+38a8U6anZRvF6yjkX7c/vLMz9LUWayx+IerEzNFEf5q/8G -Ow/xhmuQ8hSfcxNuEwZHGvM3L19BT852iXCh4uEJyR5G0e/5RI7f/bBieLo4exO9 -EO/vcxK+fcZk4XAwIa0UWdWfzk+lgTDfw0kG1fNm5QJgykGSpXw51GNrakcGsBX1 -ocu2DM6wIU7cb+orTmxRM4ra+NV4oiH63GVB79mnQtQ1PSwZv+v+tQdx/APu12MX -P23qfZECgYEA7T9NFbKQxMQxWc4YoMhtUNrURhRsgLtbkRLzzScfDhCAf576HQBe -vO3oPIF4b1i/SHQijLTjHuP32az1n9FJYakRTNUIYlKOPpRC8snULtvbhVUVoRXZ -iVnX6Nk5ISK5CpVQP9MDscbkmXejTSld4IK8y8f5eUV899rbfHq8prkCgYEA7C3Z -txJytRhwanUykG8fwF2KkJxWrgrUG6FyxQPt9hqIGbtG7naN0kucjcDmhywe5Luq -2DGxirEs08YpQKgyP+2o5+d6hCuAweA3HsZS4MdQO45IMubV1EEy/4mqODLxvGhr -0BQZ08px692iEUOQHmxbynIx8v7UwObbAncBg/sCgYANr/o9hzjM8Vi7iqVnGUkd -QhK/HEyKPMTyoLpKGriy8gbH1h8t7yiIE92zJ/EP03ntry2TGpiD3rkc6Nqe5s8q -ADwMR7odGhA00g7uvPAt5+dJUPhXe9A6GWHYgDfIjp1IXAbuN7ld11C2/e0A9aMB -4ekMhLQC6BxmnEzPaLFbmQKBgQCR1i4d0ZJrKNAhrISwky20Bw7NBPyxM5aOCT9p -UGfcE73+xZmjHimstWvSTE8NIL1i2E9CeEz9KzJXAoHunu2IdCRcLp+EhahYDy96 -HVSH4As2+0CxzcAz9J6dFFC7qxmCEaihMAhSsyttTcoJhwKzBo4XkDQvrBOLmgGa -oAmbiQKBgGacQ3nzSjlAfTqUKZc3wHKO2BNxSQfq7BejvGAR9bH/qUvB0Q7r7nb+ -98Epzx8K+om7BRh5cQc6QQIP4gUIi+K7IIaPLgoUwo3Uj+nq0m3cT+iWQKEwo6c3 -wtMi5c6K0MfzcMk0RVxcraL3isAV1zZMPsuAD5EzCsYF5a+opQNq ------END RSA PRIVATE KEY----- diff --git a/grpctesting/interceptor_suite.go b/grpctesting/interceptor_suite.go index aa96db98c..cbfefc049 100644 --- a/grpctesting/interceptor_suite.go +++ b/grpctesting/interceptor_suite.go @@ -5,11 +5,15 @@ package grpctesting import ( "context" + "crypto/rand" + "crypto/rsa" "crypto/tls" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" "flag" + "math/big" "net" - "path" - "runtime" "sync" "time" @@ -18,18 +22,15 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting/certs" "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting/testpb" ) var ( flagTls = flag.Bool("use_tls", true, "whether all gRPC middleware tests should use tls") -) -func getTestingCertsPath() string { - _, callerPath, _, _ := runtime.Caller(0) - return path.Join(path.Dir(callerPath), "certs") -} + certPEM []byte + keyPEM []byte +) // InterceptorTestSuite is a testify/Suite that starts a gRPC PingService server and a client. type InterceptorTestSuite struct { @@ -56,6 +57,9 @@ func (s *InterceptorTestSuite) SetupSuite() { s.serverRunning = make(chan bool) s.serverAddr = "127.0.0.1:0" + var err error + certPEM, keyPEM, err = generateCertAndKey([]string{"localhost", "example.com"}) + require.NoError(s.T(), err, "unable to generate test certificate/key") go func() { for { @@ -64,14 +68,14 @@ func (s *InterceptorTestSuite) SetupSuite() { s.serverAddr = s.ServerListener.Addr().String() require.NoError(s.T(), err, "must be able to allocate a port for serverListener") if *flagTls { - localhostCert, err := tls.X509KeyPair(certs.LocalhostCert, certs.LocalhostKey) - require.NoError(s.T(), err, "failed loading server credentials for localhostCert") - creds := credentials.NewServerTLSFromCert(&localhostCert) + cert, err := tls.X509KeyPair(certPEM, keyPEM) + require.NoError(s.T(), err, "unable to load test TLS certificate") + creds := credentials.NewServerTLSFromCert(&cert) s.ServerOpts = append(s.ServerOpts, grpc.Creds(creds)) } - // This is the point where we hook up the interceptor + // This is the point where we hook up the interceptor. s.Server = grpc.NewServer(s.ServerOpts...) - // Crete a service of the instantiator hasn't provided one. + // Create a service if the instantiator hasn't provided one. if s.TestService == nil { s.TestService = &TestPingService{T: s.T()} } @@ -112,9 +116,11 @@ func (s *InterceptorTestSuite) RestartServer(delayedStart time.Duration) <-chan func (s *InterceptorTestSuite) NewClient(dialOpts ...grpc.DialOption) testpb.TestServiceClient { newDialOpts := append(dialOpts, grpc.WithBlock()) if *flagTls { - creds, err := credentials.NewClientTLSFromFile( - path.Join(getTestingCertsPath(), "localhost.crt"), "localhost") - require.NoError(s.T(), err, "failed reading client credentials for localhost.crt") + cp := x509.NewCertPool() + if !cp.AppendCertsFromPEM(certPEM) { + s.T().Fatal("failed to append certificate") + } + creds := credentials.NewTLS(&tls.Config{ServerName: "localhost", RootCAs: cp}) newDialOpts = append(newDialOpts, grpc.WithTransportCredentials(creds)) } else { newDialOpts = append(newDialOpts, grpc.WithInsecure()) @@ -156,3 +162,45 @@ func (s *InterceptorTestSuite) TearDownSuite() { c() } } + +// generateCertAndKey copied from https://github.com/johanbrandhorst/certify/blob/master/issuers/vault/vault_suite_test.go#L255 +// with minor modifications. +func generateCertAndKey(san []string) ([]byte, []byte, error) { + priv, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + return nil, nil, err + } + notBefore := time.Now() + notAfter := notBefore.Add(time.Hour) + serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) + serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) + if err != nil { + return nil, nil, err + } + template := x509.Certificate{ + SerialNumber: serialNumber, + Subject: pkix.Name{ + CommonName: "example.com", + }, + NotBefore: notBefore, + NotAfter: notAfter, + KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + BasicConstraintsValid: true, + DNSNames: san, + } + derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, priv.Public(), priv) + if err != nil { + return nil, nil, err + } + certOut := pem.EncodeToMemory(&pem.Block{ + Type: "CERTIFICATE", + Bytes: derBytes, + }) + keyOut := pem.EncodeToMemory(&pem.Block{ + Type: "RSA PRIVATE KEY", + Bytes: x509.MarshalPKCS1PrivateKey(priv), + }) + + return certOut, keyOut, nil +} From a4fdb5df3a633efa358dc1475c698711c7e8bb3b Mon Sep 17 00:00:00 2001 From: Dmitry Savintsev Date: Wed, 9 Sep 2020 19:25:12 +0200 Subject: [PATCH 02/27] add all make target, reword instructions (#335) * add all make target, reword instructions * remove extra line, reword per suggestion --- CONTRIBUTING.md | 12 ++++++------ Makefile | 4 +++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 89cb00786..da51fa2c0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,9 +6,9 @@ Fork, then clone the repo: ```bash git clone git@github.com:your-username/go-grpc-middleware.git -``` -Before submitting a patch, please make sure to run the following make commands for running checks - -Make commands for running formatting/tests/generate proto files/vetting +``` +Before submitting a patch, please make sure to run the following make commands to execute the +formatting check, regenerate the proto files, and run the tests and linters: ```powershell make fmt : Run formatting across all go files @@ -16,7 +16,7 @@ make proto : Generate proto files make test : Run all the tests -make vet : Run vetting across all go files +make lint : Run linting across all go files ``` One command to rule them all: @@ -25,7 +25,7 @@ One command to rule them all: make all ``` -This will `vet`, `fmt`, regenerate documentation and run all tests. +This will `lint`, `fmt`, regenerate proto files and documentation and run all tests. -Push to your fork and open a pull request. \ No newline at end of file +Push to your fork and open a pull request. diff --git a/Makefile b/Makefile index 0286512df..1868f27c0 100644 --- a/Makefile +++ b/Makefile @@ -36,6 +36,8 @@ define require_clean_work_tree endef +all: fmt proto lint test + .PHONY: fmt fmt: $(GOIMPORTS) @echo "Running fmt for all modules: $(MODULES)" @@ -65,7 +67,7 @@ test_module: # --cpu-profile-path string Path to CPU profile output file # --mem-profile-path string Path to memory profile output file # to debug big allocations during linting. -lint: ## Runs various static analysis against our code. +lint: ## Runs various static analysis tools against our code. lint: fmt $(FAILLINT) $(GOLANGCI_LINT) $(MISSPELL) @echo "Running lint for all modules: $(MODULES)" ./scripts/git-tree.sh From 88c8444e0d49557588702f78a974cd415bb27264 Mon Sep 17 00:00:00 2001 From: Dmitry Savintsev Date: Thu, 10 Sep 2020 10:58:07 +0200 Subject: [PATCH 03/27] remove 1.12.x from build config for consistency with master (#337) * remove 1.12.x from build config for consistency with master * fix quote Co-authored-by: Johan Brandhorst-Satzkorn Co-authored-by: Johan Brandhorst-Satzkorn --- .github/workflows/go.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/go.yaml b/.github/workflows/go.yaml index 127861bef..3e0f3b79c 100644 --- a/.github/workflows/go.yaml +++ b/.github/workflows/go.yaml @@ -34,7 +34,7 @@ jobs: strategy: fail-fast: false matrix: - go: [ '1.12.x', '1.13.x', '1.14.x', '1.15.x' ] + go: [ '1.13.x', '1.14.x', '1.15.x' ] platform: [ubuntu-latest, macos-latest] steps: - name: Checkout code into the Go module directory. From 2a8b5ab51b913ef2ed8efb1b05c1525ec7713a27 Mon Sep 17 00:00:00 2001 From: Tiernan Date: Thu, 17 Sep 2020 21:13:26 +1000 Subject: [PATCH 04/27] [v2] Fix the special case for jaeger format traceid extraction (#340) * Fix the special case for jaeger format traceid extraction being overridden regression introduced with #262 * Add unit test for Jaeger trace id parsing fix --- interceptors/tracing/id_extract.go | 31 +++++++++++++----------- interceptors/tracing/id_extract_test.go | 32 +++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 14 deletions(-) create mode 100644 interceptors/tracing/id_extract_test.go diff --git a/interceptors/tracing/id_extract.go b/interceptors/tracing/id_extract.go index abdb9a8e4..a0e482cb0 100644 --- a/interceptors/tracing/id_extract.go +++ b/interceptors/tracing/id_extract.go @@ -41,20 +41,6 @@ type tagsCarrier struct { func (t *tagsCarrier) Set(key, val string) { key = strings.ToLower(key) - if strings.Contains(key, "traceid") { - t.Tags.Set(TagTraceId, val) // this will most likely be base-16 (hex) encoded - } - - if strings.Contains(key, "spanid") && !strings.Contains(strings.ToLower(key), "parent") { - t.Tags.Set(TagSpanId, val) // this will most likely be base-16 (hex) encoded - } - - if strings.Contains(key, "sampled") { - switch val { - case "true", "false": - t.Tags.Set(TagSampled, val) - } - } if key == t.traceHeaderName { parts := strings.Split(val, ":") @@ -67,6 +53,23 @@ func (t *tagsCarrier) Set(key, val string) { } else { t.Tags.Set(TagSampled, "false") } + + return + } + } + + if strings.Contains(key, "traceid") { + t.Tags.Set(TagTraceId, val) // this will most likely be base-16 (hex) encoded + } + + if strings.Contains(key, "spanid") && !strings.Contains(strings.ToLower(key), "parent") { + t.Tags.Set(TagSpanId, val) // this will most likely be base-16 (hex) encoded + } + + if strings.Contains(key, "sampled") { + switch val { + case "true", "false": + t.Tags.Set(TagSampled, val) } } diff --git a/interceptors/tracing/id_extract_test.go b/interceptors/tracing/id_extract_test.go new file mode 100644 index 000000000..f0bca9459 --- /dev/null +++ b/interceptors/tracing/id_extract_test.go @@ -0,0 +1,32 @@ +package tracing + +import ( + "fmt" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tags" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestTagsCarrier_Set_JaegerTraceFormat(t *testing.T) { + var ( + fakeTraceSampled = 1 + fakeInboundTraceId = "deadbeef" + fakeInboundSpanId = "c0decafe" + traceHeaderName = "uber-trace-id" + ) + + traceHeaderValue := fmt.Sprintf("%s:%s:%s:%d", fakeInboundTraceId, fakeInboundSpanId, fakeInboundSpanId, fakeTraceSampled) + + c := &tagsCarrier{ + Tags: tags.NewTags(), + traceHeaderName: traceHeaderName, + } + + c.Set(traceHeaderName, traceHeaderValue) + + assert.EqualValues(t, map[string]string{ + TagTraceId: fakeInboundTraceId, + TagSpanId: fakeInboundSpanId, + TagSampled: "true", + }, c.Tags.Values()) +} From 9d12ea682302e40eccdd3dfa41000129ec0907c2 Mon Sep 17 00:00:00 2001 From: Tiernan Date: Fri, 18 Sep 2020 20:55:18 +1000 Subject: [PATCH 05/27] Fix ctxtags TagBasedRequestFieldExtractor extracting from fields in a oneof (PR #327 rebased on v2 branch) (#339) --- grpctesting/gogotestpb/fields.pb.go | 1456 ++-------------------- grpctesting/gogotestpb/fields.proto | 7 + interceptors/tags/fieldextractor.go | 4 +- interceptors/tags/fieldextractor_test.go | 10 + 4 files changed, 151 insertions(+), 1326 deletions(-) diff --git a/grpctesting/gogotestpb/fields.pb.go b/grpctesting/gogotestpb/fields.pb.go index 315ffdf8a..ccd5fdafa 100644 --- a/grpctesting/gogotestpb/fields.pb.go +++ b/grpctesting/gogotestpb/fields.pb.go @@ -7,14 +7,11 @@ package gogotestpb import ( fmt "fmt" - io "io" - math "math" - time "time" - _ "github.com/gogo/protobuf/gogoproto" - _ "github.com/gogo/protobuf/types" - github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" proto "github.com/golang/protobuf/proto" + _ "github.com/golang/protobuf/ptypes/timestamp" + math "math" + time "time" ) // Reference imports to suppress errors if they are not otherwise used. @@ -27,7 +24,7 @@ var _ = time.Kitchen // is compatible with the proto package it is being compiled against. // A compilation error at this line likely means your copy of the // proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package type Metadata struct { Tags []string `protobuf:"bytes,1,rep,name=tags,proto3" json:"tags,omitempty" log_field:"meta_tags"` @@ -43,25 +40,16 @@ func (*Metadata) Descriptor() ([]byte, []int) { return fileDescriptor_d39ad626ec0e575e, []int{0} } func (m *Metadata) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) + return xxx_messageInfo_Metadata.Unmarshal(m, b) } func (m *Metadata) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_Metadata.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalTo(b) - if err != nil { - return nil, err - } - return b[:n], nil - } + return xxx_messageInfo_Metadata.Marshal(b, m, deterministic) } func (m *Metadata) XXX_Merge(src proto.Message) { xxx_messageInfo_Metadata.Merge(m, src) } func (m *Metadata) XXX_Size() int { - return m.Size() + return xxx_messageInfo_Metadata.Size(m) } func (m *Metadata) XXX_DiscardUnknown() { xxx_messageInfo_Metadata.DiscardUnknown(m) @@ -90,25 +78,16 @@ func (*PingId) Descriptor() ([]byte, []int) { return fileDescriptor_d39ad626ec0e575e, []int{1} } func (m *PingId) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) + return xxx_messageInfo_PingId.Unmarshal(m, b) } func (m *PingId) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_PingId.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalTo(b) - if err != nil { - return nil, err - } - return b[:n], nil - } + return xxx_messageInfo_PingId.Marshal(b, m, deterministic) } func (m *PingId) XXX_Merge(src proto.Message) { xxx_messageInfo_PingId.Merge(m, src) } func (m *PingId) XXX_Size() int { - return m.Size() + return xxx_messageInfo_PingId.Size(m) } func (m *PingId) XXX_DiscardUnknown() { xxx_messageInfo_PingId.DiscardUnknown(m) @@ -138,25 +117,16 @@ func (*Ping) Descriptor() ([]byte, []int) { return fileDescriptor_d39ad626ec0e575e, []int{2} } func (m *Ping) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) + return xxx_messageInfo_Ping.Unmarshal(m, b) } func (m *Ping) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_Ping.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalTo(b) - if err != nil { - return nil, err - } - return b[:n], nil - } + return xxx_messageInfo_Ping.Marshal(b, m, deterministic) } func (m *Ping) XXX_Merge(src proto.Message) { xxx_messageInfo_Ping.Merge(m, src) } func (m *Ping) XXX_Size() int { - return m.Size() + return xxx_messageInfo_Ping.Size(m) } func (m *Ping) XXX_DiscardUnknown() { xxx_messageInfo_Ping.DiscardUnknown(m) @@ -193,25 +163,16 @@ func (*PingRequest) Descriptor() ([]byte, []int) { return fileDescriptor_d39ad626ec0e575e, []int{3} } func (m *PingRequest) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) + return xxx_messageInfo_PingRequest.Unmarshal(m, b) } func (m *PingRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_PingRequest.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalTo(b) - if err != nil { - return nil, err - } - return b[:n], nil - } + return xxx_messageInfo_PingRequest.Marshal(b, m, deterministic) } func (m *PingRequest) XXX_Merge(src proto.Message) { xxx_messageInfo_PingRequest.Merge(m, src) } func (m *PingRequest) XXX_Size() int { - return m.Size() + return xxx_messageInfo_PingRequest.Size(m) } func (m *PingRequest) XXX_DiscardUnknown() { xxx_messageInfo_PingRequest.DiscardUnknown(m) @@ -247,25 +208,16 @@ func (*Pong) Descriptor() ([]byte, []int) { return fileDescriptor_d39ad626ec0e575e, []int{4} } func (m *Pong) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) + return xxx_messageInfo_Pong.Unmarshal(m, b) } func (m *Pong) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_Pong.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalTo(b) - if err != nil { - return nil, err - } - return b[:n], nil - } + return xxx_messageInfo_Pong.Marshal(b, m, deterministic) } func (m *Pong) XXX_Merge(src proto.Message) { xxx_messageInfo_Pong.Merge(m, src) } func (m *Pong) XXX_Size() int { - return m.Size() + return xxx_messageInfo_Pong.Size(m) } func (m *Pong) XXX_DiscardUnknown() { xxx_messageInfo_Pong.DiscardUnknown(m) @@ -295,25 +247,16 @@ func (*PongRequest) Descriptor() ([]byte, []int) { return fileDescriptor_d39ad626ec0e575e, []int{5} } func (m *PongRequest) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) + return xxx_messageInfo_PongRequest.Unmarshal(m, b) } func (m *PongRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_PongRequest.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalTo(b) - if err != nil { - return nil, err - } - return b[:n], nil - } + return xxx_messageInfo_PongRequest.Marshal(b, m, deterministic) } func (m *PongRequest) XXX_Merge(src proto.Message) { xxx_messageInfo_PongRequest.Merge(m, src) } func (m *PongRequest) XXX_Size() int { - return m.Size() + return xxx_messageInfo_PongRequest.Size(m) } func (m *PongRequest) XXX_DiscardUnknown() { xxx_messageInfo_PongRequest.DiscardUnknown(m) @@ -335,6 +278,83 @@ func (m *PongRequest) GetMeta() *Metadata { return nil } +type OneOfLogField struct { + // Types that are valid to be assigned to Identifier: + // *OneOfLogField_BarId + // *OneOfLogField_BazId + Identifier isOneOfLogField_Identifier `protobuf_oneof:"identifier"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *OneOfLogField) Reset() { *m = OneOfLogField{} } +func (m *OneOfLogField) String() string { return proto.CompactTextString(m) } +func (*OneOfLogField) ProtoMessage() {} +func (*OneOfLogField) Descriptor() ([]byte, []int) { + return fileDescriptor_d39ad626ec0e575e, []int{6} +} +func (m *OneOfLogField) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_OneOfLogField.Unmarshal(m, b) +} +func (m *OneOfLogField) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_OneOfLogField.Marshal(b, m, deterministic) +} +func (m *OneOfLogField) XXX_Merge(src proto.Message) { + xxx_messageInfo_OneOfLogField.Merge(m, src) +} +func (m *OneOfLogField) XXX_Size() int { + return xxx_messageInfo_OneOfLogField.Size(m) +} +func (m *OneOfLogField) XXX_DiscardUnknown() { + xxx_messageInfo_OneOfLogField.DiscardUnknown(m) +} + +var xxx_messageInfo_OneOfLogField proto.InternalMessageInfo + +type isOneOfLogField_Identifier interface { + isOneOfLogField_Identifier() +} + +type OneOfLogField_BarId struct { + BarId string `protobuf:"bytes,1,opt,name=bar_id,json=barId,proto3,oneof" json:"bar_id,omitempty" log_field:"bar_id"` +} +type OneOfLogField_BazId struct { + BazId string `protobuf:"bytes,2,opt,name=baz_id,json=bazId,proto3,oneof" json:"baz_id,omitempty" log_field:"baz_id"` +} + +func (*OneOfLogField_BarId) isOneOfLogField_Identifier() {} +func (*OneOfLogField_BazId) isOneOfLogField_Identifier() {} + +func (m *OneOfLogField) GetIdentifier() isOneOfLogField_Identifier { + if m != nil { + return m.Identifier + } + return nil +} + +func (m *OneOfLogField) GetBarId() string { + if x, ok := m.GetIdentifier().(*OneOfLogField_BarId); ok { + return x.BarId + } + return "" +} + +func (m *OneOfLogField) GetBazId() string { + if x, ok := m.GetIdentifier().(*OneOfLogField_BazId); ok { + return x.BazId + } + return "" +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*OneOfLogField) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*OneOfLogField_BarId)(nil), + (*OneOfLogField_BazId)(nil), + } +} + type GoGoProtoStdTime struct { Timestamp *time.Time `protobuf:"bytes,1,opt,name=timestamp,proto3,stdtime" json:"timestamp,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` @@ -346,28 +366,19 @@ func (m *GoGoProtoStdTime) Reset() { *m = GoGoProtoStdTime{} } func (m *GoGoProtoStdTime) String() string { return proto.CompactTextString(m) } func (*GoGoProtoStdTime) ProtoMessage() {} func (*GoGoProtoStdTime) Descriptor() ([]byte, []int) { - return fileDescriptor_d39ad626ec0e575e, []int{6} + return fileDescriptor_d39ad626ec0e575e, []int{7} } func (m *GoGoProtoStdTime) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) + return xxx_messageInfo_GoGoProtoStdTime.Unmarshal(m, b) } func (m *GoGoProtoStdTime) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_GoGoProtoStdTime.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalTo(b) - if err != nil { - return nil, err - } - return b[:n], nil - } + return xxx_messageInfo_GoGoProtoStdTime.Marshal(b, m, deterministic) } func (m *GoGoProtoStdTime) XXX_Merge(src proto.Message) { xxx_messageInfo_GoGoProtoStdTime.Merge(m, src) } func (m *GoGoProtoStdTime) XXX_Size() int { - return m.Size() + return xxx_messageInfo_GoGoProtoStdTime.Size(m) } func (m *GoGoProtoStdTime) XXX_DiscardUnknown() { xxx_messageInfo_GoGoProtoStdTime.DiscardUnknown(m) @@ -389,1242 +400,39 @@ func init() { proto.RegisterType((*PingRequest)(nil), "grpc_middleware.gogotestpb.PingRequest") proto.RegisterType((*Pong)(nil), "grpc_middleware.gogotestpb.Pong") proto.RegisterType((*PongRequest)(nil), "grpc_middleware.gogotestpb.PongRequest") + proto.RegisterType((*OneOfLogField)(nil), "grpc_middleware.gogotestpb.OneOfLogField") proto.RegisterType((*GoGoProtoStdTime)(nil), "grpc_middleware.gogotestpb.GoGoProtoStdTime") } func init() { proto.RegisterFile("fields.proto", fileDescriptor_d39ad626ec0e575e) } var fileDescriptor_d39ad626ec0e575e = []byte{ - // 387 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x92, 0x3d, 0x6e, 0xdb, 0x30, - 0x14, 0xc7, 0x4b, 0x57, 0x36, 0x2a, 0xba, 0x43, 0xc1, 0xba, 0xa8, 0x2b, 0x14, 0x92, 0x40, 0x14, - 0xa8, 0x97, 0x4a, 0xa8, 0xdb, 0xa1, 0xed, 0xd0, 0x41, 0x8b, 0x91, 0x21, 0x80, 0xc0, 0x78, 0xca, - 0x22, 0xd0, 0x21, 0x4d, 0x10, 0x90, 0x4c, 0xc5, 0xa2, 0x93, 0x29, 0x77, 0xc8, 0x98, 0x23, 0x65, - 0xcc, 0x09, 0x9c, 0xc0, 0xb9, 0x81, 0x4f, 0x10, 0x90, 0xf2, 0x57, 0x10, 0xe4, 0x03, 0xc8, 0x46, - 0x42, 0xff, 0xdf, 0xe3, 0xef, 0x3d, 0x3d, 0xf8, 0x7e, 0x2c, 0x79, 0xce, 0xaa, 0xa8, 0x9c, 0x2a, - 0xad, 0x90, 0x27, 0xa6, 0xe5, 0x51, 0x56, 0x48, 0xc6, 0x72, 0x7e, 0x4a, 0xa7, 0x3c, 0x12, 0x4a, - 0x28, 0xcd, 0x2b, 0x5d, 0x8e, 0xbc, 0x8e, 0x39, 0xdb, 0x58, 0x6c, 0x4e, 0x35, 0xe1, 0x05, 0x42, - 0x29, 0x91, 0xf3, 0xd8, 0xde, 0x46, 0xb3, 0x71, 0xac, 0x65, 0xc1, 0x2b, 0x4d, 0x8b, 0xb2, 0x0e, - 0xe0, 0xbf, 0xf0, 0xdd, 0x3e, 0xd7, 0x94, 0x51, 0x4d, 0xd1, 0x0f, 0xe8, 0x68, 0x2a, 0xaa, 0x2e, - 0x08, 0xdf, 0xf6, 0xdc, 0xe4, 0xcb, 0x72, 0x1e, 0x7c, 0xca, 0x95, 0xc8, 0xac, 0xc2, 0x3f, 0x5c, - 0x70, 0x4d, 0x33, 0xf3, 0x1d, 0x13, 0x1b, 0xc3, 0x3f, 0x61, 0x2b, 0x95, 0x13, 0xb1, 0xc7, 0xd0, - 0x77, 0xd8, 0x90, 0xac, 0x0b, 0x42, 0xd0, 0x6b, 0x26, 0x9f, 0x97, 0xf3, 0xe0, 0xe3, 0x0e, 0x56, - 0xca, 0x89, 0xc8, 0x24, 0xc3, 0xa4, 0x21, 0x19, 0x4e, 0xa1, 0x63, 0x10, 0xd4, 0xdf, 0x00, 0xed, - 0x3e, 0x8e, 0x1e, 0xef, 0x2a, 0xaa, 0x1f, 0x30, 0x2c, 0xea, 0xc0, 0xe6, 0x09, 0xcd, 0x67, 0xbc, - 0xdb, 0x08, 0x41, 0xcf, 0x25, 0xf5, 0x05, 0x9f, 0xc1, 0xb6, 0xc9, 0x10, 0x7e, 0x3c, 0xe3, 0x95, - 0x46, 0xbf, 0xa1, 0x63, 0x1e, 0x5c, 0x95, 0x0e, 0x9f, 0x2b, 0x4d, 0x6c, 0x1a, 0xfd, 0x81, 0x8e, - 0xe9, 0xce, 0x56, 0x6e, 0xf7, 0xbf, 0x3d, 0x45, 0xad, 0x87, 0x45, 0x2c, 0x81, 0x63, 0xe8, 0xa4, - 0x6a, 0x22, 0x76, 0x26, 0xe0, 0x3e, 0x9c, 0x80, 0xda, 0x99, 0x80, 0xf1, 0x55, 0xf7, 0x7d, 0xd5, - 0x0b, 0x7d, 0x95, 0xf5, 0x55, 0xaf, 0xf2, 0x25, 0xf0, 0xc3, 0x40, 0x0d, 0x54, 0x6a, 0xfe, 0xfd, - 0x81, 0x66, 0x43, 0x59, 0x70, 0xf4, 0x1f, 0xba, 0x9b, 0xad, 0x58, 0x89, 0x78, 0x51, 0xbd, 0x37, - 0xd1, 0x7a, 0x6f, 0xa2, 0xe1, 0x3a, 0x91, 0x38, 0xe7, 0xd7, 0x01, 0x20, 0x5b, 0x24, 0xf9, 0x7a, - 0xb9, 0xf0, 0xc1, 0xd5, 0xc2, 0x07, 0x37, 0x0b, 0x1f, 0x5c, 0xdc, 0xfa, 0x6f, 0x0e, 0xe1, 0x56, - 0x60, 0xd4, 0xb2, 0x25, 0x7e, 0xdd, 0x05, 0x00, 0x00, 0xff, 0xff, 0x28, 0x7e, 0xe2, 0x59, 0xca, - 0x02, 0x00, 0x00, -} - -func (m *Metadata) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *Metadata) MarshalTo(dAtA []byte) (int, error) { - var i int - _ = i - var l int - _ = l - if len(m.Tags) > 0 { - for _, s := range m.Tags { - dAtA[i] = 0xa - i++ - l = len(s) - for l >= 1<<7 { - dAtA[i] = uint8(uint64(l)&0x7f | 0x80) - l >>= 7 - i++ - } - dAtA[i] = uint8(l) - i++ - i += copy(dAtA[i:], s) - } - } - if m.XXX_unrecognized != nil { - i += copy(dAtA[i:], m.XXX_unrecognized) - } - return i, nil -} - -func (m *PingId) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *PingId) MarshalTo(dAtA []byte) (int, error) { - var i int - _ = i - var l int - _ = l - if m.Id != 0 { - dAtA[i] = 0x8 - i++ - i = encodeVarintFields(dAtA, i, uint64(m.Id)) - } - if m.XXX_unrecognized != nil { - i += copy(dAtA[i:], m.XXX_unrecognized) - } - return i, nil -} - -func (m *Ping) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *Ping) MarshalTo(dAtA []byte) (int, error) { - var i int - _ = i - var l int - _ = l - if m.Id != nil { - dAtA[i] = 0xa - i++ - i = encodeVarintFields(dAtA, i, uint64(m.Id.Size())) - n1, err := m.Id.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n1 - } - if len(m.Value) > 0 { - dAtA[i] = 0x12 - i++ - i = encodeVarintFields(dAtA, i, uint64(len(m.Value))) - i += copy(dAtA[i:], m.Value) - } - if m.XXX_unrecognized != nil { - i += copy(dAtA[i:], m.XXX_unrecognized) - } - return i, nil + // 431 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x92, 0xcf, 0xaa, 0xd3, 0x40, + 0x14, 0x87, 0x6f, 0x6a, 0x5a, 0xec, 0xe9, 0x15, 0x2e, 0xe3, 0x55, 0x6b, 0x17, 0xa6, 0x0c, 0x82, + 0xdd, 0x98, 0x60, 0x75, 0xa1, 0x2e, 0x5c, 0x64, 0xe1, 0xb5, 0xa0, 0xdc, 0x32, 0xde, 0x95, 0x9b, + 0x30, 0x71, 0xa6, 0xc3, 0x40, 0x92, 0x13, 0x93, 0xa9, 0x42, 0x41, 0x7c, 0x05, 0x97, 0x3e, 0x5d, + 0x5d, 0xf8, 0x06, 0x7d, 0x02, 0x99, 0x49, 0xff, 0x44, 0xa4, 0x2a, 0xb8, 0x9b, 0x61, 0x7e, 0xdf, + 0x99, 0xef, 0x1c, 0x0e, 0x9c, 0x2e, 0xb4, 0xcc, 0x44, 0x1d, 0x96, 0x15, 0x1a, 0x24, 0x23, 0x55, + 0x95, 0xef, 0x93, 0x5c, 0x0b, 0x91, 0xc9, 0x4f, 0xbc, 0x92, 0xa1, 0x42, 0x85, 0x46, 0xd6, 0xa6, + 0x4c, 0x47, 0xe7, 0xf6, 0xec, 0x62, 0x91, 0x3d, 0x35, 0xc4, 0x28, 0x50, 0x88, 0x2a, 0x93, 0x91, + 0xbb, 0xa5, 0xcb, 0x45, 0x64, 0x74, 0x2e, 0x6b, 0xc3, 0xf3, 0xb2, 0x09, 0xd0, 0x67, 0x70, 0xfd, + 0x8d, 0x34, 0x5c, 0x70, 0xc3, 0xc9, 0x43, 0xf0, 0x0d, 0x57, 0xf5, 0xd0, 0x1b, 0x5f, 0x9b, 0xf4, + 0xe3, 0xbb, 0x9b, 0x75, 0x70, 0x2b, 0x43, 0x95, 0x38, 0x85, 0xe7, 0x34, 0x97, 0x86, 0x27, 0xf6, + 0x9d, 0x32, 0x17, 0xa3, 0x8f, 0xa0, 0x37, 0xd7, 0x85, 0x9a, 0x09, 0xf2, 0x00, 0x3a, 0x5a, 0x0c, + 0xbd, 0xb1, 0x37, 0xe9, 0xc6, 0x77, 0x36, 0xeb, 0xe0, 0x66, 0x0b, 0x2b, 0x75, 0xa1, 0x12, 0x2d, + 0x28, 0xeb, 0x68, 0x41, 0xe7, 0xe0, 0x5b, 0x84, 0x4c, 0xf7, 0xc0, 0x60, 0x4a, 0xc3, 0xe3, 0x5d, + 0x85, 0xcd, 0x07, 0x96, 0x25, 0xe7, 0xd0, 0xfd, 0xc8, 0xb3, 0xa5, 0x1c, 0x76, 0xc6, 0xde, 0xa4, + 0xcf, 0x9a, 0x0b, 0xfd, 0x0c, 0x03, 0x9b, 0x61, 0xf2, 0xc3, 0x52, 0xd6, 0x86, 0x3c, 0x01, 0xdf, + 0x7e, 0xb8, 0x2d, 0x3d, 0xfe, 0x5b, 0x69, 0xe6, 0xd2, 0xe4, 0x29, 0xf8, 0xb6, 0x3b, 0x57, 0x79, + 0x30, 0xbd, 0xff, 0x27, 0x6a, 0x37, 0x2c, 0xe6, 0x08, 0x1a, 0x81, 0x3f, 0xc7, 0x42, 0xb5, 0x26, + 0xd0, 0xff, 0x7d, 0x02, 0xd8, 0x9a, 0x80, 0xf5, 0xc5, 0x5f, 0x7d, 0xf1, 0x1f, 0x7d, 0xd1, 0xf9, + 0xe2, 0x7f, 0xf9, 0x7e, 0x81, 0x1b, 0x97, 0x85, 0xbc, 0x5c, 0xbc, 0x46, 0xf5, 0xd2, 0xda, 0x91, + 0x08, 0x7a, 0x29, 0xaf, 0x92, 0xbd, 0xfc, 0xed, 0xcd, 0x3a, 0x20, 0x2d, 0xf9, 0xe6, 0x91, 0xbe, + 0x3a, 0x61, 0xdd, 0x94, 0x57, 0xb3, 0x2d, 0xb0, 0xb2, 0x40, 0xe7, 0x08, 0xb0, 0x3a, 0x00, 0xab, + 0x99, 0x88, 0x4f, 0x01, 0xb4, 0x90, 0x85, 0xd1, 0x0b, 0x2d, 0x2b, 0xca, 0xe0, 0xec, 0x02, 0x2f, + 0x70, 0x6e, 0x97, 0xef, 0xad, 0x11, 0x57, 0x3a, 0x97, 0xe4, 0x05, 0xf4, 0xf7, 0x6b, 0xb9, 0x9d, + 0xc4, 0x28, 0x6c, 0x16, 0x37, 0xdc, 0x2d, 0x6e, 0x78, 0xb5, 0x4b, 0xc4, 0xfe, 0xd7, 0xef, 0x81, + 0xc7, 0x0e, 0x48, 0x7c, 0xf6, 0xed, 0xc7, 0xbd, 0x93, 0x77, 0x70, 0xe8, 0x3a, 0xed, 0x39, 0xec, + 0xf1, 0xcf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7b, 0x9a, 0xee, 0xac, 0x3f, 0x03, 0x00, 0x00, } - -func (m *PingRequest) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *PingRequest) MarshalTo(dAtA []byte) (int, error) { - var i int - _ = i - var l int - _ = l - if m.Ping != nil { - dAtA[i] = 0xa - i++ - i = encodeVarintFields(dAtA, i, uint64(m.Ping.Size())) - n2, err := m.Ping.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n2 - } - if m.Meta != nil { - dAtA[i] = 0x12 - i++ - i = encodeVarintFields(dAtA, i, uint64(m.Meta.Size())) - n3, err := m.Meta.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n3 - } - if m.XXX_unrecognized != nil { - i += copy(dAtA[i:], m.XXX_unrecognized) - } - return i, nil -} - -func (m *Pong) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *Pong) MarshalTo(dAtA []byte) (int, error) { - var i int - _ = i - var l int - _ = l - if len(m.Id) > 0 { - dAtA[i] = 0xa - i++ - i = encodeVarintFields(dAtA, i, uint64(len(m.Id))) - i += copy(dAtA[i:], m.Id) - } - if m.XXX_unrecognized != nil { - i += copy(dAtA[i:], m.XXX_unrecognized) - } - return i, nil -} - -func (m *PongRequest) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *PongRequest) MarshalTo(dAtA []byte) (int, error) { - var i int - _ = i - var l int - _ = l - if m.Pong != nil { - dAtA[i] = 0xa - i++ - i = encodeVarintFields(dAtA, i, uint64(m.Pong.Size())) - n4, err := m.Pong.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n4 - } - if m.Meta != nil { - dAtA[i] = 0x12 - i++ - i = encodeVarintFields(dAtA, i, uint64(m.Meta.Size())) - n5, err := m.Meta.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n5 - } - if m.XXX_unrecognized != nil { - i += copy(dAtA[i:], m.XXX_unrecognized) - } - return i, nil -} - -func (m *GoGoProtoStdTime) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *GoGoProtoStdTime) MarshalTo(dAtA []byte) (int, error) { - var i int - _ = i - var l int - _ = l - if m.Timestamp != nil { - dAtA[i] = 0xa - i++ - i = encodeVarintFields(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(*m.Timestamp))) - n6, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(*m.Timestamp, dAtA[i:]) - if err != nil { - return 0, err - } - i += n6 - } - if m.XXX_unrecognized != nil { - i += copy(dAtA[i:], m.XXX_unrecognized) - } - return i, nil -} - -func encodeVarintFields(dAtA []byte, offset int, v uint64) int { - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return offset + 1 -} -func (m *Metadata) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if len(m.Tags) > 0 { - for _, s := range m.Tags { - l = len(s) - n += 1 + l + sovFields(uint64(l)) - } - } - if m.XXX_unrecognized != nil { - n += len(m.XXX_unrecognized) - } - return n -} - -func (m *PingId) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.Id != 0 { - n += 1 + sovFields(uint64(m.Id)) - } - if m.XXX_unrecognized != nil { - n += len(m.XXX_unrecognized) - } - return n -} - -func (m *Ping) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.Id != nil { - l = m.Id.Size() - n += 1 + l + sovFields(uint64(l)) - } - l = len(m.Value) - if l > 0 { - n += 1 + l + sovFields(uint64(l)) - } - if m.XXX_unrecognized != nil { - n += len(m.XXX_unrecognized) - } - return n -} - -func (m *PingRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.Ping != nil { - l = m.Ping.Size() - n += 1 + l + sovFields(uint64(l)) - } - if m.Meta != nil { - l = m.Meta.Size() - n += 1 + l + sovFields(uint64(l)) - } - if m.XXX_unrecognized != nil { - n += len(m.XXX_unrecognized) - } - return n -} - -func (m *Pong) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Id) - if l > 0 { - n += 1 + l + sovFields(uint64(l)) - } - if m.XXX_unrecognized != nil { - n += len(m.XXX_unrecognized) - } - return n -} - -func (m *PongRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.Pong != nil { - l = m.Pong.Size() - n += 1 + l + sovFields(uint64(l)) - } - if m.Meta != nil { - l = m.Meta.Size() - n += 1 + l + sovFields(uint64(l)) - } - if m.XXX_unrecognized != nil { - n += len(m.XXX_unrecognized) - } - return n -} - -func (m *GoGoProtoStdTime) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.Timestamp != nil { - l = github_com_gogo_protobuf_types.SizeOfStdTime(*m.Timestamp) - n += 1 + l + sovFields(uint64(l)) - } - if m.XXX_unrecognized != nil { - n += len(m.XXX_unrecognized) - } - return n -} - -func sovFields(x uint64) (n int) { - for { - n++ - x >>= 7 - if x == 0 { - break - } - } - return n -} -func sozFields(x uint64) (n int) { - return sovFields(uint64((x << 1) ^ uint64((int64(x) >> 63)))) -} -func (m *Metadata) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowFields - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: Metadata: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: Metadata: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Tags", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowFields - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthFields - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthFields - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Tags = append(m.Tags, string(dAtA[iNdEx:postIndex])) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipFields(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthFields - } - if (iNdEx + skippy) < 0 { - return ErrInvalidLengthFields - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *PingId) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowFields - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: PingId: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: PingId: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) - } - m.Id = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowFields - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Id |= int32(b&0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skipFields(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthFields - } - if (iNdEx + skippy) < 0 { - return ErrInvalidLengthFields - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *Ping) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowFields - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: Ping: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: Ping: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowFields - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthFields - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthFields - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Id == nil { - m.Id = &PingId{} - } - if err := m.Id.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowFields - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthFields - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthFields - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Value = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipFields(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthFields - } - if (iNdEx + skippy) < 0 { - return ErrInvalidLengthFields - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *PingRequest) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowFields - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: PingRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: PingRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Ping", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowFields - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthFields - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthFields - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Ping == nil { - m.Ping = &Ping{} - } - if err := m.Ping.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Meta", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowFields - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthFields - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthFields - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Meta == nil { - m.Meta = &Metadata{} - } - if err := m.Meta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipFields(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthFields - } - if (iNdEx + skippy) < 0 { - return ErrInvalidLengthFields - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *Pong) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowFields - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: Pong: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: Pong: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowFields - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthFields - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthFields - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Id = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipFields(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthFields - } - if (iNdEx + skippy) < 0 { - return ErrInvalidLengthFields - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *PongRequest) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowFields - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: PongRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: PongRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Pong", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowFields - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthFields - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthFields - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Pong == nil { - m.Pong = &Pong{} - } - if err := m.Pong.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Meta", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowFields - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthFields - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthFields - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Meta == nil { - m.Meta = &Metadata{} - } - if err := m.Meta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipFields(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthFields - } - if (iNdEx + skippy) < 0 { - return ErrInvalidLengthFields - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *GoGoProtoStdTime) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowFields - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: GoGoProtoStdTime: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: GoGoProtoStdTime: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowFields - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthFields - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthFields - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Timestamp == nil { - m.Timestamp = new(time.Time) - } - if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(m.Timestamp, dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipFields(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthFields - } - if (iNdEx + skippy) < 0 { - return ErrInvalidLengthFields - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func skipFields(dAtA []byte) (n int, err error) { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowFields - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - wireType := int(wire & 0x7) - switch wireType { - case 0: - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowFields - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - iNdEx++ - if dAtA[iNdEx-1] < 0x80 { - break - } - } - return iNdEx, nil - case 1: - iNdEx += 8 - return iNdEx, nil - case 2: - var length int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowFields - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - length |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if length < 0 { - return 0, ErrInvalidLengthFields - } - iNdEx += length - if iNdEx < 0 { - return 0, ErrInvalidLengthFields - } - return iNdEx, nil - case 3: - for { - var innerWire uint64 - var start int = iNdEx - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowFields - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - innerWire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - innerWireType := int(innerWire & 0x7) - if innerWireType == 4 { - break - } - next, err := skipFields(dAtA[start:]) - if err != nil { - return 0, err - } - iNdEx = start + next - if iNdEx < 0 { - return 0, ErrInvalidLengthFields - } - } - return iNdEx, nil - case 4: - return iNdEx, nil - case 5: - iNdEx += 4 - return iNdEx, nil - default: - return 0, fmt.Errorf("proto: illegal wireType %d", wireType) - } - } - panic("unreachable") -} - -var ( - ErrInvalidLengthFields = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowFields = fmt.Errorf("proto: integer overflow") -) diff --git a/grpctesting/gogotestpb/fields.proto b/grpctesting/gogotestpb/fields.proto index 0166fc429..27de34520 100644 --- a/grpctesting/gogotestpb/fields.proto +++ b/grpctesting/gogotestpb/fields.proto @@ -37,6 +37,13 @@ message PongRequest { Metadata meta = 2; } +message OneOfLogField { + oneof identifier { + string bar_id = 1 [(gogoproto.moretags) = "log_field:\"bar_id\""]; + string baz_id = 2 [(gogoproto.moretags) = "log_field:\"baz_id\""]; + } +} + message GoGoProtoStdTime { google.protobuf.Timestamp timestamp = 1 [(gogoproto.stdtime) = true]; } diff --git a/interceptors/tags/fieldextractor.go b/interceptors/tags/fieldextractor.go index d77b546c4..6e20fca57 100644 --- a/interceptors/tags/fieldextractor.go +++ b/interceptors/tags/fieldextractor.go @@ -64,8 +64,8 @@ func reflectMessageTags(msg interface{}, existingMap map[string]string, tagName for i := 0; i < v.NumField(); i++ { field := v.Field(i) kind := field.Kind() - // Only recurse down direct pointers, which should only be to nested structs. - if kind == reflect.Ptr && field.CanInterface() { + // Only recurse down direct pointers or interfaces, which should only be to nested structs. + if (kind == reflect.Ptr || kind == reflect.Interface) && field.CanInterface() { reflectMessageTags(field.Interface(), existingMap, tagName) } // In case of arrays/slices (repeated fields) go down to the concrete type. diff --git a/interceptors/tags/fieldextractor_test.go b/interceptors/tags/fieldextractor_test.go index 8593ff95b..93dd76040 100644 --- a/interceptors/tags/fieldextractor_test.go +++ b/interceptors/tags/fieldextractor_test.go @@ -53,6 +53,16 @@ func TestTaggedRequestFiledExtractor_PongRequest(t *testing.T) { assert.EqualValues(t, "[tagone tagtwo]", valMap["meta_tags"]) } +func TestTaggedRequestFiledExtractor_OneOfLogField(t *testing.T) { + req := &gogotestpb.OneOfLogField{ + Identifier: &gogotestpb.OneOfLogField_BarId{ + BarId: "bar-log-field", + }, + } + valMap := tags.TagBasedRequestFieldExtractor("log_field")("", req) + assert.EqualValues(t, "bar-log-field", valMap["bar_id"]) +} + // Test to ensure TagBasedRequestFieldExtractor does not panic when encountering private struct members such as // when using gogoproto.stdtime which results in a time.Time that has private struct members func TestTaggedRequestFiledExtractor_GogoTime(t *testing.T) { From 73cf2ae9d89195f8a2d4860d7b3f2bc4871d9ec7 Mon Sep 17 00:00:00 2001 From: Yash Sharma Date: Fri, 2 Oct 2020 15:06:00 +0530 Subject: [PATCH 06/27] Request Logging (#311) * add initial setup for the request logger Signed-off-by: Yash Sharma * compose the request logger in the original logger itself Signed-off-by: Yash Sharma * modify the tests to use the new param signature Signed-off-by: Yash Sharma * configure the option to enable or disable request logger Signed-off-by: Yash Sharma * added logging of metadata of the request object Signed-off-by: Yash Sharma * nitpickings Signed-off-by: Yash Sharma * added pre call implementation Signed-off-by: Yash Sharma * Nitpickings * Change the naming of PostRequestLoggingDecider to PreRequestLoggingDecider * Log only request details not response Signed-off-by: Yash Sharma * Removed the request decider and added another option for enabling the request logging * This ensures that the current logging works as it was working earlier * If the user wants to enable the request logging, use the options for enabling the logging * The request logging is switched off by default Signed-off-by: Yash Sharma * Removed the decider from the tests Signed-off-by: Yash Sharma * Apply suggestions from code review Add changes from bartek's review * Added logging of start and end messages of the request and response from the server side Signed-off-by: Yash Sharma * Added a decider for enabling request logging Signed-off-by: Yash Sharma * Added level of logging and contextual message for identifying the start and end of request and response start messages Signed-off-by: Yash Sharma * add more fields to record the start and end of the call Signed-off-by: Yash Sharma * modified the logging message Signed-off-by: Yash Sharma * Added tests for the request logging * Unary Server testing * Stream server testing * Unary Error testing Signed-off-by: Yash Sharma nitpickings Signed-off-by: Yash Sharma more nitpickings Signed-off-by: Yash Sharma * Added changes as suggested by Bartek * return early for multiple cases * intialize the level early Signed-off-by: Yash Sharma * Reverted logging strategy * Now enabling logging logs out all the details of the request/response * Breaks the initial logging api Signed-off-by: Yash Sharma * Added underscore for proper spacing and added grpc.error for protocol encoding Signed-off-by: Yash Sharma * Changes as requested by the reviewer - * Human Readable Messages - All the log entries are changed to use space instead of `_`. * Using key-value pairs for storing the kind, type and component. * Changed to start call and finished call. Signed-off-by: Yash Sharma * Modified the tests for the new API Signed-off-by: Yash Sharma * nitpickings Signed-off-by: Yash Sharma * Multiple changes * Abstracted out repititive fields into a single method * Added test fields, instead of creating a whole suite * Changed field values to adhere the common convention Signed-off-by: Yash Sharma * Added tests for the finish call\n*Test the finish call in every test suite rather than creating a new suite Signed-off-by: Yash Sharma * Modified the decider to use only method for deciding the logging Signed-off-by: Yash Sharma * Added ENUM based decider for logging * Currently 3 types of logging configured * NoLogCall - No logging * LogFinishCall - For logging the end of the call * LogAllCall - For logging the start and end of the call Signed-off-by: Yash Sharma * added some comments for usage of decider Signed-off-by: Yash Sharma * renamed LogAllCall to LogStartAndFinishCall Signed-off-by: Yash Sharma * remove unused comments Signed-off-by: Yash Sharma More comments removal Signed-off-by: Yash Sharma * modified the examples in the provider Signed-off-by: Yash Sharma --- interceptors/logging/interceptors.go | 72 +++++--- interceptors/logging/interceptors_test.go | 214 +++++++++++++--------- interceptors/logging/logging.go | 25 ++- providers/kit/examples_test.go | 9 +- providers/logrus/examples_test.go | 8 +- providers/zap/examples_test.go | 8 +- providers/zerolog/examples_test.go | 8 +- 7 files changed, 214 insertions(+), 130 deletions(-) diff --git a/interceptors/logging/interceptors.go b/interceptors/logging/interceptors.go index e7314b52d..6d170270b 100644 --- a/interceptors/logging/interceptors.go +++ b/interceptors/logging/interceptors.go @@ -25,34 +25,55 @@ type reporter struct { ctx context.Context typ interceptors.GRPCType service, method string + startCallLogged bool + opts *options + logger Logger + kind string +} - opts *options - logger Logger - - kind string +func (c *reporter) logMessage(logger Logger, err error, msg string, duration time.Duration) { + code := c.opts.codeFunc(err) + logger = logger.With("grpc.code", code.String()) + if err != nil { + logger = logger.With("grpc.error", fmt.Sprintf("%v", err)) + } + logger = logger.With(extractFields(tags.Extract(c.ctx))...) + logger.With(c.opts.durationFieldFunc(duration)...).Log(c.opts.levelFunc(code), msg) } func (c *reporter) PostCall(err error, duration time.Duration) { - if !c.opts.shouldLog(interceptors.FullMethod(c.service, c.method), err) { + switch c.opts.shouldLog(interceptors.FullMethod(c.service, c.method)) { + case LogFinishCall, LogStartAndFinishCall: + if err == io.EOF { + err = nil + } + c.logMessage(c.logger, err, "finished call", duration) + default: return } - if err == io.EOF { - err = nil - } - // Get optional, fresh tags. - logger := c.logger.With(extractFields(tags.Extract(c.ctx))...) +} - code := c.opts.codeFunc(err) - logger = logger.With("grpc.code", code.String()) - if err != nil { - logger = logger.With("error", fmt.Sprintf("%v", err)) +func (c *reporter) PostMsgSend(_ interface{}, err error, duration time.Duration) { + if c.startCallLogged { + return + } + switch c.opts.shouldLog(interceptors.FullMethod(c.service, c.method)) { + case LogStartAndFinishCall: + c.startCallLogged = true + c.logMessage(c.logger, err, "started call", duration) } - logger.With(c.opts.durationFieldFunc(duration)...).Log(c.opts.levelFunc(code), fmt.Sprintf("finished %s %s call", c.kind, c.typ)) } -func (c *reporter) PostMsgSend(interface{}, error, time.Duration) {} - -func (c *reporter) PostMsgReceive(interface{}, error, time.Duration) {} +func (c *reporter) PostMsgReceive(_ interface{}, err error, duration time.Duration) { + if c.startCallLogged { + return + } + switch c.opts.shouldLog(interceptors.FullMethod(c.service, c.method)) { + case LogStartAndFinishCall: + c.startCallLogged = true + c.logMessage(c.logger, err, "started call", duration) + } +} type reportable struct { opts *options @@ -74,13 +95,14 @@ func (r *reportable) reporter(ctx context.Context, typ interceptors.GRPCType, se fields = append(fields, "grpc.request.deadline", d.Format(time.RFC3339)) } return &reporter{ - ctx: ctx, - typ: typ, - service: service, - method: method, - opts: r.opts, - logger: r.logger.With(fields...), - kind: kind, + ctx: ctx, + typ: typ, + service: service, + method: method, + startCallLogged: false, + opts: r.opts, + logger: r.logger.With(fields...), + kind: kind, }, ctx } diff --git a/interceptors/logging/interceptors_test.go b/interceptors/logging/interceptors_test.go index f3967ce5c..d1f15f28b 100644 --- a/interceptors/logging/interceptors_test.go +++ b/interceptors/logging/interceptors_test.go @@ -60,8 +60,8 @@ func (l LogLines) Len() int { } func (l LogLines) Less(i, j int) bool { - if l[i].fields[logging.KindFieldKey] != l[j].fields[logging.KindFieldKey] { - return l[i].fields[logging.KindFieldKey] < l[j].fields[logging.KindFieldKey] + if l[i].fields[logging.ComponentFieldKey] != l[j].fields[logging.ComponentFieldKey] { + return l[i].fields[logging.ComponentFieldKey] < l[j].fields[logging.ComponentFieldKey] } if l[i].msg != l[j].msg { return l[i].msg < l[j].msg @@ -184,7 +184,7 @@ func TestSuite(t *testing.T) { func assertStandardFields(t *testing.T, kind string, f testDisposableFields, method string, typ interceptors.GRPCType) testDisposableFields { return f.AssertNextField(t, logging.SystemTag[0], logging.SystemTag[1]). - AssertNextField(t, logging.KindFieldKey, kind). + AssertNextField(t, logging.ComponentFieldKey, kind). AssertNextField(t, logging.ServiceFieldKey, "grpc_middleware.testpb.TestService"). AssertNextField(t, logging.MethodFieldKey, method). AssertNextField(t, logging.MethodTypeFieldKey, string(typ)) @@ -194,24 +194,34 @@ func (s *loggingClientServerSuite) TestPing() { _, err := s.Client.Ping(s.SimpleCtx(), goodPing) assert.NoError(s.T(), err, "there must be not be an on a successful call") lines := s.logger.Lines() - require.Len(s.T(), lines, 2) - - serverLogLine := lines[0] - assert.Equal(s.T(), logging.DEBUG, serverLogLine.lvl) - assert.Equal(s.T(), "finished server unary call", serverLogLine.msg) - serverFields := assertStandardFields(s.T(), logging.KindServerFieldValue, serverLogLine.fields, "Ping", interceptors.Unary) - serverFields.AssertNextField(s.T(), "grpc.request.value", "something"). + require.Len(s.T(), lines, 4) + + clientStartCallLogLine := lines[0] + assert.Equal(s.T(), logging.DEBUG, clientStartCallLogLine.lvl) + assert.Equal(s.T(), "started call", clientStartCallLogLine.msg) + _ = assertStandardFields(s.T(), logging.KindClientFieldValue, clientStartCallLogLine.fields, "Ping", interceptors.Unary) + + serverStartCallLogLine := lines[1] + assert.Equal(s.T(), logging.DEBUG, serverStartCallLogLine.lvl) + assert.Equal(s.T(), "started call", serverStartCallLogLine.msg) + _ = assertStandardFields(s.T(), logging.KindServerFieldValue, serverStartCallLogLine.fields, "Ping", interceptors.Unary) + + serverFinishCallLogLine := lines[2] + assert.Equal(s.T(), logging.DEBUG, serverFinishCallLogLine.lvl) + assert.Equal(s.T(), "finished call", serverFinishCallLogLine.msg) + serverFinishCallFields := assertStandardFields(s.T(), logging.KindServerFieldValue, serverFinishCallLogLine.fields, "Ping", interceptors.Unary) + serverFinishCallFields.AssertNextField(s.T(), "grpc.request.value", "something"). AssertNextFieldNotEmpty(s.T(), "peer.address"). AssertNextFieldNotEmpty(s.T(), "grpc.start_time"). AssertNextFieldNotEmpty(s.T(), "grpc.request.deadline"). AssertNextField(s.T(), "grpc.code", "OK"). AssertNextFieldNotEmpty(s.T(), "grpc.time_ms").AssertNoMoreTags(s.T()) - clientLogLine := lines[1] - assert.Equal(s.T(), logging.DEBUG, clientLogLine.lvl) - assert.Equal(s.T(), "finished client unary call", clientLogLine.msg) - clientFields := assertStandardFields(s.T(), logging.KindClientFieldValue, clientLogLine.fields, "Ping", interceptors.Unary) - clientFields.AssertNextFieldNotEmpty(s.T(), "grpc.start_time"). + clientFinishCallLogLine := lines[3] + assert.Equal(s.T(), logging.DEBUG, clientFinishCallLogLine.lvl) + assert.Equal(s.T(), "finished call", clientFinishCallLogLine.msg) + clientFinishCallFields := assertStandardFields(s.T(), logging.KindClientFieldValue, clientFinishCallLogLine.fields, "Ping", interceptors.Unary) + clientFinishCallFields.AssertNextFieldNotEmpty(s.T(), "grpc.start_time"). AssertNextFieldNotEmpty(s.T(), "grpc.request.deadline"). AssertNextField(s.T(), "grpc.code", "OK"). AssertNextFieldNotEmpty(s.T(), "grpc.time_ms").AssertNoMoreTags(s.T()) @@ -228,24 +238,34 @@ func (s *loggingClientServerSuite) TestPingList() { require.NoError(s.T(), err, "reading stream should not fail") } lines := s.logger.Lines() - require.Len(s.T(), lines, 2) - - serverLogLine := lines[0] - assert.Equal(s.T(), logging.DEBUG, serverLogLine.lvl) - assert.Equal(s.T(), "finished server server_stream call", serverLogLine.msg) - serverFields := assertStandardFields(s.T(), logging.KindServerFieldValue, serverLogLine.fields, "PingList", interceptors.ServerStream) - serverFields.AssertNextField(s.T(), "grpc.request.value", "something"). + require.Len(s.T(), lines, 4) + + serverStartCallLogLine := lines[1] + assert.Equal(s.T(), logging.DEBUG, serverStartCallLogLine.lvl) + assert.Equal(s.T(), "started call", serverStartCallLogLine.msg) + _ = assertStandardFields(s.T(), logging.KindServerFieldValue, serverStartCallLogLine.fields, "PingList", interceptors.ServerStream) + + clientStartCallLogLine := lines[0] + assert.Equal(s.T(), logging.DEBUG, clientStartCallLogLine.lvl) + assert.Equal(s.T(), "started call", clientStartCallLogLine.msg) + _ = assertStandardFields(s.T(), logging.KindClientFieldValue, clientStartCallLogLine.fields, "PingList", interceptors.ServerStream) + + serverFinishCallLogLine := lines[2] + assert.Equal(s.T(), logging.DEBUG, serverFinishCallLogLine.lvl) + assert.Equal(s.T(), "finished call", serverFinishCallLogLine.msg) + serverFinishCallFields := assertStandardFields(s.T(), logging.KindServerFieldValue, serverFinishCallLogLine.fields, "PingList", interceptors.ServerStream) + serverFinishCallFields.AssertNextField(s.T(), "grpc.request.value", "something"). AssertNextFieldNotEmpty(s.T(), "peer.address"). AssertNextFieldNotEmpty(s.T(), "grpc.start_time"). AssertNextFieldNotEmpty(s.T(), "grpc.request.deadline"). AssertNextField(s.T(), "grpc.code", "OK"). AssertNextFieldNotEmpty(s.T(), "grpc.time_ms").AssertNoMoreTags(s.T()) - clientLogLine := lines[1] - assert.Equal(s.T(), logging.DEBUG, clientLogLine.lvl) - assert.Equal(s.T(), "finished client server_stream call", clientLogLine.msg) - clientFields := assertStandardFields(s.T(), logging.KindClientFieldValue, clientLogLine.fields, "PingList", interceptors.ServerStream) - clientFields.AssertNextFieldNotEmpty(s.T(), "grpc.start_time"). + clientFinishCallLogLine := lines[3] + assert.Equal(s.T(), logging.DEBUG, clientFinishCallLogLine.lvl) + assert.Equal(s.T(), "finished call", clientFinishCallLogLine.msg) + clientFinishCallFields := assertStandardFields(s.T(), logging.KindClientFieldValue, clientFinishCallLogLine.fields, "PingList", interceptors.ServerStream) + clientFinishCallFields.AssertNextFieldNotEmpty(s.T(), "grpc.start_time"). AssertNextFieldNotEmpty(s.T(), "grpc.request.deadline"). AssertNextField(s.T(), "grpc.code", "OK"). AssertNextFieldNotEmpty(s.T(), "grpc.time_ms").AssertNoMoreTags(s.T()) @@ -285,28 +305,28 @@ func (s *loggingClientServerSuite) TestPingError_WithCustomLevels() { &testpb.PingRequest{Value: "something", ErrorCodeReturned: uint32(tcase.code)}) require.Error(t, err, "each call here must return an error") lines := s.logger.Lines() - require.Len(t, lines, 2) + require.Len(t, lines, 4) - serverLogLine := lines[0] - assert.Equal(t, tcase.level, serverLogLine.lvl) - assert.Equal(t, "finished server unary call", serverLogLine.msg) - serverFields := assertStandardFields(t, logging.KindServerFieldValue, serverLogLine.fields, "PingError", interceptors.Unary) - serverFields.AssertNextField(t, "grpc.request.value", "something"). + serverFinishCallLogLine := lines[2] + assert.Equal(t, tcase.level, serverFinishCallLogLine.lvl) + assert.Equal(t, "finished call", serverFinishCallLogLine.msg) + serverFinishCallFields := assertStandardFields(t, logging.KindServerFieldValue, serverFinishCallLogLine.fields, "PingError", interceptors.Unary) + serverFinishCallFields.AssertNextField(t, "grpc.request.value", "something"). AssertNextFieldNotEmpty(t, "peer.address"). AssertNextFieldNotEmpty(t, "grpc.start_time"). AssertNextFieldNotEmpty(t, "grpc.request.deadline"). AssertNextField(t, "grpc.code", tcase.code.String()). - AssertNextField(t, "error", fmt.Sprintf("rpc error: code = %s desc = Userspace error.", tcase.code.String())). + AssertNextField(t, "grpc.error", fmt.Sprintf("rpc error: code = %s desc = Userspace error.", tcase.code.String())). AssertNextFieldNotEmpty(t, "grpc.time_ms").AssertNoMoreTags(t) - clientLogLine := lines[1] - assert.Equal(t, tcase.level, clientLogLine.lvl) - assert.Equal(t, "finished client unary call", clientLogLine.msg) - clientFields := assertStandardFields(t, logging.KindClientFieldValue, clientLogLine.fields, "PingError", interceptors.Unary) - clientFields.AssertNextFieldNotEmpty(t, "grpc.start_time"). + clientFinishCallLogLine := lines[3] + assert.Equal(t, tcase.level, clientFinishCallLogLine.lvl) + assert.Equal(t, "finished call", clientFinishCallLogLine.msg) + clientFinishCallFields := assertStandardFields(t, logging.KindClientFieldValue, clientFinishCallLogLine.fields, "PingError", interceptors.Unary) + clientFinishCallFields.AssertNextFieldNotEmpty(t, "grpc.start_time"). AssertNextFieldNotEmpty(t, "grpc.request.deadline"). AssertNextField(t, "grpc.code", tcase.code.String()). - AssertNextField(t, "error", fmt.Sprintf("rpc error: code = %s desc = Userspace error.", tcase.code.String())). + AssertNextField(t, "grpc.error", fmt.Sprintf("rpc error: code = %s desc = Userspace error.", tcase.code.String())). AssertNextFieldNotEmpty(t, "grpc.time_ms").AssertNoMoreTags(t) }) } @@ -350,24 +370,34 @@ func (s *loggingCustomDurationSuite) TestPing_HasOverriddenDuration() { assert.NoError(s.T(), err, "there must be not be an on a successful call") lines := s.logger.Lines() - require.Len(s.T(), lines, 2) - - serverLogLine := lines[0] - assert.Equal(s.T(), logging.INFO, serverLogLine.lvl) - assert.Equal(s.T(), "finished server unary call", serverLogLine.msg) - serverFields := assertStandardFields(s.T(), logging.KindServerFieldValue, serverLogLine.fields, "Ping", interceptors.Unary) - serverFields.AssertNextField(s.T(), "grpc.request.value", "something"). + require.Len(s.T(), lines, 4) + + serverStartedCallLogLine := lines[1] + assert.Equal(s.T(), logging.INFO, serverStartedCallLogLine.lvl) + assert.Equal(s.T(), "started call", serverStartedCallLogLine.msg) + _ = assertStandardFields(s.T(), logging.KindServerFieldValue, serverStartedCallLogLine.fields, "Ping", interceptors.Unary) + + clientStartedCallLogLine := lines[0] + assert.Equal(s.T(), logging.DEBUG, clientStartedCallLogLine.lvl) + assert.Equal(s.T(), "started call", clientStartedCallLogLine.msg) + _ = assertStandardFields(s.T(), logging.KindClientFieldValue, clientStartedCallLogLine.fields, "Ping", interceptors.Unary) + + serverFinishCallLogLine := lines[2] + assert.Equal(s.T(), logging.INFO, serverFinishCallLogLine.lvl) + assert.Equal(s.T(), "finished call", serverFinishCallLogLine.msg) + serverFinishCallFields := assertStandardFields(s.T(), logging.KindServerFieldValue, serverFinishCallLogLine.fields, "Ping", interceptors.Unary) + serverFinishCallFields.AssertNextField(s.T(), "grpc.request.value", "something"). AssertNextFieldNotEmpty(s.T(), "peer.address"). AssertNextFieldNotEmpty(s.T(), "grpc.start_time"). AssertNextFieldNotEmpty(s.T(), "grpc.request.deadline"). AssertNextField(s.T(), "grpc.code", "OK"). AssertNextFieldNotEmpty(s.T(), "grpc.duration").AssertNoMoreTags(s.T()) - clientLogLine := lines[1] - assert.Equal(s.T(), logging.DEBUG, clientLogLine.lvl) - assert.Equal(s.T(), "finished client unary call", clientLogLine.msg) - clientFields := assertStandardFields(s.T(), logging.KindClientFieldValue, clientLogLine.fields, "Ping", interceptors.Unary) - clientFields.AssertNextFieldNotEmpty(s.T(), "grpc.start_time"). + clientFinishCallLogLine := lines[3] + assert.Equal(s.T(), logging.DEBUG, clientFinishCallLogLine.lvl) + assert.Equal(s.T(), "finished call", clientFinishCallLogLine.msg) + clientFinishCallFields := assertStandardFields(s.T(), logging.KindClientFieldValue, clientFinishCallLogLine.fields, "Ping", interceptors.Unary) + clientFinishCallFields.AssertNextFieldNotEmpty(s.T(), "grpc.start_time"). AssertNextFieldNotEmpty(s.T(), "grpc.request.deadline"). AssertNextField(s.T(), "grpc.code", "OK"). AssertNextFieldNotEmpty(s.T(), "grpc.duration").AssertNoMoreTags(s.T()) @@ -385,24 +415,34 @@ func (s *loggingCustomDurationSuite) TestPingList_HasOverriddenDuration() { } lines := s.logger.Lines() - require.Len(s.T(), lines, 2) - - serverLogLine := lines[0] - assert.Equal(s.T(), logging.INFO, serverLogLine.lvl) - assert.Equal(s.T(), "finished server server_stream call", serverLogLine.msg) - serverFields := assertStandardFields(s.T(), logging.KindServerFieldValue, serverLogLine.fields, "PingList", interceptors.ServerStream) - serverFields.AssertNextField(s.T(), "grpc.request.value", "something"). + require.Len(s.T(), lines, 4) + + serverStartedCallLogLine := lines[1] + assert.Equal(s.T(), logging.INFO, serverStartedCallLogLine.lvl) + assert.Equal(s.T(), "started call", serverStartedCallLogLine.msg) + _ = assertStandardFields(s.T(), logging.KindServerFieldValue, serverStartedCallLogLine.fields, "PingList", interceptors.ServerStream) + + clientStartedCallLogLine := lines[0] + assert.Equal(s.T(), logging.DEBUG, clientStartedCallLogLine.lvl) + assert.Equal(s.T(), "started call", clientStartedCallLogLine.msg) + _ = assertStandardFields(s.T(), logging.KindClientFieldValue, clientStartedCallLogLine.fields, "PingList", interceptors.ServerStream) + + serverFinishCallLogLine := lines[2] + assert.Equal(s.T(), logging.INFO, serverFinishCallLogLine.lvl) + assert.Equal(s.T(), "finished call", serverFinishCallLogLine.msg) + serverFinishCallFields := assertStandardFields(s.T(), logging.KindServerFieldValue, serverFinishCallLogLine.fields, "PingList", interceptors.ServerStream) + serverFinishCallFields.AssertNextField(s.T(), "grpc.request.value", "something"). AssertNextFieldNotEmpty(s.T(), "peer.address"). AssertNextFieldNotEmpty(s.T(), "grpc.start_time"). AssertNextFieldNotEmpty(s.T(), "grpc.request.deadline"). AssertNextField(s.T(), "grpc.code", "OK"). AssertNextFieldNotEmpty(s.T(), "grpc.duration").AssertNoMoreTags(s.T()) - clientLogLine := lines[1] - assert.Equal(s.T(), logging.DEBUG, clientLogLine.lvl) - assert.Equal(s.T(), "finished client server_stream call", clientLogLine.msg) - clientFields := assertStandardFields(s.T(), logging.KindClientFieldValue, clientLogLine.fields, "PingList", interceptors.ServerStream) - clientFields.AssertNextFieldNotEmpty(s.T(), "grpc.start_time"). + clientFinishCallLogLine := lines[3] + assert.Equal(s.T(), logging.DEBUG, clientFinishCallLogLine.lvl) + assert.Equal(s.T(), "finished call", clientFinishCallLogLine.msg) + clientFinishCallFields := assertStandardFields(s.T(), logging.KindClientFieldValue, clientFinishCallLogLine.fields, "PingList", interceptors.ServerStream) + clientFinishCallFields.AssertNextFieldNotEmpty(s.T(), "grpc.start_time"). AssertNextFieldNotEmpty(s.T(), "grpc.request.deadline"). AssertNextField(s.T(), "grpc.code", "OK"). AssertNextFieldNotEmpty(s.T(), "grpc.duration").AssertNoMoreTags(s.T()) @@ -417,11 +457,11 @@ func TestCustomDeciderSuite(t *testing.T) { t.Skip("Skipping due to json.RawMessage incompatibility with go1.7") return } - opts := logging.WithDecider(func(method string, err error) bool { - if err != nil && method == "/grpc_middleware.testpb.TestService/PingError" { - return true + opts := logging.WithDecider(func(method string) logging.Decision { + if method == "/grpc_middleware.testpb.TestService/PingError" { + return logging.LogStartAndFinishCall } - return false + return logging.NoLogCall }) s := &loggingCustomDeciderSuite{ @@ -463,28 +503,38 @@ func (s *loggingCustomDeciderSuite) TestPingError_HasCustomDecider() { require.Error(s.T(), err, "each call here must return an error") lines := s.logger.Lines() - require.Len(s.T(), lines, 2) - - serverLogLine := lines[0] - assert.Equal(s.T(), logging.INFO, serverLogLine.lvl) - assert.Equal(s.T(), "finished server unary call", serverLogLine.msg) - serverFields := assertStandardFields(s.T(), logging.KindServerFieldValue, serverLogLine.fields, "PingError", interceptors.Unary) - serverFields.AssertNextField(s.T(), "grpc.request.value", "something"). + require.Len(s.T(), lines, 4) + + serverStartedCallLogLine := lines[1] + assert.Equal(s.T(), logging.INFO, serverStartedCallLogLine.lvl) + assert.Equal(s.T(), "started call", serverStartedCallLogLine.msg) + _ = assertStandardFields(s.T(), logging.KindServerFieldValue, serverStartedCallLogLine.fields, "PingError", interceptors.Unary) + + clientStartedCallLogLine := lines[0] + assert.Equal(s.T(), logging.DEBUG, clientStartedCallLogLine.lvl) + assert.Equal(s.T(), "started call", clientStartedCallLogLine.msg) + _ = assertStandardFields(s.T(), logging.KindClientFieldValue, clientStartedCallLogLine.fields, "PingError", interceptors.Unary) + + serverFinishCallLogLine := lines[2] + assert.Equal(s.T(), logging.INFO, serverFinishCallLogLine.lvl) + assert.Equal(s.T(), "finished call", serverFinishCallLogLine.msg) + serverFinishCallFields := assertStandardFields(s.T(), logging.KindServerFieldValue, serverFinishCallLogLine.fields, "PingError", interceptors.Unary) + serverFinishCallFields.AssertNextField(s.T(), "grpc.request.value", "something"). AssertNextFieldNotEmpty(s.T(), "peer.address"). AssertNextFieldNotEmpty(s.T(), "grpc.start_time"). AssertNextFieldNotEmpty(s.T(), "grpc.request.deadline"). AssertNextField(s.T(), "grpc.code", "NotFound"). - AssertNextField(s.T(), "error", "rpc error: code = NotFound desc = Userspace error."). + AssertNextField(s.T(), "grpc.error", "rpc error: code = NotFound desc = Userspace error."). AssertNextFieldNotEmpty(s.T(), "grpc.time_ms").AssertNoMoreTags(s.T()) - clientLogLine := lines[1] - assert.Equal(s.T(), logging.DEBUG, clientLogLine.lvl) - assert.Equal(s.T(), "finished client unary call", clientLogLine.msg) - clientFields := assertStandardFields(s.T(), logging.KindClientFieldValue, clientLogLine.fields, "PingError", interceptors.Unary) - clientFields.AssertNextFieldNotEmpty(s.T(), "grpc.start_time"). + clientFinishCallLogLine := lines[3] + assert.Equal(s.T(), logging.DEBUG, clientFinishCallLogLine.lvl) + assert.Equal(s.T(), "finished call", clientFinishCallLogLine.msg) + clientFinishCallFields := assertStandardFields(s.T(), logging.KindClientFieldValue, clientFinishCallLogLine.fields, "PingError", interceptors.Unary) + clientFinishCallFields.AssertNextFieldNotEmpty(s.T(), "grpc.start_time"). AssertNextFieldNotEmpty(s.T(), "grpc.request.deadline"). AssertNextField(s.T(), "grpc.code", "NotFound"). - AssertNextField(s.T(), "error", "rpc error: code = NotFound desc = Userspace error."). + AssertNextField(s.T(), "grpc.error", "rpc error: code = NotFound desc = Userspace error."). AssertNextFieldNotEmpty(s.T(), "grpc.time_ms").AssertNoMoreTags(s.T()) } diff --git a/interceptors/logging/logging.go b/interceptors/logging/logging.go index 461310240..9f5f2346a 100644 --- a/interceptors/logging/logging.go +++ b/interceptors/logging/logging.go @@ -14,10 +14,23 @@ import ( "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors" ) +// Decision defines rules for enabling start and end of logging. +type Decision int + +const ( + // NoLogCall - Logging is disabled. + NoLogCall Decision = iota + // LogFinishCall - Only finish logs of request is enabled. + LogFinishCall + // LogStartAndFinishCall - Logging of start and end of request is enabled. + LogStartAndFinishCall +) + var ( // SystemTag is tag representing an event inside gRPC call. - SystemTag = []string{"system", "grpc"} - KindFieldKey = "kind" + SystemTag = []string{"protocol", "grpc"} + // ComponentFieldKey is a tag representing the client/server that is calling. + ComponentFieldKey = "grpc.component" KindServerFieldValue = "server" KindClientFieldValue = "client" ServiceFieldKey = "grpc.service" @@ -28,7 +41,7 @@ var ( func commonFields(kind string, typ interceptors.GRPCType, service string, method string) Fields { return Fields{ SystemTag[0], SystemTag[1], - KindFieldKey, kind, + ComponentFieldKey, kind, ServiceFieldKey, service, MethodFieldKey, method, MethodTypeFieldKey, string(typ), @@ -47,12 +60,12 @@ func DefaultErrorToCode(err error) codes.Code { } // Decider function defines rules for suppressing any interceptor logs -type Decider func(fullMethodName string, err error) bool +type Decider func(fullMethodName string) Decision // DefaultDeciderMethod is the default implementation of decider to see if you should log the call // by default this if always true so all calls are logged -func DefaultDeciderMethod(_ string, _ error) bool { - return true +func DefaultDeciderMethod(_ string) Decision { + return LogStartAndFinishCall } // ServerPayloadLoggingDecider is a user-provided function for deciding whether to log the server-side diff --git a/providers/kit/examples_test.go b/providers/kit/examples_test.go index 244bf9916..63facbeef 100644 --- a/providers/kit/examples_test.go +++ b/providers/kit/examples_test.go @@ -79,14 +79,13 @@ func ExampleWithDecider() { logger := log.NewNopLogger() // Shared options for the logger, with a custom decider that log everything except successful calls from "/blah.foo.healthcheck/Check" method. opts := []logging.Option{ - logging.WithDecider(func(methodFullName string, err error) bool { + logging.WithDecider(func(methodFullName string) logging.Decision { // will not log gRPC calls if it was a call to healthcheck and no error was raised - if err == nil && methodFullName == "/blah.foo.healthcheck/Check" { - return false + if methodFullName == "/blah.foo.healthcheck/Check" { + return logging.NoLogCall } - // by default you will log all calls - return true + return logging.LogStartAndFinishCall }), } // Create a server, make sure we put the tags context before everything else. diff --git a/providers/logrus/examples_test.go b/providers/logrus/examples_test.go index 9cd1d3903..bc03f4bc1 100644 --- a/providers/logrus/examples_test.go +++ b/providers/logrus/examples_test.go @@ -79,14 +79,14 @@ func ExampleWithDecider() { logger := logrus.New() // Shared options for the logger, with a custom decider that log everything except successful calls from "/blah.foo.healthcheck/Check" method. opts := []logging.Option{ - logging.WithDecider(func(methodFullName string, err error) bool { + logging.WithDecider(func(methodFullName string) logging.Decision { // will not log gRPC calls if it was a call to healthcheck and no error was raised - if err == nil && methodFullName == "/blah.foo.healthcheck/Check" { - return false + if methodFullName == "/blah.foo.healthcheck/Check" { + return logging.NoLogCall } // by default you will log all calls - return true + return logging.LogStartAndFinishCall }), } // Create a server, make sure we put the tags context before everything else. diff --git a/providers/zap/examples_test.go b/providers/zap/examples_test.go index 5c164fd7c..d17364a0e 100644 --- a/providers/zap/examples_test.go +++ b/providers/zap/examples_test.go @@ -79,14 +79,14 @@ func ExampleWithDecider() { logger := zap.NewNop() // Shared options for the logger, with a custom decider that log everything except successful calls from "/blah.foo.healthcheck/Check" method. opts := []logging.Option{ - logging.WithDecider(func(methodFullName string, err error) bool { + logging.WithDecider(func(methodFullName string) logging.Decision { // will not log gRPC calls if it was a call to healthcheck and no error was raised - if err == nil && methodFullName == "/blah.foo.healthcheck/Check" { - return false + if methodFullName == "/blah.foo.healthcheck/Check" { + return logging.NoLogCall } // by default you will log all calls - return true + return logging.LogStartAndFinishCall }), } // Create a server, make sure we put the tags context before everything else. diff --git a/providers/zerolog/examples_test.go b/providers/zerolog/examples_test.go index a812dc4d5..9e10383d7 100644 --- a/providers/zerolog/examples_test.go +++ b/providers/zerolog/examples_test.go @@ -81,14 +81,14 @@ func ExampleWithDecider() { // Shared options for the logger, with a custom decider that log everything except successful // calls from "/blah.foo.healthcheck/Check" method. opts := []logging.Option{ - logging.WithDecider(func(methodFullName string, err error) bool { + logging.WithDecider(func(methodFullName string) logging.Decision { // will not log gRPC calls if it was a call to healthcheck and no error was raised - if err == nil && methodFullName == "/blah.foo.healthcheck/Check" { - return false + if methodFullName == "/blah.foo.healthcheck/Check" { + return logging.NoLogCall } // by default you will log all calls - return true + return logging.LogStartAndFinishCall }), } // Create a server, make sure we put the tags context before everything else. From 7d39267e1db4b2cbf2deb9b303fcd96a5cb1cd45 Mon Sep 17 00:00:00 2001 From: Yash Sharma Date: Thu, 19 Nov 2020 17:21:04 +0530 Subject: [PATCH 07/27] Bug fix for data race (#354) * comment some tests and add a lock Signed-off-by: Yash Sharma * Added the latest version of grpc middleware Signed-off-by: Yash Sharma * Added the new version of middleware commit for importing the new API for logging in the example tests Signed-off-by: Yash Sharma * more changes Signed-off-by: Yash Sharma * Added some locks and checks Signed-off-by: Yash Sharma * added some changes as suggested by reviewer Signed-off-by: Yash Sharma * Extra changes Signed-off-by: Yash Sharma * Renamed the baseMockLogger to sharedResults and added some more locks Signed-off-by: Yash Sharma * Renamed the sharedResults to mockStdOutput and sorted the stdoutput slice so that even due to concurrency, the output remains in a fixed sorted order Signed-off-by: Yash Sharma --- interceptors/logging/interceptors_test.go | 83 +++++++++++++---------- interceptors/logging/payload_test.go | 3 +- providers/kit/go.mod | 2 +- providers/kit/go.sum | 3 + providers/logrus/go.mod | 2 +- providers/logrus/go.sum | 3 + providers/zap/go.mod | 2 +- providers/zap/go.sum | 3 + providers/zerolog/go.mod | 2 +- providers/zerolog/go.sum | 3 + 10 files changed, 64 insertions(+), 42 deletions(-) diff --git a/interceptors/logging/interceptors_test.go b/interceptors/logging/interceptors_test.go index d1f15f28b..a4526c143 100644 --- a/interceptors/logging/interceptors_test.go +++ b/interceptors/logging/interceptors_test.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "runtime" + "sort" "strings" "sync" "testing" @@ -66,9 +67,6 @@ func (l LogLines) Less(i, j int) bool { if l[i].msg != l[j].msg { return l[i].msg < l[j].msg } - //_ , aok = l[i].fields["grpc.response.content"] - //_ ,baok = l[i].fields["grpc.response.content"] - //if // We want to sort by counter which in string, so we need to parse it. a := testpb.PingResponse{} @@ -88,47 +86,51 @@ func (l LogLines) Swap(i, j int) { l[i], l[j] = l[j], l[i] } -type baseMockLogger struct { - // Shared. It's slice on purpose to find potential duplicates. - lines []LogLine +type mockStdOutput struct { + // All the output of the mockLogger is shared in a single + // shared slice. Behaves like a stdout which contains all + // the log lines. + lines LogLines m sync.Mutex } -func (l *baseMockLogger) Add(line LogLine) { +func (l *mockStdOutput) Lines() LogLines { l.m.Lock() defer l.m.Unlock() - l.lines = append(l.lines, line) -} + retLines := make(LogLines, len(l.lines)) + copy(retLines, l.lines) -func (l *baseMockLogger) Lines() []LogLine { - l.m.Lock() - defer l.m.Unlock() - - return l.lines + return retLines } type mockLogger struct { - *baseMockLogger + *mockStdOutput fields logging.Fields } func (l *mockLogger) Log(lvl logging.Level, msg string) { + l.m.Lock() + defer l.m.Unlock() + line := LogLine{ lvl: lvl, msg: msg, fields: map[string]string{}, } + for i := 0; i < len(l.fields); i += 2 { line.fields[l.fields[i]] = l.fields[i+1] } - l.Add(line) + l.lines = append(l.lines, line) } func (l *mockLogger) With(fields ...string) logging.Logger { - // Append twice to copy slice, so we don't reuse array. - return &mockLogger{baseMockLogger: l.baseMockLogger, fields: append(append(logging.Fields{}, l.fields...), fields...)} + l.m.Lock() + defer l.m.Unlock() + + return &mockLogger{mockStdOutput: l.mockStdOutput, fields: append(append(logging.Fields{}, l.fields...), fields...)} } type baseLoggingSuite struct { @@ -161,7 +163,7 @@ func TestSuite(t *testing.T) { s := &loggingClientServerSuite{ &baseLoggingSuite{ - logger: &mockLogger{baseMockLogger: &baseMockLogger{}}, + logger: &mockLogger{mockStdOutput: &mockStdOutput{}}, InterceptorTestSuite: &grpctesting.InterceptorTestSuite{ TestService: &grpctesting.TestPingService{T: t}, }, @@ -193,15 +195,17 @@ func assertStandardFields(t *testing.T, kind string, f testDisposableFields, met func (s *loggingClientServerSuite) TestPing() { _, err := s.Client.Ping(s.SimpleCtx(), goodPing) assert.NoError(s.T(), err, "there must be not be an on a successful call") + lines := s.logger.Lines() + sort.Sort(lines) require.Len(s.T(), lines, 4) - clientStartCallLogLine := lines[0] + clientStartCallLogLine := lines[1] assert.Equal(s.T(), logging.DEBUG, clientStartCallLogLine.lvl) assert.Equal(s.T(), "started call", clientStartCallLogLine.msg) _ = assertStandardFields(s.T(), logging.KindClientFieldValue, clientStartCallLogLine.fields, "Ping", interceptors.Unary) - serverStartCallLogLine := lines[1] + serverStartCallLogLine := lines[3] assert.Equal(s.T(), logging.DEBUG, serverStartCallLogLine.lvl) assert.Equal(s.T(), "started call", serverStartCallLogLine.msg) _ = assertStandardFields(s.T(), logging.KindServerFieldValue, serverStartCallLogLine.fields, "Ping", interceptors.Unary) @@ -217,7 +221,7 @@ func (s *loggingClientServerSuite) TestPing() { AssertNextField(s.T(), "grpc.code", "OK"). AssertNextFieldNotEmpty(s.T(), "grpc.time_ms").AssertNoMoreTags(s.T()) - clientFinishCallLogLine := lines[3] + clientFinishCallLogLine := lines[0] assert.Equal(s.T(), logging.DEBUG, clientFinishCallLogLine.lvl) assert.Equal(s.T(), "finished call", clientFinishCallLogLine.msg) clientFinishCallFields := assertStandardFields(s.T(), logging.KindClientFieldValue, clientFinishCallLogLine.fields, "Ping", interceptors.Unary) @@ -238,14 +242,15 @@ func (s *loggingClientServerSuite) TestPingList() { require.NoError(s.T(), err, "reading stream should not fail") } lines := s.logger.Lines() + sort.Sort(lines) require.Len(s.T(), lines, 4) - serverStartCallLogLine := lines[1] + serverStartCallLogLine := lines[3] assert.Equal(s.T(), logging.DEBUG, serverStartCallLogLine.lvl) assert.Equal(s.T(), "started call", serverStartCallLogLine.msg) _ = assertStandardFields(s.T(), logging.KindServerFieldValue, serverStartCallLogLine.fields, "PingList", interceptors.ServerStream) - clientStartCallLogLine := lines[0] + clientStartCallLogLine := lines[1] assert.Equal(s.T(), logging.DEBUG, clientStartCallLogLine.lvl) assert.Equal(s.T(), "started call", clientStartCallLogLine.msg) _ = assertStandardFields(s.T(), logging.KindClientFieldValue, clientStartCallLogLine.fields, "PingList", interceptors.ServerStream) @@ -261,7 +266,7 @@ func (s *loggingClientServerSuite) TestPingList() { AssertNextField(s.T(), "grpc.code", "OK"). AssertNextFieldNotEmpty(s.T(), "grpc.time_ms").AssertNoMoreTags(s.T()) - clientFinishCallLogLine := lines[3] + clientFinishCallLogLine := lines[0] assert.Equal(s.T(), logging.DEBUG, clientFinishCallLogLine.lvl) assert.Equal(s.T(), "finished call", clientFinishCallLogLine.msg) clientFinishCallFields := assertStandardFields(s.T(), logging.KindClientFieldValue, clientFinishCallLogLine.fields, "PingList", interceptors.ServerStream) @@ -305,6 +310,7 @@ func (s *loggingClientServerSuite) TestPingError_WithCustomLevels() { &testpb.PingRequest{Value: "something", ErrorCodeReturned: uint32(tcase.code)}) require.Error(t, err, "each call here must return an error") lines := s.logger.Lines() + sort.Sort(lines) require.Len(t, lines, 4) serverFinishCallLogLine := lines[2] @@ -319,7 +325,7 @@ func (s *loggingClientServerSuite) TestPingError_WithCustomLevels() { AssertNextField(t, "grpc.error", fmt.Sprintf("rpc error: code = %s desc = Userspace error.", tcase.code.String())). AssertNextFieldNotEmpty(t, "grpc.time_ms").AssertNoMoreTags(t) - clientFinishCallLogLine := lines[3] + clientFinishCallLogLine := lines[0] assert.Equal(t, tcase.level, clientFinishCallLogLine.lvl) assert.Equal(t, "finished call", clientFinishCallLogLine.msg) clientFinishCallFields := assertStandardFields(t, logging.KindClientFieldValue, clientFinishCallLogLine.fields, "PingError", interceptors.Unary) @@ -344,7 +350,7 @@ func TestCustomDurationSuite(t *testing.T) { s := &loggingCustomDurationSuite{ baseLoggingSuite: &baseLoggingSuite{ - logger: &mockLogger{baseMockLogger: &baseMockLogger{}}, + logger: &mockLogger{mockStdOutput: &mockStdOutput{}}, InterceptorTestSuite: &grpctesting.InterceptorTestSuite{ TestService: &grpctesting.TestPingService{T: t}, }, @@ -370,14 +376,15 @@ func (s *loggingCustomDurationSuite) TestPing_HasOverriddenDuration() { assert.NoError(s.T(), err, "there must be not be an on a successful call") lines := s.logger.Lines() + sort.Sort(lines) require.Len(s.T(), lines, 4) - serverStartedCallLogLine := lines[1] + serverStartedCallLogLine := lines[3] assert.Equal(s.T(), logging.INFO, serverStartedCallLogLine.lvl) assert.Equal(s.T(), "started call", serverStartedCallLogLine.msg) _ = assertStandardFields(s.T(), logging.KindServerFieldValue, serverStartedCallLogLine.fields, "Ping", interceptors.Unary) - clientStartedCallLogLine := lines[0] + clientStartedCallLogLine := lines[1] assert.Equal(s.T(), logging.DEBUG, clientStartedCallLogLine.lvl) assert.Equal(s.T(), "started call", clientStartedCallLogLine.msg) _ = assertStandardFields(s.T(), logging.KindClientFieldValue, clientStartedCallLogLine.fields, "Ping", interceptors.Unary) @@ -393,7 +400,7 @@ func (s *loggingCustomDurationSuite) TestPing_HasOverriddenDuration() { AssertNextField(s.T(), "grpc.code", "OK"). AssertNextFieldNotEmpty(s.T(), "grpc.duration").AssertNoMoreTags(s.T()) - clientFinishCallLogLine := lines[3] + clientFinishCallLogLine := lines[0] assert.Equal(s.T(), logging.DEBUG, clientFinishCallLogLine.lvl) assert.Equal(s.T(), "finished call", clientFinishCallLogLine.msg) clientFinishCallFields := assertStandardFields(s.T(), logging.KindClientFieldValue, clientFinishCallLogLine.fields, "Ping", interceptors.Unary) @@ -415,14 +422,15 @@ func (s *loggingCustomDurationSuite) TestPingList_HasOverriddenDuration() { } lines := s.logger.Lines() + sort.Sort(lines) require.Len(s.T(), lines, 4) - serverStartedCallLogLine := lines[1] + serverStartedCallLogLine := lines[3] assert.Equal(s.T(), logging.INFO, serverStartedCallLogLine.lvl) assert.Equal(s.T(), "started call", serverStartedCallLogLine.msg) _ = assertStandardFields(s.T(), logging.KindServerFieldValue, serverStartedCallLogLine.fields, "PingList", interceptors.ServerStream) - clientStartedCallLogLine := lines[0] + clientStartedCallLogLine := lines[1] assert.Equal(s.T(), logging.DEBUG, clientStartedCallLogLine.lvl) assert.Equal(s.T(), "started call", clientStartedCallLogLine.msg) _ = assertStandardFields(s.T(), logging.KindClientFieldValue, clientStartedCallLogLine.fields, "PingList", interceptors.ServerStream) @@ -438,7 +446,7 @@ func (s *loggingCustomDurationSuite) TestPingList_HasOverriddenDuration() { AssertNextField(s.T(), "grpc.code", "OK"). AssertNextFieldNotEmpty(s.T(), "grpc.duration").AssertNoMoreTags(s.T()) - clientFinishCallLogLine := lines[3] + clientFinishCallLogLine := lines[0] assert.Equal(s.T(), logging.DEBUG, clientFinishCallLogLine.lvl) assert.Equal(s.T(), "finished call", clientFinishCallLogLine.msg) clientFinishCallFields := assertStandardFields(s.T(), logging.KindClientFieldValue, clientFinishCallLogLine.fields, "PingList", interceptors.ServerStream) @@ -466,7 +474,7 @@ func TestCustomDeciderSuite(t *testing.T) { s := &loggingCustomDeciderSuite{ baseLoggingSuite: &baseLoggingSuite{ - logger: &mockLogger{baseMockLogger: &baseMockLogger{}}, + logger: &mockLogger{mockStdOutput: &mockStdOutput{}}, InterceptorTestSuite: &grpctesting.InterceptorTestSuite{ TestService: &grpctesting.TestPingService{T: t}, }, @@ -503,14 +511,15 @@ func (s *loggingCustomDeciderSuite) TestPingError_HasCustomDecider() { require.Error(s.T(), err, "each call here must return an error") lines := s.logger.Lines() + sort.Sort(lines) require.Len(s.T(), lines, 4) - serverStartedCallLogLine := lines[1] + serverStartedCallLogLine := lines[3] assert.Equal(s.T(), logging.INFO, serverStartedCallLogLine.lvl) assert.Equal(s.T(), "started call", serverStartedCallLogLine.msg) _ = assertStandardFields(s.T(), logging.KindServerFieldValue, serverStartedCallLogLine.fields, "PingError", interceptors.Unary) - clientStartedCallLogLine := lines[0] + clientStartedCallLogLine := lines[1] assert.Equal(s.T(), logging.DEBUG, clientStartedCallLogLine.lvl) assert.Equal(s.T(), "started call", clientStartedCallLogLine.msg) _ = assertStandardFields(s.T(), logging.KindClientFieldValue, clientStartedCallLogLine.fields, "PingError", interceptors.Unary) @@ -527,7 +536,7 @@ func (s *loggingCustomDeciderSuite) TestPingError_HasCustomDecider() { AssertNextField(s.T(), "grpc.error", "rpc error: code = NotFound desc = Userspace error."). AssertNextFieldNotEmpty(s.T(), "grpc.time_ms").AssertNoMoreTags(s.T()) - clientFinishCallLogLine := lines[3] + clientFinishCallLogLine := lines[0] assert.Equal(s.T(), logging.DEBUG, clientFinishCallLogLine.lvl) assert.Equal(s.T(), "finished call", clientFinishCallLogLine.msg) clientFinishCallFields := assertStandardFields(s.T(), logging.KindClientFieldValue, clientFinishCallLogLine.fields, "PingError", interceptors.Unary) diff --git a/interceptors/logging/payload_test.go b/interceptors/logging/payload_test.go index 1acdc0153..e2d24c859 100644 --- a/interceptors/logging/payload_test.go +++ b/interceptors/logging/payload_test.go @@ -36,7 +36,7 @@ func TestPayloadSuite(t *testing.T) { s := &loggingPayloadSuite{ baseLoggingSuite: &baseLoggingSuite{ - logger: &mockLogger{baseMockLogger: &baseMockLogger{}}, + logger: &mockLogger{mockStdOutput: &mockStdOutput{}}, InterceptorTestSuite: &grpctesting.InterceptorTestSuite{ TestService: &grpctesting.TestPingService{T: t}, }, @@ -136,6 +136,7 @@ func (s *loggingPayloadSuite) TestPingError_LogsOnlyRequestsOnError() { require.Error(s.T(), err, "there must be an error on an unsuccessful call") lines := s.logger.Lines() + sort.Sort(lines) require.Len(s.T(), lines, 2) // Only client & server requests. clientRequestLogLine := lines[0] diff --git a/providers/kit/go.mod b/providers/kit/go.mod index 3a766d76f..046f207a6 100644 --- a/providers/kit/go.mod +++ b/providers/kit/go.mod @@ -4,6 +4,6 @@ go 1.14 require ( github.com/go-kit/kit v0.10.0 - github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-20200501113911-9a95f0fdbfea + github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20201002093600-73cf2ae9d891 google.golang.org/grpc v1.26.0 ) diff --git a/providers/kit/go.sum b/providers/kit/go.sum index f57c555bf..c139da7d4 100644 --- a/providers/kit/go.sum +++ b/providers/kit/go.sum @@ -98,6 +98,8 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-20200501113911-9a95f0fdbfea h1:1Tk1IbruXbunEnaIZEFb+Hpv9BIZti3OxKwKn5wWyKk= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-20200501113911-9a95f0fdbfea/go.mod h1:GugMBs30ZSAkckqXEAIEGyYdDH6EgqowG8ppA3Zt+AY= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20201002093600-73cf2ae9d891 h1:2F7/en805byWQR92etfFjOqtRtWsUu09R7wm6LtlHEw= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20201002093600-73cf2ae9d891/go.mod h1:GhphxcdlaRyAuBSvo6rV71BvQcvB/vuX8ugCyybuS2k= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= @@ -191,6 +193,7 @@ github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0 github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= diff --git a/providers/logrus/go.mod b/providers/logrus/go.mod index 7d99f1fdc..fb21909c9 100644 --- a/providers/logrus/go.mod +++ b/providers/logrus/go.mod @@ -3,7 +3,7 @@ module github.com/grpc-ecosystem/go-grpc-middleware/providers/logrus/v2 go 1.14 require ( - github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-20200501113911-9a95f0fdbfea + github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20201002093600-73cf2ae9d891 github.com/sirupsen/logrus v1.5.0 google.golang.org/grpc v1.19.0 ) diff --git a/providers/logrus/go.sum b/providers/logrus/go.sum index fbad7081b..b0cb2e848 100644 --- a/providers/logrus/go.sum +++ b/providers/logrus/go.sum @@ -14,11 +14,14 @@ github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-20200501113911-9a95f0fdbfea h1:1Tk1IbruXbunEnaIZEFb+Hpv9BIZti3OxKwKn5wWyKk= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-20200501113911-9a95f0fdbfea/go.mod h1:GugMBs30ZSAkckqXEAIEGyYdDH6EgqowG8ppA3Zt+AY= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20201002093600-73cf2ae9d891 h1:2F7/en805byWQR92etfFjOqtRtWsUu09R7wm6LtlHEw= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20201002093600-73cf2ae9d891/go.mod h1:GhphxcdlaRyAuBSvo6rV71BvQcvB/vuX8ugCyybuS2k= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/sirupsen/logrus v1.5.0 h1:1N5EYkVAPEywqZRJd7cwnRtCb6xJx7NH3T3WUTF980Q= diff --git a/providers/zap/go.mod b/providers/zap/go.mod index 604d03952..e3cde6c07 100644 --- a/providers/zap/go.mod +++ b/providers/zap/go.mod @@ -3,7 +3,7 @@ module github.com/grpc-ecosystem/go-grpc-middleware/providers/zap/v2 go 1.14 require ( - github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-20200501113911-9a95f0fdbfea + github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20201002093600-73cf2ae9d891 go.uber.org/zap v1.15.0 google.golang.org/grpc v1.19.0 ) diff --git a/providers/zap/go.sum b/providers/zap/go.sum index 6048ee1b4..943c5a98d 100644 --- a/providers/zap/go.sum +++ b/providers/zap/go.sum @@ -16,6 +16,8 @@ github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-20200501113911-9a95f0fdbfea h1:1Tk1IbruXbunEnaIZEFb+Hpv9BIZti3OxKwKn5wWyKk= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-20200501113911-9a95f0fdbfea/go.mod h1:GugMBs30ZSAkckqXEAIEGyYdDH6EgqowG8ppA3Zt+AY= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20201002093600-73cf2ae9d891 h1:2F7/en805byWQR92etfFjOqtRtWsUu09R7wm6LtlHEw= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20201002093600-73cf2ae9d891/go.mod h1:GhphxcdlaRyAuBSvo6rV71BvQcvB/vuX8ugCyybuS2k= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= @@ -26,6 +28,7 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= diff --git a/providers/zerolog/go.mod b/providers/zerolog/go.mod index 7aa781af8..2dba6ac32 100644 --- a/providers/zerolog/go.mod +++ b/providers/zerolog/go.mod @@ -3,7 +3,7 @@ module github.com/grpc-ecosystem/go-grpc-middleware/providers/zerolog/v2 go 1.14 require ( - github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-20200501113911-9a95f0fdbfea + github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20201002093600-73cf2ae9d891 github.com/rs/zerolog v1.19.0 google.golang.org/grpc v1.19.0 ) diff --git a/providers/zerolog/go.sum b/providers/zerolog/go.sum index a23fc41a7..98e99c8e9 100644 --- a/providers/zerolog/go.sum +++ b/providers/zerolog/go.sum @@ -14,10 +14,13 @@ github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-20200501113911-9a95f0fdbfea h1:1Tk1IbruXbunEnaIZEFb+Hpv9BIZti3OxKwKn5wWyKk= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-20200501113911-9a95f0fdbfea/go.mod h1:GugMBs30ZSAkckqXEAIEGyYdDH6EgqowG8ppA3Zt+AY= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20201002093600-73cf2ae9d891 h1:2F7/en805byWQR92etfFjOqtRtWsUu09R7wm6LtlHEw= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20201002093600-73cf2ae9d891/go.mod h1:GhphxcdlaRyAuBSvo6rV71BvQcvB/vuX8ugCyybuS2k= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= From 38f54d9b88d36b4d94c4a4e8712191a3bed06fbb Mon Sep 17 00:00:00 2001 From: Xiao Xin Date: Sat, 28 Nov 2020 04:09:16 -0800 Subject: [PATCH 08/27] make ratelimit interface context aware (#367) * make ratelimit interface context aware. * cleanup ratelimit testcases --- interceptors/ratelimit/examples_test.go | 4 +- interceptors/ratelimit/ratelimit.go | 6 +- interceptors/ratelimit/ratelimit_test.go | 71 +++++++++++++++--------- 3 files changed, 51 insertions(+), 30 deletions(-) diff --git a/interceptors/ratelimit/examples_test.go b/interceptors/ratelimit/examples_test.go index ac734eed6..9b73fabeb 100644 --- a/interceptors/ratelimit/examples_test.go +++ b/interceptors/ratelimit/examples_test.go @@ -1,6 +1,8 @@ package ratelimit_test import ( + "context" + "google.golang.org/grpc" middleware "github.com/grpc-ecosystem/go-grpc-middleware/v2" @@ -11,7 +13,7 @@ import ( // It does not limit any request because Limit function always returns false. type alwaysPassLimiter struct{} -func (*alwaysPassLimiter) Limit() bool { +func (*alwaysPassLimiter) Limit(_ context.Context) bool { return false } diff --git a/interceptors/ratelimit/ratelimit.go b/interceptors/ratelimit/ratelimit.go index 0a794e77d..afc843106 100644 --- a/interceptors/ratelimit/ratelimit.go +++ b/interceptors/ratelimit/ratelimit.go @@ -12,13 +12,13 @@ import ( // If Limit function return true, the request will be rejected. // Otherwise, the request will pass. type Limiter interface { - Limit() bool + Limit(ctx context.Context) bool } // UnaryServerInterceptor returns a new unary server interceptors that performs request rate limiting. func UnaryServerInterceptor(limiter Limiter) grpc.UnaryServerInterceptor { return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { - if limiter.Limit() { + if limiter.Limit(ctx) { return nil, status.Errorf(codes.ResourceExhausted, "%s is rejected by grpc_ratelimit middleware, please retry later.", info.FullMethod) } return handler(ctx, req) @@ -28,7 +28,7 @@ func UnaryServerInterceptor(limiter Limiter) grpc.UnaryServerInterceptor { // StreamServerInterceptor returns a new stream server interceptor that performs rate limiting on the request. func StreamServerInterceptor(limiter Limiter) grpc.StreamServerInterceptor { return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { - if limiter.Limit() { + if limiter.Limit(stream.Context()) { return status.Errorf(codes.ResourceExhausted, "%s is rejected by grpc_ratelimit middleware, please retry later.", info.FullMethod) } return handler(srv, stream) diff --git a/interceptors/ratelimit/ratelimit_test.go b/interceptors/ratelimit/ratelimit_test.go index d0aea9d70..019f0a5de 100644 --- a/interceptors/ratelimit/ratelimit_test.go +++ b/interceptors/ratelimit/ratelimit_test.go @@ -11,64 +11,83 @@ import ( const errMsgFake = "fake error" -type mockPassLimiter struct{} +var ctxLimitKey = struct{}{} -func (*mockPassLimiter) Limit() bool { - return false +type mockGRPCServerStream struct { + grpc.ServerStream + + ctx context.Context } -func TestUnaryServerInterceptor_RateLimitPass(t *testing.T) { - interceptor := UnaryServerInterceptor(&mockPassLimiter{}) - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return nil, errors.New(errMsgFake) - } - info := &grpc.UnaryServerInfo{ - FullMethod: "FakeMethod", - } - req, err := interceptor(nil, nil, info, handler) - assert.Nil(t, req) - assert.EqualError(t, err, errMsgFake) +func (m *mockGRPCServerStream) Context() context.Context { + return m.ctx } -type mockFailLimiter struct{} +type mockContextBasedLimiter struct{} -func (*mockFailLimiter) Limit() bool { - return true +func (*mockContextBasedLimiter) Limit(ctx context.Context) bool { + l, ok := ctx.Value(ctxLimitKey).(bool) + return ok && l } -func TestUnaryServerInterceptor_RateLimitFail(t *testing.T) { - interceptor := UnaryServerInterceptor(&mockFailLimiter{}) +func TestUnaryServerInterceptor_RateLimitPass(t *testing.T) { + limiter := new(mockContextBasedLimiter) + ctx := context.WithValue(context.Background(), ctxLimitKey, false) + + interceptor := UnaryServerInterceptor(limiter) handler := func(ctx context.Context, req interface{}) (interface{}, error) { return nil, errors.New(errMsgFake) } info := &grpc.UnaryServerInfo{ FullMethod: "FakeMethod", } - req, err := interceptor(nil, nil, info, handler) - assert.Nil(t, req) - assert.EqualError(t, err, "rpc error: code = ResourceExhausted desc = FakeMethod is rejected by grpc_ratelimit middleware, please retry later.") + resp, err := interceptor(ctx, nil, info, handler) + assert.Nil(t, resp) + assert.EqualError(t, err, errMsgFake) } func TestStreamServerInterceptor_RateLimitPass(t *testing.T) { - interceptor := StreamServerInterceptor(&mockPassLimiter{}) + limiter := new(mockContextBasedLimiter) + ctx := context.WithValue(context.Background(), ctxLimitKey, false) + + interceptor := StreamServerInterceptor(limiter) handler := func(srv interface{}, stream grpc.ServerStream) error { return errors.New(errMsgFake) } info := &grpc.StreamServerInfo{ FullMethod: "FakeMethod", } - err := interceptor(nil, nil, info, handler) + err := interceptor(nil, &mockGRPCServerStream{ctx: ctx}, info, handler) assert.EqualError(t, err, errMsgFake) } +func TestUnaryServerInterceptor_RateLimitFail(t *testing.T) { + limiter := new(mockContextBasedLimiter) + ctx := context.WithValue(context.Background(), ctxLimitKey, true) + + interceptor := UnaryServerInterceptor(limiter) + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return nil, errors.New(errMsgFake) + } + info := &grpc.UnaryServerInfo{ + FullMethod: "FakeMethod", + } + resp, err := interceptor(ctx, nil, info, handler) + assert.Nil(t, resp) + assert.EqualError(t, err, "rpc error: code = ResourceExhausted desc = FakeMethod is rejected by grpc_ratelimit middleware, please retry later.") +} + func TestStreamServerInterceptor_RateLimitFail(t *testing.T) { - interceptor := StreamServerInterceptor(&mockFailLimiter{}) + limiter := new(mockContextBasedLimiter) + ctx := context.WithValue(context.Background(), ctxLimitKey, true) + + interceptor := StreamServerInterceptor(limiter) handler := func(srv interface{}, stream grpc.ServerStream) error { return errors.New(errMsgFake) } info := &grpc.StreamServerInfo{ FullMethod: "FakeMethod", } - err := interceptor(nil, nil, info, handler) + err := interceptor(nil, &mockGRPCServerStream{ctx: ctx}, info, handler) assert.EqualError(t, err, "rpc error: code = ResourceExhausted desc = FakeMethod is rejected by grpc_ratelimit middleware, please retry later.") } From 9f6bf00c00a7d2eba3a6808c96fb798ab0b3c3ad Mon Sep 17 00:00:00 2001 From: Yash Sharma Date: Mon, 7 Dec 2020 21:04:54 +0530 Subject: [PATCH 09/27] Added an error param for decider method (#372) Signed-off-by: Yash Sharma --- interceptors/logging/interceptors.go | 6 +++--- interceptors/logging/interceptors_test.go | 2 +- interceptors/logging/logging.go | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/interceptors/logging/interceptors.go b/interceptors/logging/interceptors.go index 6d170270b..654223f2a 100644 --- a/interceptors/logging/interceptors.go +++ b/interceptors/logging/interceptors.go @@ -42,7 +42,7 @@ func (c *reporter) logMessage(logger Logger, err error, msg string, duration tim } func (c *reporter) PostCall(err error, duration time.Duration) { - switch c.opts.shouldLog(interceptors.FullMethod(c.service, c.method)) { + switch c.opts.shouldLog(interceptors.FullMethod(c.service, c.method), err) { case LogFinishCall, LogStartAndFinishCall: if err == io.EOF { err = nil @@ -57,7 +57,7 @@ func (c *reporter) PostMsgSend(_ interface{}, err error, duration time.Duration) if c.startCallLogged { return } - switch c.opts.shouldLog(interceptors.FullMethod(c.service, c.method)) { + switch c.opts.shouldLog(interceptors.FullMethod(c.service, c.method), err) { case LogStartAndFinishCall: c.startCallLogged = true c.logMessage(c.logger, err, "started call", duration) @@ -68,7 +68,7 @@ func (c *reporter) PostMsgReceive(_ interface{}, err error, duration time.Durati if c.startCallLogged { return } - switch c.opts.shouldLog(interceptors.FullMethod(c.service, c.method)) { + switch c.opts.shouldLog(interceptors.FullMethod(c.service, c.method), err) { case LogStartAndFinishCall: c.startCallLogged = true c.logMessage(c.logger, err, "started call", duration) diff --git a/interceptors/logging/interceptors_test.go b/interceptors/logging/interceptors_test.go index a4526c143..9cd0a5740 100644 --- a/interceptors/logging/interceptors_test.go +++ b/interceptors/logging/interceptors_test.go @@ -465,7 +465,7 @@ func TestCustomDeciderSuite(t *testing.T) { t.Skip("Skipping due to json.RawMessage incompatibility with go1.7") return } - opts := logging.WithDecider(func(method string) logging.Decision { + opts := logging.WithDecider(func(method string, _ error) logging.Decision { if method == "/grpc_middleware.testpb.TestService/PingError" { return logging.LogStartAndFinishCall } diff --git a/interceptors/logging/logging.go b/interceptors/logging/logging.go index 9f5f2346a..67d6861bd 100644 --- a/interceptors/logging/logging.go +++ b/interceptors/logging/logging.go @@ -60,11 +60,11 @@ func DefaultErrorToCode(err error) codes.Code { } // Decider function defines rules for suppressing any interceptor logs -type Decider func(fullMethodName string) Decision +type Decider func(fullMethodName string, err error) Decision // DefaultDeciderMethod is the default implementation of decider to see if you should log the call // by default this if always true so all calls are logged -func DefaultDeciderMethod(_ string) Decision { +func DefaultDeciderMethod(_ string, _ error) Decision { return LogStartAndFinishCall } From 08b17eb52c1fcbd6875f94119dde3bc6d662c60e Mon Sep 17 00:00:00 2001 From: Sam Xie Date: Thu, 31 Dec 2020 00:37:48 +0800 Subject: [PATCH 10/27] [v2] Add skip interceptor (#364) * Export `SplitMethodName` and `StreamRPCType` function * Add skip interceptor * Fix lint * Apply suggestions from code review Co-authored-by: Bartlomiej Plotka * Use allowlist * Add skip interceptor into README Co-authored-by: Bartlomiej Plotka --- README.md | 3 + interceptors/reporter.go | 4 +- interceptors/server.go | 4 +- interceptors/skip/doc.go | 6 + interceptors/skip/examples_test.go | 39 +++++ interceptors/skip/interceptor.go | 43 ++++++ interceptors/skip/interceptor_test.go | 194 ++++++++++++++++++++++++ interceptors/tracing/id_extract_test.go | 6 +- 8 files changed, 293 insertions(+), 6 deletions(-) create mode 100644 interceptors/skip/doc.go create mode 100644 interceptors/skip/examples_test.go create mode 100644 interceptors/skip/interceptor.go create mode 100644 interceptors/skip/interceptor_test.go diff --git a/README.md b/README.md index a88372b33..fc293af27 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,9 @@ myServer := grpc.NewServer( * [`recovery`](interceptors/recovery) - turn panics into gRPC errors * [`ratelimit`](interceptors/ratelimit) - grpc rate limiting by your own limiter +#### Utility + * [`skip`](interceptors/skip) - allow users to skip interceptors in certain condition. + ## Status diff --git a/interceptors/reporter.go b/interceptors/reporter.go index 17c9d6102..210134e83 100644 --- a/interceptors/reporter.go +++ b/interceptors/reporter.go @@ -30,7 +30,7 @@ var ( } ) -func splitMethodName(fullMethod string) (string, string) { +func SplitMethodName(fullMethod string) (string, string) { fullMethod = strings.TrimPrefix(fullMethod, "/") // remove leading slash if i := strings.Index(fullMethod, "/"); i >= 0 { return fullMethod[:i], fullMethod[i+1:] @@ -77,6 +77,6 @@ func newReport(typ GRPCType, fullMethod string) report { startTime: time.Now(), rpcType: typ, } - r.service, r.method = splitMethodName(fullMethod) + r.service, r.method = SplitMethodName(fullMethod) return r } diff --git a/interceptors/server.go b/interceptors/server.go index 5536c3ea2..61afbc06e 100644 --- a/interceptors/server.go +++ b/interceptors/server.go @@ -31,14 +31,14 @@ func UnaryServerInterceptor(reportable ServerReportable) grpc.UnaryServerInterce func StreamServerInterceptor(reportable ServerReportable) grpc.StreamServerInterceptor { return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { r := newReport(ServerStream, info.FullMethod) - reporter, newCtx := reportable.ServerReporter(ss.Context(), nil, streamRPCType(info), r.service, r.method) + reporter, newCtx := reportable.ServerReporter(ss.Context(), nil, StreamRPCType(info), r.service, r.method) err := handler(srv, &monitoredServerStream{ServerStream: ss, newCtx: newCtx, reporter: reporter}) reporter.PostCall(err, time.Since(r.startTime)) return err } } -func streamRPCType(info *grpc.StreamServerInfo) GRPCType { +func StreamRPCType(info *grpc.StreamServerInfo) GRPCType { if info.IsClientStream && !info.IsServerStream { return ClientStream } else if !info.IsClientStream && info.IsServerStream { diff --git a/interceptors/skip/doc.go b/interceptors/skip/doc.go new file mode 100644 index 000000000..284e7eeca --- /dev/null +++ b/interceptors/skip/doc.go @@ -0,0 +1,6 @@ +/* +`skip` allow users to skip interceptors in certain condition. + +Users can use grpc type, service name, method name and metadata to determine whether to skip the interceptor. +*/ +package skip diff --git a/interceptors/skip/examples_test.go b/interceptors/skip/examples_test.go new file mode 100644 index 000000000..28d30c554 --- /dev/null +++ b/interceptors/skip/examples_test.go @@ -0,0 +1,39 @@ +package skip_test + +import ( + "context" + + "google.golang.org/grpc" + + middleware "github.com/grpc-ecosystem/go-grpc-middleware/v2" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/auth" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/skip" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tags" +) + +// Simple example of skipping auth interceptor in the reflection method. +func Example_initialization() { + _ = grpc.NewServer( + grpc.UnaryInterceptor(skip.UnaryServerInterceptor(auth.UnaryServerInterceptor(dummyAuth), SkipReflectionService)), + grpc.StreamInterceptor(skip.StreamServerInterceptor(auth.StreamServerInterceptor(dummyAuth), SkipReflectionService)), + ) +} + +func Example_chain() { + _ = grpc.NewServer( + grpc.UnaryInterceptor(skip.UnaryServerInterceptor( + middleware.ChainUnaryServer( + tags.UnaryServerInterceptor(), + auth.UnaryServerInterceptor(dummyAuth), + ), SkipReflectionService)), + ) +} + +func dummyAuth(ctx context.Context) (context.Context, error) { + return ctx, nil +} + +func SkipReflectionService(ctx context.Context, gRPCType interceptors.GRPCType, service string, method string) bool { + return service != "grpc.reflection.v1alpha.ServerReflection" +} diff --git a/interceptors/skip/interceptor.go b/interceptors/skip/interceptor.go new file mode 100644 index 000000000..57fc1f53a --- /dev/null +++ b/interceptors/skip/interceptor.go @@ -0,0 +1,43 @@ +package skip + +import ( + "context" + + "google.golang.org/grpc" + + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors" +) + +type Filter func(ctx context.Context, typ interceptors.GRPCType, svc string, method string) bool + +// UnaryServerInterceptor returns a new unary server interceptor that determines whether to skip the input interceptor. +func UnaryServerInterceptor(in grpc.UnaryServerInterceptor, filter Filter) grpc.UnaryServerInterceptor { + if filter == nil { + return in + } + + return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + service, method := interceptors.SplitMethodName(info.FullMethod) + if !filter(ctx, interceptors.Unary, service, method) { + // Skip interceptor. + return handler(ctx, req) + } + return in(ctx, req, info, handler) + } +} + +// StreamServerInterceptor returns a new streaming server interceptor that determines whether to skip the input interceptor. +func StreamServerInterceptor(in grpc.StreamServerInterceptor, filter Filter) grpc.StreamServerInterceptor { + if filter == nil { + return in + } + + return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { + service, method := interceptors.SplitMethodName(info.FullMethod) + if !filter(ss.Context(), interceptors.StreamRPCType(info), service, method) { + // Skip interceptor. + return handler(srv, ss) + } + return in(srv, ss, info, handler) + } +} diff --git a/interceptors/skip/interceptor_test.go b/interceptors/skip/interceptor_test.go new file mode 100644 index 000000000..d1382ae07 --- /dev/null +++ b/interceptors/skip/interceptor_test.go @@ -0,0 +1,194 @@ +package skip_test + +import ( + "context" + "fmt" + "io" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" + + "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting/testpb" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/skip" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tags" +) + +var ( + goodPing = &testpb.PingRequest{Value: "something", SleepTimeMs: 9999} +) + +const ( + keyGRPCType = "skip.grpc_type" + keyService = "skip.service" + keyMethod = "skip.method" +) + +func skipped(ctx context.Context) bool { + return len(tags.Extract(ctx).Values()) <= 0 +} + +type skipPingService struct { + testpb.TestServiceServer +} + +func checkMetadata(ctx context.Context, grpcType interceptors.GRPCType, service string, method string) error { + m, _ := metadata.FromIncomingContext(ctx) + if typeFromMetadata := m.Get(keyGRPCType)[0]; typeFromMetadata != string(grpcType) { + return status.Errorf(codes.Internal, fmt.Sprintf("expected grpc type %s, got: %s", grpcType, typeFromMetadata)) + } + if serviceFromMetadata := m.Get(keyService)[0]; serviceFromMetadata != service { + return status.Errorf(codes.Internal, fmt.Sprintf("expected service %s, got: %s", service, serviceFromMetadata)) + } + if methodFromMetadata := m.Get(keyMethod)[0]; methodFromMetadata != method { + return status.Errorf(codes.Internal, fmt.Sprintf("expected method %s, got: %s", method, methodFromMetadata)) + } + return nil +} + +func (s *skipPingService) Ping(ctx context.Context, _ *testpb.PingRequest) (*testpb.PingResponse, error) { + err := checkMetadata(ctx, interceptors.Unary, "grpc_middleware.testpb.TestService", "Ping") + if err != nil { + return nil, err + } + + if skipped(ctx) { + return &testpb.PingResponse{Value: "skipped"}, nil + } + + return &testpb.PingResponse{}, nil +} + +func (s *skipPingService) PingList(_ *testpb.PingRequest, stream testpb.TestService_PingListServer) error { + err := checkMetadata(stream.Context(), interceptors.ServerStream, "grpc_middleware.testpb.TestService", "PingList") + if err != nil { + return err + } + + var out testpb.PingResponse + if skipped(stream.Context()) { + out.Value = "skipped" + } + return stream.Send(&out) +} + +func filter(ctx context.Context, gRPCType interceptors.GRPCType, service string, method string) bool { + m, _ := metadata.FromIncomingContext(ctx) + // Set parameters into metadata + m.Set(keyGRPCType, string(gRPCType)) + m.Set(keyService, service) + m.Set(keyMethod, method) + + if v := m.Get("skip"); len(v) > 0 && v[0] == "true" { + return false + } + return true +} + +func TestSkipSuite(t *testing.T) { + s := &SkipSuite{ + InterceptorTestSuite: &grpctesting.InterceptorTestSuite{ + TestService: &skipPingService{&grpctesting.TestPingService{T: t}}, + ServerOpts: []grpc.ServerOption{ + grpc.UnaryInterceptor(skip.UnaryServerInterceptor(tags.UnaryServerInterceptor(), filter)), + grpc.StreamInterceptor(skip.StreamServerInterceptor(tags.StreamServerInterceptor(), filter)), + }, + }, + } + suite.Run(t, s) +} + +type SkipSuite struct { + *grpctesting.InterceptorTestSuite +} + +func (s *SkipSuite) TestPing() { + t := s.T() + + testCases := []struct { + name string + skip bool + }{ + { + name: "skip tags interceptor", + skip: true, + }, + { + name: "do not skip", + skip: false, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + var m metadata.MD + if tc.skip { + m = metadata.New(map[string]string{ + "skip": "true", + }) + } + + resp, err := s.Client.Ping(metadata.NewOutgoingContext(s.SimpleCtx(), m), goodPing) + require.NoError(t, err) + + var value string + if tc.skip { + value = "skipped" + } + assert.Equal(t, value, resp.Value) + }) + } +} + +func (s *SkipSuite) TestPingList() { + t := s.T() + + testCases := []struct { + name string + skip bool + }{ + { + name: "skip tags interceptor", + skip: true, + }, + { + name: "do not skip", + skip: false, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + var m metadata.MD + if tc.skip { + m = metadata.New(map[string]string{ + "skip": "true", + }) + } + + stream, err := s.Client.PingList(metadata.NewOutgoingContext(s.SimpleCtx(), m), goodPing) + require.NoError(t, err) + + for { + resp, err := stream.Recv() + if err == io.EOF { + break + } + require.NoError(s.T(), err) + + var value string + if tc.skip { + value = "skipped" + } + assert.Equal(t, value, resp.Value) + } + }) + } +} diff --git a/interceptors/tracing/id_extract_test.go b/interceptors/tracing/id_extract_test.go index f0bca9459..ce93b6e91 100644 --- a/interceptors/tracing/id_extract_test.go +++ b/interceptors/tracing/id_extract_test.go @@ -2,9 +2,11 @@ package tracing import ( "fmt" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tags" - "github.com/stretchr/testify/assert" "testing" + + "github.com/stretchr/testify/assert" + + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tags" ) func TestTagsCarrier_Set_JaegerTraceFormat(t *testing.T) { From 4a659d8f2b00f6e4fd7a248d2250cd00e0df40cf Mon Sep 17 00:00:00 2001 From: Drew Wells Date: Wed, 20 Jan 2021 04:22:00 -0600 Subject: [PATCH 11/27] Remove custom chain middleware (#385) * remove dependency on middleware.Chain from providers/kit * skip wont be able to bypass multiple interceptors without an API change * update examples by removing middleware chains --- README.md | 8 +-- chain.go | 64 ---------------------- doc.go | 7 +-- go.mod | 4 +- go.sum | 19 +++++++ interceptors/logging/interceptors_test.go | 13 ++--- interceptors/logging/payload_test.go | 5 +- interceptors/ratelimit/examples_test.go | 5 +- interceptors/recovery/examples_test.go | 5 +- interceptors/recovery/interceptors_test.go | 9 ++- interceptors/skip/examples_test.go | 12 ---- interceptors/tracing/interceptors_test.go | 5 +- providers/kit/examples_test.go | 21 ++++--- providers/kit/go.mod | 2 +- providers/kit/go.sum | 8 +++ 15 files changed, 64 insertions(+), 123 deletions(-) diff --git a/README.md b/README.md index fc293af27..b1e1f3cff 100644 --- a/README.md +++ b/README.md @@ -30,22 +30,22 @@ some of them itself, but also will link to useful external repos. import "github.com/grpc-ecosystem/go-grpc-middleware/v2" myServer := grpc.NewServer( - grpc.StreamInterceptor(middleware.ChainStreamServer( + grpc.ChainStreamInterceptor( tags.StreamServerInterceptor(), opentracing.StreamServerInterceptor(), prometheus.StreamServerInterceptor, zap.StreamServerInterceptor(zapLogger), auth.StreamServerInterceptor(myAuthFunction), recovery.StreamServerInterceptor(), - )), - grpc.UnaryInterceptor(middleware.ChainUnaryServer( + ), + grpc.ChainUnaryInterceptor( tags.UnaryServerInterceptor(), opentracing.UnaryServerInterceptor(), prometheus.UnaryServerInterceptor, zap.UnaryServerInterceptor(zapLogger), auth.UnaryServerInterceptor(myAuthFunction), recovery.UnaryServerInterceptor(), - )), + ), ) ``` diff --git a/chain.go b/chain.go index d77394f03..0eacce0ff 100644 --- a/chain.go +++ b/chain.go @@ -11,56 +11,6 @@ import ( "google.golang.org/grpc" ) -// TODO(bwplotka): Remove and replace with updated gRPC default chaining WithChainUnaryInterceptor etc. - -// ChainUnaryServer creates a single interceptor out of a chain of many interceptors. -// -// Execution is done in left-to-right order, including passing of context. -// For example ChainUnaryServer(one, two, three) will execute one before two before three, and three -// will see context changes of one and two. -func ChainUnaryServer(interceptors ...grpc.UnaryServerInterceptor) grpc.UnaryServerInterceptor { - n := len(interceptors) - - return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { - chainer := func(currentInter grpc.UnaryServerInterceptor, currentHandler grpc.UnaryHandler) grpc.UnaryHandler { - return func(currentCtx context.Context, currentReq interface{}) (interface{}, error) { - return currentInter(currentCtx, currentReq, info, currentHandler) - } - } - - chainedHandler := handler - for i := n - 1; i >= 0; i-- { - chainedHandler = chainer(interceptors[i], chainedHandler) - } - - return chainedHandler(ctx, req) - } -} - -// ChainStreamServer creates a single interceptor out of a chain of many interceptors. -// -// Execution is done in left-to-right order, including passing of context. -// For example ChainUnaryServer(one, two, three) will execute one before two before three. -// If you want to pass context between interceptors, use WrapServerStream. -func ChainStreamServer(interceptors ...grpc.StreamServerInterceptor) grpc.StreamServerInterceptor { - n := len(interceptors) - - return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { - chainer := func(currentInter grpc.StreamServerInterceptor, currentHandler grpc.StreamHandler) grpc.StreamHandler { - return func(currentSrv interface{}, currentStream grpc.ServerStream) error { - return currentInter(currentSrv, currentStream, info, currentHandler) - } - } - - chainedHandler := handler - for i := n - 1; i >= 0; i-- { - chainedHandler = chainer(interceptors[i], chainedHandler) - } - - return chainedHandler(srv, ss) - } -} - // ChainUnaryClient creates a single interceptor out of a chain of many interceptors. // // Execution is done in left-to-right order, including passing of context. @@ -106,17 +56,3 @@ func ChainStreamClient(interceptors ...grpc.StreamClientInterceptor) grpc.Stream return chainedStreamer(ctx, desc, cc, method, opts...) } } - -// Chain creates a single interceptor out of a chain of many interceptors. -// -// WithUnaryServerChain is a grpc.Server config option that accepts multiple unary interceptors. -// Basically syntactic sugar. -func WithUnaryServerChain(interceptors ...grpc.UnaryServerInterceptor) grpc.ServerOption { - return grpc.UnaryInterceptor(ChainUnaryServer(interceptors...)) -} - -// WithStreamServerChain is a grpc.Server config option that accepts multiple stream interceptors. -// Basically syntactic sugar. -func WithStreamServerChain(interceptors ...grpc.StreamServerInterceptor) grpc.ServerOption { - return grpc.StreamInterceptor(ChainStreamServer(interceptors...)) -} diff --git a/doc.go b/doc.go index b540770a9..d1b78274a 100644 --- a/doc.go +++ b/doc.go @@ -15,15 +15,12 @@ functions for chaining said interceptors, metadata convenience methods and more. Chaining -By default, gRPC doesn't allow one to have more than one interceptor either on the client nor on -the server side. `middleware` provides convenient chaining methods - Simple way of turning a multiple interceptors into a single interceptor. Here's an example for server chaining: myServer := grpc.NewServer( - grpc.StreamInterceptor(middleware.ChainStreamServer(loggingStream, monitoringStream, authStream)), - grpc.UnaryInterceptor(middleware.ChainUnaryServer(loggingUnary, monitoringUnary, authUnary), + grpc.ChainStreamInterceptor(loggingStream, monitoringStream, authStream)), + grpc.ChainUnaryInterceptor(loggingUnary, monitoringUnary, authUnary), ) These interceptors will be executed from left to right: logging, monitoring and auth. diff --git a/go.mod b/go.mod index 39557f630..6654f4e2e 100644 --- a/go.mod +++ b/go.mod @@ -4,12 +4,12 @@ go 1.14 require ( github.com/gogo/protobuf v1.2.1 - github.com/golang/protobuf v1.3.2 + github.com/golang/protobuf v1.3.3 github.com/opentracing/opentracing-go v1.1.0 github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.4.0 golang.org/x/net v0.0.0-20190620200207-3b0461eec859 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 // indirect - google.golang.org/grpc v1.19.0 + google.golang.org/grpc v1.28.0 ) diff --git a/go.sum b/go.sum index 8cb06aad9..0f8563412 100644 --- a/go.sum +++ b/go.sum @@ -2,9 +2,14 @@ cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= @@ -13,6 +18,9 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= @@ -21,6 +29,7 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -28,15 +37,18 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 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-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -45,6 +57,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -53,8 +67,13 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2El google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/grpc v1.19.0 h1:cfg4PD8YEdSFnm7qLV4++93WcmhH2nIUhMjhdCvl3j8= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.28.0 h1:bO/TA4OxCOummhSf10siHuG7vJOiwh7SpRpFZDkOgl4= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/interceptors/logging/interceptors_test.go b/interceptors/logging/interceptors_test.go index 9cd0a5740..fe7601952 100644 --- a/interceptors/logging/interceptors_test.go +++ b/interceptors/logging/interceptors_test.go @@ -16,7 +16,6 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/codes" - middleware "github.com/grpc-ecosystem/go-grpc-middleware/v2" "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting" "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting/testpb" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors" @@ -174,10 +173,10 @@ func TestSuite(t *testing.T) { grpc.WithStreamInterceptor(logging.StreamClientInterceptor(s.logger, logging.WithLevels(customClientCodeToLevel))), } s.InterceptorTestSuite.ServerOpts = []grpc.ServerOption{ - middleware.WithStreamServerChain( + grpc.ChainStreamInterceptor( tags.StreamServerInterceptor(tags.WithFieldExtractor(tags.CodeGenRequestFieldExtractor)), logging.StreamServerInterceptor(s.logger, logging.WithLevels(customClientCodeToLevel))), - middleware.WithUnaryServerChain( + grpc.ChainUnaryInterceptor( tags.UnaryServerInterceptor(tags.WithFieldExtractor(tags.CodeGenRequestFieldExtractor)), logging.UnaryServerInterceptor(s.logger, logging.WithLevels(customClientCodeToLevel))), } @@ -361,10 +360,10 @@ func TestCustomDurationSuite(t *testing.T) { grpc.WithStreamInterceptor(logging.StreamClientInterceptor(s.logger, logging.WithDurationField(logging.DurationToDurationField))), } s.InterceptorTestSuite.ServerOpts = []grpc.ServerOption{ - middleware.WithStreamServerChain( + grpc.ChainStreamInterceptor( tags.StreamServerInterceptor(tags.WithFieldExtractor(tags.CodeGenRequestFieldExtractor)), logging.StreamServerInterceptor(s.logger, logging.WithDurationField(logging.DurationToDurationField))), - middleware.WithUnaryServerChain( + grpc.ChainUnaryInterceptor( tags.UnaryServerInterceptor(tags.WithFieldExtractor(tags.CodeGenRequestFieldExtractor)), logging.UnaryServerInterceptor(s.logger, logging.WithDurationField(logging.DurationToDurationField))), } @@ -485,10 +484,10 @@ func TestCustomDeciderSuite(t *testing.T) { grpc.WithStreamInterceptor(logging.StreamClientInterceptor(s.logger, opts)), } s.InterceptorTestSuite.ServerOpts = []grpc.ServerOption{ - middleware.WithStreamServerChain( + grpc.ChainStreamInterceptor( tags.StreamServerInterceptor(tags.WithFieldExtractor(tags.CodeGenRequestFieldExtractor)), logging.StreamServerInterceptor(s.logger, opts)), - middleware.WithUnaryServerChain( + grpc.ChainUnaryInterceptor( tags.UnaryServerInterceptor(tags.WithFieldExtractor(tags.CodeGenRequestFieldExtractor)), logging.UnaryServerInterceptor(s.logger, opts)), } diff --git a/interceptors/logging/payload_test.go b/interceptors/logging/payload_test.go index e2d24c859..969b3a63d 100644 --- a/interceptors/logging/payload_test.go +++ b/interceptors/logging/payload_test.go @@ -13,7 +13,6 @@ import ( "github.com/stretchr/testify/suite" "google.golang.org/grpc" - middleware "github.com/grpc-ecosystem/go-grpc-middleware/v2" "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting" "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting/testpb" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors" @@ -47,10 +46,10 @@ func TestPayloadSuite(t *testing.T) { grpc.WithStreamInterceptor(logging.PayloadStreamClientInterceptor(s.logger, alwaysLoggingDeciderClient)), } s.InterceptorTestSuite.ServerOpts = []grpc.ServerOption{ - middleware.WithStreamServerChain( + grpc.ChainStreamInterceptor( tags.StreamServerInterceptor(tags.WithFieldExtractor(tags.CodeGenRequestFieldExtractor)), logging.PayloadStreamServerInterceptor(s.logger, alwaysLoggingDeciderServer)), - middleware.WithUnaryServerChain( + grpc.ChainUnaryInterceptor( tags.UnaryServerInterceptor(tags.WithFieldExtractor(tags.CodeGenRequestFieldExtractor)), logging.PayloadUnaryServerInterceptor(s.logger, alwaysLoggingDeciderServer)), } diff --git a/interceptors/ratelimit/examples_test.go b/interceptors/ratelimit/examples_test.go index 9b73fabeb..c624f6dec 100644 --- a/interceptors/ratelimit/examples_test.go +++ b/interceptors/ratelimit/examples_test.go @@ -5,7 +5,6 @@ import ( "google.golang.org/grpc" - middleware "github.com/grpc-ecosystem/go-grpc-middleware/v2" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/ratelimit" ) @@ -23,10 +22,10 @@ func Example() { // You can implement your own ratelimiter for the interface. limiter := &alwaysPassLimiter{} _ = grpc.NewServer( - middleware.WithUnaryServerChain( + grpc.ChainUnaryInterceptor( ratelimit.UnaryServerInterceptor(limiter), ), - middleware.WithStreamServerChain( + grpc.ChainStreamInterceptor( ratelimit.StreamServerInterceptor(limiter), ), ) diff --git a/interceptors/recovery/examples_test.go b/interceptors/recovery/examples_test.go index c30281297..6e41f9066 100644 --- a/interceptors/recovery/examples_test.go +++ b/interceptors/recovery/examples_test.go @@ -8,7 +8,6 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - middleware "github.com/grpc-ecosystem/go-grpc-middleware/v2" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/recovery" ) @@ -29,10 +28,10 @@ func Example_initialization() { // Create a server. Recovery handlers should typically be last in the chain so that other middleware // (e.g. logging) can operate on the recovered state instead of being directly affected by any panic _ = grpc.NewServer( - middleware.WithUnaryServerChain( + grpc.UnaryInterceptor( recovery.UnaryServerInterceptor(opts...), ), - middleware.WithStreamServerChain( + grpc.StreamInterceptor( recovery.StreamServerInterceptor(opts...), ), ) diff --git a/interceptors/recovery/interceptors_test.go b/interceptors/recovery/interceptors_test.go index 0703bc939..84c539e81 100644 --- a/interceptors/recovery/interceptors_test.go +++ b/interceptors/recovery/interceptors_test.go @@ -14,7 +14,6 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - middleware "github.com/grpc-ecosystem/go-grpc-middleware/v2" "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting" "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting/testpb" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/recovery" @@ -48,9 +47,9 @@ func TestRecoverySuite(t *testing.T) { InterceptorTestSuite: &grpctesting.InterceptorTestSuite{ TestService: &recoveryAssertService{TestServiceServer: &grpctesting.TestPingService{T: t}}, ServerOpts: []grpc.ServerOption{ - middleware.WithStreamServerChain( + grpc.StreamInterceptor( recovery.StreamServerInterceptor()), - middleware.WithUnaryServerChain( + grpc.UnaryInterceptor( recovery.UnaryServerInterceptor()), }, }, @@ -101,9 +100,9 @@ func TestRecoveryOverrideSuite(t *testing.T) { InterceptorTestSuite: &grpctesting.InterceptorTestSuite{ TestService: &recoveryAssertService{TestServiceServer: &grpctesting.TestPingService{T: t}}, ServerOpts: []grpc.ServerOption{ - middleware.WithStreamServerChain( + grpc.StreamInterceptor( recovery.StreamServerInterceptor(opts...)), - middleware.WithUnaryServerChain( + grpc.UnaryInterceptor( recovery.UnaryServerInterceptor(opts...)), }, }, diff --git a/interceptors/skip/examples_test.go b/interceptors/skip/examples_test.go index 28d30c554..b34e9ee6f 100644 --- a/interceptors/skip/examples_test.go +++ b/interceptors/skip/examples_test.go @@ -5,11 +5,9 @@ import ( "google.golang.org/grpc" - middleware "github.com/grpc-ecosystem/go-grpc-middleware/v2" "github.com/grpc-ecosystem/go-grpc-middleware/v2/auth" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/skip" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tags" ) // Simple example of skipping auth interceptor in the reflection method. @@ -20,16 +18,6 @@ func Example_initialization() { ) } -func Example_chain() { - _ = grpc.NewServer( - grpc.UnaryInterceptor(skip.UnaryServerInterceptor( - middleware.ChainUnaryServer( - tags.UnaryServerInterceptor(), - auth.UnaryServerInterceptor(dummyAuth), - ), SkipReflectionService)), - ) -} - func dummyAuth(ctx context.Context) (context.Context, error) { return ctx, nil } diff --git a/interceptors/tracing/interceptors_test.go b/interceptors/tracing/interceptors_test.go index 2328267ed..894634833 100644 --- a/interceptors/tracing/interceptors_test.go +++ b/interceptors/tracing/interceptors_test.go @@ -21,7 +21,6 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/codes" - middleware "github.com/grpc-ecosystem/go-grpc-middleware/v2" "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting" "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting/testpb" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tags" @@ -110,10 +109,10 @@ func makeInterceptorTestSuite(t *testing.T, opts []tracing.Option) *grpctesting. grpc.WithStreamInterceptor(tracing.StreamClientInterceptor(opts...)), }, ServerOpts: []grpc.ServerOption{ - middleware.WithStreamServerChain( + grpc.ChainStreamInterceptor( tags.StreamServerInterceptor(tags.WithFieldExtractor(tags.CodeGenRequestFieldExtractor)), tracing.StreamServerInterceptor(opts...)), - middleware.WithUnaryServerChain( + grpc.ChainUnaryInterceptor( tags.UnaryServerInterceptor(tags.WithFieldExtractor(tags.CodeGenRequestFieldExtractor)), tracing.UnaryServerInterceptor(opts...)), }, diff --git a/providers/kit/examples_test.go b/providers/kit/examples_test.go index 63facbeef..f1afda54c 100644 --- a/providers/kit/examples_test.go +++ b/providers/kit/examples_test.go @@ -8,7 +8,6 @@ import ( "github.com/grpc-ecosystem/go-grpc-middleware/providers/kit/v2" "google.golang.org/grpc" - middleware "github.com/grpc-ecosystem/go-grpc-middleware/v2" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/logging" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tags" ) @@ -27,11 +26,11 @@ func Example_initializationWithCustomLevels() { } // Create a server, make sure we put the tags context before everything else. _ = grpc.NewServer( - middleware.WithUnaryServerChain( + grpc.ChainUnaryInterceptor( tags.UnaryServerInterceptor(), logging.UnaryServerInterceptor(kit.InterceptorLogger(logger), opts...), ), - middleware.WithStreamServerChain( + grpc.ChainStreamInterceptor( tags.StreamServerInterceptor(), logging.StreamServerInterceptor(kit.InterceptorLogger(logger), opts...), ), @@ -47,11 +46,11 @@ func Example_initializationWithDurationFieldOverride() { } // Create a server, make sure we put the tags context before everything else. _ = grpc.NewServer( - middleware.WithUnaryServerChain( + grpc.ChainUnaryInterceptor( tags.UnaryServerInterceptor(), logging.UnaryServerInterceptor(kit.InterceptorLogger(logger), opts...), ), - middleware.WithStreamServerChain( + grpc.ChainStreamInterceptor( tags.StreamServerInterceptor(), logging.StreamServerInterceptor(kit.InterceptorLogger(logger), opts...), ), @@ -63,11 +62,11 @@ func Example_initializationWithCodeGenRequestFieldExtractor() { logger := log.NewNopLogger() // Create a server, make sure we put the tags context before everything else. _ = grpc.NewServer( - middleware.WithUnaryServerChain( + grpc.ChainUnaryInterceptor( tags.UnaryServerInterceptor(tags.WithFieldExtractor(tags.CodeGenRequestFieldExtractor)), logging.UnaryServerInterceptor(kit.InterceptorLogger(logger)), ), - middleware.WithStreamServerChain( + grpc.ChainStreamInterceptor( tags.StreamServerInterceptor(tags.WithFieldExtractor(tags.CodeGenRequestFieldExtractor)), logging.StreamServerInterceptor(kit.InterceptorLogger(logger)), ), @@ -90,11 +89,11 @@ func ExampleWithDecider() { } // Create a server, make sure we put the tags context before everything else. _ = []grpc.ServerOption{ - middleware.WithUnaryServerChain( + grpc.ChainUnaryInterceptor( tags.UnaryServerInterceptor(), logging.UnaryServerInterceptor(kit.InterceptorLogger(logger), opts...), ), - middleware.WithStreamServerChain( + grpc.ChainStreamInterceptor( tags.StreamServerInterceptor(), logging.StreamServerInterceptor(kit.InterceptorLogger(logger), opts...), ), @@ -111,12 +110,12 @@ func ExampleWithPayloadLogging() { // Create a server, make sure we put the tags context before everything else. _ = []grpc.ServerOption{ - middleware.WithUnaryServerChain( + grpc.ChainUnaryInterceptor( tags.UnaryServerInterceptor(), logging.UnaryServerInterceptor(kit.InterceptorLogger(logger)), logging.PayloadUnaryServerInterceptor(kit.InterceptorLogger(logger), payloadDecider), ), - middleware.WithStreamServerChain( + grpc.ChainStreamInterceptor( tags.StreamServerInterceptor(), logging.StreamServerInterceptor(kit.InterceptorLogger(logger)), logging.PayloadStreamServerInterceptor(kit.InterceptorLogger(logger), payloadDecider), diff --git a/providers/kit/go.mod b/providers/kit/go.mod index 046f207a6..578848dc4 100644 --- a/providers/kit/go.mod +++ b/providers/kit/go.mod @@ -5,5 +5,5 @@ go 1.14 require ( github.com/go-kit/kit v0.10.0 github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20201002093600-73cf2ae9d891 - google.golang.org/grpc v1.26.0 + google.golang.org/grpc v1.28.0 ) diff --git a/providers/kit/go.sum b/providers/kit/go.sum index c139da7d4..446fcd42b 100644 --- a/providers/kit/go.sum +++ b/providers/kit/go.sum @@ -29,6 +29,7 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -47,7 +48,9 @@ github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1 github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= @@ -79,6 +82,8 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -352,8 +357,11 @@ google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ij google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0 h1:bO/TA4OxCOummhSf10siHuG7vJOiwh7SpRpFZDkOgl4= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From ad3d951538311e100ede0ac8592b33a573c6c326 Mon Sep 17 00:00:00 2001 From: Drew Wells Date: Wed, 20 Jan 2021 04:22:33 -0600 Subject: [PATCH 12/27] Update travis ci badge to Github actions badge. (#384) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b1e1f3cff..8f6ad51c3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Go gRPC Middleware V2 -[![Travis Build](https://travis-ci.org/grpc-ecosystem/go-grpc-middleware.svg?branch=master)](https://travis-ci.org/grpc-ecosystem/go-grpc-middleware) +[![go](https://github.com/grpc-ecosystem/go-grpc-middleware/workflows/go/badge.svg?branch=v2)](https://github.com/grpc-ecosystem/go-grpc-middleware/actions?query=branch%3Av2) [![Go Report Card](https://goreportcard.com/badge/github.com/grpc-ecosystem/go-grpc-middleware)](https://goreportcard.com/report/github.com/grpc-ecosystem/go-grpc-middleware) [![GoDoc](http://img.shields.io/badge/GoDoc-Reference-blue.svg)](https://godoc.org/github.com/grpc-ecosystem/go-grpc-middleware) [![SourceGraph](https://sourcegraph.com/github.com/grpc-ecosystem/go-grpc-middleware/-/badge.svg)](https://sourcegraph.com/github.com/grpc-ecosystem/go-grpc-middleware/?badge) From c1f1e53b80a7205e622f9d6c3325021d8a99ebe9 Mon Sep 17 00:00:00 2001 From: Bartlomiej Plotka Date: Fri, 22 Jan 2021 14:30:14 +0000 Subject: [PATCH 13/27] Upgraded proto related deps: grpc and protobuf; removed gogo from core. (#321) * Upgraded proto related deps: grpc and protobuf; removed gogo from core. Signed-off-by: Bartlomiej Plotka * Addressed Yash comment. Signed-off-by: Bartlomiej Plotka * Addressed Johan comments. Signed-off-by: Bartlomiej Plotka Co-authored-by: Yash Sharma --- .bingo/README.md | 3 +- .bingo/Variables.mk | 41 +- .bingo/bingo.mod | 2 +- .bingo/golangci-lint.mod | 5 +- .bingo/protoc-gen-go-grpc.mod | 5 + ...toc-gen-gogofast.mod => protoc-gen-go.mod} | 2 +- .bingo/variables.env | 22 +- .gitignore | 3 +- Makefile | 44 +- README.md | 1 + go.mod | 10 +- go.sum | 58 +- grpctesting/gogotestpb/fields.pb.go | 438 ------ grpctesting/gogotestpb/fields.proto | 49 - grpctesting/pingservice.go | 6 + grpctesting/pingservice_test.go | 90 ++ grpctesting/testpb/test.pb.go | 1211 ++++------------- grpctesting/testpb/test.proto | 2 +- grpctesting/testpb/test_grpc.pb.go | 295 ++++ interceptors/client_test.go | 184 ++- interceptors/logging/interceptors_test.go | 70 +- interceptors/logging/logging.go | 5 +- interceptors/logging/payload.go | 74 +- interceptors/logging/payload_test.go | 17 +- interceptors/server_test.go | 61 +- interceptors/tags/fieldextractor.go | 7 +- interceptors/tags/fieldextractor_test.go | 58 +- providers/kit/examples_test.go | 4 +- providers/kit/go.mod | 2 +- providers/kit/go.sum | 21 +- providers/logrus/examples_test.go | 4 +- providers/logrus/go.mod | 2 +- providers/logrus/go.sum | 26 +- providers/zap/examples_test.go | 4 +- providers/zap/go.mod | 2 +- providers/zap/go.sum | 23 +- providers/zerolog/examples_test.go | 4 +- providers/zerolog/go.mod | 2 +- providers/zerolog/go.sum | 25 +- scripts/genproto.sh | 25 +- 40 files changed, 1098 insertions(+), 1809 deletions(-) create mode 100644 .bingo/protoc-gen-go-grpc.mod rename .bingo/{protoc-gen-gogofast.mod => protoc-gen-go.mod} (57%) delete mode 100644 grpctesting/gogotestpb/fields.pb.go delete mode 100644 grpctesting/gogotestpb/fields.proto create mode 100644 grpctesting/pingservice_test.go create mode 100644 grpctesting/testpb/test_grpc.pb.go diff --git a/.bingo/README.md b/.bingo/README.md index 70f928603..7a5c2d4f6 100755 --- a/.bingo/README.md +++ b/.bingo/README.md @@ -5,7 +5,8 @@ This is directory which stores Go modules with pinned buildable package that is * Run `bingo get` to install all tools having each own module file in this directory. * Run `bingo get ` to install that have own module file in this directory. * For Makefile: Make sure to put `include .bingo/Variables.mk` in your Makefile, then use $() variable where is the .bingo/.mod. -* For shell: Run `source .bingo/variables.env` to source all environment variable for each tool +* For shell: Run `source .bingo/variables.env` to source all environment variable for each tool. +* For go: Import `.bingo/variables.go` to for variable names. * See https://github.com/bwplotka/bingo or -h on how to add, remove or change binaries dependencies. ## Requirements diff --git a/.bingo/Variables.mk b/.bingo/Variables.mk index a33fba2be..f15748270 100644 --- a/.bingo/Variables.mk +++ b/.bingo/Variables.mk @@ -1,5 +1,6 @@ -# Auto generated binary variables helper managed by https://github.com/bwplotka/bingo v0.2.2. DO NOT EDIT. +# Auto generated binary variables helper managed by https://github.com/bwplotka/bingo v0.3.0. DO NOT EDIT. # All tools are designed to be build inside $GOBIN. +BINGO_DIR := $(dir $(lastword $(MAKEFILE_LIST))) GOPATH ?= $(shell go env GOPATH) GOBIN ?= $(firstword $(subst :, ,${GOPATH}))/bin GO ?= $(shell which go) @@ -16,39 +17,45 @@ GO ?= $(shell which go) # @echo "Running bingo" # @$(BINGO) # -BINGO := $(GOBIN)/bingo-v0.2.2 -$(BINGO): .bingo/bingo.mod +BINGO := $(GOBIN)/bingo-v0.3.0 +$(BINGO): $(BINGO_DIR)/bingo.mod @# Install binary/ries using Go 1.14+ build command. This is using bwplotka/bingo-controlled, separate go module with pinned dependencies. - @echo "(re)installing $(GOBIN)/bingo-v0.2.2" - @cd .bingo && $(GO) build -modfile=bingo.mod -o=$(GOBIN)/bingo-v0.2.2 "github.com/bwplotka/bingo" + @echo "(re)installing $(GOBIN)/bingo-v0.3.0" + @cd $(BINGO_DIR) && $(GO) build -mod=mod -modfile=bingo.mod -o=$(GOBIN)/bingo-v0.3.0 "github.com/bwplotka/bingo" FAILLINT := $(GOBIN)/faillint-v1.5.0 -$(FAILLINT): .bingo/faillint.mod +$(FAILLINT): $(BINGO_DIR)/faillint.mod @# Install binary/ries using Go 1.14+ build command. This is using bwplotka/bingo-controlled, separate go module with pinned dependencies. @echo "(re)installing $(GOBIN)/faillint-v1.5.0" - @cd .bingo && $(GO) build -modfile=faillint.mod -o=$(GOBIN)/faillint-v1.5.0 "github.com/fatih/faillint" + @cd $(BINGO_DIR) && $(GO) build -mod=mod -modfile=faillint.mod -o=$(GOBIN)/faillint-v1.5.0 "github.com/fatih/faillint" GOIMPORTS := $(GOBIN)/goimports-v0.0.0-20200529172331-a64b76657301 -$(GOIMPORTS): .bingo/goimports.mod +$(GOIMPORTS): $(BINGO_DIR)/goimports.mod @# Install binary/ries using Go 1.14+ build command. This is using bwplotka/bingo-controlled, separate go module with pinned dependencies. @echo "(re)installing $(GOBIN)/goimports-v0.0.0-20200529172331-a64b76657301" - @cd .bingo && $(GO) build -modfile=goimports.mod -o=$(GOBIN)/goimports-v0.0.0-20200529172331-a64b76657301 "golang.org/x/tools/cmd/goimports" + @cd $(BINGO_DIR) && $(GO) build -mod=mod -modfile=goimports.mod -o=$(GOBIN)/goimports-v0.0.0-20200529172331-a64b76657301 "golang.org/x/tools/cmd/goimports" GOLANGCI_LINT := $(GOBIN)/golangci-lint-v1.27.0 -$(GOLANGCI_LINT): .bingo/golangci-lint.mod +$(GOLANGCI_LINT): $(BINGO_DIR)/golangci-lint.mod @# Install binary/ries using Go 1.14+ build command. This is using bwplotka/bingo-controlled, separate go module with pinned dependencies. @echo "(re)installing $(GOBIN)/golangci-lint-v1.27.0" - @cd .bingo && $(GO) build -modfile=golangci-lint.mod -o=$(GOBIN)/golangci-lint-v1.27.0 "github.com/golangci/golangci-lint/cmd/golangci-lint" + @cd $(BINGO_DIR) && $(GO) build -mod=mod -modfile=golangci-lint.mod -o=$(GOBIN)/golangci-lint-v1.27.0 "github.com/golangci/golangci-lint/cmd/golangci-lint" MISSPELL := $(GOBIN)/misspell-v0.3.4 -$(MISSPELL): .bingo/misspell.mod +$(MISSPELL): $(BINGO_DIR)/misspell.mod @# Install binary/ries using Go 1.14+ build command. This is using bwplotka/bingo-controlled, separate go module with pinned dependencies. @echo "(re)installing $(GOBIN)/misspell-v0.3.4" - @cd .bingo && $(GO) build -modfile=misspell.mod -o=$(GOBIN)/misspell-v0.3.4 "github.com/client9/misspell/cmd/misspell" + @cd $(BINGO_DIR) && $(GO) build -mod=mod -modfile=misspell.mod -o=$(GOBIN)/misspell-v0.3.4 "github.com/client9/misspell/cmd/misspell" -PROTOC_GEN_GOGOFAST := $(GOBIN)/protoc-gen-gogofast-v1.3.1 -$(PROTOC_GEN_GOGOFAST): .bingo/protoc-gen-gogofast.mod +PROTOC_GEN_GO_GRPC := $(GOBIN)/protoc-gen-go-grpc-v0.0.0-20200723182653-9106c3fff523 +$(PROTOC_GEN_GO_GRPC): $(BINGO_DIR)/protoc-gen-go-grpc.mod @# Install binary/ries using Go 1.14+ build command. This is using bwplotka/bingo-controlled, separate go module with pinned dependencies. - @echo "(re)installing $(GOBIN)/protoc-gen-gogofast-v1.3.1" - @cd .bingo && $(GO) build -modfile=protoc-gen-gogofast.mod -o=$(GOBIN)/protoc-gen-gogofast-v1.3.1 "github.com/gogo/protobuf/protoc-gen-gogofast" + @echo "(re)installing $(GOBIN)/protoc-gen-go-grpc-v0.0.0-20200723182653-9106c3fff523" + @cd $(BINGO_DIR) && $(GO) build -mod=mod -modfile=protoc-gen-go-grpc.mod -o=$(GOBIN)/protoc-gen-go-grpc-v0.0.0-20200723182653-9106c3fff523 "google.golang.org/grpc/cmd/protoc-gen-go-grpc" + +PROTOC_GEN_GO := $(GOBIN)/protoc-gen-go-v1.25.0 +$(PROTOC_GEN_GO): $(BINGO_DIR)/protoc-gen-go.mod + @# Install binary/ries using Go 1.14+ build command. This is using bwplotka/bingo-controlled, separate go module with pinned dependencies. + @echo "(re)installing $(GOBIN)/protoc-gen-go-v1.25.0" + @cd $(BINGO_DIR) && $(GO) build -mod=mod -modfile=protoc-gen-go.mod -o=$(GOBIN)/protoc-gen-go-v1.25.0 "google.golang.org/protobuf/cmd/protoc-gen-go" diff --git a/.bingo/bingo.mod b/.bingo/bingo.mod index 3489e772b..7007d9020 100644 --- a/.bingo/bingo.mod +++ b/.bingo/bingo.mod @@ -2,4 +2,4 @@ module _ // Auto generated by https://github.com/bwplotka/bingo. DO NOT EDIT go 1.14 -require github.com/bwplotka/bingo v0.2.2 +require github.com/bwplotka/bingo v0.3.0 diff --git a/.bingo/golangci-lint.mod b/.bingo/golangci-lint.mod index b4460743e..da0835531 100644 --- a/.bingo/golangci-lint.mod +++ b/.bingo/golangci-lint.mod @@ -2,7 +2,4 @@ module _ // Auto generated by https://github.com/bwplotka/bingo. DO NOT EDIT go 1.14 -require ( - github.com/golangci/golangci-lint v1.27.0 // cmd/golangci-lint - github.com/securego/gosec v0.0.0-20200316084457-7da9f46445fd // indirect -) +require github.com/golangci/golangci-lint v1.27.0 // cmd/golangci-lint diff --git a/.bingo/protoc-gen-go-grpc.mod b/.bingo/protoc-gen-go-grpc.mod new file mode 100644 index 000000000..c4d6abfcd --- /dev/null +++ b/.bingo/protoc-gen-go-grpc.mod @@ -0,0 +1,5 @@ +module _ // Auto generated by https://github.com/bwplotka/bingo. DO NOT EDIT + +go 1.14 + +require google.golang.org/grpc/cmd/protoc-gen-go-grpc v0.0.0-20200723182653-9106c3fff523 diff --git a/.bingo/protoc-gen-gogofast.mod b/.bingo/protoc-gen-go.mod similarity index 57% rename from .bingo/protoc-gen-gogofast.mod rename to .bingo/protoc-gen-go.mod index c596d0970..0640b1ef7 100644 --- a/.bingo/protoc-gen-gogofast.mod +++ b/.bingo/protoc-gen-go.mod @@ -2,4 +2,4 @@ module _ // Auto generated by https://github.com/bwplotka/bingo. DO NOT EDIT go 1.14 -require github.com/gogo/protobuf v1.3.1 // protoc-gen-gogofast +require google.golang.org/protobuf v1.25.0 // cmd/protoc-gen-go diff --git a/.bingo/variables.env b/.bingo/variables.env index e825d3bc8..153d97ddb 100644 --- a/.bingo/variables.env +++ b/.bingo/variables.env @@ -1,22 +1,24 @@ -# Auto generated binary variables helper managed by https://github.com/bwplotka/bingo v0.2.2. DO NOT EDIT. +# Auto generated binary variables helper managed by https://github.com/bwplotka/bingo v0.3.0. DO NOT EDIT. # All tools are designed to be build inside $GOBIN. # Those variables will work only until 'bingo get' was invoked, or if tools were installed via Makefile's Variables.mk. -local gobin=$(go env GOBIN) +GOBIN=${GOBIN:=$(go env GOBIN)} -if [ -z "$gobin" ]; then - gobin="$(go env GOPATH)/bin" +if [ -z "$GOBIN" ]; then + GOBIN="$(go env GOPATH)/bin" fi -BINGO="${gobin}/bingo-v0.2.2" +BINGO="${GOBIN}/bingo-v0.3.0" -FAILLINT="${gobin}/faillint-v1.5.0" +FAILLINT="${GOBIN}/faillint-v1.5.0" -GOIMPORTS="${gobin}/goimports-v0.0.0-20200529172331-a64b76657301" +GOIMPORTS="${GOBIN}/goimports-v0.0.0-20200529172331-a64b76657301" -GOLANGCI_LINT="${gobin}/golangci-lint-v1.27.0" +GOLANGCI_LINT="${GOBIN}/golangci-lint-v1.27.0" -MISSPELL="${gobin}/misspell-v0.3.4" +MISSPELL="${GOBIN}/misspell-v0.3.4" -PROTOC_GEN_GOGOFAST="${gobin}/protoc-gen-gogofast-v1.3.1" +PROTOC_GEN_GO_GRPC="${GOBIN}/protoc-gen-go-grpc-v0.0.0-20200723182653-9106c3fff523" + +PROTOC_GEN_GO="${GOBIN}/protoc-gen-go-v1.25.0" diff --git a/.gitignore b/.gitignore index 826caa390..b818e03db 100644 --- a/.gitignore +++ b/.gitignore @@ -201,4 +201,5 @@ coverage.txt #vendor vendor/ -.envrc \ No newline at end of file +.envrc +.bin diff --git a/Makefile b/Makefile index 1868f27c0..5cb0bd328 100644 --- a/Makefile +++ b/Makefile @@ -2,16 +2,16 @@ include .bingo/Variables.mk SHELL=/bin/bash -PROVIDER_MODULES ?= $(shell ls -d $(PWD)/providers/*) +PROVIDER_MODULES ?= $(shell find $(PWD)/providers/ -name "go.mod" | grep -v ".bingo" | xargs dirname) MODULES ?= $(PROVIDER_MODULES) $(PWD)/ GOBIN ?= $(firstword $(subst :, ,${GOPATH}))/bin +// TODO(bwplotka): Move to buf. PROTOC_VERSION ?= 3.12.3 PROTOC ?= $(GOBIN)/protoc-$(PROTOC_VERSION) TMP_GOPATH ?= /tmp/gopath - GO111MODULE ?= on export GO111MODULE GOPROXY ?= https://proxy.golang.org @@ -45,8 +45,8 @@ fmt: $(GOIMPORTS) .PHONY: proto proto: ## Generates Go files from Thanos proto files. -proto: $(GOIMPORTS) $(PROTOC) $(PROTOC_GEN_GOGOFAST) ./grpctesting/testpb/test.proto - @GOIMPORTS_BIN="$(GOIMPORTS)" PROTOC_BIN="$(PROTOC)" PROTOC_GEN_GOGOFAST_BIN="$(PROTOC_GEN_GOGOFAST)" scripts/genproto.sh +proto: $(GOIMPORTS) $(PROTOC) $(PROTOC_GEN_GO) $(PROTOC_GEN_GO_GRPC) ./grpctesting/testpb/test.proto + @GOIMPORTS_BIN="$(GOIMPORTS)" PROTOC_BIN="$(PROTOC)" PROTOC_GEN_GO_BIN="$(PROTOC_GEN_GO)" PROTOC_GEN_GO_GRPC_BIN="$(PROTOC_GEN_GO_GRPC)" scripts/genproto.sh .PHONY: test test: @@ -61,6 +61,14 @@ test_module: @echo "Running tests for dir: $(DIR)" cd $(DIR) && go test -v -race ./... +.PHONY: deps +deps: + @echo "Running deps tidy for all modules: $(MODULES)" + for dir in $(MODULES) ; do \ + echo "$${dir}"; \ + cd $${dir} && go mod tidy; \ + done + .PHONY: lint # PROTIP: # Add @@ -68,20 +76,30 @@ test_module: # --mem-profile-path string Path to memory profile output file # to debug big allocations during linting. lint: ## Runs various static analysis tools against our code. -lint: fmt $(FAILLINT) $(GOLANGCI_LINT) $(MISSPELL) +lint: fmt proto @echo "Running lint for all modules: $(MODULES)" ./scripts/git-tree.sh + for dir in $(MODULES) ; do \ + $(MAKE) lint_module DIR=$${dir} ; \ + done + +.PHONY: lint_module +# PROTIP: +# Add +# --cpu-profile-path string Path to CPU profile output file +# --mem-profile-path string Path to memory profile output file +# to debug big allocations during linting. +lint_module: ## Runs various static analysis against our code. +lint_module: $(FAILLINT) $(GOLANGCI_LINT) $(MISSPELL) @echo ">> verifying modules being imported" - @$(FAILLINT) -paths "errors=github.com/pkg/errors,fmt.{Print,Printf,Println}" ./... + @cd $(DIR) && $(FAILLINT) -paths "errors=github.com/pkg/errors,fmt.{Print,Printf,Println}" ./... @echo ">> examining all of the Go files" - @go vet -stdmethods=false ./... + @cd $(DIR) && go vet -stdmethods=false ./... @echo ">> linting all of the Go files GOGC=${GOGC}" - @$(GOLANGCI_LINT) run - @echo ">> detecting misspells" - @find . -type f | grep -v vendor/ | grep -vE '\./\..*' | xargs $(MISSPELL) -error - @echo ">> ensuring generated proto files are up to date" - @$(MAKE) proto - ./scripts/git-tree.sh + @cd $(DIR) && $(GOLANGCI_LINT) run + @./scripts/git-tree.sh + +# TODO(bwplotka): Move to buf. $(PROTOC): @mkdir -p $(TMP_GOPATH) @echo ">> fetching protoc@${PROTOC_VERSION}" diff --git a/README.md b/README.md index 8f6ad51c3..dfeb8d370 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,7 @@ myServer := grpc.NewServer( * [`auth`](auth) - a customizable (via `AuthFunc`) piece of auth middleware #### Logging + * [`tags`](interceptors/tags) - a library that adds a `Tag` map to context, with data populated from request body * [`zap`](providers/zap) - integration of [zap](https://github.com/uber-go/zap) logging library into gRPC handlers. * [`logrus`](providers/logrus) - integration of [logrus](https://github.com/sirupsen/logrus) logging library into gRPC handlers. diff --git a/go.mod b/go.mod index 6654f4e2e..ab40ea18b 100644 --- a/go.mod +++ b/go.mod @@ -3,13 +3,13 @@ module github.com/grpc-ecosystem/go-grpc-middleware/v2 go 1.14 require ( - github.com/gogo/protobuf v1.2.1 - github.com/golang/protobuf v1.3.3 + github.com/golang/protobuf v1.4.3 github.com/opentracing/opentracing-go v1.1.0 github.com/pkg/errors v0.9.1 - github.com/stretchr/testify v1.4.0 + github.com/stretchr/testify v1.7.0 golang.org/x/net v0.0.0-20190620200207-3b0461eec859 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be - google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 // indirect - google.golang.org/grpc v1.28.0 + google.golang.org/grpc v1.30.1 + google.golang.org/grpc/examples v0.0.0-20200723182653-9106c3fff523 + google.golang.org/protobuf v1.25.0 ) diff --git a/go.sum b/go.sum index 0f8563412..42190ddfa 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,5 @@ cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= @@ -8,21 +7,29 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -31,8 +38,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -54,26 +61,43 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/grpc v1.19.0 h1:cfg4PD8YEdSFnm7qLV4++93WcmhH2nIUhMjhdCvl3j8= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200624020401-64a14ca9d1ad h1:uAwc13+y0Y8QZLTYhLCu6lHhnG99ecQU5FYTj8zxAng= +google.golang.org/genproto v0.0.0-20200624020401-64a14ca9d1ad/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.28.0 h1:bO/TA4OxCOummhSf10siHuG7vJOiwh7SpRpFZDkOgl4= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.30.1 h1:oJTcovwKSu7V3TaBKd0/AXOuJVHjTdGTutbMHIOgVEQ= +google.golang.org/grpc v1.30.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc/examples v0.0.0-20200723182653-9106c3fff523 h1:kp+Qy+IEZxLiQvPeK4Qq7ebiaMwiFSg3YVnohbEXLMg= +google.golang.org/grpc/examples v0.0.0-20200723182653-9106c3fff523/go.mod h1:5j1uub0jRGhRiSghIlrThmBUgcgLXOVJQ/l1getT4uo= +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= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/grpctesting/gogotestpb/fields.pb.go b/grpctesting/gogotestpb/fields.pb.go deleted file mode 100644 index ccd5fdafa..000000000 --- a/grpctesting/gogotestpb/fields.pb.go +++ /dev/null @@ -1,438 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: fields.proto - -// This file is used for grpctesting discovery of log fields from requests using reflection and gogo proto more tags. - -package gogotestpb - -import ( - fmt "fmt" - _ "github.com/gogo/protobuf/gogoproto" - proto "github.com/golang/protobuf/proto" - _ "github.com/golang/protobuf/ptypes/timestamp" - math "math" - time "time" -) - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf -var _ = time.Kitchen - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package - -type Metadata struct { - Tags []string `protobuf:"bytes,1,rep,name=tags,proto3" json:"tags,omitempty" log_field:"meta_tags"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Metadata) Reset() { *m = Metadata{} } -func (m *Metadata) String() string { return proto.CompactTextString(m) } -func (*Metadata) ProtoMessage() {} -func (*Metadata) Descriptor() ([]byte, []int) { - return fileDescriptor_d39ad626ec0e575e, []int{0} -} -func (m *Metadata) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Metadata.Unmarshal(m, b) -} -func (m *Metadata) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Metadata.Marshal(b, m, deterministic) -} -func (m *Metadata) XXX_Merge(src proto.Message) { - xxx_messageInfo_Metadata.Merge(m, src) -} -func (m *Metadata) XXX_Size() int { - return xxx_messageInfo_Metadata.Size(m) -} -func (m *Metadata) XXX_DiscardUnknown() { - xxx_messageInfo_Metadata.DiscardUnknown(m) -} - -var xxx_messageInfo_Metadata proto.InternalMessageInfo - -func (m *Metadata) GetTags() []string { - if m != nil { - return m.Tags - } - return nil -} - -type PingId struct { - Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty" log_field:"ping_id"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *PingId) Reset() { *m = PingId{} } -func (m *PingId) String() string { return proto.CompactTextString(m) } -func (*PingId) ProtoMessage() {} -func (*PingId) Descriptor() ([]byte, []int) { - return fileDescriptor_d39ad626ec0e575e, []int{1} -} -func (m *PingId) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_PingId.Unmarshal(m, b) -} -func (m *PingId) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_PingId.Marshal(b, m, deterministic) -} -func (m *PingId) XXX_Merge(src proto.Message) { - xxx_messageInfo_PingId.Merge(m, src) -} -func (m *PingId) XXX_Size() int { - return xxx_messageInfo_PingId.Size(m) -} -func (m *PingId) XXX_DiscardUnknown() { - xxx_messageInfo_PingId.DiscardUnknown(m) -} - -var xxx_messageInfo_PingId proto.InternalMessageInfo - -func (m *PingId) GetId() int32 { - if m != nil { - return m.Id - } - return 0 -} - -type Ping struct { - Id *PingId `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Ping) Reset() { *m = Ping{} } -func (m *Ping) String() string { return proto.CompactTextString(m) } -func (*Ping) ProtoMessage() {} -func (*Ping) Descriptor() ([]byte, []int) { - return fileDescriptor_d39ad626ec0e575e, []int{2} -} -func (m *Ping) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Ping.Unmarshal(m, b) -} -func (m *Ping) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Ping.Marshal(b, m, deterministic) -} -func (m *Ping) XXX_Merge(src proto.Message) { - xxx_messageInfo_Ping.Merge(m, src) -} -func (m *Ping) XXX_Size() int { - return xxx_messageInfo_Ping.Size(m) -} -func (m *Ping) XXX_DiscardUnknown() { - xxx_messageInfo_Ping.DiscardUnknown(m) -} - -var xxx_messageInfo_Ping proto.InternalMessageInfo - -func (m *Ping) GetId() *PingId { - if m != nil { - return m.Id - } - return nil -} - -func (m *Ping) GetValue() string { - if m != nil { - return m.Value - } - return "" -} - -type PingRequest struct { - Ping *Ping `protobuf:"bytes,1,opt,name=ping,proto3" json:"ping,omitempty"` - Meta *Metadata `protobuf:"bytes,2,opt,name=meta,proto3" json:"meta,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *PingRequest) Reset() { *m = PingRequest{} } -func (m *PingRequest) String() string { return proto.CompactTextString(m) } -func (*PingRequest) ProtoMessage() {} -func (*PingRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_d39ad626ec0e575e, []int{3} -} -func (m *PingRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_PingRequest.Unmarshal(m, b) -} -func (m *PingRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_PingRequest.Marshal(b, m, deterministic) -} -func (m *PingRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_PingRequest.Merge(m, src) -} -func (m *PingRequest) XXX_Size() int { - return xxx_messageInfo_PingRequest.Size(m) -} -func (m *PingRequest) XXX_DiscardUnknown() { - xxx_messageInfo_PingRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_PingRequest proto.InternalMessageInfo - -func (m *PingRequest) GetPing() *Ping { - if m != nil { - return m.Ping - } - return nil -} - -func (m *PingRequest) GetMeta() *Metadata { - if m != nil { - return m.Meta - } - return nil -} - -type Pong struct { - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty" log_field:"pong_id"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Pong) Reset() { *m = Pong{} } -func (m *Pong) String() string { return proto.CompactTextString(m) } -func (*Pong) ProtoMessage() {} -func (*Pong) Descriptor() ([]byte, []int) { - return fileDescriptor_d39ad626ec0e575e, []int{4} -} -func (m *Pong) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Pong.Unmarshal(m, b) -} -func (m *Pong) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Pong.Marshal(b, m, deterministic) -} -func (m *Pong) XXX_Merge(src proto.Message) { - xxx_messageInfo_Pong.Merge(m, src) -} -func (m *Pong) XXX_Size() int { - return xxx_messageInfo_Pong.Size(m) -} -func (m *Pong) XXX_DiscardUnknown() { - xxx_messageInfo_Pong.DiscardUnknown(m) -} - -var xxx_messageInfo_Pong proto.InternalMessageInfo - -func (m *Pong) GetId() string { - if m != nil { - return m.Id - } - return "" -} - -type PongRequest struct { - Pong *Pong `protobuf:"bytes,1,opt,name=pong,proto3" json:"pong,omitempty"` - Meta *Metadata `protobuf:"bytes,2,opt,name=meta,proto3" json:"meta,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *PongRequest) Reset() { *m = PongRequest{} } -func (m *PongRequest) String() string { return proto.CompactTextString(m) } -func (*PongRequest) ProtoMessage() {} -func (*PongRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_d39ad626ec0e575e, []int{5} -} -func (m *PongRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_PongRequest.Unmarshal(m, b) -} -func (m *PongRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_PongRequest.Marshal(b, m, deterministic) -} -func (m *PongRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_PongRequest.Merge(m, src) -} -func (m *PongRequest) XXX_Size() int { - return xxx_messageInfo_PongRequest.Size(m) -} -func (m *PongRequest) XXX_DiscardUnknown() { - xxx_messageInfo_PongRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_PongRequest proto.InternalMessageInfo - -func (m *PongRequest) GetPong() *Pong { - if m != nil { - return m.Pong - } - return nil -} - -func (m *PongRequest) GetMeta() *Metadata { - if m != nil { - return m.Meta - } - return nil -} - -type OneOfLogField struct { - // Types that are valid to be assigned to Identifier: - // *OneOfLogField_BarId - // *OneOfLogField_BazId - Identifier isOneOfLogField_Identifier `protobuf_oneof:"identifier"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *OneOfLogField) Reset() { *m = OneOfLogField{} } -func (m *OneOfLogField) String() string { return proto.CompactTextString(m) } -func (*OneOfLogField) ProtoMessage() {} -func (*OneOfLogField) Descriptor() ([]byte, []int) { - return fileDescriptor_d39ad626ec0e575e, []int{6} -} -func (m *OneOfLogField) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_OneOfLogField.Unmarshal(m, b) -} -func (m *OneOfLogField) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_OneOfLogField.Marshal(b, m, deterministic) -} -func (m *OneOfLogField) XXX_Merge(src proto.Message) { - xxx_messageInfo_OneOfLogField.Merge(m, src) -} -func (m *OneOfLogField) XXX_Size() int { - return xxx_messageInfo_OneOfLogField.Size(m) -} -func (m *OneOfLogField) XXX_DiscardUnknown() { - xxx_messageInfo_OneOfLogField.DiscardUnknown(m) -} - -var xxx_messageInfo_OneOfLogField proto.InternalMessageInfo - -type isOneOfLogField_Identifier interface { - isOneOfLogField_Identifier() -} - -type OneOfLogField_BarId struct { - BarId string `protobuf:"bytes,1,opt,name=bar_id,json=barId,proto3,oneof" json:"bar_id,omitempty" log_field:"bar_id"` -} -type OneOfLogField_BazId struct { - BazId string `protobuf:"bytes,2,opt,name=baz_id,json=bazId,proto3,oneof" json:"baz_id,omitempty" log_field:"baz_id"` -} - -func (*OneOfLogField_BarId) isOneOfLogField_Identifier() {} -func (*OneOfLogField_BazId) isOneOfLogField_Identifier() {} - -func (m *OneOfLogField) GetIdentifier() isOneOfLogField_Identifier { - if m != nil { - return m.Identifier - } - return nil -} - -func (m *OneOfLogField) GetBarId() string { - if x, ok := m.GetIdentifier().(*OneOfLogField_BarId); ok { - return x.BarId - } - return "" -} - -func (m *OneOfLogField) GetBazId() string { - if x, ok := m.GetIdentifier().(*OneOfLogField_BazId); ok { - return x.BazId - } - return "" -} - -// XXX_OneofWrappers is for the internal use of the proto package. -func (*OneOfLogField) XXX_OneofWrappers() []interface{} { - return []interface{}{ - (*OneOfLogField_BarId)(nil), - (*OneOfLogField_BazId)(nil), - } -} - -type GoGoProtoStdTime struct { - Timestamp *time.Time `protobuf:"bytes,1,opt,name=timestamp,proto3,stdtime" json:"timestamp,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *GoGoProtoStdTime) Reset() { *m = GoGoProtoStdTime{} } -func (m *GoGoProtoStdTime) String() string { return proto.CompactTextString(m) } -func (*GoGoProtoStdTime) ProtoMessage() {} -func (*GoGoProtoStdTime) Descriptor() ([]byte, []int) { - return fileDescriptor_d39ad626ec0e575e, []int{7} -} -func (m *GoGoProtoStdTime) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_GoGoProtoStdTime.Unmarshal(m, b) -} -func (m *GoGoProtoStdTime) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_GoGoProtoStdTime.Marshal(b, m, deterministic) -} -func (m *GoGoProtoStdTime) XXX_Merge(src proto.Message) { - xxx_messageInfo_GoGoProtoStdTime.Merge(m, src) -} -func (m *GoGoProtoStdTime) XXX_Size() int { - return xxx_messageInfo_GoGoProtoStdTime.Size(m) -} -func (m *GoGoProtoStdTime) XXX_DiscardUnknown() { - xxx_messageInfo_GoGoProtoStdTime.DiscardUnknown(m) -} - -var xxx_messageInfo_GoGoProtoStdTime proto.InternalMessageInfo - -func (m *GoGoProtoStdTime) GetTimestamp() *time.Time { - if m != nil { - return m.Timestamp - } - return nil -} - -func init() { - proto.RegisterType((*Metadata)(nil), "grpc_middleware.gogotestpb.Metadata") - proto.RegisterType((*PingId)(nil), "grpc_middleware.gogotestpb.PingId") - proto.RegisterType((*Ping)(nil), "grpc_middleware.gogotestpb.Ping") - proto.RegisterType((*PingRequest)(nil), "grpc_middleware.gogotestpb.PingRequest") - proto.RegisterType((*Pong)(nil), "grpc_middleware.gogotestpb.Pong") - proto.RegisterType((*PongRequest)(nil), "grpc_middleware.gogotestpb.PongRequest") - proto.RegisterType((*OneOfLogField)(nil), "grpc_middleware.gogotestpb.OneOfLogField") - proto.RegisterType((*GoGoProtoStdTime)(nil), "grpc_middleware.gogotestpb.GoGoProtoStdTime") -} - -func init() { proto.RegisterFile("fields.proto", fileDescriptor_d39ad626ec0e575e) } - -var fileDescriptor_d39ad626ec0e575e = []byte{ - // 431 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x92, 0xcf, 0xaa, 0xd3, 0x40, - 0x14, 0x87, 0x6f, 0x6a, 0x5a, 0xec, 0xe9, 0x15, 0x2e, 0xe3, 0x55, 0x6b, 0x17, 0xa6, 0x0c, 0x82, - 0xdd, 0x98, 0x60, 0x75, 0xa1, 0x2e, 0x5c, 0x64, 0xe1, 0xb5, 0xa0, 0xdc, 0x32, 0xde, 0x95, 0x9b, - 0x30, 0x71, 0xa6, 0xc3, 0x40, 0x92, 0x13, 0x93, 0xa9, 0x42, 0x41, 0x7c, 0x05, 0x97, 0x3e, 0x5d, - 0x5d, 0xf8, 0x06, 0x7d, 0x02, 0x99, 0x49, 0xff, 0x44, 0xa4, 0x2a, 0xb8, 0x9b, 0x61, 0x7e, 0xdf, - 0x99, 0xef, 0x1c, 0x0e, 0x9c, 0x2e, 0xb4, 0xcc, 0x44, 0x1d, 0x96, 0x15, 0x1a, 0x24, 0x23, 0x55, - 0x95, 0xef, 0x93, 0x5c, 0x0b, 0x91, 0xc9, 0x4f, 0xbc, 0x92, 0xa1, 0x42, 0x85, 0x46, 0xd6, 0xa6, - 0x4c, 0x47, 0xe7, 0xf6, 0xec, 0x62, 0x91, 0x3d, 0x35, 0xc4, 0x28, 0x50, 0x88, 0x2a, 0x93, 0x91, - 0xbb, 0xa5, 0xcb, 0x45, 0x64, 0x74, 0x2e, 0x6b, 0xc3, 0xf3, 0xb2, 0x09, 0xd0, 0x67, 0x70, 0xfd, - 0x8d, 0x34, 0x5c, 0x70, 0xc3, 0xc9, 0x43, 0xf0, 0x0d, 0x57, 0xf5, 0xd0, 0x1b, 0x5f, 0x9b, 0xf4, - 0xe3, 0xbb, 0x9b, 0x75, 0x70, 0x2b, 0x43, 0x95, 0x38, 0x85, 0xe7, 0x34, 0x97, 0x86, 0x27, 0xf6, - 0x9d, 0x32, 0x17, 0xa3, 0x8f, 0xa0, 0x37, 0xd7, 0x85, 0x9a, 0x09, 0xf2, 0x00, 0x3a, 0x5a, 0x0c, - 0xbd, 0xb1, 0x37, 0xe9, 0xc6, 0x77, 0x36, 0xeb, 0xe0, 0x66, 0x0b, 0x2b, 0x75, 0xa1, 0x12, 0x2d, - 0x28, 0xeb, 0x68, 0x41, 0xe7, 0xe0, 0x5b, 0x84, 0x4c, 0xf7, 0xc0, 0x60, 0x4a, 0xc3, 0xe3, 0x5d, - 0x85, 0xcd, 0x07, 0x96, 0x25, 0xe7, 0xd0, 0xfd, 0xc8, 0xb3, 0xa5, 0x1c, 0x76, 0xc6, 0xde, 0xa4, - 0xcf, 0x9a, 0x0b, 0xfd, 0x0c, 0x03, 0x9b, 0x61, 0xf2, 0xc3, 0x52, 0xd6, 0x86, 0x3c, 0x01, 0xdf, - 0x7e, 0xb8, 0x2d, 0x3d, 0xfe, 0x5b, 0x69, 0xe6, 0xd2, 0xe4, 0x29, 0xf8, 0xb6, 0x3b, 0x57, 0x79, - 0x30, 0xbd, 0xff, 0x27, 0x6a, 0x37, 0x2c, 0xe6, 0x08, 0x1a, 0x81, 0x3f, 0xc7, 0x42, 0xb5, 0x26, - 0xd0, 0xff, 0x7d, 0x02, 0xd8, 0x9a, 0x80, 0xf5, 0xc5, 0x5f, 0x7d, 0xf1, 0x1f, 0x7d, 0xd1, 0xf9, - 0xe2, 0x7f, 0xf9, 0x7e, 0x81, 0x1b, 0x97, 0x85, 0xbc, 0x5c, 0xbc, 0x46, 0xf5, 0xd2, 0xda, 0x91, - 0x08, 0x7a, 0x29, 0xaf, 0x92, 0xbd, 0xfc, 0xed, 0xcd, 0x3a, 0x20, 0x2d, 0xf9, 0xe6, 0x91, 0xbe, - 0x3a, 0x61, 0xdd, 0x94, 0x57, 0xb3, 0x2d, 0xb0, 0xb2, 0x40, 0xe7, 0x08, 0xb0, 0x3a, 0x00, 0xab, - 0x99, 0x88, 0x4f, 0x01, 0xb4, 0x90, 0x85, 0xd1, 0x0b, 0x2d, 0x2b, 0xca, 0xe0, 0xec, 0x02, 0x2f, - 0x70, 0x6e, 0x97, 0xef, 0xad, 0x11, 0x57, 0x3a, 0x97, 0xe4, 0x05, 0xf4, 0xf7, 0x6b, 0xb9, 0x9d, - 0xc4, 0x28, 0x6c, 0x16, 0x37, 0xdc, 0x2d, 0x6e, 0x78, 0xb5, 0x4b, 0xc4, 0xfe, 0xd7, 0xef, 0x81, - 0xc7, 0x0e, 0x48, 0x7c, 0xf6, 0xed, 0xc7, 0xbd, 0x93, 0x77, 0x70, 0xe8, 0x3a, 0xed, 0x39, 0xec, - 0xf1, 0xcf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7b, 0x9a, 0xee, 0xac, 0x3f, 0x03, 0x00, 0x00, -} diff --git a/grpctesting/gogotestpb/fields.proto b/grpctesting/gogotestpb/fields.proto deleted file mode 100644 index 27de34520..000000000 --- a/grpctesting/gogotestpb/fields.proto +++ /dev/null @@ -1,49 +0,0 @@ -syntax = "proto3"; - -// This file is used for grpctesting discovery of log fields from requests using reflection and gogo proto more tags. -package grpc_middleware.gogotestpb; - -import "gogoproto/gogo.proto"; -import "google/protobuf/timestamp.proto"; - -option (gogoproto.gogoproto_import) = false; - -option go_package = "gogotestpb"; - -message Metadata { - repeated string tags = 1 [(gogoproto.moretags) = "log_field:\"meta_tags\""]; -} - -message PingId { - int32 id = 1 [(gogoproto.moretags) = "log_field:\"ping_id\""]; -} - -message Ping { - PingId id = 1; - string value = 2; -} - -message PingRequest { - Ping ping = 1; - Metadata meta = 2; -} - -message Pong { - string id = 1 [(gogoproto.moretags) = "log_field:\"pong_id\""]; -} - -message PongRequest { - Pong pong = 1; - Metadata meta = 2; -} - -message OneOfLogField { - oneof identifier { - string bar_id = 1 [(gogoproto.moretags) = "log_field:\"bar_id\""]; - string baz_id = 2 [(gogoproto.moretags) = "log_field:\"baz_id\""]; - } -} - -message GoGoProtoStdTime { - google.protobuf.Timestamp timestamp = 1 [(gogoproto.stdtime) = true]; -} diff --git a/grpctesting/pingservice.go b/grpctesting/pingservice.go index 6acbf23e5..714bfc97b 100644 --- a/grpctesting/pingservice.go +++ b/grpctesting/pingservice.go @@ -25,7 +25,12 @@ const ( ListResponseCount = 100 ) +// Interface implementation assert. +var _ testpb.TestServiceServer = &TestPingService{} + type TestPingService struct { + testpb.UnimplementedTestServiceServer + T *testing.T } @@ -47,6 +52,7 @@ func (s *TestPingService) PingList(ping *testpb.PingRequest, stream testpb.TestS if ping.ErrorCodeReturned != 0 { return status.Errorf(codes.Code(ping.ErrorCodeReturned), "foobar") } + // Send user trailers and headers. for i := 0; i < ListResponseCount; i++ { if err := stream.Send(&testpb.PingResponse{Value: ping.Value, Counter: int32(i)}); err != nil { diff --git a/grpctesting/pingservice_test.go b/grpctesting/pingservice_test.go new file mode 100644 index 000000000..5efe0f8fa --- /dev/null +++ b/grpctesting/pingservice_test.go @@ -0,0 +1,90 @@ +package grpctesting + +import ( + "context" + "fmt" + "net" + "testing" + "time" + + "github.com/stretchr/testify/require" + "google.golang.org/grpc" + + "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting/testpb" +) + +func TestPingServiceOnWire(t *testing.T) { + stopped := make(chan error) + serverListener, err := net.Listen("tcp", "127.0.0.1:0") + require.NoError(t, err, "must be able to allocate a port for serverListener") + + server := grpc.NewServer() + testpb.RegisterTestServiceServer(server, &TestPingService{T: t}) + + go func() { + defer close(stopped) + stopped <- server.Serve(serverListener) + }() + defer func() { + server.Stop() + <-stopped + }() + + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) + defer cancel() + + // This is the point where we hook up the interceptor. + clientConn, err := grpc.DialContext( + ctx, + serverListener.Addr().String(), + grpc.WithInsecure(), + grpc.WithBlock(), + ) + require.NoError(t, err, "must not error on client Dial") + + testClient := testpb.NewTestServiceClient(clientConn) + select { + case err := <-stopped: + t.Fatal("gRPC server stopped prematurely", err) + default: + } + + r, err := testClient.PingEmpty(context.Background(), &testpb.Empty{}) + require.NoError(t, err) + require.Equal(t, "default_response_value", r.Value) + require.Equal(t, int32(0), r.Counter) + + r2, err := testClient.Ping(context.Background(), &testpb.PingRequest{Value: "24"}) + require.NoError(t, err) + require.Equal(t, "24", r2.Value) + require.Equal(t, int32(0), r2.Counter) + + _, err = testClient.PingError(context.Background(), &testpb.PingRequest{Value: "24"}) + require.Error(t, err) + + l, err := testClient.PingList(context.Background(), &testpb.PingRequest{Value: "24"}) + require.NoError(t, err) + for i := 0; i < ListResponseCount; i++ { + r, err := l.Recv() + require.NoError(t, err) + require.Equal(t, "24", r.Value) + require.Equal(t, int32(i), r.Counter) + } + + s, err := testClient.PingStream(context.Background()) + require.NoError(t, err) + for i := 0; i < ListResponseCount; i++ { + require.NoError(t, s.Send(&testpb.PingRequest{Value: fmt.Sprintf("%v", i)})) + + r, err := s.Recv() + require.NoError(t, err) + require.Equal(t, fmt.Sprintf("%v", i), r.Value) + require.Equal(t, int32(i), r.Counter) + } + + select { + case err := <-stopped: + t.Fatal("gRPC server stopped prematurely", err) + default: + } +} diff --git a/grpctesting/testpb/test.pb.go b/grpctesting/testpb/test.pb.go index bba2dd4f3..2e07a7648 100644 --- a/grpctesting/testpb/test.pb.go +++ b/grpctesting/testpb/test.pb.go @@ -1,1037 +1,332 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.25.0 +// protoc v3.12.3 // source: test.proto package testpb import ( - context "context" - fmt "fmt" - io "io" - math "math" + reflect "reflect" + sync "sync" - proto "github.com/gogo/protobuf/proto" - grpc "google.golang.org/grpc" + proto "github.com/golang/protobuf/proto" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" ) -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package +// This is a compile-time assertion that a sufficiently up-to-date version +// of the legacy proto package is being used. +const _ = proto.ProtoPackageIsVersion4 type Empty struct { - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields } -func (m *Empty) Reset() { *m = Empty{} } -func (m *Empty) String() string { return proto.CompactTextString(m) } -func (*Empty) ProtoMessage() {} -func (*Empty) Descriptor() ([]byte, []int) { - return fileDescriptor_c161fcfdc0c3ff1e, []int{0} -} -func (m *Empty) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *Empty) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_Empty.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalTo(b) - if err != nil { - return nil, err - } - return b[:n], nil +func (x *Empty) Reset() { + *x = Empty{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } } -func (m *Empty) XXX_Merge(src proto.Message) { - xxx_messageInfo_Empty.Merge(m, src) -} -func (m *Empty) XXX_Size() int { - return m.Size() -} -func (m *Empty) XXX_DiscardUnknown() { - xxx_messageInfo_Empty.DiscardUnknown(m) -} -var xxx_messageInfo_Empty proto.InternalMessageInfo - -type PingRequest struct { - Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` - SleepTimeMs int32 `protobuf:"varint,2,opt,name=sleep_time_ms,json=sleepTimeMs,proto3" json:"sleep_time_ms,omitempty"` - ErrorCodeReturned uint32 `protobuf:"varint,3,opt,name=error_code_returned,json=errorCodeReturned,proto3" json:"error_code_returned,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` +func (x *Empty) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *PingRequest) Reset() { *m = PingRequest{} } -func (m *PingRequest) String() string { return proto.CompactTextString(m) } -func (*PingRequest) ProtoMessage() {} -func (*PingRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_c161fcfdc0c3ff1e, []int{1} -} -func (m *PingRequest) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *PingRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_PingRequest.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalTo(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *PingRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_PingRequest.Merge(m, src) -} -func (m *PingRequest) XXX_Size() int { - return m.Size() -} -func (m *PingRequest) XXX_DiscardUnknown() { - xxx_messageInfo_PingRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_PingRequest proto.InternalMessageInfo - -func (m *PingRequest) GetValue() string { - if m != nil { - return m.Value - } - return "" -} +func (*Empty) ProtoMessage() {} -func (m *PingRequest) GetSleepTimeMs() int32 { - if m != nil { - return m.SleepTimeMs - } - return 0 -} - -func (m *PingRequest) GetErrorCodeReturned() uint32 { - if m != nil { - return m.ErrorCodeReturned - } - return 0 -} - -type PingResponse struct { - Value string `protobuf:"bytes,1,opt,name=Value,proto3" json:"Value,omitempty"` - Counter int32 `protobuf:"varint,2,opt,name=counter,proto3" json:"counter,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *PingResponse) Reset() { *m = PingResponse{} } -func (m *PingResponse) String() string { return proto.CompactTextString(m) } -func (*PingResponse) ProtoMessage() {} -func (*PingResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_c161fcfdc0c3ff1e, []int{2} -} -func (m *PingResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *PingResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_PingResponse.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalTo(b) - if err != nil { - return nil, err +func (x *Empty) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) } - return b[:n], nil - } -} -func (m *PingResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_PingResponse.Merge(m, src) -} -func (m *PingResponse) XXX_Size() int { - return m.Size() -} -func (m *PingResponse) XXX_DiscardUnknown() { - xxx_messageInfo_PingResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_PingResponse proto.InternalMessageInfo - -func (m *PingResponse) GetValue() string { - if m != nil { - return m.Value + return ms } - return "" -} - -func (m *PingResponse) GetCounter() int32 { - if m != nil { - return m.Counter - } - return 0 + return mi.MessageOf(x) } -func init() { - proto.RegisterType((*Empty)(nil), "grpc_middleware.testpb.Empty") - proto.RegisterType((*PingRequest)(nil), "grpc_middleware.testpb.PingRequest") - proto.RegisterType((*PingResponse)(nil), "grpc_middleware.testpb.PingResponse") -} - -func init() { proto.RegisterFile("test.proto", fileDescriptor_c161fcfdc0c3ff1e) } - -var fileDescriptor_c161fcfdc0c3ff1e = []byte{ - // 320 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x52, 0xcd, 0x4a, 0x33, 0x31, - 0x14, 0x6d, 0xbe, 0x7e, 0x6d, 0xed, 0xad, 0x5d, 0x18, 0x8b, 0x0c, 0x82, 0xa5, 0x44, 0x17, 0xb3, - 0x1a, 0x8a, 0xee, 0x5d, 0x28, 0xee, 0x14, 0x34, 0x2d, 0x82, 0x82, 0x0c, 0xed, 0xcc, 0xa5, 0x04, - 0x9a, 0x49, 0x4c, 0x32, 0x2d, 0x3e, 0x9f, 0x1b, 0x97, 0x3e, 0x82, 0xf4, 0x49, 0x24, 0x69, 0x85, - 0x2e, 0xb4, 0x74, 0xd1, 0xe5, 0x3d, 0xe7, 0x70, 0x7e, 0x42, 0x00, 0x1c, 0x5a, 0x97, 0x68, 0xa3, - 0x9c, 0xa2, 0x47, 0x13, 0xa3, 0xb3, 0x54, 0x8a, 0x3c, 0x9f, 0xe2, 0x7c, 0x64, 0x30, 0xf1, 0x9c, - 0x1e, 0xb3, 0x06, 0xd4, 0x6e, 0xa4, 0x76, 0x6f, 0x6c, 0x0e, 0xad, 0x7b, 0x51, 0x4c, 0x38, 0xbe, - 0x96, 0x68, 0x1d, 0xed, 0x40, 0x6d, 0x36, 0x9a, 0x96, 0x18, 0x91, 0x1e, 0x89, 0x9b, 0x7c, 0x79, - 0x50, 0x06, 0x6d, 0x3b, 0x45, 0xd4, 0xa9, 0x13, 0x12, 0x53, 0x69, 0xa3, 0x7f, 0x3d, 0x12, 0xd7, - 0x78, 0x2b, 0x80, 0x43, 0x21, 0xf1, 0xce, 0xd2, 0x04, 0x0e, 0xd1, 0x18, 0x65, 0xd2, 0x4c, 0xe5, - 0x98, 0x1a, 0x74, 0xa5, 0x29, 0x30, 0x8f, 0xaa, 0x3d, 0x12, 0xb7, 0xf9, 0x41, 0xa0, 0xae, 0x55, - 0x8e, 0x7c, 0x45, 0xb0, 0x4b, 0xd8, 0x5f, 0x06, 0x5b, 0xad, 0x0a, 0x8b, 0x3e, 0xf9, 0x71, 0x3d, - 0x39, 0x1c, 0x34, 0x82, 0x46, 0xa6, 0xca, 0xc2, 0xa1, 0x59, 0x65, 0xfe, 0x9c, 0xe7, 0xef, 0x55, - 0x68, 0x0d, 0xd1, 0xba, 0x01, 0x9a, 0x99, 0xc8, 0x90, 0x72, 0x68, 0x7a, 0xbf, 0xb0, 0x8a, 0x9e, - 0x24, 0xbf, 0xef, 0x4e, 0x02, 0x7d, 0x7c, 0xf6, 0x17, 0xbd, 0xde, 0x88, 0x55, 0xe8, 0x00, 0xfe, - 0x7b, 0x84, 0x9e, 0x6e, 0xd6, 0x87, 0xa7, 0xdb, 0xda, 0xf4, 0x61, 0x55, 0xd4, 0xbf, 0xc8, 0x76, - 0xce, 0x9b, 0xd7, 0xb0, 0x0a, 0x7d, 0x82, 0x3d, 0xaf, 0xbf, 0x15, 0xd6, 0xed, 0xb4, 0x6b, 0x9f, - 0xd0, 0x17, 0x00, 0x8f, 0x0d, 0x9c, 0xc1, 0x91, 0xdc, 0xa9, 0x79, 0x4c, 0xfa, 0xe4, 0xaa, 0xf3, - 0xb1, 0xe8, 0x92, 0xcf, 0x45, 0x97, 0x7c, 0x2d, 0xba, 0xe4, 0xb9, 0xbe, 0x14, 0x8e, 0xeb, 0xe1, - 0xf3, 0x5e, 0x7c, 0x07, 0x00, 0x00, 0xff, 0xff, 0x92, 0x21, 0xeb, 0x3f, 0xca, 0x02, 0x00, 0x00, -} - -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ grpc.ClientConn - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion4 - -// TestServiceClient is the client API for TestService service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type TestServiceClient interface { - PingEmpty(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*PingResponse, error) - Ping(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*PingResponse, error) - PingError(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*Empty, error) - PingList(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (TestService_PingListClient, error) - PingStream(ctx context.Context, opts ...grpc.CallOption) (TestService_PingStreamClient, error) -} - -type testServiceClient struct { - cc *grpc.ClientConn -} - -func NewTestServiceClient(cc *grpc.ClientConn) TestServiceClient { - return &testServiceClient{cc} -} - -func (c *testServiceClient) PingEmpty(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*PingResponse, error) { - out := new(PingResponse) - err := c.cc.Invoke(ctx, "/grpc_middleware.testpb.TestService/PingEmpty", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *testServiceClient) Ping(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*PingResponse, error) { - out := new(PingResponse) - err := c.cc.Invoke(ctx, "/grpc_middleware.testpb.TestService/Ping", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *testServiceClient) PingError(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*Empty, error) { - out := new(Empty) - err := c.cc.Invoke(ctx, "/grpc_middleware.testpb.TestService/PingError", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *testServiceClient) PingList(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (TestService_PingListClient, error) { - stream, err := c.cc.NewStream(ctx, &_TestService_serviceDesc.Streams[0], "/grpc_middleware.testpb.TestService/PingList", opts...) - if err != nil { - return nil, err - } - x := &testServicePingListClient{stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -type TestService_PingListClient interface { - Recv() (*PingResponse, error) - grpc.ClientStream -} - -type testServicePingListClient struct { - grpc.ClientStream -} - -func (x *testServicePingListClient) Recv() (*PingResponse, error) { - m := new(PingResponse) - if err := x.ClientStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - -func (c *testServiceClient) PingStream(ctx context.Context, opts ...grpc.CallOption) (TestService_PingStreamClient, error) { - stream, err := c.cc.NewStream(ctx, &_TestService_serviceDesc.Streams[1], "/grpc_middleware.testpb.TestService/PingStream", opts...) - if err != nil { - return nil, err - } - x := &testServicePingStreamClient{stream} - return x, nil -} - -type TestService_PingStreamClient interface { - Send(*PingRequest) error - Recv() (*PingResponse, error) - grpc.ClientStream +// Deprecated: Use Empty.ProtoReflect.Descriptor instead. +func (*Empty) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{0} } -type testServicePingStreamClient struct { - grpc.ClientStream -} +type PingRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -func (x *testServicePingStreamClient) Send(m *PingRequest) error { - return x.ClientStream.SendMsg(m) + Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` + SleepTimeMs int32 `protobuf:"varint,2,opt,name=sleep_time_ms,json=sleepTimeMs,proto3" json:"sleep_time_ms,omitempty"` + ErrorCodeReturned uint32 `protobuf:"varint,3,opt,name=error_code_returned,json=errorCodeReturned,proto3" json:"error_code_returned,omitempty"` } -func (x *testServicePingStreamClient) Recv() (*PingResponse, error) { - m := new(PingResponse) - if err := x.ClientStream.RecvMsg(m); err != nil { - return nil, err +func (x *PingRequest) Reset() { + *x = PingRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } - return m, nil } -// TestServiceServer is the server API for TestService service. -type TestServiceServer interface { - PingEmpty(context.Context, *Empty) (*PingResponse, error) - Ping(context.Context, *PingRequest) (*PingResponse, error) - PingError(context.Context, *PingRequest) (*Empty, error) - PingList(*PingRequest, TestService_PingListServer) error - PingStream(TestService_PingStreamServer) error +func (x *PingRequest) String() string { + return protoimpl.X.MessageStringOf(x) } -func RegisterTestServiceServer(s *grpc.Server, srv TestServiceServer) { - s.RegisterService(&_TestService_serviceDesc, srv) -} +func (*PingRequest) ProtoMessage() {} -func _TestService_PingEmpty_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(TestServiceServer).PingEmpty(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/grpc_middleware.testpb.TestService/PingEmpty", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(TestServiceServer).PingEmpty(ctx, req.(*Empty)) +func (x *PingRequest) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms } - return interceptor(ctx, in, info, handler) + return mi.MessageOf(x) } -func _TestService_Ping_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(PingRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(TestServiceServer).Ping(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/grpc_middleware.testpb.TestService/Ping", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(TestServiceServer).Ping(ctx, req.(*PingRequest)) - } - return interceptor(ctx, in, info, handler) +// Deprecated: Use PingRequest.ProtoReflect.Descriptor instead. +func (*PingRequest) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{1} } -func _TestService_PingError_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(PingRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(TestServiceServer).PingError(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/grpc_middleware.testpb.TestService/PingError", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(TestServiceServer).PingError(ctx, req.(*PingRequest)) +func (x *PingRequest) GetValue() string { + if x != nil { + return x.Value } - return interceptor(ctx, in, info, handler) + return "" } -func _TestService_PingList_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(PingRequest) - if err := stream.RecvMsg(m); err != nil { - return err +func (x *PingRequest) GetSleepTimeMs() int32 { + if x != nil { + return x.SleepTimeMs } - return srv.(TestServiceServer).PingList(m, &testServicePingListServer{stream}) -} - -type TestService_PingListServer interface { - Send(*PingResponse) error - grpc.ServerStream -} - -type testServicePingListServer struct { - grpc.ServerStream -} - -func (x *testServicePingListServer) Send(m *PingResponse) error { - return x.ServerStream.SendMsg(m) -} - -func _TestService_PingStream_Handler(srv interface{}, stream grpc.ServerStream) error { - return srv.(TestServiceServer).PingStream(&testServicePingStreamServer{stream}) -} - -type TestService_PingStreamServer interface { - Send(*PingResponse) error - Recv() (*PingRequest, error) - grpc.ServerStream -} - -type testServicePingStreamServer struct { - grpc.ServerStream -} - -func (x *testServicePingStreamServer) Send(m *PingResponse) error { - return x.ServerStream.SendMsg(m) + return 0 } -func (x *testServicePingStreamServer) Recv() (*PingRequest, error) { - m := new(PingRequest) - if err := x.ServerStream.RecvMsg(m); err != nil { - return nil, err +func (x *PingRequest) GetErrorCodeReturned() uint32 { + if x != nil { + return x.ErrorCodeReturned } - return m, nil -} - -var _TestService_serviceDesc = grpc.ServiceDesc{ - ServiceName: "grpc_middleware.testpb.TestService", - HandlerType: (*TestServiceServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "PingEmpty", - Handler: _TestService_PingEmpty_Handler, - }, - { - MethodName: "Ping", - Handler: _TestService_Ping_Handler, - }, - { - MethodName: "PingError", - Handler: _TestService_PingError_Handler, - }, - }, - Streams: []grpc.StreamDesc{ - { - StreamName: "PingList", - Handler: _TestService_PingList_Handler, - ServerStreams: true, - }, - { - StreamName: "PingStream", - Handler: _TestService_PingStream_Handler, - ServerStreams: true, - ClientStreams: true, - }, - }, - Metadata: "test.proto", + return 0 } -func (m *Empty) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} +type PingResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -func (m *Empty) MarshalTo(dAtA []byte) (int, error) { - var i int - _ = i - var l int - _ = l - if m.XXX_unrecognized != nil { - i += copy(dAtA[i:], m.XXX_unrecognized) - } - return i, nil + Value string `protobuf:"bytes,1,opt,name=Value,proto3" json:"Value,omitempty"` + Counter int32 `protobuf:"varint,2,opt,name=counter,proto3" json:"counter,omitempty"` } -func (m *PingRequest) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) - if err != nil { - return nil, err +func (x *PingResponse) Reset() { + *x = PingResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } - return dAtA[:n], nil } -func (m *PingRequest) MarshalTo(dAtA []byte) (int, error) { - var i int - _ = i - var l int - _ = l - if len(m.Value) > 0 { - dAtA[i] = 0xa - i++ - i = encodeVarintTest(dAtA, i, uint64(len(m.Value))) - i += copy(dAtA[i:], m.Value) - } - if m.SleepTimeMs != 0 { - dAtA[i] = 0x10 - i++ - i = encodeVarintTest(dAtA, i, uint64(m.SleepTimeMs)) - } - if m.ErrorCodeReturned != 0 { - dAtA[i] = 0x18 - i++ - i = encodeVarintTest(dAtA, i, uint64(m.ErrorCodeReturned)) - } - if m.XXX_unrecognized != nil { - i += copy(dAtA[i:], m.XXX_unrecognized) - } - return i, nil +func (x *PingResponse) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *PingResponse) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} +func (*PingResponse) ProtoMessage() {} -func (m *PingResponse) MarshalTo(dAtA []byte) (int, error) { - var i int - _ = i - var l int - _ = l - if len(m.Value) > 0 { - dAtA[i] = 0xa - i++ - i = encodeVarintTest(dAtA, i, uint64(len(m.Value))) - i += copy(dAtA[i:], m.Value) - } - if m.Counter != 0 { - dAtA[i] = 0x10 - i++ - i = encodeVarintTest(dAtA, i, uint64(m.Counter)) - } - if m.XXX_unrecognized != nil { - i += copy(dAtA[i:], m.XXX_unrecognized) +func (x *PingResponse) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms } - return i, nil + return mi.MessageOf(x) } -func encodeVarintTest(dAtA []byte, offset int, v uint64) int { - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return offset + 1 -} -func (m *Empty) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.XXX_unrecognized != nil { - n += len(m.XXX_unrecognized) - } - return n +// Deprecated: Use PingResponse.ProtoReflect.Descriptor instead. +func (*PingResponse) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{2} } -func (m *PingRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Value) - if l > 0 { - n += 1 + l + sovTest(uint64(l)) - } - if m.SleepTimeMs != 0 { - n += 1 + sovTest(uint64(m.SleepTimeMs)) - } - if m.ErrorCodeReturned != 0 { - n += 1 + sovTest(uint64(m.ErrorCodeReturned)) - } - if m.XXX_unrecognized != nil { - n += len(m.XXX_unrecognized) +func (x *PingResponse) GetValue() string { + if x != nil { + return x.Value } - return n + return "" } -func (m *PingResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Value) - if l > 0 { - n += 1 + l + sovTest(uint64(l)) - } - if m.Counter != 0 { - n += 1 + sovTest(uint64(m.Counter)) - } - if m.XXX_unrecognized != nil { - n += len(m.XXX_unrecognized) +func (x *PingResponse) GetCounter() int32 { + if x != nil { + return x.Counter } - return n + return 0 } -func sovTest(x uint64) (n int) { - for { - n++ - x >>= 7 - if x == 0 { - break - } - } - return n +var File_test_proto protoreflect.FileDescriptor + +var file_test_proto_rawDesc = []byte{ + 0x0a, 0x0a, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x16, 0x67, 0x72, + 0x70, 0x63, 0x5f, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x74, 0x65, + 0x73, 0x74, 0x70, 0x62, 0x22, 0x07, 0x0a, 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x77, 0x0a, + 0x0b, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x5f, 0x74, 0x69, 0x6d, 0x65, + 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x73, 0x6c, 0x65, 0x65, 0x70, + 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, + 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x11, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, + 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x22, 0x3e, 0x0a, 0x0c, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x18, 0x0a, 0x07, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x32, 0xc3, 0x03, 0x0a, 0x0b, 0x54, 0x65, 0x73, 0x74, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x52, 0x0a, 0x09, 0x50, 0x69, 0x6e, 0x67, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x12, 0x1d, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x6d, 0x69, 0x64, 0x64, 0x6c, + 0x65, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x1a, 0x24, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, + 0x77, 0x61, 0x72, 0x65, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x50, 0x69, 0x6e, 0x67, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x53, 0x0a, 0x04, 0x50, 0x69, + 0x6e, 0x67, 0x12, 0x23, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, + 0x77, 0x61, 0x72, 0x65, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x50, 0x69, 0x6e, 0x67, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x6d, + 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, + 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x51, 0x0a, 0x09, 0x50, 0x69, 0x6e, 0x67, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x23, 0x2e, 0x67, + 0x72, 0x70, 0x63, 0x5f, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x74, + 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, + 0x61, 0x72, 0x65, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x22, 0x00, 0x12, 0x59, 0x0a, 0x08, 0x50, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x23, + 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, + 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x6d, 0x69, 0x64, 0x64, 0x6c, + 0x65, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x50, 0x69, 0x6e, + 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x5d, 0x0a, + 0x0a, 0x50, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x23, 0x2e, 0x67, 0x72, + 0x70, 0x63, 0x5f, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x74, 0x65, + 0x73, 0x74, 0x70, 0x62, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x24, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, + 0x72, 0x65, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x42, 0x0b, 0x5a, 0x09, + 0x2e, 0x2e, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } -func sozTest(x uint64) (n int) { - return sovTest(uint64((x << 1) ^ uint64((int64(x) >> 63)))) -} -func (m *Empty) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTest - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: Empty: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: Empty: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - default: - iNdEx = preIndex - skippy, err := skipTest(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthTest - } - if (iNdEx + skippy) < 0 { - return ErrInvalidLengthTest - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) - iNdEx += skippy - } - } - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *PingRequest) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTest - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: PingRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: PingRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTest - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthTest - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTest - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Value = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field SleepTimeMs", wireType) - } - m.SleepTimeMs = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTest - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.SleepTimeMs |= int32(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field ErrorCodeReturned", wireType) - } - m.ErrorCodeReturned = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTest - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.ErrorCodeReturned |= uint32(b&0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skipTest(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthTest - } - if (iNdEx + skippy) < 0 { - return ErrInvalidLengthTest - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) - iNdEx += skippy - } - } +var ( + file_test_proto_rawDescOnce sync.Once + file_test_proto_rawDescData = file_test_proto_rawDesc +) - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *PingResponse) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTest - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break +func file_test_proto_rawDescGZIP() []byte { + file_test_proto_rawDescOnce.Do(func() { + file_test_proto_rawDescData = protoimpl.X.CompressGZIP(file_test_proto_rawDescData) + }) + return file_test_proto_rawDescData +} + +var file_test_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_test_proto_goTypes = []interface{}{ + (*Empty)(nil), // 0: grpc_middleware.testpb.Empty + (*PingRequest)(nil), // 1: grpc_middleware.testpb.PingRequest + (*PingResponse)(nil), // 2: grpc_middleware.testpb.PingResponse +} +var file_test_proto_depIdxs = []int32{ + 0, // 0: grpc_middleware.testpb.TestService.PingEmpty:input_type -> grpc_middleware.testpb.Empty + 1, // 1: grpc_middleware.testpb.TestService.Ping:input_type -> grpc_middleware.testpb.PingRequest + 1, // 2: grpc_middleware.testpb.TestService.PingError:input_type -> grpc_middleware.testpb.PingRequest + 1, // 3: grpc_middleware.testpb.TestService.PingList:input_type -> grpc_middleware.testpb.PingRequest + 1, // 4: grpc_middleware.testpb.TestService.PingStream:input_type -> grpc_middleware.testpb.PingRequest + 2, // 5: grpc_middleware.testpb.TestService.PingEmpty:output_type -> grpc_middleware.testpb.PingResponse + 2, // 6: grpc_middleware.testpb.TestService.Ping:output_type -> grpc_middleware.testpb.PingResponse + 0, // 7: grpc_middleware.testpb.TestService.PingError:output_type -> grpc_middleware.testpb.Empty + 2, // 8: grpc_middleware.testpb.TestService.PingList:output_type -> grpc_middleware.testpb.PingResponse + 2, // 9: grpc_middleware.testpb.TestService.PingStream:output_type -> grpc_middleware.testpb.PingResponse + 5, // [5:10] is the sub-list for method output_type + 0, // [0:5] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_test_proto_init() } +func file_test_proto_init() { + if File_test_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_test_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Empty); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil } } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: PingResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: PingResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTest - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthTest - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTest - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Value = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Counter", wireType) - } - m.Counter = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTest - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Counter |= int32(b&0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skipTest(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthTest - } - if (iNdEx + skippy) < 0 { - return ErrInvalidLengthTest - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func skipTest(dAtA []byte) (n int, err error) { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowTest - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break + file_test_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PingRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil } } - wireType := int(wire & 0x7) - switch wireType { - case 0: - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowTest - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - iNdEx++ - if dAtA[iNdEx-1] < 0x80 { - break - } - } - return iNdEx, nil - case 1: - iNdEx += 8 - return iNdEx, nil - case 2: - var length int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowTest - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - length |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } + file_test_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PingResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil } - if length < 0 { - return 0, ErrInvalidLengthTest - } - iNdEx += length - if iNdEx < 0 { - return 0, ErrInvalidLengthTest - } - return iNdEx, nil - case 3: - for { - var innerWire uint64 - var start int = iNdEx - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowTest - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - innerWire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - innerWireType := int(innerWire & 0x7) - if innerWireType == 4 { - break - } - next, err := skipTest(dAtA[start:]) - if err != nil { - return 0, err - } - iNdEx = start + next - if iNdEx < 0 { - return 0, ErrInvalidLengthTest - } - } - return iNdEx, nil - case 4: - return iNdEx, nil - case 5: - iNdEx += 4 - return iNdEx, nil - default: - return 0, fmt.Errorf("proto: illegal wireType %d", wireType) } } - panic("unreachable") + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_test_proto_rawDesc, + NumEnums: 0, + NumMessages: 3, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_test_proto_goTypes, + DependencyIndexes: file_test_proto_depIdxs, + MessageInfos: file_test_proto_msgTypes, + }.Build() + File_test_proto = out.File + file_test_proto_rawDesc = nil + file_test_proto_goTypes = nil + file_test_proto_depIdxs = nil } - -var ( - ErrInvalidLengthTest = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowTest = fmt.Errorf("proto: integer overflow") -) diff --git a/grpctesting/testpb/test.proto b/grpctesting/testpb/test.proto index 85bfd2d66..04dd4e837 100644 --- a/grpctesting/testpb/test.proto +++ b/grpctesting/testpb/test.proto @@ -2,7 +2,7 @@ syntax = "proto3"; package grpc_middleware.testpb; -option go_package = "testpb"; +option go_package = "../testpb"; message Empty { } diff --git a/grpctesting/testpb/test_grpc.pb.go b/grpctesting/testpb/test_grpc.pb.go new file mode 100644 index 000000000..148471a4e --- /dev/null +++ b/grpctesting/testpb/test_grpc.pb.go @@ -0,0 +1,295 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. + +package testpb + +import ( + context "context" + + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion6 + +// TestServiceClient is the client API for TestService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type TestServiceClient interface { + PingEmpty(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*PingResponse, error) + Ping(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*PingResponse, error) + PingError(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*Empty, error) + PingList(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (TestService_PingListClient, error) + PingStream(ctx context.Context, opts ...grpc.CallOption) (TestService_PingStreamClient, error) +} + +type testServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewTestServiceClient(cc grpc.ClientConnInterface) TestServiceClient { + return &testServiceClient{cc} +} + +func (c *testServiceClient) PingEmpty(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*PingResponse, error) { + out := new(PingResponse) + err := c.cc.Invoke(ctx, "/grpc_middleware.testpb.TestService/PingEmpty", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *testServiceClient) Ping(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*PingResponse, error) { + out := new(PingResponse) + err := c.cc.Invoke(ctx, "/grpc_middleware.testpb.TestService/Ping", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *testServiceClient) PingError(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*Empty, error) { + out := new(Empty) + err := c.cc.Invoke(ctx, "/grpc_middleware.testpb.TestService/PingError", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *testServiceClient) PingList(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (TestService_PingListClient, error) { + stream, err := c.cc.NewStream(ctx, &_TestService_serviceDesc.Streams[0], "/grpc_middleware.testpb.TestService/PingList", opts...) + if err != nil { + return nil, err + } + x := &testServicePingListClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type TestService_PingListClient interface { + Recv() (*PingResponse, error) + grpc.ClientStream +} + +type testServicePingListClient struct { + grpc.ClientStream +} + +func (x *testServicePingListClient) Recv() (*PingResponse, error) { + m := new(PingResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *testServiceClient) PingStream(ctx context.Context, opts ...grpc.CallOption) (TestService_PingStreamClient, error) { + stream, err := c.cc.NewStream(ctx, &_TestService_serviceDesc.Streams[1], "/grpc_middleware.testpb.TestService/PingStream", opts...) + if err != nil { + return nil, err + } + x := &testServicePingStreamClient{stream} + return x, nil +} + +type TestService_PingStreamClient interface { + Send(*PingRequest) error + Recv() (*PingResponse, error) + grpc.ClientStream +} + +type testServicePingStreamClient struct { + grpc.ClientStream +} + +func (x *testServicePingStreamClient) Send(m *PingRequest) error { + return x.ClientStream.SendMsg(m) +} + +func (x *testServicePingStreamClient) Recv() (*PingResponse, error) { + m := new(PingResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// TestServiceServer is the server API for TestService service. +// All implementations must embed UnimplementedTestServiceServer +// for forward compatibility +type TestServiceServer interface { + PingEmpty(context.Context, *Empty) (*PingResponse, error) + Ping(context.Context, *PingRequest) (*PingResponse, error) + PingError(context.Context, *PingRequest) (*Empty, error) + PingList(*PingRequest, TestService_PingListServer) error + PingStream(TestService_PingStreamServer) error + mustEmbedUnimplementedTestServiceServer() +} + +// UnimplementedTestServiceServer must be embedded to have forward compatible implementations. +type UnimplementedTestServiceServer struct { +} + +func (*UnimplementedTestServiceServer) PingEmpty(context.Context, *Empty) (*PingResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method PingEmpty not implemented") +} +func (*UnimplementedTestServiceServer) Ping(context.Context, *PingRequest) (*PingResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Ping not implemented") +} +func (*UnimplementedTestServiceServer) PingError(context.Context, *PingRequest) (*Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method PingError not implemented") +} +func (*UnimplementedTestServiceServer) PingList(*PingRequest, TestService_PingListServer) error { + return status.Errorf(codes.Unimplemented, "method PingList not implemented") +} +func (*UnimplementedTestServiceServer) PingStream(TestService_PingStreamServer) error { + return status.Errorf(codes.Unimplemented, "method PingStream not implemented") +} +func (*UnimplementedTestServiceServer) mustEmbedUnimplementedTestServiceServer() {} + +func RegisterTestServiceServer(s *grpc.Server, srv TestServiceServer) { + s.RegisterService(&_TestService_serviceDesc, srv) +} + +func _TestService_PingEmpty_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TestServiceServer).PingEmpty(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/grpc_middleware.testpb.TestService/PingEmpty", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TestServiceServer).PingEmpty(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _TestService_Ping_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PingRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TestServiceServer).Ping(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/grpc_middleware.testpb.TestService/Ping", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TestServiceServer).Ping(ctx, req.(*PingRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _TestService_PingError_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PingRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TestServiceServer).PingError(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/grpc_middleware.testpb.TestService/PingError", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TestServiceServer).PingError(ctx, req.(*PingRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _TestService_PingList_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(PingRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(TestServiceServer).PingList(m, &testServicePingListServer{stream}) +} + +type TestService_PingListServer interface { + Send(*PingResponse) error + grpc.ServerStream +} + +type testServicePingListServer struct { + grpc.ServerStream +} + +func (x *testServicePingListServer) Send(m *PingResponse) error { + return x.ServerStream.SendMsg(m) +} + +func _TestService_PingStream_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(TestServiceServer).PingStream(&testServicePingStreamServer{stream}) +} + +type TestService_PingStreamServer interface { + Send(*PingResponse) error + Recv() (*PingRequest, error) + grpc.ServerStream +} + +type testServicePingStreamServer struct { + grpc.ServerStream +} + +func (x *testServicePingStreamServer) Send(m *PingResponse) error { + return x.ServerStream.SendMsg(m) +} + +func (x *testServicePingStreamServer) Recv() (*PingRequest, error) { + m := new(PingRequest) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +var _TestService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "grpc_middleware.testpb.TestService", + HandlerType: (*TestServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "PingEmpty", + Handler: _TestService_PingEmpty_Handler, + }, + { + MethodName: "Ping", + Handler: _TestService_Ping_Handler, + }, + { + MethodName: "PingError", + Handler: _TestService_PingError_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "PingList", + Handler: _TestService_PingList_Handler, + ServerStreams: true, + }, + { + StreamName: "PingStream", + Handler: _TestService_PingStream_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, + Metadata: "test.proto", +} diff --git a/interceptors/client_test.go b/interceptors/client_test.go index d9e1819bc..7f397dcf1 100644 --- a/interceptors/client_test.go +++ b/interceptors/client_test.go @@ -21,8 +21,7 @@ import ( "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting/testpb" ) -type mockedReporter struct { - m *sync.Mutex +type mockReport struct { typ GRPCType svcName, methodName string @@ -31,32 +30,98 @@ type mockedReporter struct { postMsgReceives []error } -func (m *mockedReporter) PostCall(err error, _ time.Duration) { +type mockReportable struct { + m sync.Mutex + curr *mockReport + + reports []*mockReport +} + +// Equal replaces require.Equal as google.golang.org/grpc/status errors are not easily comparable. +func (m *mockReportable) Equal(t *testing.T, expected []*mockReport) { + require.Len(t, expected, len(m.reports)) + for i, e := range m.reports { + require.Equal(t, expected[i].typ, e.typ, "%v", i) + require.Equal(t, expected[i].svcName, e.svcName, "%v", i) + require.Equal(t, expected[i].methodName, e.methodName, "%v", i) + + require.Len(t, expected[i].postCalls, len(e.postCalls), "%v", i) + for k, err := range e.postCalls { + if expected[i].postCalls[k] == nil { + require.NoError(t, err) + continue + } + require.Equal(t, expected[i].postCalls[k].Error(), err.Error(), "%v %v", i, k) + } + require.Len(t, expected[i].postMsgSends, len(e.postMsgSends), "%v", i) + for k, err := range e.postMsgSends { + if expected[i].postMsgSends[k] == nil { + require.NoError(t, err) + continue + } + require.Equal(t, expected[i].postMsgSends[k].Error(), err.Error(), "%v %v", i, k) + } + require.Len(t, expected[i].postMsgReceives, len(e.postMsgReceives), "%v", i) + for k, err := range e.postMsgReceives { + if expected[i].postMsgReceives[k] == nil { + require.NoError(t, err) + continue + } + require.Equal(t, expected[i].postMsgReceives[k].Error(), err.Error(), "%v %v", i, k) + } + + } + +} + +func (m *mockReportable) requireOneReportWithRetry(ctx context.Context, t *testing.T, expected *mockReport) { + for { + select { + case <-ctx.Done(): + t.Fatal("timeout waiting for mockReport") + case <-time.After(200 * time.Millisecond): + } + + m.m.Lock() + if len(m.reports) == 0 { + m.m.Unlock() + continue + } + defer m.m.Unlock() + break + } + // Even without reading, we should get initial mockReport. + m.Equal(t, []*mockReport{expected}) +} + +func (m *mockReportable) PostCall(err error, _ time.Duration) { m.m.Lock() defer m.m.Unlock() - m.postCalls = append(m.postCalls, err) + m.curr.postCalls = append(m.curr.postCalls, err) } -func (m *mockedReporter) PostMsgSend(_ interface{}, err error, _ time.Duration) { +func (m *mockReportable) PostMsgSend(_ interface{}, err error, _ time.Duration) { m.m.Lock() defer m.m.Unlock() - m.postMsgSends = append(m.postMsgSends, err) + m.curr.postMsgSends = append(m.curr.postMsgSends, err) } -func (m *mockedReporter) PostMsgReceive(_ interface{}, err error, _ time.Duration) { +func (m *mockReportable) PostMsgReceive(_ interface{}, err error, _ time.Duration) { m.m.Lock() defer m.m.Unlock() - m.postMsgReceives = append(m.postMsgReceives, err) + m.curr.postMsgReceives = append(m.curr.postMsgReceives, err) } -type mockClientReportable struct { - reports []*mockedReporter +func (m *mockReportable) ClientReporter(ctx context.Context, _ interface{}, typ GRPCType, serviceName string, methodName string) (Reporter, context.Context) { + m.curr = &mockReport{typ: typ, svcName: serviceName, methodName: methodName} + m.reports = append(m.reports, m.curr) + return m, ctx } -func (m *mockClientReportable) ClientReporter(ctx context.Context, _ interface{}, typ GRPCType, serviceName string, methodName string) (Reporter, context.Context) { - mock := &mockedReporter{m: &sync.Mutex{}, typ: typ, svcName: serviceName, methodName: methodName} - m.reports = append(m.reports, mock) - return mock, ctx +func (m *mockReportable) ServerReporter(ctx context.Context, _ interface{}, typ GRPCType, serviceName string, methodName string) (Reporter, context.Context) { + m.curr = &mockReport{typ: typ, svcName: serviceName, methodName: methodName} + m.reports = append(m.reports, m.curr) + return m, ctx } func TestClientInterceptorSuite(t *testing.T) { @@ -73,27 +138,31 @@ type ClientInterceptorTestSuite struct { ctx context.Context cancel context.CancelFunc - mock *mockClientReportable + mock *mockReportable + + stopped chan error } func (s *ClientInterceptorTestSuite) SetupSuite() { var err error - - s.mock = &mockClientReportable{} + s.stopped = make(chan error) + s.mock = &mockReportable{} s.serverListener, err = net.Listen("tcp", "127.0.0.1:0") require.NoError(s.T(), err, "must be able to allocate a port for serverListener") - // This is the point where we hook up the interceptor s.server = grpc.NewServer() testpb.RegisterTestServiceServer(s.server, &grpctesting.TestPingService{T: s.T()}) go func() { - _ = s.server.Serve(s.serverListener) + defer close(s.stopped) + s.stopped <- s.server.Serve(s.serverListener) }() ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) defer cancel() + + // This is the point where we hook up the interceptor. s.clientConn, err = grpc.DialContext( ctx, s.serverListener.Addr().String(), @@ -107,9 +176,14 @@ func (s *ClientInterceptorTestSuite) SetupSuite() { } func (s *ClientInterceptorTestSuite) SetupTest() { + select { + case err := <-s.stopped: + s.T().Fatal("gRPC server stopped prematurely", err) + default: + } + // Make all RPC calls last at most 2 sec, meaning all async issues or deadlock will not kill tests. s.ctx, s.cancel = context.WithTimeout(context.TODO(), 2*time.Second) - s.mock.reports = s.mock.reports[:0] } @@ -118,11 +192,11 @@ func (s *ClientInterceptorTestSuite) TearDownSuite() { s.server.Stop() s.T().Logf("stopped grpc.Server at: %v", s.serverListener.Addr().String()) _ = s.serverListener.Close() - } if s.clientConn != nil { _ = s.clientConn.Close() } + <-s.stopped } func (s *ClientInterceptorTestSuite) TearDownTest() { @@ -132,62 +206,61 @@ func (s *ClientInterceptorTestSuite) TearDownTest() { func (s *ClientInterceptorTestSuite) TestUnaryReporting() { _, err := s.testClient.PingEmpty(s.ctx, &testpb.Empty{}) // should return with code=OK require.NoError(s.T(), err) - require.Equal(s.T(), []*mockedReporter{{ - m: &sync.Mutex{}, + s.mock.Equal(s.T(), []*mockReport{{ typ: Unary, svcName: testpb.TestServiceFullName, methodName: "PingEmpty", postCalls: []error{nil}, postMsgReceives: []error{nil}, postMsgSends: []error{nil}, - }}, s.mock.reports) + }}) s.mock.reports = s.mock.reports[:0] // Reset. _, err = s.testClient.PingError(s.ctx, &testpb.PingRequest{ErrorCodeReturned: uint32(codes.FailedPrecondition)}) // should return with code=FailedPrecondition require.Error(s.T(), err) - require.Equal(s.T(), []*mockedReporter{{ - m: &sync.Mutex{}, + s.mock.Equal(s.T(), []*mockReport{{ typ: Unary, svcName: testpb.TestServiceFullName, methodName: "PingError", postCalls: []error{status.Errorf(codes.FailedPrecondition, "Userspace error.")}, postMsgReceives: []error{status.Errorf(codes.FailedPrecondition, "Userspace error.")}, postMsgSends: []error{nil}, - }}, s.mock.reports) + }}) } -func (s *ClientInterceptorTestSuite) TestStartedStreamingReporting() { +func (s *ClientInterceptorTestSuite) TestStartedListReporting() { _, err := s.testClient.PingList(s.ctx, &testpb.PingRequest{}) require.NoError(s.T(), err) - // Even without reading, we should get initial report. - require.Equal(s.T(), []*mockedReporter{{ - m: &sync.Mutex{}, + + // Even without reading, we should get initial mockReport. + s.mock.Equal(s.T(), []*mockReport{{ typ: ServerStream, svcName: testpb.TestServiceFullName, methodName: "PingList", postMsgSends: []error{nil}, - }}, s.mock.reports) + }}) - _, err = s.testClient.PingList(s.ctx, &testpb.PingRequest{ErrorCodeReturned: uint32(codes.FailedPrecondition)}) // should return with code=FailedPrecondition + _, err = s.testClient.PingList(s.ctx, &testpb.PingRequest{ErrorCodeReturned: uint32(codes.FailedPrecondition)}) require.NoError(s.T(), err, "PingList must not fail immediately") - // Even without reading, we should get initial report. - require.Equal(s.T(), []*mockedReporter{{ - m: &sync.Mutex{}, + + // Even without reading, we should get initial mockReport. + s.mock.Equal(s.T(), []*mockReport{{ typ: ServerStream, svcName: testpb.TestServiceFullName, methodName: "PingList", postMsgSends: []error{nil}, }, { - m: &sync.Mutex{}, typ: ServerStream, svcName: testpb.TestServiceFullName, methodName: "PingList", postMsgSends: []error{nil}, - }}, s.mock.reports) + }}) } -func (s *ClientInterceptorTestSuite) TestStreamingReporting() { - ss, _ := s.testClient.PingList(s.ctx, &testpb.PingRequest{}) // should return with code=OK +func (s *ClientInterceptorTestSuite) TestListReporting() { + ss, err := s.testClient.PingList(s.ctx, &testpb.PingRequest{}) + require.NoError(s.T(), err) + // Do a read, just for kicks. count := 0 for { @@ -200,41 +273,46 @@ func (s *ClientInterceptorTestSuite) TestStreamingReporting() { } require.EqualValues(s.T(), grpctesting.ListResponseCount, count, "Number of received msg on the wire must match") - require.Equal(s.T(), []*mockedReporter{{ - m: &sync.Mutex{}, + s.mock.Equal(s.T(), []*mockReport{{ typ: ServerStream, svcName: testpb.TestServiceFullName, methodName: "PingList", postCalls: []error{io.EOF}, postMsgReceives: append(make([]error, grpctesting.ListResponseCount), io.EOF), postMsgSends: []error{nil}, - }}, s.mock.reports) + }}) s.mock.reports = s.mock.reports[:0] // Reset. - ss, err := s.testClient.PingList(s.ctx, &testpb.PingRequest{ErrorCodeReturned: uint32(codes.FailedPrecondition)}) // should return with code=FailedPrecondition + ss, err = s.testClient.PingList(s.ctx, &testpb.PingRequest{ErrorCodeReturned: uint32(codes.FailedPrecondition)}) require.NoError(s.T(), err, "PingList must not fail immediately") // Do a read, just to propagate errors. _, err = ss.Recv() + require.Error(s.T(), err) st, _ := status.FromError(err) require.Equal(s.T(), codes.FailedPrecondition, st.Code(), "Recv must return FailedPrecondition, otherwise the test is wrong") - require.Equal(s.T(), []*mockedReporter{{ - m: &sync.Mutex{}, + // Next same. + _, err = ss.Recv() + require.Error(s.T(), err) + st, _ = status.FromError(err) + require.Equal(s.T(), codes.FailedPrecondition, st.Code(), "Recv must return FailedPrecondition, otherwise the test is wrong") + + s.mock.Equal(s.T(), []*mockReport{{ typ: ServerStream, svcName: testpb.TestServiceFullName, methodName: "PingList", - postCalls: []error{status.Errorf(codes.FailedPrecondition, "foobar")}, - postMsgReceives: []error{status.Errorf(codes.FailedPrecondition, "foobar")}, + postCalls: []error{status.Errorf(codes.FailedPrecondition, "foobar"), status.Errorf(codes.FailedPrecondition, "foobar")}, + postMsgReceives: []error{status.Errorf(codes.FailedPrecondition, "foobar"), status.Errorf(codes.FailedPrecondition, "foobar")}, postMsgSends: []error{nil}, - }}, s.mock.reports) + }}) } func (s *ClientInterceptorTestSuite) TestBiStreamingReporting() { ss, err := s.testClient.PingStream(s.ctx) require.NoError(s.T(), err) - wg := sync.WaitGroup{} + wg := sync.WaitGroup{} defer func() { _ = ss.CloseSend() wg.Wait() @@ -264,14 +342,12 @@ func (s *ClientInterceptorTestSuite) TestBiStreamingReporting() { wg.Wait() require.EqualValues(s.T(), count, 100, "Number of received msg on the wire must match") - - require.Equal(s.T(), []*mockedReporter{{ - m: &sync.Mutex{}, + s.mock.Equal(s.T(), []*mockReport{{ typ: BidiStream, svcName: testpb.TestServiceFullName, methodName: "PingStream", postCalls: []error{io.EOF}, postMsgReceives: append(make([]error, 100), io.EOF), postMsgSends: make([]error, 100), - }}, s.mock.reports) + }}) } diff --git a/interceptors/logging/interceptors_test.go b/interceptors/logging/interceptors_test.go index fe7601952..f0916d8d5 100644 --- a/interceptors/logging/interceptors_test.go +++ b/interceptors/logging/interceptors_test.go @@ -85,34 +85,45 @@ func (l LogLines) Swap(i, j int) { l[i], l[j] = l[j], l[i] } -type mockStdOutput struct { - // All the output of the mockLogger is shared in a single - // shared slice. Behaves like a stdout which contains all - // the log lines. - lines LogLines +type output struct { m sync.Mutex + lines LogLines } -func (l *mockStdOutput) Lines() LogLines { - l.m.Lock() - defer l.m.Unlock() +func (o *output) Lines() LogLines { + o.m.Lock() + defer o.m.Unlock() - retLines := make(LogLines, len(l.lines)) - copy(retLines, l.lines) + retLines := make(LogLines, len(o.lines)) + copy(retLines, o.lines) return retLines } +func (o *output) Append(lines ...LogLine) { + o.m.Lock() + defer o.m.Unlock() + + o.lines = append(o.lines, lines...) +} +func (o *output) Reset() { + o.m.Lock() + defer o.m.Unlock() + + o.lines = o.lines[:0] +} + type mockLogger struct { - *mockStdOutput + o *output fields logging.Fields } -func (l *mockLogger) Log(lvl logging.Level, msg string) { - l.m.Lock() - defer l.m.Unlock() +func newMockLogger() *mockLogger { + return &mockLogger{o: &output{}} +} +func (l *mockLogger) Log(lvl logging.Level, msg string) { line := LogLine{ lvl: lvl, msg: msg, @@ -122,14 +133,11 @@ func (l *mockLogger) Log(lvl logging.Level, msg string) { for i := 0; i < len(l.fields); i += 2 { line.fields[l.fields[i]] = l.fields[i+1] } - l.lines = append(l.lines, line) + l.o.Append(line) } func (l *mockLogger) With(fields ...string) logging.Logger { - l.m.Lock() - defer l.m.Unlock() - - return &mockLogger{mockStdOutput: l.mockStdOutput, fields: append(append(logging.Fields{}, l.fields...), fields...)} + return &mockLogger{o: l.o, fields: append(append(logging.Fields{}, l.fields...), fields...)} } type baseLoggingSuite struct { @@ -139,7 +147,7 @@ type baseLoggingSuite struct { func (s *baseLoggingSuite) SetupTest() { s.logger.fields = s.logger.fields[:0] - s.logger.lines = s.logger.lines[:0] + s.logger.o.Reset() } func customClientCodeToLevel(c codes.Code) logging.Level { @@ -162,7 +170,7 @@ func TestSuite(t *testing.T) { s := &loggingClientServerSuite{ &baseLoggingSuite{ - logger: &mockLogger{mockStdOutput: &mockStdOutput{}}, + logger: newMockLogger(), InterceptorTestSuite: &grpctesting.InterceptorTestSuite{ TestService: &grpctesting.TestPingService{T: t}, }, @@ -195,7 +203,7 @@ func (s *loggingClientServerSuite) TestPing() { _, err := s.Client.Ping(s.SimpleCtx(), goodPing) assert.NoError(s.T(), err, "there must be not be an on a successful call") - lines := s.logger.Lines() + lines := s.logger.o.Lines() sort.Sort(lines) require.Len(s.T(), lines, 4) @@ -240,7 +248,7 @@ func (s *loggingClientServerSuite) TestPingList() { } require.NoError(s.T(), err, "reading stream should not fail") } - lines := s.logger.Lines() + lines := s.logger.o.Lines() sort.Sort(lines) require.Len(s.T(), lines, 4) @@ -308,7 +316,7 @@ func (s *loggingClientServerSuite) TestPingError_WithCustomLevels() { s.SimpleCtx(), &testpb.PingRequest{Value: "something", ErrorCodeReturned: uint32(tcase.code)}) require.Error(t, err, "each call here must return an error") - lines := s.logger.Lines() + lines := s.logger.o.Lines() sort.Sort(lines) require.Len(t, lines, 4) @@ -349,7 +357,7 @@ func TestCustomDurationSuite(t *testing.T) { s := &loggingCustomDurationSuite{ baseLoggingSuite: &baseLoggingSuite{ - logger: &mockLogger{mockStdOutput: &mockStdOutput{}}, + logger: newMockLogger(), InterceptorTestSuite: &grpctesting.InterceptorTestSuite{ TestService: &grpctesting.TestPingService{T: t}, }, @@ -374,7 +382,7 @@ func (s *loggingCustomDurationSuite) TestPing_HasOverriddenDuration() { _, err := s.Client.Ping(s.SimpleCtx(), goodPing) assert.NoError(s.T(), err, "there must be not be an on a successful call") - lines := s.logger.Lines() + lines := s.logger.o.Lines() sort.Sort(lines) require.Len(s.T(), lines, 4) @@ -420,7 +428,7 @@ func (s *loggingCustomDurationSuite) TestPingList_HasOverriddenDuration() { require.NoError(s.T(), err, "reading stream should not fail") } - lines := s.logger.Lines() + lines := s.logger.o.Lines() sort.Sort(lines) require.Len(s.T(), lines, 4) @@ -473,7 +481,7 @@ func TestCustomDeciderSuite(t *testing.T) { s := &loggingCustomDeciderSuite{ baseLoggingSuite: &baseLoggingSuite{ - logger: &mockLogger{mockStdOutput: &mockStdOutput{}}, + logger: newMockLogger(), InterceptorTestSuite: &grpctesting.InterceptorTestSuite{ TestService: &grpctesting.TestPingService{T: t}, }, @@ -498,7 +506,7 @@ func (s *loggingCustomDeciderSuite) TestPing_HasCustomDecider() { _, err := s.Client.Ping(s.SimpleCtx(), goodPing) require.NoError(s.T(), err, "there must be not be an error on a successful call") - require.Len(s.T(), s.logger.Lines(), 0) // Decider should suppress. + require.Len(s.T(), s.logger.o.Lines(), 0) // Decider should suppress. } func (s *loggingCustomDeciderSuite) TestPingError_HasCustomDecider() { @@ -509,7 +517,7 @@ func (s *loggingCustomDeciderSuite) TestPingError_HasCustomDecider() { &testpb.PingRequest{Value: "something", ErrorCodeReturned: uint32(code)}) require.Error(s.T(), err, "each call here must return an error") - lines := s.logger.Lines() + lines := s.logger.o.Lines() sort.Sort(lines) require.Len(s.T(), lines, 4) @@ -557,5 +565,5 @@ func (s *loggingCustomDeciderSuite) TestPingList_HasCustomDecider() { require.NoError(s.T(), err, "reading stream should not fail") } - require.Len(s.T(), s.logger.Lines(), 0) // Decider should suppress. + require.Len(s.T(), s.logger.o.Lines(), 0) // Decider should suppress. } diff --git a/interceptors/logging/logging.go b/interceptors/logging/logging.go index 67d6861bd..8ab7c8b54 100644 --- a/interceptors/logging/logging.go +++ b/interceptors/logging/logging.go @@ -5,11 +5,10 @@ package logging import ( "context" - "io" - "github.com/golang/protobuf/proto" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors" ) @@ -78,7 +77,7 @@ type ClientPayloadLoggingDecider func(ctx context.Context, fullMethodName string // JsonPbMarshaller is a marshaller that serializes protobuf messages. type JsonPbMarshaler interface { - Marshal(out io.Writer, pb proto.Message) error + Marshal(pb proto.Message) ([]byte, error) } // Logger is unified interface that we used for all our interceptors. Official implementations are available under diff --git a/interceptors/logging/payload.go b/interceptors/logging/payload.go index ea5e2ceec..936ea4a45 100644 --- a/interceptors/logging/payload.go +++ b/interceptors/logging/payload.go @@ -6,20 +6,14 @@ import ( "fmt" "time" - "github.com/golang/protobuf/jsonpb" - "github.com/golang/protobuf/proto" "google.golang.org/grpc" + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/proto" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tags" ) -var ( - // JsonPbMarshaller is the marshaller used for serializing protobuf messages. - // If needed, this variable can be reassigned with a different marshaller with the same Marshal() signature. - JsonPbMarshaller JsonPbMarshaler = &jsonpb.Marshaler{} -) - type serverPayloadReporter struct { ctx context.Context logger Logger @@ -31,18 +25,32 @@ func (c *serverPayloadReporter) PostMsgSend(req interface{}, err error, duration if err != nil { return } + logger := c.logger.With(extractFields(tags.Extract(c.ctx))...) + p, ok := req.(proto.Message) + if !ok { + logger.With("req.type", fmt.Sprintf("%T", req)).Log(ERROR, "req is not a google.golang.org/protobuf/proto.Message; programmatic error?") + + return + } // For server send message is the response. - logProtoMessageAsJson(logger.With("grpc.send.duration", duration.String()), req, "grpc.response.content", "response payload logged as grpc.response.content field") + logProtoMessageAsJson(logger.With("grpc.send.duration", duration.String()), p, "grpc.response.content", "response payload logged as grpc.response.content field") } func (c *serverPayloadReporter) PostMsgReceive(reply interface{}, err error, duration time.Duration) { if err != nil { return } + logger := c.logger.With(extractFields(tags.Extract(c.ctx))...) + + p, ok := reply.(proto.Message) + if !ok { + logger.With("reply.type", fmt.Sprintf("%T", reply)).Log(ERROR, "reply is not a google.golang.org/protobuf/proto.Message; programmatic error?") + return + } // For server recv message is the request. - logProtoMessageAsJson(logger.With("grpc.recv.duration", duration.String()), reply, "grpc.request.content", "request payload logged as grpc.request.content field") + logProtoMessageAsJson(logger.With("grpc.recv.duration", duration.String()), p, "grpc.request.content", "request payload logged as grpc.request.content field") } type clientPayloadReporter struct { @@ -56,16 +64,28 @@ func (c *clientPayloadReporter) PostMsgSend(req interface{}, err error, duration if err != nil { return } + logger := c.logger.With(extractFields(tags.Extract(c.ctx))...) - logProtoMessageAsJson(logger.With("grpc.send.duration", duration.String()), req, "grpc.request.content", "request payload logged as grpc.request.content field") + p, ok := req.(proto.Message) + if !ok { + logger.With("req.type", fmt.Sprintf("%T", req)).Log(ERROR, "req is not a google.golang.org/protobuf/proto.Message; programmatic error?") + return + } + logProtoMessageAsJson(logger.With("grpc.send.duration", duration.String()), p, "grpc.request.content", "request payload logged as grpc.request.content field") } func (c *clientPayloadReporter) PostMsgReceive(reply interface{}, err error, duration time.Duration) { if err != nil { return } + logger := c.logger.With(extractFields(tags.Extract(c.ctx))...) - logProtoMessageAsJson(logger.With("grpc.recv.duration", duration.String()), reply, "grpc.response.content", "response payload logged as grpc.response.content field") + p, ok := reply.(proto.Message) + if !ok { + logger.With("reply.type", fmt.Sprintf("%T", reply)).Log(ERROR, "reply is not a google.golang.org/protobuf/proto.Message; programmatic error?") + return + } + logProtoMessageAsJson(logger.With("grpc.recv.duration", duration.String()), p, "grpc.response.content", "response payload logged as grpc.response.content field") } type payloadReportable struct { @@ -127,26 +147,14 @@ func PayloadStreamClientInterceptor(logger Logger, decider ClientPayloadLoggingD return interceptors.StreamClientInterceptor(&payloadReportable{logger: logger, clientDecider: decider}) } -func logProtoMessageAsJson(logger Logger, pbMsg interface{}, key string, msg string) { - if p, ok := pbMsg.(proto.Message); ok { - payload, err := (&jsonpbObjectMarshaler{pb: p}).marshalJSON() - if err != nil { - logger = logger.With(key, err.Error()) - } else { - logger = logger.With(key, string(payload)) - } - logger.Log(INFO, msg) - } -} - -type jsonpbObjectMarshaler struct { - pb proto.Message -} - -func (j *jsonpbObjectMarshaler) marshalJSON() ([]byte, error) { - b := &bytes.Buffer{} - if err := JsonPbMarshaller.Marshal(b, j.pb); err != nil { - return nil, fmt.Errorf("jsonpb serializer failed: %v", err) +func logProtoMessageAsJson(logger Logger, pbMsg proto.Message, key string, msg string) { + payload, err := protojson.Marshal(pbMsg) + if err != nil { + logger = logger.With(key, err.Error()) + } else { + // Trim spaces for deterministic output. + // See: https://github.com/golang/protobuf/issues/1269 + logger = logger.With(key, string(bytes.Replace(payload, []byte{' '}, []byte{}, -1))) } - return b.Bytes(), nil + logger.Log(INFO, msg) } diff --git a/interceptors/logging/payload_test.go b/interceptors/logging/payload_test.go index 969b3a63d..1db9ad8f0 100644 --- a/interceptors/logging/payload_test.go +++ b/interceptors/logging/payload_test.go @@ -3,9 +3,7 @@ package logging_test import ( "context" "fmt" - "runtime" "sort" - "strings" "testing" "github.com/stretchr/testify/assert" @@ -25,17 +23,12 @@ type loggingPayloadSuite struct { } func TestPayloadSuite(t *testing.T) { - if strings.HasPrefix(runtime.Version(), "go1.7") { - t.Skipf("Skipping due to json.RawMessage incompatibility with go1.7") - return - } - alwaysLoggingDeciderServer := func(ctx context.Context, fullMethodName string, servingObject interface{}) bool { return true } alwaysLoggingDeciderClient := func(ctx context.Context, fullMethodName string) bool { return true } s := &loggingPayloadSuite{ baseLoggingSuite: &baseLoggingSuite{ - logger: &mockLogger{mockStdOutput: &mockStdOutput{}}, + logger: newMockLogger(), InterceptorTestSuite: &grpctesting.InterceptorTestSuite{ TestService: &grpctesting.TestPingService{T: t}, }, @@ -60,7 +53,7 @@ func (s *loggingPayloadSuite) TestPing_LogsBothRequestAndResponse() { _, err := s.Client.Ping(s.SimpleCtx(), goodPing) require.NoError(s.T(), err, "there must be not be an error on a successful call") - lines := s.logger.Lines() + lines := s.logger.o.Lines() require.Len(s.T(), lines, 4) s.assertPayloadLogLinesForMessage(lines, "Ping", interceptors.Unary) } @@ -134,14 +127,14 @@ func (s *loggingPayloadSuite) TestPingError_LogsOnlyRequestsOnError() { _, err := s.Client.PingError(s.SimpleCtx(), &testpb.PingRequest{Value: "something", ErrorCodeReturned: uint32(4)}) require.Error(s.T(), err, "there must be an error on an unsuccessful call") - lines := s.logger.Lines() + lines := s.logger.o.Lines() sort.Sort(lines) require.Len(s.T(), lines, 2) // Only client & server requests. - clientRequestLogLine := lines[0] assert.Equal(s.T(), logging.INFO, clientRequestLogLine.lvl) assert.Equal(s.T(), "request payload logged as grpc.request.content field", clientRequestLogLine.msg) clientRequestFields := assertStandardFields(s.T(), logging.KindClientFieldValue, clientRequestLogLine.fields, "PingError", interceptors.Unary) + clientRequestFields.AssertNextFieldNotEmpty(s.T(), "grpc.start_time"). AssertNextFieldNotEmpty(s.T(), "grpc.send.duration"). AssertNextField(s.T(), "grpc.request.content", `{"value":"something","errorCodeReturned":4}`). @@ -162,7 +155,7 @@ func (s *loggingPayloadSuite) TestPingStream_LogsAllRequestsAndResponses() { } require.NoError(s.T(), stream.CloseSend(), "no error on send stream") - lines := s.logger.Lines() + lines := s.logger.o.Lines() require.Len(s.T(), lines, 4*messagesExpected) s.assertPayloadLogLinesForMessage(lines, "PingStream", interceptors.BidiStream) } diff --git a/interceptors/server_test.go b/interceptors/server_test.go index 5fa9a125f..afe7eb435 100644 --- a/interceptors/server_test.go +++ b/interceptors/server_test.go @@ -21,20 +21,6 @@ import ( "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting/testpb" ) -type mockServerReportable struct { - m sync.Mutex - reports []*mockedReporter -} - -func (m *mockServerReportable) ServerReporter(ctx context.Context, _ interface{}, typ GRPCType, serviceName string, methodName string) (Reporter, context.Context) { - mock := &mockedReporter{m: &m.m, typ: typ, svcName: serviceName, methodName: methodName} - m.m.Lock() - defer m.m.Unlock() - - m.reports = append(m.reports, mock) - return mock, ctx -} - func TestServerInterceptorSuite(t *testing.T) { suite.Run(t, &ServerInterceptorTestSuite{}) } @@ -49,13 +35,13 @@ type ServerInterceptorTestSuite struct { ctx context.Context cancel context.CancelFunc - mock *mockServerReportable + mock *mockReportable } func (s *ServerInterceptorTestSuite) SetupSuite() { var err error - s.mock = &mockServerReportable{} + s.mock = &mockReportable{} s.serverListener, err = net.Listen("tcp", "127.0.0.1:0") require.NoError(s.T(), err, "must be able to allocate a port for serverListener") @@ -105,28 +91,26 @@ func (s *ServerInterceptorTestSuite) TearDownTest() { func (s *ServerInterceptorTestSuite) TestUnaryReporting() { _, err := s.testClient.PingEmpty(s.ctx, &testpb.Empty{}) // should return with code=OK require.NoError(s.T(), err) - require.Equal(s.T(), []*mockedReporter{{ - m: &sync.Mutex{}, + s.mock.Equal(s.T(), []*mockReport{{ typ: Unary, svcName: testpb.TestServiceFullName, methodName: "PingEmpty", postCalls: []error{nil}, postMsgReceives: []error{nil}, postMsgSends: []error{nil}, - }}, s.mock.reports) + }}) s.mock.reports = s.mock.reports[:0] // Reset. _, err = s.testClient.PingError(s.ctx, &testpb.PingRequest{ErrorCodeReturned: uint32(codes.FailedPrecondition)}) // should return with code=FailedPrecondition require.Error(s.T(), err) - require.Equal(s.T(), []*mockedReporter{{ - m: &sync.Mutex{}, + s.mock.Equal(s.T(), []*mockReport{{ typ: Unary, svcName: testpb.TestServiceFullName, methodName: "PingError", postCalls: []error{status.Errorf(codes.FailedPrecondition, "Userspace error.")}, postMsgReceives: []error{nil}, postMsgSends: []error{status.Errorf(codes.FailedPrecondition, "Userspace error.")}, - }}, s.mock.reports) + }}) } func (s *ServerInterceptorTestSuite) TestStreamingReports() { @@ -142,21 +126,20 @@ func (s *ServerInterceptorTestSuite) TestStreamingReports() { count++ } require.EqualValues(s.T(), grpctesting.ListResponseCount, count, "Number of received msg on the wire must match") - require.Equal(s.T(), []*mockedReporter{{ - m: &sync.Mutex{}, + s.mock.Equal(s.T(), []*mockReport{{ typ: ServerStream, svcName: testpb.TestServiceFullName, methodName: "PingList", postCalls: []error{nil}, postMsgReceives: []error{nil}, postMsgSends: make([]error, grpctesting.ListResponseCount), - }}, s.mock.reports) + }}) s.mock.reports = s.mock.reports[:0] // Reset. _, err := s.testClient.PingList(s.ctx, &testpb.PingRequest{ErrorCodeReturned: uint32(codes.FailedPrecondition)}) // should return with code=FailedPrecondition require.NoError(s.T(), err, "PingList must not fail immediately") - s.mock.requireOneReportWithRetry(s.ctx, s.T(), &mockedReporter{ + s.mock.requireOneReportWithRetry(s.ctx, s.T(), &mockReport{ typ: ServerStream, svcName: testpb.TestServiceFullName, methodName: "PingList", @@ -165,27 +148,6 @@ func (s *ServerInterceptorTestSuite) TestStreamingReports() { }) } -func (m *mockServerReportable) requireOneReportWithRetry(ctx context.Context, t *testing.T, expected *mockedReporter) { - for { - select { - case <-ctx.Done(): - t.Fatal("timeout waiting for report") - case <-time.After(200 * time.Millisecond): - } - - m.m.Lock() - if len(m.reports) == 0 { - m.m.Unlock() - continue - } - defer m.m.Unlock() - break - } - expected.m = &m.m - // Even without reading, we should get initial report. - require.Equal(t, []*mockedReporter{expected}, m.reports) -} - func (s *ServerInterceptorTestSuite) TestBiStreamingReporting() { ss, err := s.testClient.PingStream(s.ctx) require.NoError(s.T(), err) @@ -221,13 +183,12 @@ func (s *ServerInterceptorTestSuite) TestBiStreamingReporting() { require.EqualValues(s.T(), count, 100, "Number of received msg on the wire must match") - require.Equal(s.T(), []*mockedReporter{{ - m: &sync.Mutex{}, + s.mock.Equal(s.T(), []*mockReport{{ typ: BidiStream, svcName: testpb.TestServiceFullName, methodName: "PingStream", postCalls: []error{nil}, postMsgReceives: append(make([]error, 100), io.EOF), postMsgSends: make([]error, 100), - }}, s.mock.reports) + }}) } diff --git a/interceptors/tags/fieldextractor.go b/interceptors/tags/fieldextractor.go index 6e20fca57..1d0f2172b 100644 --- a/interceptors/tags/fieldextractor.go +++ b/interceptors/tags/fieldextractor.go @@ -34,12 +34,7 @@ func CodeGenRequestFieldExtractor(_ string, req interface{}) map[string]string { } // TagBasedRequestFieldExtractor is a function that relies on Go struct tags to export log fields from requests. -// These are usually coming from a protoc-plugin, such as Gogo protobuf. -// -// message Metadata { -// repeated string tags = 1 [ (gogoproto.moretags) = "log_field:\"meta_tags\"" ]; -// } -// +// TODO(bwplotka): Add tests/examples https://github.com/grpc-ecosystem/go-grpc-middleware/issues/382 // The tagName is configurable using the tagName variable. Here it would be "log_field". func TagBasedRequestFieldExtractor(tagName string) RequestFieldExtractorFunc { return func(fullMethod string, req interface{}) map[string]string { diff --git a/interceptors/tags/fieldextractor_test.go b/interceptors/tags/fieldextractor_test.go index 93dd76040..3fdd3c11f 100644 --- a/interceptors/tags/fieldextractor_test.go +++ b/interceptors/tags/fieldextractor_test.go @@ -5,73 +5,17 @@ package tags_test import ( "testing" - "time" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting/gogotestpb" "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting/testpb" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tags" ) +// TODO(bwplotka): Add tests/examples https://github.com/grpc-ecosystem/go-grpc-middleware/issues/382 func TestCodeGenRequestLogFieldExtractor_ManualIsDeclared(t *testing.T) { req := &testpb.PingRequest{Value: "my_value"} valMap := tags.CodeGenRequestFieldExtractor("", req) require.Len(t, valMap, 1, "PingRequest should have a ExtractLogFields method declared in test.manual_extractfields.pb") require.EqualValues(t, valMap, map[string]string{"value": "my_value"}) } - -func TestTaggedRequestFiledExtractor_PingRequest(t *testing.T) { - req := &gogotestpb.PingRequest{ - Ping: &gogotestpb.Ping{ - Id: &gogotestpb.PingId{ - Id: 1337, // logfield is ping_id - }, - Value: "something", - }, - Meta: &gogotestpb.Metadata{ - Tags: []string{"tagone", "tagtwo"}, // logfield is meta_tags - }, - } - valMap := tags.TagBasedRequestFieldExtractor("log_field")("", req) - assert.EqualValues(t, "1337", valMap["ping_id"]) - assert.EqualValues(t, "[tagone tagtwo]", valMap["meta_tags"]) -} - -func TestTaggedRequestFiledExtractor_PongRequest(t *testing.T) { - req := &gogotestpb.PongRequest{ - Pong: &gogotestpb.Pong{ - Id: "some_id", - }, - Meta: &gogotestpb.Metadata{ - Tags: []string{"tagone", "tagtwo"}, // logfield is meta_tags - }, - } - valMap := tags.TagBasedRequestFieldExtractor("log_field")("", req) - assert.EqualValues(t, "some_id", valMap["pong_id"]) - assert.EqualValues(t, "[tagone tagtwo]", valMap["meta_tags"]) -} - -func TestTaggedRequestFiledExtractor_OneOfLogField(t *testing.T) { - req := &gogotestpb.OneOfLogField{ - Identifier: &gogotestpb.OneOfLogField_BarId{ - BarId: "bar-log-field", - }, - } - valMap := tags.TagBasedRequestFieldExtractor("log_field")("", req) - assert.EqualValues(t, "bar-log-field", valMap["bar_id"]) -} - -// Test to ensure TagBasedRequestFieldExtractor does not panic when encountering private struct members such as -// when using gogoproto.stdtime which results in a time.Time that has private struct members -func TestTaggedRequestFiledExtractor_GogoTime(t *testing.T) { - ts := time.Date(2010, 01, 01, 0, 0, 0, 0, time.UTC) - req := &gogotestpb.GoGoProtoStdTime{ - Timestamp: &ts, - } - assert.NotPanics(t, func() { - valMap := tags.TagBasedRequestFieldExtractor("log_field")("", req) - assert.Empty(t, valMap) - }) -} diff --git a/providers/kit/examples_test.go b/providers/kit/examples_test.go index f1afda54c..8e775c5dd 100644 --- a/providers/kit/examples_test.go +++ b/providers/kit/examples_test.go @@ -100,7 +100,7 @@ func ExampleWithDecider() { } } -func ExampleWithPayloadLogging() { +func ExampleServerPayloadLoggingDecider() { // Logger is used, allowing pre-definition of certain fields by the user. logger := log.NewNopLogger() // Expect payload from "/blah.foo.healthcheck/Check" call to be logged. @@ -128,5 +128,5 @@ func TestExamplesBuildable(t *testing.T) { Example_initializationWithDurationFieldOverride() Example_initializationWithCodeGenRequestFieldExtractor() ExampleWithDecider() - ExampleWithPayloadLogging() + ExampleServerPayloadLoggingDecider() } diff --git a/providers/kit/go.mod b/providers/kit/go.mod index 578848dc4..f5388b7ea 100644 --- a/providers/kit/go.mod +++ b/providers/kit/go.mod @@ -5,5 +5,5 @@ go 1.14 require ( github.com/go-kit/kit v0.10.0 github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20201002093600-73cf2ae9d891 - google.golang.org/grpc v1.28.0 + google.golang.org/grpc v1.30.0 ) diff --git a/providers/kit/go.sum b/providers/kit/go.sum index 446fcd42b..cb27dbf58 100644 --- a/providers/kit/go.sum +++ b/providers/kit/go.sum @@ -37,7 +37,6 @@ github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7 github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -73,14 +72,12 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= @@ -89,8 +86,9 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -101,8 +99,6 @@ github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 h1:z53tR0945TRRQO/fLEVPI6SMv7ZflF0TEaTAoU7tOzg= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-20200501113911-9a95f0fdbfea h1:1Tk1IbruXbunEnaIZEFb+Hpv9BIZti3OxKwKn5wWyKk= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-20200501113911-9a95f0fdbfea/go.mod h1:GugMBs30ZSAkckqXEAIEGyYdDH6EgqowG8ppA3Zt+AY= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20201002093600-73cf2ae9d891 h1:2F7/en805byWQR92etfFjOqtRtWsUu09R7wm6LtlHEw= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20201002093600-73cf2ae9d891/go.mod h1:GhphxcdlaRyAuBSvo6rV71BvQcvB/vuX8ugCyybuS2k= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= @@ -198,6 +194,7 @@ github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0 github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -288,7 +285,6 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 h1:fHDIZ2oxGnUZRN6WgWFCbYBjH9uqVPRCUVUDhs0wnbA= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -308,7 +304,6 @@ golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -317,7 +312,6 @@ golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191220142924-d4481acd189f h1:68K/z8GLUxV76xGSqwTWw2gyk/jwn79LUL43rES2g8o= golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -338,6 +332,8 @@ golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -349,7 +345,6 @@ google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dT google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= -google.golang.org/grpc v1.19.0 h1:cfg4PD8YEdSFnm7qLV4++93WcmhH2nIUhMjhdCvl3j8= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -358,12 +353,10 @@ google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0 h1:bO/TA4OxCOummhSf10siHuG7vJOiwh7SpRpFZDkOgl4= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/providers/logrus/examples_test.go b/providers/logrus/examples_test.go index bc03f4bc1..6a5e81f74 100644 --- a/providers/logrus/examples_test.go +++ b/providers/logrus/examples_test.go @@ -102,7 +102,7 @@ func ExampleWithDecider() { } } -func ExampleWithPayloadLogging() { +func ExampleServerPayloadLoggingDecider() { // Logger is used, allowing pre-definition of certain fields by the user. logger := logrus.New() // Expect payload from "/blah.foo.healthcheck/Check" call to be logged. @@ -130,5 +130,5 @@ func TestExamplesBuildable(t *testing.T) { Example_initializationWithDurationFieldOverride() Example_initializationWithCodeGenRequestFieldExtractor() ExampleWithDecider() - ExampleWithPayloadLogging() + ExampleServerPayloadLoggingDecider() } diff --git a/providers/logrus/go.mod b/providers/logrus/go.mod index fb21909c9..c5f105946 100644 --- a/providers/logrus/go.mod +++ b/providers/logrus/go.mod @@ -5,5 +5,5 @@ go 1.14 require ( github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20201002093600-73cf2ae9d891 github.com/sirupsen/logrus v1.5.0 - google.golang.org/grpc v1.19.0 + google.golang.org/grpc v1.30.0 ) diff --git a/providers/logrus/go.sum b/providers/logrus/go.sum index b0cb2e848..a9ef17630 100644 --- a/providers/logrus/go.sum +++ b/providers/logrus/go.sum @@ -1,9 +1,14 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= @@ -12,8 +17,11 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-20200501113911-9a95f0fdbfea h1:1Tk1IbruXbunEnaIZEFb+Hpv9BIZti3OxKwKn5wWyKk= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-20200501113911-9a95f0fdbfea/go.mod h1:GugMBs30ZSAkckqXEAIEGyYdDH6EgqowG8ppA3Zt+AY= +github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20201002093600-73cf2ae9d891 h1:2F7/en805byWQR92etfFjOqtRtWsUu09R7wm6LtlHEw= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20201002093600-73cf2ae9d891/go.mod h1:GhphxcdlaRyAuBSvo6rV71BvQcvB/vuX8ugCyybuS2k= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= @@ -21,9 +29,11 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/sirupsen/logrus v1.5.0 h1:1N5EYkVAPEywqZRJd7cwnRtCb6xJx7NH3T3WUTF980Q= github.com/sirupsen/logrus v1.5.0/go.mod h1:+F7Ogzej0PZc/94MaYx/nvG9jOFMD2osvC3s+Squfpo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -34,14 +44,17 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 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-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= @@ -51,6 +64,10 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -58,8 +75,13 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2El google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/grpc v1.19.0 h1:cfg4PD8YEdSFnm7qLV4++93WcmhH2nIUhMjhdCvl3j8= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/providers/zap/examples_test.go b/providers/zap/examples_test.go index d17364a0e..378ca5d67 100644 --- a/providers/zap/examples_test.go +++ b/providers/zap/examples_test.go @@ -102,7 +102,7 @@ func ExampleWithDecider() { } } -func ExampleWithPayloadLogging() { +func ExampleServerPayloadLoggingDecider() { // Logger is used, allowing pre-definition of certain fields by the user. logger := zap.NewNop() // Expect payload from "/blah.foo.healthcheck/Check" call to be logged. @@ -130,5 +130,5 @@ func TestExamplesBuildable(t *testing.T) { Example_initializationWithDurationFieldOverride() Example_initializationWithCodeGenRequestFieldExtractor() ExampleWithDecider() - ExampleWithPayloadLogging() + ExampleServerPayloadLoggingDecider() } diff --git a/providers/zap/go.mod b/providers/zap/go.mod index e3cde6c07..b3180093e 100644 --- a/providers/zap/go.mod +++ b/providers/zap/go.mod @@ -5,5 +5,5 @@ go 1.14 require ( github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20201002093600-73cf2ae9d891 go.uber.org/zap v1.15.0 - google.golang.org/grpc v1.19.0 + google.golang.org/grpc v1.30.0 ) diff --git a/providers/zap/go.sum b/providers/zap/go.sum index 943c5a98d..e1a0d181f 100644 --- a/providers/zap/go.sum +++ b/providers/zap/go.sum @@ -1,10 +1,15 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= @@ -13,9 +18,12 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-20200501113911-9a95f0fdbfea h1:1Tk1IbruXbunEnaIZEFb+Hpv9BIZti3OxKwKn5wWyKk= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-20200501113911-9a95f0fdbfea/go.mod h1:GugMBs30ZSAkckqXEAIEGyYdDH6EgqowG8ppA3Zt+AY= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20201002093600-73cf2ae9d891 h1:2F7/en805byWQR92etfFjOqtRtWsUu09R7wm6LtlHEw= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20201002093600-73cf2ae9d891/go.mod h1:GhphxcdlaRyAuBSvo6rV71BvQcvB/vuX8ugCyybuS2k= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= @@ -28,9 +36,11 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -49,6 +59,7 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -73,11 +84,14 @@ golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -85,6 +99,10 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2El google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/grpc v1.19.0 h1:cfg4PD8YEdSFnm7qLV4++93WcmhH2nIUhMjhdCvl3j8= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -92,5 +110,6 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= diff --git a/providers/zerolog/examples_test.go b/providers/zerolog/examples_test.go index 9e10383d7..e7cd11567 100644 --- a/providers/zerolog/examples_test.go +++ b/providers/zerolog/examples_test.go @@ -104,7 +104,7 @@ func ExampleWithDecider() { } } -func ExampleWithPayloadLogging() { +func ExampleServerPayloadLoggingDecider() { // Logger is used, allowing pre-definition of certain fields by the user. logger := zerolog.New(os.Stderr) // Expect payload from "/blah.foo.healthcheck/Check" call to be logged. @@ -132,5 +132,5 @@ func TestExamplesBuildable(t *testing.T) { Example_initializationWithDurationFieldOverride() Example_initializationWithCodeGenRequestFieldExtractor() ExampleWithDecider() - ExampleWithPayloadLogging() + ExampleServerPayloadLoggingDecider() } diff --git a/providers/zerolog/go.mod b/providers/zerolog/go.mod index 2dba6ac32..d2fe1ab3f 100644 --- a/providers/zerolog/go.mod +++ b/providers/zerolog/go.mod @@ -5,5 +5,5 @@ go 1.14 require ( github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20201002093600-73cf2ae9d891 github.com/rs/zerolog v1.19.0 - google.golang.org/grpc v1.19.0 + google.golang.org/grpc v1.30.0 ) diff --git a/providers/zerolog/go.sum b/providers/zerolog/go.sum index 98e99c8e9..cfb4d966f 100644 --- a/providers/zerolog/go.sum +++ b/providers/zerolog/go.sum @@ -1,9 +1,14 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= @@ -12,17 +17,22 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-20200501113911-9a95f0fdbfea h1:1Tk1IbruXbunEnaIZEFb+Hpv9BIZti3OxKwKn5wWyKk= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-20200501113911-9a95f0fdbfea/go.mod h1:GugMBs30ZSAkckqXEAIEGyYdDH6EgqowG8ppA3Zt+AY= +github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20201002093600-73cf2ae9d891 h1:2F7/en805byWQR92etfFjOqtRtWsUu09R7wm6LtlHEw= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20201002093600-73cf2ae9d891/go.mod h1:GhphxcdlaRyAuBSvo6rV71BvQcvB/vuX8ugCyybuS2k= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.19.0 h1:hYz4ZVdUgjXTBUmrkrw55j1nHx68LfOKIQk5IYtyScg= github.com/rs/zerolog v1.19.0/go.mod h1:IzD0RJ65iWH0w97OQQebJEvTZYvsCUm9WVLWBQrJRjo= @@ -33,9 +43,11 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -50,8 +62,12 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190828213141-aed303cbaa74/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -59,8 +75,13 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2El google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/grpc v1.19.0 h1:cfg4PD8YEdSFnm7qLV4++93WcmhH2nIUhMjhdCvl3j8= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/scripts/genproto.sh b/scripts/genproto.sh index 6fcc22442..a3964d97b 100755 --- a/scripts/genproto.sh +++ b/scripts/genproto.sh @@ -7,32 +7,27 @@ set -u PROTOC_BIN=${PROTOC_BIN:-protoc} GOIMPORTS_BIN=${GOIMPORTS_BIN:-goimports} -PROTOC_GEN_GOGOFAST_BIN=${PROTOC_GEN_GOGOFAST_BIN:-protoc-gen-gogofast} +PROTOC_GEN_GO_BIN=${PROTOC_GEN_GO_BIN:-protoc-gen-go} +PROTOC_GEN_GO_GRPC_BIN=${PROTOC_GEN_GO_GRPC_BIN:-protoc-gen-go-grpc} if ! [[ "$0" =~ "scripts/genproto.sh" ]]; then echo "must be run from repository root" exit 255 fi +OLDPATH=${PATH} + mkdir -p /tmp/protobin/ -cp ${PROTOC_GEN_GOGOFAST_BIN} /tmp/protobin/protoc-gen-gogofast -PATH=${PATH}:/tmp/protobin -GOGOPROTO_ROOT="$(GO111MODULE=on go list -modfile=.bingo/protoc-gen-gogofast.mod -f '{{ .Dir }}' -m github.com/gogo/protobuf)" -GOGOPROTO_PATH="${GOGOPROTO_ROOT}:${GOGOPROTO_ROOT}/protobuf" +cp ${PROTOC_GEN_GO_BIN} /tmp/protobin/protoc-gen-go +cp ${PROTOC_GEN_GO_GRPC_BIN} /tmp/protobin/protoc-gen-go-grpc +PATH=${OLDPATH}:/tmp/protobin -DIRS="grpctesting/testpb grpctesting/gogotestpb" -echo "generating code" +DIRS="grpctesting/testpb" +echo "generating protobuf code" for dir in ${DIRS}; do pushd ${dir} - ${PROTOC_BIN} --gogofast_out=\ -Mgoogle/protobuf/any.proto=github.com/gogo/protobuf/types,\ -Mgoogle/protobuf/duration.proto=github.com/gogo/protobuf/types,\ -Mgoogle/protobuf/struct.proto=github.com/gogo/protobuf/types,\ -Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types,\ -Mgoogle/protobuf/wrappers.proto=github.com/gogo/protobuf/types,\ -plugins=grpc:. \ + ${PROTOC_BIN} --go_out=. --go-grpc_out=.\ -I=. \ - -I="${GOGOPROTO_PATH}" \ *.proto ${GOIMPORTS_BIN} -w *.pb.go From 6672a20f21d1899f93f6f8bc47edc136a445038d Mon Sep 17 00:00:00 2001 From: Dario Maiocchi Date: Fri, 22 Jan 2021 21:28:20 +0100 Subject: [PATCH 14/27] improve v2 rate-limiter (#380) * Add error instead of bool to ratelimit interceptor Signed-off-by: dmaiocchi * Improve comment based on suggesitons Signed-off-by: dmaiocchi * Update interceptors/ratelimit/ratelimit.go Co-authored-by: Bartlomiej Plotka --- interceptors/ratelimit/examples_test.go | 4 ++-- interceptors/ratelimit/ratelimit.go | 12 ++++++------ interceptors/ratelimit/ratelimit_test.go | 10 +++++----- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/interceptors/ratelimit/examples_test.go b/interceptors/ratelimit/examples_test.go index c624f6dec..a7c0e8ced 100644 --- a/interceptors/ratelimit/examples_test.go +++ b/interceptors/ratelimit/examples_test.go @@ -12,8 +12,8 @@ import ( // It does not limit any request because Limit function always returns false. type alwaysPassLimiter struct{} -func (*alwaysPassLimiter) Limit(_ context.Context) bool { - return false +func (*alwaysPassLimiter) Limit(_ context.Context) error { + return nil } // Simple example of server initialization code. diff --git a/interceptors/ratelimit/ratelimit.go b/interceptors/ratelimit/ratelimit.go index afc843106..23bf36e6d 100644 --- a/interceptors/ratelimit/ratelimit.go +++ b/interceptors/ratelimit/ratelimit.go @@ -9,17 +9,17 @@ import ( ) // Limiter defines the interface to perform request rate limiting. -// If Limit function return true, the request will be rejected. +// If Limit function returns an error, the request will be rejected with the gRPC codes.ResourceExhausted and the provided error. // Otherwise, the request will pass. type Limiter interface { - Limit(ctx context.Context) bool + Limit(ctx context.Context) error } // UnaryServerInterceptor returns a new unary server interceptors that performs request rate limiting. func UnaryServerInterceptor(limiter Limiter) grpc.UnaryServerInterceptor { return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { - if limiter.Limit(ctx) { - return nil, status.Errorf(codes.ResourceExhausted, "%s is rejected by grpc_ratelimit middleware, please retry later.", info.FullMethod) + if err := limiter.Limit(ctx); err != nil { + return nil, status.Errorf(codes.ResourceExhausted, "%s is rejected by grpc_ratelimit middleware, please retry later. %s", info.FullMethod, err) } return handler(ctx, req) } @@ -28,8 +28,8 @@ func UnaryServerInterceptor(limiter Limiter) grpc.UnaryServerInterceptor { // StreamServerInterceptor returns a new stream server interceptor that performs rate limiting on the request. func StreamServerInterceptor(limiter Limiter) grpc.StreamServerInterceptor { return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { - if limiter.Limit(stream.Context()) { - return status.Errorf(codes.ResourceExhausted, "%s is rejected by grpc_ratelimit middleware, please retry later.", info.FullMethod) + if err := limiter.Limit(stream.Context()); err != nil { + return status.Errorf(codes.ResourceExhausted, "%s is rejected by grpc_ratelimit middleware, please retry later. %s", info.FullMethod, err) } return handler(srv, stream) } diff --git a/interceptors/ratelimit/ratelimit_test.go b/interceptors/ratelimit/ratelimit_test.go index 019f0a5de..8c7c5371f 100644 --- a/interceptors/ratelimit/ratelimit_test.go +++ b/interceptors/ratelimit/ratelimit_test.go @@ -25,9 +25,9 @@ func (m *mockGRPCServerStream) Context() context.Context { type mockContextBasedLimiter struct{} -func (*mockContextBasedLimiter) Limit(ctx context.Context) bool { - l, ok := ctx.Value(ctxLimitKey).(bool) - return ok && l +func (*mockContextBasedLimiter) Limit(ctx context.Context) error { + l, _ := ctx.Value(ctxLimitKey).(error) + return l } func TestUnaryServerInterceptor_RateLimitPass(t *testing.T) { @@ -74,7 +74,7 @@ func TestUnaryServerInterceptor_RateLimitFail(t *testing.T) { } resp, err := interceptor(ctx, nil, info, handler) assert.Nil(t, resp) - assert.EqualError(t, err, "rpc error: code = ResourceExhausted desc = FakeMethod is rejected by grpc_ratelimit middleware, please retry later.") + assert.EqualError(t, err, errMsgFake) } func TestStreamServerInterceptor_RateLimitFail(t *testing.T) { @@ -89,5 +89,5 @@ func TestStreamServerInterceptor_RateLimitFail(t *testing.T) { FullMethod: "FakeMethod", } err := interceptor(nil, &mockGRPCServerStream{ctx: ctx}, info, handler) - assert.EqualError(t, err, "rpc error: code = ResourceExhausted desc = FakeMethod is rejected by grpc_ratelimit middleware, please retry later.") + assert.EqualError(t, err, errMsgFake) } From 468f61573a348653e9ef47588ebcc8da3181a3c5 Mon Sep 17 00:00:00 2001 From: Bartlomiej Plotka Date: Fri, 22 Jan 2021 20:43:22 +0000 Subject: [PATCH 15/27] =?UTF-8?q?Moved=20to=20buf;=20Added=20buf=20lint;?= =?UTF-8?q?=20Fixed=20ping=20service=20to=20match=20standards;=20=E2=80=A6?= =?UTF-8?q?=20(#383)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Moved to buf; Added buf lint; Fixed ping service to match standards; Moved auth to interceptors. Signed-off-by: Bartlomiej Plotka * Fixed flakiness. Signed-off-by: Bartlomiej Plotka --- .bingo/Variables.mk | 6 + .bingo/buf.mod | 5 + .bingo/variables.env | 2 + Makefile | 36 +- buf.yaml | 7 + go.sum | 1 + grpctesting/mutex_readerwriter.go | 31 - grpctesting/pingservice.go | 82 -- .../testpb/test.manual_extractfields.pb.go | 10 - .../testpb/test.manual_validator.pb.go | 12 - grpctesting/testpb/test.pb.go | 332 ------- grpctesting/testpb/test.proto | 32 - {auth => interceptors/auth}/auth.go | 0 {auth => interceptors/auth}/auth_test.go | 43 +- {auth => interceptors/auth}/doc.go | 0 {auth => interceptors/auth}/examples_test.go | 2 +- {auth => interceptors/auth}/metadata.go | 0 {auth => interceptors/auth}/metadata_test.go | 0 interceptors/client_test.go | 23 +- interceptors/logging/interceptors_test.go | 42 +- interceptors/logging/payload_test.go | 54 +- interceptors/recovery/interceptors_test.go | 38 +- interceptors/retry/examples_test.go | 4 +- interceptors/retry/retry_test.go | 60 +- interceptors/server_test.go | 19 +- interceptors/skip/examples_test.go | 4 +- interceptors/skip/interceptor_test.go | 25 +- interceptors/tags/fieldextractor_test.go | 2 +- interceptors/tags/interceptors_test.go | 42 +- interceptors/tracing/interceptors_test.go | 29 +- interceptors/validator/validator_test.go | 37 +- scripts/genproto.sh | 35 - scripts/installprotoc.sh | 59 -- .../testpb}/interceptor_suite.go | 14 +- testing/testpb/pingservice.go | 78 ++ .../testpb}/pingservice_test.go | 21 +- .../testpb/test.manual_extractfields.pb.go | 25 + testing/testpb/test.manual_validator.pb.go | 45 + testing/testpb/test.pb.go | 853 ++++++++++++++++++ .../testpb/test_grpc.pb.go | 86 +- testing/testpb/v1/test.proto | 68 ++ 41 files changed, 1373 insertions(+), 891 deletions(-) create mode 100644 .bingo/buf.mod create mode 100644 buf.yaml delete mode 100644 grpctesting/mutex_readerwriter.go delete mode 100644 grpctesting/pingservice.go delete mode 100644 grpctesting/testpb/test.manual_extractfields.pb.go delete mode 100644 grpctesting/testpb/test.manual_validator.pb.go delete mode 100644 grpctesting/testpb/test.pb.go delete mode 100644 grpctesting/testpb/test.proto rename {auth => interceptors/auth}/auth.go (100%) rename {auth => interceptors/auth}/auth_test.go (84%) rename {auth => interceptors/auth}/doc.go (100%) rename {auth => interceptors/auth}/examples_test.go (97%) rename {auth => interceptors/auth}/metadata.go (100%) rename {auth => interceptors/auth}/metadata_test.go (100%) delete mode 100755 scripts/genproto.sh delete mode 100755 scripts/installprotoc.sh rename {grpctesting => testing/testpb}/interceptor_suite.go (94%) create mode 100644 testing/testpb/pingservice.go rename {grpctesting => testing/testpb}/pingservice_test.go (70%) create mode 100644 testing/testpb/test.manual_extractfields.pb.go create mode 100644 testing/testpb/test.manual_validator.pb.go create mode 100644 testing/testpb/test.pb.go rename {grpctesting => testing}/testpb/test_grpc.pb.go (73%) create mode 100644 testing/testpb/v1/test.proto diff --git a/.bingo/Variables.mk b/.bingo/Variables.mk index f15748270..6258760bc 100644 --- a/.bingo/Variables.mk +++ b/.bingo/Variables.mk @@ -23,6 +23,12 @@ $(BINGO): $(BINGO_DIR)/bingo.mod @echo "(re)installing $(GOBIN)/bingo-v0.3.0" @cd $(BINGO_DIR) && $(GO) build -mod=mod -modfile=bingo.mod -o=$(GOBIN)/bingo-v0.3.0 "github.com/bwplotka/bingo" +BUF := $(GOBIN)/buf-v0.35.1 +$(BUF): $(BINGO_DIR)/buf.mod + @# Install binary/ries using Go 1.14+ build command. This is using bwplotka/bingo-controlled, separate go module with pinned dependencies. + @echo "(re)installing $(GOBIN)/buf-v0.35.1" + @cd $(BINGO_DIR) && $(GO) build -mod=mod -modfile=buf.mod -o=$(GOBIN)/buf-v0.35.1 "github.com/bufbuild/buf/cmd/buf" + FAILLINT := $(GOBIN)/faillint-v1.5.0 $(FAILLINT): $(BINGO_DIR)/faillint.mod @# Install binary/ries using Go 1.14+ build command. This is using bwplotka/bingo-controlled, separate go module with pinned dependencies. diff --git a/.bingo/buf.mod b/.bingo/buf.mod new file mode 100644 index 000000000..8f2ac1879 --- /dev/null +++ b/.bingo/buf.mod @@ -0,0 +1,5 @@ +module _ // Auto generated by https://github.com/bwplotka/bingo. DO NOT EDIT + +go 1.15 + +require github.com/bufbuild/buf v0.35.1 // cmd/buf diff --git a/.bingo/variables.env b/.bingo/variables.env index 153d97ddb..f1263bb1f 100644 --- a/.bingo/variables.env +++ b/.bingo/variables.env @@ -10,6 +10,8 @@ fi BINGO="${GOBIN}/bingo-v0.3.0" +BUF="${GOBIN}/buf-v0.35.1" + FAILLINT="${GOBIN}/faillint-v1.5.0" GOIMPORTS="${GOBIN}/goimports-v0.0.0-20200529172331-a64b76657301" diff --git a/Makefile b/Makefile index 5cb0bd328..7e36dbd1f 100644 --- a/Makefile +++ b/Makefile @@ -7,9 +7,6 @@ MODULES ?= $(PROVIDER_MODULES) $(PWD)/ GOBIN ?= $(firstword $(subst :, ,${GOPATH}))/bin -// TODO(bwplotka): Move to buf. -PROTOC_VERSION ?= 3.12.3 -PROTOC ?= $(GOBIN)/protoc-$(PROTOC_VERSION) TMP_GOPATH ?= /tmp/gopath GO111MODULE ?= on @@ -43,11 +40,6 @@ fmt: $(GOIMPORTS) @echo "Running fmt for all modules: $(MODULES)" @$(GOIMPORTS) -local github.com/grpc-ecosystem/go-grpc-middleware/v2 -w $(MODULES) -.PHONY: proto -proto: ## Generates Go files from Thanos proto files. -proto: $(GOIMPORTS) $(PROTOC) $(PROTOC_GEN_GO) $(PROTOC_GEN_GO_GRPC) ./grpctesting/testpb/test.proto - @GOIMPORTS_BIN="$(GOIMPORTS)" PROTOC_BIN="$(PROTOC)" PROTOC_GEN_GO_BIN="$(PROTOC_GEN_GO)" PROTOC_GEN_GO_GRPC_BIN="$(PROTOC_GEN_GO_GRPC)" scripts/genproto.sh - .PHONY: test test: @echo "Running tests for all modules: $(MODULES)" @@ -76,7 +68,9 @@ deps: # --mem-profile-path string Path to memory profile output file # to debug big allocations during linting. lint: ## Runs various static analysis tools against our code. -lint: fmt proto +lint: $(BUF) fmt + @echo ">> lint proto files" + @$(BUF) lint @echo "Running lint for all modules: $(MODULES)" ./scripts/git-tree.sh for dir in $(MODULES) ; do \ @@ -99,11 +93,21 @@ lint_module: $(FAILLINT) $(GOLANGCI_LINT) $(MISSPELL) @cd $(DIR) && $(GOLANGCI_LINT) run @./scripts/git-tree.sh -# TODO(bwplotka): Move to buf. -$(PROTOC): + +# For protoc naming matters. +PROTOC_GEN_GO_CURRENT := $(TMP_GOPATH)/protoc-gen-go +PROTOC_GEN_GO_GRPC_CURRENT := $(TMP_GOPATH)/protoc-gen-go-grpc +PROTO_TEST_DIR := testing/testpb/v1 + +.PHONY: proto +proto: ## Generate testing protobufs +proto: $(BUF) $(PROTOC_GEN_GO) $(PROTOC_GEN_GO_GRPC) $(PROTO_TEST_DIR)/test.proto @mkdir -p $(TMP_GOPATH) - @echo ">> fetching protoc@${PROTOC_VERSION}" - @PROTOC_VERSION="$(PROTOC_VERSION)" TMP_GOPATH="$(TMP_GOPATH)" scripts/installprotoc.sh - @echo ">> installing protoc@${PROTOC_VERSION}" - @mv -- "$(TMP_GOPATH)/bin/protoc" "$(GOBIN)/protoc-$(PROTOC_VERSION)" - @echo ">> produced $(GOBIN)/protoc-$(PROTOC_VERSION)" + @cp $(PROTOC_GEN_GO) $(PROTOC_GEN_GO_CURRENT) + @cp $(PROTOC_GEN_GO_GRPC) $(PROTOC_GEN_GO_GRPC_CURRENT) + @echo ">> generating $(PROTO_TEST_DIR)" + @PATH=$(GOBIN):$(TMP_GOPATH) $(BUF) protoc \ + -I $(PROTO_TEST_DIR) \ + --go_out=$(PROTO_TEST_DIR)/../ \ + --go-grpc_out=$(PROTO_TEST_DIR)/../ \ + $(PROTO_TEST_DIR)/*.proto diff --git a/buf.yaml b/buf.yaml new file mode 100644 index 000000000..f91a41324 --- /dev/null +++ b/buf.yaml @@ -0,0 +1,7 @@ +version: v1beta1 +build: + roots: + - . +lint: + use: + - DEFAULT \ No newline at end of file diff --git a/go.sum b/go.sum index 42190ddfa..e1d0ddb5a 100644 --- a/go.sum +++ b/go.sum @@ -30,6 +30,7 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 h1:FlFbCRLd5Jr4iYXZufAvgWN6Ao0JrI5chLINnUXDDr0= github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= diff --git a/grpctesting/mutex_readerwriter.go b/grpctesting/mutex_readerwriter.go deleted file mode 100644 index 0cd1a283d..000000000 --- a/grpctesting/mutex_readerwriter.go +++ /dev/null @@ -1,31 +0,0 @@ -package grpctesting - -import ( - "io" - "sync" -) - -// MutexReadWriter is a io.ReadWriter that can be read and worked on from multiple go routines. -type MutexReadWriter struct { - sync.Mutex - rw io.ReadWriter -} - -// NewMutexReadWriter creates a new thread-safe io.ReadWriter. -func NewMutexReadWriter(rw io.ReadWriter) *MutexReadWriter { - return &MutexReadWriter{rw: rw} -} - -// Write implements the io.Writer interface. -func (m *MutexReadWriter) Write(p []byte) (int, error) { - m.Lock() - defer m.Unlock() - return m.rw.Write(p) -} - -// Read implements the io.Reader interface. -func (m *MutexReadWriter) Read(p []byte) (int, error) { - m.Lock() - defer m.Unlock() - return m.rw.Read(p) -} diff --git a/grpctesting/pingservice.go b/grpctesting/pingservice.go deleted file mode 100644 index 714bfc97b..000000000 --- a/grpctesting/pingservice.go +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2016 Michal Witkowski. All Rights Reserved. -// See LICENSE for licensing terms. - -/* -Package `grpc_testing` provides helper functions for testing validators in this package. -*/ - -package grpctesting - -import ( - "context" - "io" - "testing" - - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - - "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting/testpb" -) - -const ( - // DefaultPongValue is the default value used. - DefaultResponseValue = "default_response_value" - // ListResponseCount is the expected number of responses to PingList - ListResponseCount = 100 -) - -// Interface implementation assert. -var _ testpb.TestServiceServer = &TestPingService{} - -type TestPingService struct { - testpb.UnimplementedTestServiceServer - - T *testing.T -} - -func (s *TestPingService) PingEmpty(_ context.Context, _ *testpb.Empty) (*testpb.PingResponse, error) { - return &testpb.PingResponse{Value: DefaultResponseValue, Counter: 0}, nil -} - -func (s *TestPingService) Ping(_ context.Context, ping *testpb.PingRequest) (*testpb.PingResponse, error) { - // Send user trailers and headers. - return &testpb.PingResponse{Value: ping.Value, Counter: 0}, nil -} - -func (s *TestPingService) PingError(_ context.Context, ping *testpb.PingRequest) (*testpb.Empty, error) { - code := codes.Code(ping.ErrorCodeReturned) - return nil, status.Errorf(code, "Userspace error.") -} - -func (s *TestPingService) PingList(ping *testpb.PingRequest, stream testpb.TestService_PingListServer) error { - if ping.ErrorCodeReturned != 0 { - return status.Errorf(codes.Code(ping.ErrorCodeReturned), "foobar") - } - - // Send user trailers and headers. - for i := 0; i < ListResponseCount; i++ { - if err := stream.Send(&testpb.PingResponse{Value: ping.Value, Counter: int32(i)}); err != nil { - return err - } - } - return nil -} - -func (s *TestPingService) PingStream(stream testpb.TestService_PingStreamServer) error { - count := 0 - for { - ping, err := stream.Recv() - if err == io.EOF { - break - } - if err != nil { - return err - } - if err := stream.Send(&testpb.PingResponse{Value: ping.Value, Counter: int32(count)}); err != nil { - return err - } - - count += 1 - } - return nil -} diff --git a/grpctesting/testpb/test.manual_extractfields.pb.go b/grpctesting/testpb/test.manual_extractfields.pb.go deleted file mode 100644 index 8d36746bf..000000000 --- a/grpctesting/testpb/test.manual_extractfields.pb.go +++ /dev/null @@ -1,10 +0,0 @@ -// Manual code for logging field extraction tests. - -package testpb - -const TestServiceFullName = "grpc_middleware.testpb.TestService" - -// This is implementing tags.requestFieldsExtractor -func (m *PingRequest) ExtractRequestFields(appendToMap map[string]string) { - appendToMap["value"] = m.Value -} diff --git a/grpctesting/testpb/test.manual_validator.pb.go b/grpctesting/testpb/test.manual_validator.pb.go deleted file mode 100644 index f123c70b7..000000000 --- a/grpctesting/testpb/test.manual_validator.pb.go +++ /dev/null @@ -1,12 +0,0 @@ -// Manual code for validation tests. - -package testpb - -import "github.com/pkg/errors" - -func (m *PingRequest) Validate() error { - if m.SleepTimeMs > 10000 { - return errors.New("cannot sleep for more than 10s") - } - return nil -} diff --git a/grpctesting/testpb/test.pb.go b/grpctesting/testpb/test.pb.go deleted file mode 100644 index 2e07a7648..000000000 --- a/grpctesting/testpb/test.pb.go +++ /dev/null @@ -1,332 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.25.0 -// protoc v3.12.3 -// source: test.proto - -package testpb - -import ( - reflect "reflect" - sync "sync" - - proto "github.com/golang/protobuf/proto" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// This is a compile-time assertion that a sufficiently up-to-date version -// of the legacy proto package is being used. -const _ = proto.ProtoPackageIsVersion4 - -type Empty struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *Empty) Reset() { - *x = Empty{} - if protoimpl.UnsafeEnabled { - mi := &file_test_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Empty) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Empty) ProtoMessage() {} - -func (x *Empty) ProtoReflect() protoreflect.Message { - mi := &file_test_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Empty.ProtoReflect.Descriptor instead. -func (*Empty) Descriptor() ([]byte, []int) { - return file_test_proto_rawDescGZIP(), []int{0} -} - -type PingRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` - SleepTimeMs int32 `protobuf:"varint,2,opt,name=sleep_time_ms,json=sleepTimeMs,proto3" json:"sleep_time_ms,omitempty"` - ErrorCodeReturned uint32 `protobuf:"varint,3,opt,name=error_code_returned,json=errorCodeReturned,proto3" json:"error_code_returned,omitempty"` -} - -func (x *PingRequest) Reset() { - *x = PingRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_test_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PingRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PingRequest) ProtoMessage() {} - -func (x *PingRequest) ProtoReflect() protoreflect.Message { - mi := &file_test_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PingRequest.ProtoReflect.Descriptor instead. -func (*PingRequest) Descriptor() ([]byte, []int) { - return file_test_proto_rawDescGZIP(), []int{1} -} - -func (x *PingRequest) GetValue() string { - if x != nil { - return x.Value - } - return "" -} - -func (x *PingRequest) GetSleepTimeMs() int32 { - if x != nil { - return x.SleepTimeMs - } - return 0 -} - -func (x *PingRequest) GetErrorCodeReturned() uint32 { - if x != nil { - return x.ErrorCodeReturned - } - return 0 -} - -type PingResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value string `protobuf:"bytes,1,opt,name=Value,proto3" json:"Value,omitempty"` - Counter int32 `protobuf:"varint,2,opt,name=counter,proto3" json:"counter,omitempty"` -} - -func (x *PingResponse) Reset() { - *x = PingResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_test_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PingResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PingResponse) ProtoMessage() {} - -func (x *PingResponse) ProtoReflect() protoreflect.Message { - mi := &file_test_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PingResponse.ProtoReflect.Descriptor instead. -func (*PingResponse) Descriptor() ([]byte, []int) { - return file_test_proto_rawDescGZIP(), []int{2} -} - -func (x *PingResponse) GetValue() string { - if x != nil { - return x.Value - } - return "" -} - -func (x *PingResponse) GetCounter() int32 { - if x != nil { - return x.Counter - } - return 0 -} - -var File_test_proto protoreflect.FileDescriptor - -var file_test_proto_rawDesc = []byte{ - 0x0a, 0x0a, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x16, 0x67, 0x72, - 0x70, 0x63, 0x5f, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x74, 0x65, - 0x73, 0x74, 0x70, 0x62, 0x22, 0x07, 0x0a, 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x77, 0x0a, - 0x0b, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x5f, 0x74, 0x69, 0x6d, 0x65, - 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x73, 0x6c, 0x65, 0x65, 0x70, - 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, - 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x11, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x22, 0x3e, 0x0a, 0x0c, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x18, 0x0a, 0x07, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x32, 0xc3, 0x03, 0x0a, 0x0b, 0x54, 0x65, 0x73, 0x74, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x52, 0x0a, 0x09, 0x50, 0x69, 0x6e, 0x67, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x12, 0x1d, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x6d, 0x69, 0x64, 0x64, 0x6c, - 0x65, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x1a, 0x24, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, - 0x77, 0x61, 0x72, 0x65, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x50, 0x69, 0x6e, 0x67, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x53, 0x0a, 0x04, 0x50, 0x69, - 0x6e, 0x67, 0x12, 0x23, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, - 0x77, 0x61, 0x72, 0x65, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x50, 0x69, 0x6e, 0x67, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x6d, - 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, - 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x51, 0x0a, 0x09, 0x50, 0x69, 0x6e, 0x67, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x23, 0x2e, 0x67, - 0x72, 0x70, 0x63, 0x5f, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x74, - 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, - 0x61, 0x72, 0x65, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x22, 0x00, 0x12, 0x59, 0x0a, 0x08, 0x50, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x23, - 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, - 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x6d, 0x69, 0x64, 0x64, 0x6c, - 0x65, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x50, 0x69, 0x6e, - 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x5d, 0x0a, - 0x0a, 0x50, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x23, 0x2e, 0x67, 0x72, - 0x70, 0x63, 0x5f, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x74, 0x65, - 0x73, 0x74, 0x70, 0x62, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x24, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, - 0x72, 0x65, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x42, 0x0b, 0x5a, 0x09, - 0x2e, 0x2e, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, -} - -var ( - file_test_proto_rawDescOnce sync.Once - file_test_proto_rawDescData = file_test_proto_rawDesc -) - -func file_test_proto_rawDescGZIP() []byte { - file_test_proto_rawDescOnce.Do(func() { - file_test_proto_rawDescData = protoimpl.X.CompressGZIP(file_test_proto_rawDescData) - }) - return file_test_proto_rawDescData -} - -var file_test_proto_msgTypes = make([]protoimpl.MessageInfo, 3) -var file_test_proto_goTypes = []interface{}{ - (*Empty)(nil), // 0: grpc_middleware.testpb.Empty - (*PingRequest)(nil), // 1: grpc_middleware.testpb.PingRequest - (*PingResponse)(nil), // 2: grpc_middleware.testpb.PingResponse -} -var file_test_proto_depIdxs = []int32{ - 0, // 0: grpc_middleware.testpb.TestService.PingEmpty:input_type -> grpc_middleware.testpb.Empty - 1, // 1: grpc_middleware.testpb.TestService.Ping:input_type -> grpc_middleware.testpb.PingRequest - 1, // 2: grpc_middleware.testpb.TestService.PingError:input_type -> grpc_middleware.testpb.PingRequest - 1, // 3: grpc_middleware.testpb.TestService.PingList:input_type -> grpc_middleware.testpb.PingRequest - 1, // 4: grpc_middleware.testpb.TestService.PingStream:input_type -> grpc_middleware.testpb.PingRequest - 2, // 5: grpc_middleware.testpb.TestService.PingEmpty:output_type -> grpc_middleware.testpb.PingResponse - 2, // 6: grpc_middleware.testpb.TestService.Ping:output_type -> grpc_middleware.testpb.PingResponse - 0, // 7: grpc_middleware.testpb.TestService.PingError:output_type -> grpc_middleware.testpb.Empty - 2, // 8: grpc_middleware.testpb.TestService.PingList:output_type -> grpc_middleware.testpb.PingResponse - 2, // 9: grpc_middleware.testpb.TestService.PingStream:output_type -> grpc_middleware.testpb.PingResponse - 5, // [5:10] is the sub-list for method output_type - 0, // [0:5] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_test_proto_init() } -func file_test_proto_init() { - if File_test_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_test_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Empty); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_test_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PingRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_test_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PingResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_test_proto_rawDesc, - NumEnums: 0, - NumMessages: 3, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_test_proto_goTypes, - DependencyIndexes: file_test_proto_depIdxs, - MessageInfos: file_test_proto_msgTypes, - }.Build() - File_test_proto = out.File - file_test_proto_rawDesc = nil - file_test_proto_goTypes = nil - file_test_proto_depIdxs = nil -} diff --git a/grpctesting/testpb/test.proto b/grpctesting/testpb/test.proto deleted file mode 100644 index 04dd4e837..000000000 --- a/grpctesting/testpb/test.proto +++ /dev/null @@ -1,32 +0,0 @@ -syntax = "proto3"; - -package grpc_middleware.testpb; - -option go_package = "../testpb"; - -message Empty { -} - -message PingRequest { - string value = 1; - int32 sleep_time_ms = 2; - uint32 error_code_returned = 3; -} - -message PingResponse { - string Value = 1; - int32 counter = 2; -} - -service TestService { - rpc PingEmpty(Empty) returns (PingResponse) {} - - rpc Ping(PingRequest) returns (PingResponse) {} - - rpc PingError(PingRequest) returns (Empty) {} - - rpc PingList(PingRequest) returns (stream PingResponse) {} - - rpc PingStream(stream PingRequest) returns (stream PingResponse) {} - -} diff --git a/auth/auth.go b/interceptors/auth/auth.go similarity index 100% rename from auth/auth.go rename to interceptors/auth/auth.go diff --git a/auth/auth_test.go b/interceptors/auth/auth_test.go similarity index 84% rename from auth/auth_test.go rename to interceptors/auth/auth_test.go index 0a0f2133f..58e30cb18 100644 --- a/auth/auth_test.go +++ b/interceptors/auth/auth_test.go @@ -19,9 +19,8 @@ import ( "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/auth" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting/testpb" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/auth" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/testing/testpb" "github.com/grpc-ecosystem/go-grpc-middleware/v2/util/metautils" ) @@ -30,8 +29,6 @@ var authedMarker struct{} var ( commonAuthToken = "some_good_token" overrideAuthToken = "override_token" - - goodPing = &testpb.PingRequest{Value: "something", SleepTimeMs: 9999} ) // TODO(mwitkow): Add auth from metadata client dialer, which requires TLS. @@ -58,12 +55,12 @@ type assertingPingService struct { T *testing.T } -func (s *assertingPingService) PingError(ctx context.Context, ping *testpb.PingRequest) (*testpb.Empty, error) { +func (s *assertingPingService) PingError(ctx context.Context, ping *testpb.PingErrorRequest) (*testpb.PingErrorResponse, error) { assertAuthMarkerExists(s.T, ctx) return s.TestServiceServer.PingError(ctx, ping) } -func (s *assertingPingService) PingList(ping *testpb.PingRequest, stream testpb.TestService_PingListServer) error { +func (s *assertingPingService) PingList(ping *testpb.PingListRequest, stream testpb.TestService_PingListServer) error { assertAuthMarkerExists(s.T, stream.Context()) return s.TestServiceServer.PingList(ping, stream) } @@ -77,8 +74,8 @@ func ctxWithToken(ctx context.Context, scheme string, token string) context.Cont func TestAuthTestSuite(t *testing.T) { authFunc := buildDummyAuthFunction("bearer", commonAuthToken) s := &AuthTestSuite{ - InterceptorTestSuite: &grpctesting.InterceptorTestSuite{ - TestService: &assertingPingService{&grpctesting.TestPingService{T: t}, t}, + InterceptorTestSuite: &testpb.InterceptorTestSuite{ + TestService: &assertingPingService{&testpb.TestPingService{T: t}, t}, ServerOpts: []grpc.ServerOption{ grpc.StreamInterceptor(auth.StreamServerInterceptor(authFunc)), grpc.UnaryInterceptor(auth.UnaryServerInterceptor(authFunc)), @@ -89,35 +86,35 @@ func TestAuthTestSuite(t *testing.T) { } type AuthTestSuite struct { - *grpctesting.InterceptorTestSuite + *testpb.InterceptorTestSuite } func (s *AuthTestSuite) TestUnary_NoAuth() { - _, err := s.Client.Ping(s.SimpleCtx(), goodPing) + _, err := s.Client.Ping(s.SimpleCtx(), testpb.GoodPing) assert.Error(s.T(), err, "there must be an error") assert.Equal(s.T(), codes.Unauthenticated, status.Code(err), "must error with unauthenticated") } func (s *AuthTestSuite) TestUnary_BadAuth() { - _, err := s.Client.Ping(ctxWithToken(s.SimpleCtx(), "bearer", "bad_token"), goodPing) + _, err := s.Client.Ping(ctxWithToken(s.SimpleCtx(), "bearer", "bad_token"), testpb.GoodPing) assert.Error(s.T(), err, "there must be an error") assert.Equal(s.T(), codes.PermissionDenied, status.Code(err), "must error with permission denied") } func (s *AuthTestSuite) TestUnary_PassesAuth() { - _, err := s.Client.Ping(ctxWithToken(s.SimpleCtx(), "bearer", commonAuthToken), goodPing) + _, err := s.Client.Ping(ctxWithToken(s.SimpleCtx(), "bearer", commonAuthToken), testpb.GoodPing) require.NoError(s.T(), err, "no error must occur") } func (s *AuthTestSuite) TestUnary_PassesWithPerRpcCredentials() { grpcCreds := oauth.TokenSource{TokenSource: &fakeOAuth2TokenSource{accessToken: commonAuthToken}} client := s.NewClient(grpc.WithPerRPCCredentials(grpcCreds)) - _, err := client.Ping(s.SimpleCtx(), goodPing) + _, err := client.Ping(s.SimpleCtx(), testpb.GoodPing) require.NoError(s.T(), err, "no error must occur") } func (s *AuthTestSuite) TestStream_NoAuth() { - stream, err := s.Client.PingList(s.SimpleCtx(), goodPing) + stream, err := s.Client.PingList(s.SimpleCtx(), testpb.GoodPingList) require.NoError(s.T(), err, "should not fail on establishing the stream") _, err = stream.Recv() assert.Error(s.T(), err, "there must be an error") @@ -125,7 +122,7 @@ func (s *AuthTestSuite) TestStream_NoAuth() { } func (s *AuthTestSuite) TestStream_BadAuth() { - stream, err := s.Client.PingList(ctxWithToken(s.SimpleCtx(), "bearer", "bad_token"), goodPing) + stream, err := s.Client.PingList(ctxWithToken(s.SimpleCtx(), "bearer", "bad_token"), testpb.GoodPingList) require.NoError(s.T(), err, "should not fail on establishing the stream") _, err = stream.Recv() assert.Error(s.T(), err, "there must be an error") @@ -133,7 +130,7 @@ func (s *AuthTestSuite) TestStream_BadAuth() { } func (s *AuthTestSuite) TestStream_PassesAuth() { - stream, err := s.Client.PingList(ctxWithToken(s.SimpleCtx(), "Bearer", commonAuthToken), goodPing) + stream, err := s.Client.PingList(ctxWithToken(s.SimpleCtx(), "Bearer", commonAuthToken), testpb.GoodPingList) require.NoError(s.T(), err, "should not fail on establishing the stream") pong, err := stream.Recv() require.NoError(s.T(), err, "no error must occur") @@ -143,7 +140,7 @@ func (s *AuthTestSuite) TestStream_PassesAuth() { func (s *AuthTestSuite) TestStream_PassesWithPerRpcCredentials() { grpcCreds := oauth.TokenSource{TokenSource: &fakeOAuth2TokenSource{accessToken: commonAuthToken}} client := s.NewClient(grpc.WithPerRPCCredentials(grpcCreds)) - stream, err := client.PingList(s.SimpleCtx(), goodPing) + stream, err := client.PingList(s.SimpleCtx(), testpb.GoodPingList) require.NoError(s.T(), err, "should not fail on establishing the stream") pong, err := stream.Recv() require.NoError(s.T(), err, "no error must occur") @@ -163,8 +160,8 @@ func (s *authOverrideTestService) AuthFuncOverride(ctx context.Context, fullMeth func TestAuthOverrideTestSuite(t *testing.T) { authFunc := buildDummyAuthFunction("bearer", commonAuthToken) s := &AuthOverrideTestSuite{ - InterceptorTestSuite: &grpctesting.InterceptorTestSuite{ - TestService: &authOverrideTestService{&assertingPingService{&grpctesting.TestPingService{T: t}, t}, t}, + InterceptorTestSuite: &testpb.InterceptorTestSuite{ + TestService: &authOverrideTestService{&assertingPingService{&testpb.TestPingService{T: t}, t}, t}, ServerOpts: []grpc.ServerOption{ grpc.StreamInterceptor(auth.StreamServerInterceptor(authFunc)), grpc.UnaryInterceptor(auth.UnaryServerInterceptor(authFunc)), @@ -175,16 +172,16 @@ func TestAuthOverrideTestSuite(t *testing.T) { } type AuthOverrideTestSuite struct { - *grpctesting.InterceptorTestSuite + *testpb.InterceptorTestSuite } func (s *AuthOverrideTestSuite) TestUnary_PassesAuth() { - _, err := s.Client.Ping(ctxWithToken(s.SimpleCtx(), "bearer", overrideAuthToken), goodPing) + _, err := s.Client.Ping(ctxWithToken(s.SimpleCtx(), "bearer", overrideAuthToken), testpb.GoodPing) require.NoError(s.T(), err, "no error must occur") } func (s *AuthOverrideTestSuite) TestStream_PassesAuth() { - stream, err := s.Client.PingList(ctxWithToken(s.SimpleCtx(), "Bearer", overrideAuthToken), goodPing) + stream, err := s.Client.PingList(ctxWithToken(s.SimpleCtx(), "Bearer", overrideAuthToken), testpb.GoodPingList) require.NoError(s.T(), err, "should not fail on establishing the stream") pong, err := stream.Recv() require.NoError(s.T(), err, "no error must occur") diff --git a/auth/doc.go b/interceptors/auth/doc.go similarity index 100% rename from auth/doc.go rename to interceptors/auth/doc.go diff --git a/auth/examples_test.go b/interceptors/auth/examples_test.go similarity index 97% rename from auth/examples_test.go rename to interceptors/auth/examples_test.go index 6d938ac47..4614f7f3e 100644 --- a/auth/examples_test.go +++ b/interceptors/auth/examples_test.go @@ -9,7 +9,7 @@ import ( pb "google.golang.org/grpc/examples/helloworld/helloworld" "google.golang.org/grpc/status" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/auth" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/auth" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tags" ) diff --git a/auth/metadata.go b/interceptors/auth/metadata.go similarity index 100% rename from auth/metadata.go rename to interceptors/auth/metadata.go diff --git a/auth/metadata_test.go b/interceptors/auth/metadata_test.go similarity index 100% rename from auth/metadata_test.go rename to interceptors/auth/metadata_test.go diff --git a/interceptors/client_test.go b/interceptors/client_test.go index 7f397dcf1..84a48830c 100644 --- a/interceptors/client_test.go +++ b/interceptors/client_test.go @@ -17,8 +17,7 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting/testpb" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/testing/testpb" ) type mockReport struct { @@ -152,7 +151,7 @@ func (s *ClientInterceptorTestSuite) SetupSuite() { require.NoError(s.T(), err, "must be able to allocate a port for serverListener") s.server = grpc.NewServer() - testpb.RegisterTestServiceServer(s.server, &grpctesting.TestPingService{T: s.T()}) + testpb.RegisterTestServiceServer(s.server, &testpb.TestPingService{T: s.T()}) go func() { defer close(s.stopped) @@ -204,7 +203,7 @@ func (s *ClientInterceptorTestSuite) TearDownTest() { } func (s *ClientInterceptorTestSuite) TestUnaryReporting() { - _, err := s.testClient.PingEmpty(s.ctx, &testpb.Empty{}) // should return with code=OK + _, err := s.testClient.PingEmpty(s.ctx, &testpb.PingEmptyRequest{}) // should return with code=OK require.NoError(s.T(), err) s.mock.Equal(s.T(), []*mockReport{{ typ: Unary, @@ -216,7 +215,7 @@ func (s *ClientInterceptorTestSuite) TestUnaryReporting() { }}) s.mock.reports = s.mock.reports[:0] // Reset. - _, err = s.testClient.PingError(s.ctx, &testpb.PingRequest{ErrorCodeReturned: uint32(codes.FailedPrecondition)}) // should return with code=FailedPrecondition + _, err = s.testClient.PingError(s.ctx, &testpb.PingErrorRequest{ErrorCodeReturned: uint32(codes.FailedPrecondition)}) // should return with code=FailedPrecondition require.Error(s.T(), err) s.mock.Equal(s.T(), []*mockReport{{ typ: Unary, @@ -229,7 +228,7 @@ func (s *ClientInterceptorTestSuite) TestUnaryReporting() { } func (s *ClientInterceptorTestSuite) TestStartedListReporting() { - _, err := s.testClient.PingList(s.ctx, &testpb.PingRequest{}) + _, err := s.testClient.PingList(s.ctx, &testpb.PingListRequest{}) require.NoError(s.T(), err) // Even without reading, we should get initial mockReport. @@ -240,7 +239,7 @@ func (s *ClientInterceptorTestSuite) TestStartedListReporting() { postMsgSends: []error{nil}, }}) - _, err = s.testClient.PingList(s.ctx, &testpb.PingRequest{ErrorCodeReturned: uint32(codes.FailedPrecondition)}) + _, err = s.testClient.PingList(s.ctx, &testpb.PingListRequest{ErrorCodeReturned: uint32(codes.FailedPrecondition)}) require.NoError(s.T(), err, "PingList must not fail immediately") // Even without reading, we should get initial mockReport. @@ -258,7 +257,7 @@ func (s *ClientInterceptorTestSuite) TestStartedListReporting() { } func (s *ClientInterceptorTestSuite) TestListReporting() { - ss, err := s.testClient.PingList(s.ctx, &testpb.PingRequest{}) + ss, err := s.testClient.PingList(s.ctx, &testpb.PingListRequest{}) require.NoError(s.T(), err) // Do a read, just for kicks. @@ -271,19 +270,19 @@ func (s *ClientInterceptorTestSuite) TestListReporting() { require.NoError(s.T(), err, "reading pingList shouldn't fail") count++ } - require.EqualValues(s.T(), grpctesting.ListResponseCount, count, "Number of received msg on the wire must match") + require.EqualValues(s.T(), testpb.ListResponseCount, count, "Number of received msg on the wire must match") s.mock.Equal(s.T(), []*mockReport{{ typ: ServerStream, svcName: testpb.TestServiceFullName, methodName: "PingList", postCalls: []error{io.EOF}, - postMsgReceives: append(make([]error, grpctesting.ListResponseCount), io.EOF), + postMsgReceives: append(make([]error, testpb.ListResponseCount), io.EOF), postMsgSends: []error{nil}, }}) s.mock.reports = s.mock.reports[:0] // Reset. - ss, err = s.testClient.PingList(s.ctx, &testpb.PingRequest{ErrorCodeReturned: uint32(codes.FailedPrecondition)}) + ss, err = s.testClient.PingList(s.ctx, &testpb.PingListRequest{ErrorCodeReturned: uint32(codes.FailedPrecondition)}) require.NoError(s.T(), err, "PingList must not fail immediately") // Do a read, just to propagate errors. @@ -335,7 +334,7 @@ func (s *ClientInterceptorTestSuite) TestBiStreamingReporting() { } }() for i := 0; i < 100; i++ { - require.NoError(s.T(), ss.Send(&testpb.PingRequest{}), "sending shouldn't fail") + require.NoError(s.T(), ss.Send(&testpb.PingStreamRequest{}), "sending shouldn't fail") } require.NoError(s.T(), ss.CloseSend()) diff --git a/interceptors/logging/interceptors_test.go b/interceptors/logging/interceptors_test.go index f0916d8d5..5208ce98e 100644 --- a/interceptors/logging/interceptors_test.go +++ b/interceptors/logging/interceptors_test.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "io" + "path" "runtime" "sort" "strings" @@ -16,15 +17,10 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/codes" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting/testpb" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/logging" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tags" -) - -var ( - goodPing = &testpb.PingRequest{Value: "something", SleepTimeMs: 9999} + "github.com/grpc-ecosystem/go-grpc-middleware/v2/testing/testpb" ) type testDisposableFields map[string]string @@ -141,7 +137,7 @@ func (l *mockLogger) With(fields ...string) logging.Logger { } type baseLoggingSuite struct { - *grpctesting.InterceptorTestSuite + *testpb.InterceptorTestSuite logger *mockLogger } @@ -171,8 +167,8 @@ func TestSuite(t *testing.T) { s := &loggingClientServerSuite{ &baseLoggingSuite{ logger: newMockLogger(), - InterceptorTestSuite: &grpctesting.InterceptorTestSuite{ - TestService: &grpctesting.TestPingService{T: t}, + InterceptorTestSuite: &testpb.InterceptorTestSuite{ + TestService: &testpb.TestPingService{T: t}, }, }, } @@ -194,13 +190,13 @@ func TestSuite(t *testing.T) { func assertStandardFields(t *testing.T, kind string, f testDisposableFields, method string, typ interceptors.GRPCType) testDisposableFields { return f.AssertNextField(t, logging.SystemTag[0], logging.SystemTag[1]). AssertNextField(t, logging.ComponentFieldKey, kind). - AssertNextField(t, logging.ServiceFieldKey, "grpc_middleware.testpb.TestService"). + AssertNextField(t, logging.ServiceFieldKey, testpb.TestServiceFullName). AssertNextField(t, logging.MethodFieldKey, method). AssertNextField(t, logging.MethodTypeFieldKey, string(typ)) } func (s *loggingClientServerSuite) TestPing() { - _, err := s.Client.Ping(s.SimpleCtx(), goodPing) + _, err := s.Client.Ping(s.SimpleCtx(), testpb.GoodPing) assert.NoError(s.T(), err, "there must be not be an on a successful call") lines := s.logger.o.Lines() @@ -239,7 +235,7 @@ func (s *loggingClientServerSuite) TestPing() { } func (s *loggingClientServerSuite) TestPingList() { - stream, err := s.Client.PingList(s.SimpleCtx(), goodPing) + stream, err := s.Client.PingList(s.SimpleCtx(), testpb.GoodPingList) require.NoError(s.T(), err, "should not fail on establishing the stream") for { _, err := stream.Recv() @@ -314,7 +310,7 @@ func (s *loggingClientServerSuite) TestPingError_WithCustomLevels() { s.T().Run(tcase.msg, func(t *testing.T) { _, err := s.Client.PingError( s.SimpleCtx(), - &testpb.PingRequest{Value: "something", ErrorCodeReturned: uint32(tcase.code)}) + &testpb.PingErrorRequest{Value: "something", ErrorCodeReturned: uint32(tcase.code)}) require.Error(t, err, "each call here must return an error") lines := s.logger.o.Lines() sort.Sort(lines) @@ -358,8 +354,8 @@ func TestCustomDurationSuite(t *testing.T) { s := &loggingCustomDurationSuite{ baseLoggingSuite: &baseLoggingSuite{ logger: newMockLogger(), - InterceptorTestSuite: &grpctesting.InterceptorTestSuite{ - TestService: &grpctesting.TestPingService{T: t}, + InterceptorTestSuite: &testpb.InterceptorTestSuite{ + TestService: &testpb.TestPingService{T: t}, }, }, } @@ -379,7 +375,7 @@ func TestCustomDurationSuite(t *testing.T) { } func (s *loggingCustomDurationSuite) TestPing_HasOverriddenDuration() { - _, err := s.Client.Ping(s.SimpleCtx(), goodPing) + _, err := s.Client.Ping(s.SimpleCtx(), testpb.GoodPing) assert.NoError(s.T(), err, "there must be not be an on a successful call") lines := s.logger.o.Lines() @@ -418,7 +414,7 @@ func (s *loggingCustomDurationSuite) TestPing_HasOverriddenDuration() { } func (s *loggingCustomDurationSuite) TestPingList_HasOverriddenDuration() { - stream, err := s.Client.PingList(s.SimpleCtx(), goodPing) + stream, err := s.Client.PingList(s.SimpleCtx(), testpb.GoodPingList) require.NoError(s.T(), err, "should not fail on establishing the stream") for { _, err := stream.Recv() @@ -473,7 +469,7 @@ func TestCustomDeciderSuite(t *testing.T) { return } opts := logging.WithDecider(func(method string, _ error) logging.Decision { - if method == "/grpc_middleware.testpb.TestService/PingError" { + if method == path.Join("/", testpb.TestServiceFullName, "PingError") { return logging.LogStartAndFinishCall } return logging.NoLogCall @@ -482,8 +478,8 @@ func TestCustomDeciderSuite(t *testing.T) { s := &loggingCustomDeciderSuite{ baseLoggingSuite: &baseLoggingSuite{ logger: newMockLogger(), - InterceptorTestSuite: &grpctesting.InterceptorTestSuite{ - TestService: &grpctesting.TestPingService{T: t}, + InterceptorTestSuite: &testpb.InterceptorTestSuite{ + TestService: &testpb.TestPingService{T: t}, }, }, } @@ -503,7 +499,7 @@ func TestCustomDeciderSuite(t *testing.T) { } func (s *loggingCustomDeciderSuite) TestPing_HasCustomDecider() { - _, err := s.Client.Ping(s.SimpleCtx(), goodPing) + _, err := s.Client.Ping(s.SimpleCtx(), testpb.GoodPing) require.NoError(s.T(), err, "there must be not be an error on a successful call") require.Len(s.T(), s.logger.o.Lines(), 0) // Decider should suppress. @@ -514,7 +510,7 @@ func (s *loggingCustomDeciderSuite) TestPingError_HasCustomDecider() { _, err := s.Client.PingError( s.SimpleCtx(), - &testpb.PingRequest{Value: "something", ErrorCodeReturned: uint32(code)}) + &testpb.PingErrorRequest{Value: "something", ErrorCodeReturned: uint32(code)}) require.Error(s.T(), err, "each call here must return an error") lines := s.logger.o.Lines() @@ -555,7 +551,7 @@ func (s *loggingCustomDeciderSuite) TestPingError_HasCustomDecider() { } func (s *loggingCustomDeciderSuite) TestPingList_HasCustomDecider() { - stream, err := s.Client.PingList(s.SimpleCtx(), goodPing) + stream, err := s.Client.PingList(s.SimpleCtx(), testpb.GoodPingList) require.NoError(s.T(), err, "should not fail on establishing the stream") for { _, err := stream.Recv() diff --git a/interceptors/logging/payload_test.go b/interceptors/logging/payload_test.go index 1db9ad8f0..de95bccc1 100644 --- a/interceptors/logging/payload_test.go +++ b/interceptors/logging/payload_test.go @@ -5,17 +5,18 @@ import ( "fmt" "sort" "testing" + "time" + "github.com/pkg/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" "google.golang.org/grpc" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting/testpb" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/logging" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tags" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/testing/testpb" ) type loggingPayloadSuite struct { @@ -29,8 +30,8 @@ func TestPayloadSuite(t *testing.T) { s := &loggingPayloadSuite{ baseLoggingSuite: &baseLoggingSuite{ logger: newMockLogger(), - InterceptorTestSuite: &grpctesting.InterceptorTestSuite{ - TestService: &grpctesting.TestPingService{T: t}, + InterceptorTestSuite: &testpb.InterceptorTestSuite{ + TestService: &testpb.TestPingService{T: t}, }, }, } @@ -50,7 +51,7 @@ func TestPayloadSuite(t *testing.T) { } func (s *loggingPayloadSuite) TestPing_LogsBothRequestAndResponse() { - _, err := s.Client.Ping(s.SimpleCtx(), goodPing) + _, err := s.Client.Ping(s.SimpleCtx(), testpb.GoodPing) require.NoError(s.T(), err, "there must be not be an error on a successful call") lines := s.logger.o.Lines() @@ -84,9 +85,9 @@ func (s *loggingPayloadSuite) assertPayloadLogLinesForMessage(lines LogLines, me AssertNextFieldNotEmpty(s.T(), "grpc.recv.duration"). AssertNextFieldNotEmpty(s.T(), "grpc.request.deadline") if i-curr == 0 { - clientResponseFields = clientResponseFields.AssertNextField(s.T(), "grpc.response.content", `{"Value":"something"}`) + clientResponseFields = clientResponseFields.AssertNextField(s.T(), "grpc.response.content", `{"value":"something"}`) } else { - clientResponseFields = clientResponseFields.AssertNextField(s.T(), "grpc.response.content", fmt.Sprintf(`{"Value":"something","counter":%v}`, i-curr)) + clientResponseFields = clientResponseFields.AssertNextField(s.T(), "grpc.response.content", fmt.Sprintf(`{"value":"something","counter":%v}`, i-curr)) } clientResponseFields.AssertNoMoreTags(s.T()) } @@ -115,16 +116,16 @@ func (s *loggingPayloadSuite) assertPayloadLogLinesForMessage(lines LogLines, me AssertNextFieldNotEmpty(s.T(), "grpc.send.duration"). AssertNextFieldNotEmpty(s.T(), "grpc.request.deadline") if i-curr == 0 { - serverResponseFields = serverResponseFields.AssertNextField(s.T(), "grpc.response.content", `{"Value":"something"}`) + serverResponseFields = serverResponseFields.AssertNextField(s.T(), "grpc.response.content", `{"value":"something"}`) } else { - serverResponseFields = serverResponseFields.AssertNextField(s.T(), "grpc.response.content", fmt.Sprintf(`{"Value":"something","counter":%v}`, i-curr)) + serverResponseFields = serverResponseFields.AssertNextField(s.T(), "grpc.response.content", fmt.Sprintf(`{"value":"something","counter":%v}`, i-curr)) } serverResponseFields.AssertNoMoreTags(s.T()) } } func (s *loggingPayloadSuite) TestPingError_LogsOnlyRequestsOnError() { - _, err := s.Client.PingError(s.SimpleCtx(), &testpb.PingRequest{Value: "something", ErrorCodeReturned: uint32(4)}) + _, err := s.Client.PingError(s.SimpleCtx(), &testpb.PingErrorRequest{Value: "something", ErrorCodeReturned: uint32(4)}) require.Error(s.T(), err, "there must be an error on an unsuccessful call") lines := s.logger.o.Lines() @@ -147,7 +148,7 @@ func (s *loggingPayloadSuite) TestPingStream_LogsAllRequestsAndResponses() { require.NoError(s.T(), err, "no error on stream creation") for i := 0; i < messagesExpected; i++ { - require.NoError(s.T(), stream.Send(goodPing), "sending must succeed") + require.NoError(s.T(), stream.Send(testpb.GoodPingStream), "sending must succeed") pong := &testpb.PingResponse{} err := stream.RecvMsg(pong) @@ -155,7 +156,32 @@ func (s *loggingPayloadSuite) TestPingStream_LogsAllRequestsAndResponses() { } require.NoError(s.T(), stream.CloseSend(), "no error on send stream") - lines := s.logger.o.Lines() - require.Len(s.T(), lines, 4*messagesExpected) - s.assertPayloadLogLinesForMessage(lines, "PingStream", interceptors.BidiStream) + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) + defer cancel() + require.NoError(s.T(), waitUntil(200*time.Millisecond, ctx.Done(), func() error { + got := len(s.logger.o.Lines()) + if got >= 4*messagesExpected { + return nil + } + return errors.Errorf("not enough log lines, waiting; got: %v", got) + })) + s.assertPayloadLogLinesForMessage(s.logger.o.Lines(), "PingStream", interceptors.BidiStream) +} + +// waitUntil executes f every interval seconds until timeout or no error is returned from f. +func waitUntil(interval time.Duration, stopc <-chan struct{}, f func() error) error { + tick := time.NewTicker(interval) + defer tick.Stop() + + var err error + for { + if err = f(); err == nil { + return nil + } + select { + case <-stopc: + return err + case <-tick.C: + } + } } diff --git a/interceptors/recovery/interceptors_test.go b/interceptors/recovery/interceptors_test.go index 84c539e81..7e37d82b5 100644 --- a/interceptors/recovery/interceptors_test.go +++ b/interceptors/recovery/interceptors_test.go @@ -14,14 +14,8 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting/testpb" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/recovery" -) - -var ( - goodPing = &testpb.PingRequest{Value: "something", SleepTimeMs: 9999} - panicPing = &testpb.PingRequest{Value: "panic", SleepTimeMs: 9999} + "github.com/grpc-ecosystem/go-grpc-middleware/v2/testing/testpb" ) type recoveryAssertService struct { @@ -35,7 +29,7 @@ func (s *recoveryAssertService) Ping(ctx context.Context, ping *testpb.PingReque return s.TestServiceServer.Ping(ctx, ping) } -func (s *recoveryAssertService) PingList(ping *testpb.PingRequest, stream testpb.TestService_PingListServer) error { +func (s *recoveryAssertService) PingList(ping *testpb.PingListRequest, stream testpb.TestService_PingListServer) error { if ping.Value == "panic" { panic("very bad thing happened") } @@ -44,8 +38,8 @@ func (s *recoveryAssertService) PingList(ping *testpb.PingRequest, stream testpb func TestRecoverySuite(t *testing.T) { s := &RecoverySuite{ - InterceptorTestSuite: &grpctesting.InterceptorTestSuite{ - TestService: &recoveryAssertService{TestServiceServer: &grpctesting.TestPingService{T: t}}, + InterceptorTestSuite: &testpb.InterceptorTestSuite{ + TestService: &recoveryAssertService{TestServiceServer: &testpb.TestPingService{T: t}}, ServerOpts: []grpc.ServerOption{ grpc.StreamInterceptor( recovery.StreamServerInterceptor()), @@ -58,23 +52,23 @@ func TestRecoverySuite(t *testing.T) { } type RecoverySuite struct { - *grpctesting.InterceptorTestSuite + *testpb.InterceptorTestSuite } func (s *RecoverySuite) TestUnary_SuccessfulRequest() { - _, err := s.Client.Ping(s.SimpleCtx(), goodPing) + _, err := s.Client.Ping(s.SimpleCtx(), testpb.GoodPing) require.NoError(s.T(), err, "no error must occur") } func (s *RecoverySuite) TestUnary_PanickingRequest() { - _, err := s.Client.Ping(s.SimpleCtx(), panicPing) + _, err := s.Client.Ping(s.SimpleCtx(), &testpb.PingRequest{Value: "panic"}) require.Error(s.T(), err, "there must be an error") assert.Equal(s.T(), codes.Internal, status.Code(err), "must error with internal") assert.Equal(s.T(), "very bad thing happened", status.Convert(err).Message(), "must error with message") } func (s *RecoverySuite) TestStream_SuccessfulReceive() { - stream, err := s.Client.PingList(s.SimpleCtx(), goodPing) + stream, err := s.Client.PingList(s.SimpleCtx(), testpb.GoodPingList) require.NoError(s.T(), err, "should not fail on establishing the stream") pong, err := stream.Recv() require.NoError(s.T(), err, "no error must occur") @@ -82,7 +76,7 @@ func (s *RecoverySuite) TestStream_SuccessfulReceive() { } func (s *RecoverySuite) TestStream_PanickingReceive() { - stream, err := s.Client.PingList(s.SimpleCtx(), panicPing) + stream, err := s.Client.PingList(s.SimpleCtx(), &testpb.PingListRequest{Value: "panic"}) require.NoError(s.T(), err, "should not fail on establishing the stream") _, err = stream.Recv() require.Error(s.T(), err, "there must be an error") @@ -97,8 +91,8 @@ func TestRecoveryOverrideSuite(t *testing.T) { }), } s := &RecoveryOverrideSuite{ - InterceptorTestSuite: &grpctesting.InterceptorTestSuite{ - TestService: &recoveryAssertService{TestServiceServer: &grpctesting.TestPingService{T: t}}, + InterceptorTestSuite: &testpb.InterceptorTestSuite{ + TestService: &recoveryAssertService{TestServiceServer: &testpb.TestPingService{T: t}}, ServerOpts: []grpc.ServerOption{ grpc.StreamInterceptor( recovery.StreamServerInterceptor(opts...)), @@ -111,23 +105,23 @@ func TestRecoveryOverrideSuite(t *testing.T) { } type RecoveryOverrideSuite struct { - *grpctesting.InterceptorTestSuite + *testpb.InterceptorTestSuite } func (s *RecoveryOverrideSuite) TestUnary_SuccessfulRequest() { - _, err := s.Client.Ping(s.SimpleCtx(), goodPing) + _, err := s.Client.Ping(s.SimpleCtx(), testpb.GoodPing) require.NoError(s.T(), err, "no error must occur") } func (s *RecoveryOverrideSuite) TestUnary_PanickingRequest() { - _, err := s.Client.Ping(s.SimpleCtx(), panicPing) + _, err := s.Client.Ping(s.SimpleCtx(), &testpb.PingRequest{Value: "panic"}) require.Error(s.T(), err, "there must be an error") assert.Equal(s.T(), codes.Unknown, status.Code(err), "must error with unknown") assert.Equal(s.T(), "panic triggered: very bad thing happened", status.Convert(err).Message(), "must error with message") } func (s *RecoveryOverrideSuite) TestStream_SuccessfulReceive() { - stream, err := s.Client.PingList(s.SimpleCtx(), goodPing) + stream, err := s.Client.PingList(s.SimpleCtx(), testpb.GoodPingList) require.NoError(s.T(), err, "should not fail on establishing the stream") pong, err := stream.Recv() require.NoError(s.T(), err, "no error must occur") @@ -135,7 +129,7 @@ func (s *RecoveryOverrideSuite) TestStream_SuccessfulReceive() { } func (s *RecoveryOverrideSuite) TestStream_PanickingReceive() { - stream, err := s.Client.PingList(s.SimpleCtx(), panicPing) + stream, err := s.Client.PingList(s.SimpleCtx(), &testpb.PingListRequest{Value: "panic"}) require.NoError(s.T(), err, "should not fail on establishing the stream") _, err = stream.Recv() require.Error(s.T(), err, "there must be an error") diff --git a/interceptors/retry/examples_test.go b/interceptors/retry/examples_test.go index fd9096b0e..34cd47ece 100644 --- a/interceptors/retry/examples_test.go +++ b/interceptors/retry/examples_test.go @@ -11,8 +11,8 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/codes" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting/testpb" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/retry" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/testing/testpb" ) var cc *grpc.ClientConn @@ -56,7 +56,7 @@ func Example_simpleCall() { defer cancel() client := testpb.NewTestServiceClient(cc) - stream, _ := client.PingList(ctx, &testpb.PingRequest{}, retry.WithMax(3)) + stream, _ := client.PingList(ctx, &testpb.PingListRequest{}, retry.WithMax(3)) for { _, err := stream.Recv() // retries happen here diff --git a/interceptors/retry/retry_test.go b/interceptors/retry/retry_test.go index d52f24aeb..d3372f7f8 100644 --- a/interceptors/retry/retry_test.go +++ b/interceptors/retry/retry_test.go @@ -18,14 +18,12 @@ import ( "google.golang.org/grpc/status" middleware "github.com/grpc-ecosystem/go-grpc-middleware/v2" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting/testpb" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/retry" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/testing/testpb" ) var ( retriableErrors = []codes.Code{codes.Unavailable, codes.DataLoss} - goodPing = &testpb.PingRequest{Value: "something"} noSleep = 0 * time.Second retryTimeout = 50 * time.Millisecond ) @@ -78,7 +76,7 @@ func (s *failingService) Ping(ctx context.Context, ping *testpb.PingRequest) (*t return s.TestServiceServer.Ping(ctx, ping) } -func (s *failingService) PingList(ping *testpb.PingRequest, stream testpb.TestService_PingListServer) error { +func (s *failingService) PingList(ping *testpb.PingListRequest, stream testpb.TestService_PingListServer) error { if err := s.maybeFailRequest(); err != nil { return err } @@ -94,7 +92,7 @@ func (s *failingService) PingStream(stream testpb.TestService_PingStreamServer) func TestRetrySuite(t *testing.T) { service := &failingService{ - TestServiceServer: &grpctesting.TestPingService{T: t}, + TestServiceServer: &testpb.TestPingService{T: t}, } unaryInterceptor := retry.UnaryClientInterceptor( retry.WithCodes(retriableErrors...), @@ -108,7 +106,7 @@ func TestRetrySuite(t *testing.T) { ) s := &RetrySuite{ srv: service, - InterceptorTestSuite: &grpctesting.InterceptorTestSuite{ + InterceptorTestSuite: &testpb.InterceptorTestSuite{ TestService: service, ClientOpts: []grpc.DialOption{ grpc.WithStreamInterceptor(streamInterceptor), @@ -120,7 +118,7 @@ func TestRetrySuite(t *testing.T) { } type RetrySuite struct { - *grpctesting.InterceptorTestSuite + *testpb.InterceptorTestSuite srv *failingService } @@ -130,7 +128,7 @@ func (s *RetrySuite) SetupTest() { func (s *RetrySuite) TestUnary_FailsOnNonRetriableError() { s.srv.resetFailingConfiguration(5, codes.Internal, noSleep) - _, err := s.Client.Ping(s.SimpleCtx(), goodPing) + _, err := s.Client.Ping(s.SimpleCtx(), testpb.GoodPing) require.Error(s.T(), err, "error must occur from the failing service") require.Equal(s.T(), codes.Internal, status.Code(err), "failure code must come from retrier") require.EqualValues(s.T(), 1, s.srv.requestCount(), "one request should have been made") @@ -138,7 +136,7 @@ func (s *RetrySuite) TestUnary_FailsOnNonRetriableError() { func (s *RetrySuite) TestUnary_FailsOnNonRetriableContextError() { s.srv.resetFailingConfiguration(5, codes.Canceled, noSleep) - _, err := s.Client.Ping(s.SimpleCtx(), goodPing) + _, err := s.Client.Ping(s.SimpleCtx(), testpb.GoodPing) require.Error(s.T(), err, "error must occur from the failing service") require.Equal(s.T(), codes.Canceled, status.Code(err), "failure code must come from retrier") require.EqualValues(s.T(), 1, s.srv.requestCount(), "one request should have been made") @@ -149,7 +147,7 @@ func (s *RetrySuite) TestCallOptionsDontPanicWithoutInterceptor() { // If this code doesn't panic, that's good. s.srv.resetFailingConfiguration(100, codes.DataLoss, noSleep) // doesn't matter all requests should fail nonMiddlewareClient := s.NewClient() - _, err := nonMiddlewareClient.Ping(s.SimpleCtx(), goodPing, + _, err := nonMiddlewareClient.Ping(s.SimpleCtx(), testpb.GoodPing, retry.WithMax(5), retry.WithBackoff(retry.BackoffLinear(1*time.Millisecond)), retry.WithCodes(codes.DataLoss), @@ -160,7 +158,7 @@ func (s *RetrySuite) TestCallOptionsDontPanicWithoutInterceptor() { func (s *RetrySuite) TestServerStream_FailsOnNonRetriableError() { s.srv.resetFailingConfiguration(5, codes.Internal, noSleep) - stream, err := s.Client.PingList(s.SimpleCtx(), goodPing) + stream, err := s.Client.PingList(s.SimpleCtx(), testpb.GoodPingList) require.NoError(s.T(), err, "should not fail on establishing the stream") _, err = stream.Recv() require.Error(s.T(), err, "error must occur from the failing service") @@ -169,7 +167,7 @@ func (s *RetrySuite) TestServerStream_FailsOnNonRetriableError() { func (s *RetrySuite) TestUnary_SucceedsOnRetriableError() { s.srv.resetFailingConfiguration(3, codes.DataLoss, noSleep) // see retriable_errors - out, err := s.Client.Ping(s.SimpleCtx(), goodPing) + out, err := s.Client.Ping(s.SimpleCtx(), testpb.GoodPing) require.NoError(s.T(), err, "the third invocation should succeed") require.NotNil(s.T(), out, "Pong must be not nil") require.EqualValues(s.T(), 3, s.srv.requestCount(), "three requests should have been made") @@ -177,7 +175,7 @@ func (s *RetrySuite) TestUnary_SucceedsOnRetriableError() { func (s *RetrySuite) TestUnary_OverrideFromDialOpts() { s.srv.resetFailingConfiguration(5, codes.ResourceExhausted, noSleep) // default is 3 and retriable_errors - out, err := s.Client.Ping(s.SimpleCtx(), goodPing, retry.WithCodes(codes.ResourceExhausted), retry.WithMax(5)) + out, err := s.Client.Ping(s.SimpleCtx(), testpb.GoodPing, retry.WithCodes(codes.ResourceExhausted), retry.WithMax(5)) require.NoError(s.T(), err, "the fifth invocation should succeed") require.NotNil(s.T(), out, "Pong must be not nil") require.EqualValues(s.T(), 5, s.srv.requestCount(), "five requests should have been made") @@ -190,7 +188,7 @@ func (s *RetrySuite) TestUnary_PerCallDeadline_Succeeds() { // a retry call with a 5 millisecond deadline. The 5th one doesn't sleep and succeeds. deadlinePerCall := 5 * time.Millisecond s.srv.resetFailingConfiguration(5, codes.NotFound, 2*deadlinePerCall) - out, err := s.Client.Ping(s.SimpleCtx(), goodPing, retry.WithPerRetryTimeout(deadlinePerCall), + out, err := s.Client.Ping(s.SimpleCtx(), testpb.GoodPing, retry.WithPerRetryTimeout(deadlinePerCall), retry.WithMax(5)) require.NoError(s.T(), err, "the fifth invocation should succeed") require.NotNil(s.T(), out, "Pong must be not nil") @@ -211,7 +209,7 @@ func (s *RetrySuite) TestUnary_PerCallDeadline_FailsOnParent() { s.srv.resetFailingConfiguration(5, codes.NotFound, 2*deadlinePerCall) ctx, cancel := context.WithTimeout(context.TODO(), parentDeadline) defer cancel() - _, err := s.Client.Ping(ctx, goodPing, retry.WithPerRetryTimeout(deadlinePerCall), + _, err := s.Client.Ping(ctx, testpb.GoodPing, retry.WithPerRetryTimeout(deadlinePerCall), retry.WithMax(5)) require.Error(s.T(), err, "the retries must fail due to context deadline exceeded") require.Equal(s.T(), codes.DeadlineExceeded, status.Code(err), "failre code must be a gRPC error of Deadline class") @@ -219,7 +217,7 @@ func (s *RetrySuite) TestUnary_PerCallDeadline_FailsOnParent() { func (s *RetrySuite) TestServerStream_SucceedsOnRetriableError() { s.srv.resetFailingConfiguration(3, codes.DataLoss, noSleep) // see retriable_errors - stream, err := s.Client.PingList(s.SimpleCtx(), goodPing) + stream, err := s.Client.PingList(s.SimpleCtx(), testpb.GoodPingList) require.NoError(s.T(), err, "establishing the connection must always succeed") s.assertPingListWasCorrect(stream) require.EqualValues(s.T(), 3, s.srv.requestCount(), "three requests should have been made") @@ -227,7 +225,7 @@ func (s *RetrySuite) TestServerStream_SucceedsOnRetriableError() { func (s *RetrySuite) TestServerStream_OverrideFromContext() { s.srv.resetFailingConfiguration(5, codes.ResourceExhausted, noSleep) // default is 3 and retriable_errors - stream, err := s.Client.PingList(s.SimpleCtx(), goodPing, retry.WithCodes(codes.ResourceExhausted), retry.WithMax(5)) + stream, err := s.Client.PingList(s.SimpleCtx(), testpb.GoodPingList, retry.WithCodes(codes.ResourceExhausted), retry.WithMax(5)) require.NoError(s.T(), err, "establishing the connection must always succeed") s.assertPingListWasCorrect(stream) require.EqualValues(s.T(), 5, s.srv.requestCount(), "three requests should have been made") @@ -240,7 +238,7 @@ func (s *RetrySuite) TestServerStream_PerCallDeadline_Succeeds() { // a retry call with a 50 millisecond deadline. The 5th one doesn't sleep and succeeds. deadlinePerCall := 100 * time.Millisecond s.srv.resetFailingConfiguration(5, codes.NotFound, 2*deadlinePerCall) - stream, err := s.Client.PingList(s.SimpleCtx(), goodPing, retry.WithPerRetryTimeout(deadlinePerCall), + stream, err := s.Client.PingList(s.SimpleCtx(), testpb.GoodPingList, retry.WithPerRetryTimeout(deadlinePerCall), retry.WithMax(5)) require.NoError(s.T(), err, "establishing the connection must always succeed") s.assertPingListWasCorrect(stream) @@ -261,7 +259,7 @@ func (s *RetrySuite) TestServerStream_PerCallDeadline_FailsOnParent() { s.srv.resetFailingConfiguration(5, codes.NotFound, 2*deadlinePerCall) parentCtx, cancel := context.WithTimeout(context.TODO(), parentDeadline) defer cancel() - stream, err := s.Client.PingList(parentCtx, goodPing, retry.WithPerRetryTimeout(deadlinePerCall), + stream, err := s.Client.PingList(parentCtx, testpb.GoodPingList, retry.WithPerRetryTimeout(deadlinePerCall), retry.WithMax(5)) require.NoError(s.T(), err, "establishing the connection must always succeed") _, err = stream.Recv() @@ -270,7 +268,7 @@ func (s *RetrySuite) TestServerStream_PerCallDeadline_FailsOnParent() { func (s *RetrySuite) TestServerStream_CallFailsOnOutOfRetries() { restarted := s.RestartServer(3 * retryTimeout) - _, err := s.Client.PingList(s.SimpleCtx(), goodPing) + _, err := s.Client.PingList(s.SimpleCtx(), testpb.GoodPingList) require.Error(s.T(), err, "establishing the connection should not succeed") assert.Equal(s.T(), codes.Unavailable, status.Code(err)) @@ -282,7 +280,7 @@ func (s *RetrySuite) TestServerStream_CallFailsOnDeadlineExceeded() { restarted := s.RestartServer(3 * retryTimeout) ctx, cancel := context.WithTimeout(context.TODO(), retryTimeout) defer cancel() - _, err := s.Client.PingList(ctx, goodPing) + _, err := s.Client.PingList(ctx, testpb.GoodPingList) require.Error(s.T(), err, "establishing the connection should not succeed") assert.Equal(s.T(), codes.DeadlineExceeded, status.Code(err)) @@ -293,7 +291,7 @@ func (s *RetrySuite) TestServerStream_CallFailsOnDeadlineExceeded() { func (s *RetrySuite) TestServerStream_CallRetrySucceeds() { restarted := s.RestartServer(retryTimeout) - _, err := s.Client.PingList(s.SimpleCtx(), goodPing, + _, err := s.Client.PingList(s.SimpleCtx(), testpb.GoodPingList, retry.WithMax(40), ) @@ -310,10 +308,10 @@ func (s *RetrySuite) assertPingListWasCorrect(stream testpb.TestService_PingList } require.NoError(s.T(), err, "no errors during receive on client side") require.NotNil(s.T(), pong, "received values must not be nil") - require.Equal(s.T(), goodPing.Value, pong.Value, "the returned pong contained the outgoing ping") + require.Equal(s.T(), testpb.GoodPingList.Value, pong.Value, "the returned pong contained the outgoing ping") count += 1 } - require.EqualValues(s.T(), grpctesting.ListResponseCount, count, "should have received all ping items") + require.EqualValues(s.T(), testpb.ListResponseCount, count, "should have received all ping items") } type trackedInterceptor struct { @@ -332,7 +330,7 @@ func (ti *trackedInterceptor) StreamClientInterceptor(ctx context.Context, desc func TestChainedRetrySuite(t *testing.T) { service := &failingService{ - TestServiceServer: &grpctesting.TestPingService{T: t}, + TestServiceServer: &testpb.TestPingService{T: t}, } preRetryInterceptor := &trackedInterceptor{} postRetryInterceptor := &trackedInterceptor{} @@ -340,7 +338,7 @@ func TestChainedRetrySuite(t *testing.T) { srv: service, preRetryInterceptor: preRetryInterceptor, postRetryInterceptor: postRetryInterceptor, - InterceptorTestSuite: &grpctesting.InterceptorTestSuite{ + InterceptorTestSuite: &testpb.InterceptorTestSuite{ TestService: service, ClientOpts: []grpc.DialOption{ grpc.WithUnaryInterceptor(middleware.ChainUnaryClient(preRetryInterceptor.UnaryClientInterceptor, retry.UnaryClientInterceptor(), postRetryInterceptor.UnaryClientInterceptor)), @@ -352,7 +350,7 @@ func TestChainedRetrySuite(t *testing.T) { } type ChainedRetrySuite struct { - *grpctesting.InterceptorTestSuite + *testpb.InterceptorTestSuite srv *failingService preRetryInterceptor *trackedInterceptor postRetryInterceptor *trackedInterceptor @@ -365,7 +363,7 @@ func (s *ChainedRetrySuite) SetupTest() { } func (s *ChainedRetrySuite) TestUnaryWithChainedInterceptors_NoFailure() { - _, err := s.Client.Ping(s.SimpleCtx(), goodPing, retry.WithMax(2)) + _, err := s.Client.Ping(s.SimpleCtx(), testpb.GoodPing, retry.WithMax(2)) require.NoError(s.T(), err, "the invocation should succeed") require.EqualValues(s.T(), 1, s.srv.requestCount(), "one request should have been made") require.EqualValues(s.T(), 1, s.preRetryInterceptor.called, "pre-retry interceptor should be called once") @@ -374,7 +372,7 @@ func (s *ChainedRetrySuite) TestUnaryWithChainedInterceptors_NoFailure() { func (s *ChainedRetrySuite) TestUnaryWithChainedInterceptors_WithRetry() { s.srv.resetFailingConfiguration(2, codes.Unavailable, noSleep) - _, err := s.Client.Ping(s.SimpleCtx(), goodPing, retry.WithMax(2)) + _, err := s.Client.Ping(s.SimpleCtx(), testpb.GoodPing, retry.WithMax(2)) require.NoError(s.T(), err, "the second invocation should succeed") require.EqualValues(s.T(), 2, s.srv.requestCount(), "two requests should have been made") require.EqualValues(s.T(), 1, s.preRetryInterceptor.called, "pre-retry interceptor should be called once") @@ -382,7 +380,7 @@ func (s *ChainedRetrySuite) TestUnaryWithChainedInterceptors_WithRetry() { } func (s *ChainedRetrySuite) TestStreamWithChainedInterceptors_NoFailure() { - stream, err := s.Client.PingList(s.SimpleCtx(), goodPing, retry.WithMax(2)) + stream, err := s.Client.PingList(s.SimpleCtx(), testpb.GoodPingList, retry.WithMax(2)) require.NoError(s.T(), err, "the invocation should succeed") _, err = stream.Recv() require.NoError(s.T(), err, "the Recv should succeed") @@ -393,7 +391,7 @@ func (s *ChainedRetrySuite) TestStreamWithChainedInterceptors_NoFailure() { func (s *ChainedRetrySuite) TestStreamWithChainedInterceptors_WithRetry() { s.srv.resetFailingConfiguration(2, codes.Unavailable, noSleep) - stream, err := s.Client.PingList(s.SimpleCtx(), goodPing, retry.WithMax(2)) + stream, err := s.Client.PingList(s.SimpleCtx(), testpb.GoodPingList, retry.WithMax(2)) require.NoError(s.T(), err, "the second invocation should succeed") _, err = stream.Recv() require.NoError(s.T(), err, "the Recv should succeed") diff --git a/interceptors/server_test.go b/interceptors/server_test.go index afe7eb435..9b9f9570a 100644 --- a/interceptors/server_test.go +++ b/interceptors/server_test.go @@ -17,8 +17,7 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting/testpb" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/testing/testpb" ) func TestServerInterceptorSuite(t *testing.T) { @@ -51,7 +50,7 @@ func (s *ServerInterceptorTestSuite) SetupSuite() { grpc.StreamInterceptor(StreamServerInterceptor(s.mock)), grpc.UnaryInterceptor(UnaryServerInterceptor(s.mock)), ) - testpb.RegisterTestServiceServer(s.server, &grpctesting.TestPingService{T: s.T()}) + testpb.RegisterTestServiceServer(s.server, &testpb.TestPingService{T: s.T()}) go func() { _ = s.server.Serve(s.serverListener) @@ -89,7 +88,7 @@ func (s *ServerInterceptorTestSuite) TearDownTest() { } func (s *ServerInterceptorTestSuite) TestUnaryReporting() { - _, err := s.testClient.PingEmpty(s.ctx, &testpb.Empty{}) // should return with code=OK + _, err := s.testClient.PingEmpty(s.ctx, &testpb.PingEmptyRequest{}) // should return with code=OK require.NoError(s.T(), err) s.mock.Equal(s.T(), []*mockReport{{ typ: Unary, @@ -101,7 +100,7 @@ func (s *ServerInterceptorTestSuite) TestUnaryReporting() { }}) s.mock.reports = s.mock.reports[:0] // Reset. - _, err = s.testClient.PingError(s.ctx, &testpb.PingRequest{ErrorCodeReturned: uint32(codes.FailedPrecondition)}) // should return with code=FailedPrecondition + _, err = s.testClient.PingError(s.ctx, &testpb.PingErrorRequest{ErrorCodeReturned: uint32(codes.FailedPrecondition)}) // should return with code=FailedPrecondition require.Error(s.T(), err) s.mock.Equal(s.T(), []*mockReport{{ typ: Unary, @@ -114,7 +113,7 @@ func (s *ServerInterceptorTestSuite) TestUnaryReporting() { } func (s *ServerInterceptorTestSuite) TestStreamingReports() { - ss, _ := s.testClient.PingList(s.ctx, &testpb.PingRequest{}) // should return with code=OK + ss, _ := s.testClient.PingList(s.ctx, &testpb.PingListRequest{}) // should return with code=OK // Do a read, just for kicks. count := 0 for { @@ -125,18 +124,18 @@ func (s *ServerInterceptorTestSuite) TestStreamingReports() { require.NoError(s.T(), err, "reading pingList shouldn't fail") count++ } - require.EqualValues(s.T(), grpctesting.ListResponseCount, count, "Number of received msg on the wire must match") + require.EqualValues(s.T(), testpb.ListResponseCount, count, "Number of received msg on the wire must match") s.mock.Equal(s.T(), []*mockReport{{ typ: ServerStream, svcName: testpb.TestServiceFullName, methodName: "PingList", postCalls: []error{nil}, postMsgReceives: []error{nil}, - postMsgSends: make([]error, grpctesting.ListResponseCount), + postMsgSends: make([]error, testpb.ListResponseCount), }}) s.mock.reports = s.mock.reports[:0] // Reset. - _, err := s.testClient.PingList(s.ctx, &testpb.PingRequest{ErrorCodeReturned: uint32(codes.FailedPrecondition)}) // should return with code=FailedPrecondition + _, err := s.testClient.PingList(s.ctx, &testpb.PingListRequest{ErrorCodeReturned: uint32(codes.FailedPrecondition)}) // should return with code=FailedPrecondition require.NoError(s.T(), err, "PingList must not fail immediately") s.mock.requireOneReportWithRetry(s.ctx, s.T(), &mockReport{ @@ -175,7 +174,7 @@ func (s *ServerInterceptorTestSuite) TestBiStreamingReporting() { } }() for i := 0; i < 100; i++ { - require.NoError(s.T(), ss.Send(&testpb.PingRequest{}), "sending shouldn't fail") + require.NoError(s.T(), ss.Send(&testpb.PingStreamRequest{}), "sending shouldn't fail") } require.NoError(s.T(), ss.CloseSend()) diff --git a/interceptors/skip/examples_test.go b/interceptors/skip/examples_test.go index b34e9ee6f..907723516 100644 --- a/interceptors/skip/examples_test.go +++ b/interceptors/skip/examples_test.go @@ -5,8 +5,8 @@ import ( "google.golang.org/grpc" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/auth" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/auth" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/skip" ) @@ -22,6 +22,6 @@ func dummyAuth(ctx context.Context) (context.Context, error) { return ctx, nil } -func SkipReflectionService(ctx context.Context, gRPCType interceptors.GRPCType, service string, method string) bool { +func SkipReflectionService(_ context.Context, _ interceptors.GRPCType, service string, _ string) bool { return service != "grpc.reflection.v1alpha.ServerReflection" } diff --git a/interceptors/skip/interceptor_test.go b/interceptors/skip/interceptor_test.go index d1382ae07..96fed4ad0 100644 --- a/interceptors/skip/interceptor_test.go +++ b/interceptors/skip/interceptor_test.go @@ -14,15 +14,10 @@ import ( "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting/testpb" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/skip" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tags" -) - -var ( - goodPing = &testpb.PingRequest{Value: "something", SleepTimeMs: 9999} + "github.com/grpc-ecosystem/go-grpc-middleware/v2/testing/testpb" ) const ( @@ -54,7 +49,7 @@ func checkMetadata(ctx context.Context, grpcType interceptors.GRPCType, service } func (s *skipPingService) Ping(ctx context.Context, _ *testpb.PingRequest) (*testpb.PingResponse, error) { - err := checkMetadata(ctx, interceptors.Unary, "grpc_middleware.testpb.TestService", "Ping") + err := checkMetadata(ctx, interceptors.Unary, testpb.TestServiceFullName, "Ping") if err != nil { return nil, err } @@ -66,13 +61,13 @@ func (s *skipPingService) Ping(ctx context.Context, _ *testpb.PingRequest) (*tes return &testpb.PingResponse{}, nil } -func (s *skipPingService) PingList(_ *testpb.PingRequest, stream testpb.TestService_PingListServer) error { - err := checkMetadata(stream.Context(), interceptors.ServerStream, "grpc_middleware.testpb.TestService", "PingList") +func (s *skipPingService) PingList(_ *testpb.PingListRequest, stream testpb.TestService_PingListServer) error { + err := checkMetadata(stream.Context(), interceptors.ServerStream, testpb.TestServiceFullName, "PingList") if err != nil { return err } - var out testpb.PingResponse + var out testpb.PingListResponse if skipped(stream.Context()) { out.Value = "skipped" } @@ -94,8 +89,8 @@ func filter(ctx context.Context, gRPCType interceptors.GRPCType, service string, func TestSkipSuite(t *testing.T) { s := &SkipSuite{ - InterceptorTestSuite: &grpctesting.InterceptorTestSuite{ - TestService: &skipPingService{&grpctesting.TestPingService{T: t}}, + InterceptorTestSuite: &testpb.InterceptorTestSuite{ + TestService: &skipPingService{&testpb.TestPingService{T: t}}, ServerOpts: []grpc.ServerOption{ grpc.UnaryInterceptor(skip.UnaryServerInterceptor(tags.UnaryServerInterceptor(), filter)), grpc.StreamInterceptor(skip.StreamServerInterceptor(tags.StreamServerInterceptor(), filter)), @@ -106,7 +101,7 @@ func TestSkipSuite(t *testing.T) { } type SkipSuite struct { - *grpctesting.InterceptorTestSuite + *testpb.InterceptorTestSuite } func (s *SkipSuite) TestPing() { @@ -135,7 +130,7 @@ func (s *SkipSuite) TestPing() { }) } - resp, err := s.Client.Ping(metadata.NewOutgoingContext(s.SimpleCtx(), m), goodPing) + resp, err := s.Client.Ping(metadata.NewOutgoingContext(s.SimpleCtx(), m), testpb.GoodPing) require.NoError(t, err) var value string @@ -173,7 +168,7 @@ func (s *SkipSuite) TestPingList() { }) } - stream, err := s.Client.PingList(metadata.NewOutgoingContext(s.SimpleCtx(), m), goodPing) + stream, err := s.Client.PingList(metadata.NewOutgoingContext(s.SimpleCtx(), m), testpb.GoodPingList) require.NoError(t, err) for { diff --git a/interceptors/tags/fieldextractor_test.go b/interceptors/tags/fieldextractor_test.go index 3fdd3c11f..f367ce276 100644 --- a/interceptors/tags/fieldextractor_test.go +++ b/interceptors/tags/fieldextractor_test.go @@ -8,8 +8,8 @@ import ( "github.com/stretchr/testify/require" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting/testpb" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tags" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/testing/testpb" ) // TODO(bwplotka): Add tests/examples https://github.com/grpc-ecosystem/go-grpc-middleware/issues/382 diff --git a/interceptors/tags/interceptors_test.go b/interceptors/tags/interceptors_test.go index d7df256d6..e684b1cd1 100644 --- a/interceptors/tags/interceptors_test.go +++ b/interceptors/tags/interceptors_test.go @@ -12,14 +12,8 @@ import ( "github.com/stretchr/testify/suite" "google.golang.org/grpc" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting/testpb" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tags" -) - -var ( - goodPing = &testpb.PingRequest{Value: "something", SleepTimeMs: 9999} - anotherPing = &testpb.PingRequest{Value: "else", SleepTimeMs: 9999} + "github.com/grpc-ecosystem/go-grpc-middleware/v2/testing/testpb" ) func tagsToJson(value map[string]string) string { @@ -44,16 +38,15 @@ func (s *tagPingBack) Ping(ctx context.Context, _ *testpb.PingRequest) (*testpb. return &testpb.PingResponse{Value: tagsToJson(tags.Extract(ctx).Values())}, nil } -func (s *tagPingBack) PingError(ctx context.Context, ping *testpb.PingRequest) (*testpb.Empty, error) { +func (s *tagPingBack) PingError(ctx context.Context, ping *testpb.PingErrorRequest) (*testpb.PingErrorResponse, error) { return s.TestServiceServer.PingError(ctx, ping) } -func (s *tagPingBack) PingList(_ *testpb.PingRequest, stream testpb.TestService_PingListServer) error { - out := &testpb.PingResponse{Value: tagsToJson(tags.Extract(stream.Context()).Values())} - return stream.Send(out) +func (s *tagPingBack) PingList(_ *testpb.PingListRequest, stream testpb.TestService_PingListServer) error { + return stream.Send(&testpb.PingListResponse{Value: tagsToJson(tags.Extract(stream.Context()).Values())}) } -func (s *tagPingBack) PingEmpty(ctx context.Context, empty *testpb.Empty) (*testpb.PingResponse, error) { +func (s *tagPingBack) PingEmpty(ctx context.Context, empty *testpb.PingEmptyRequest) (*testpb.PingEmptyResponse, error) { return s.TestServiceServer.PingEmpty(ctx, empty) } @@ -66,8 +59,7 @@ func (s *tagPingBack) PingStream(stream testpb.TestService_PingStreamServer) err if err != nil { return err } - out := &testpb.PingResponse{Value: tagsToJson(tags.Extract(stream.Context()).Values())} - err = stream.Send(out) + err = stream.Send(&testpb.PingStreamResponse{Value: tagsToJson(tags.Extract(stream.Context()).Values())}) if err != nil { return err } @@ -78,8 +70,8 @@ func TestTaggingSuite(t *testing.T) { tags.WithFieldExtractor(tags.CodeGenRequestFieldExtractor), } s := &TaggingSuite{ - InterceptorTestSuite: &grpctesting.InterceptorTestSuite{ - TestService: &tagPingBack{&grpctesting.TestPingService{T: t}}, + InterceptorTestSuite: &testpb.InterceptorTestSuite{ + TestService: &tagPingBack{&testpb.TestPingService{T: t}}, ServerOpts: []grpc.ServerOption{ grpc.StreamInterceptor(tags.StreamServerInterceptor(opts...)), grpc.UnaryInterceptor(tags.UnaryServerInterceptor(opts...)), @@ -90,14 +82,14 @@ func TestTaggingSuite(t *testing.T) { } type TaggingSuite struct { - *grpctesting.InterceptorTestSuite + *testpb.InterceptorTestSuite } func (s *TaggingSuite) SetupTest() { } func (s *TaggingSuite) TestPing_WithCustomTags() { - resp, err := s.Client.Ping(s.SimpleCtx(), goodPing) + resp, err := s.Client.Ping(s.SimpleCtx(), testpb.GoodPing) require.NoError(s.T(), err, "must not be an error on a successful call") tags := tagsFromJson(s.T(), resp.Value) @@ -109,7 +101,7 @@ func (s *TaggingSuite) TestPing_WithCustomTags() { func (s *TaggingSuite) TestPing_WithDeadline() { ctx, cancel := context.WithDeadline(context.TODO(), time.Now().AddDate(0, 0, 5)) defer cancel() - resp, err := s.Client.Ping(ctx, goodPing) + resp, err := s.Client.Ping(ctx, testpb.GoodPing) require.NoError(s.T(), err, "must not be an error on a successful call") tags := tagsFromJson(s.T(), resp.Value) @@ -120,7 +112,7 @@ func (s *TaggingSuite) TestPing_WithDeadline() { func (s *TaggingSuite) TestPing_WithNoDeadline() { ctx := context.TODO() - resp, err := s.Client.Ping(ctx, goodPing) + resp, err := s.Client.Ping(ctx, testpb.GoodPing) require.NoError(s.T(), err, "must not be an error on a successful call") tags := tagsFromJson(s.T(), resp.Value) @@ -130,7 +122,7 @@ func (s *TaggingSuite) TestPing_WithNoDeadline() { } func (s *TaggingSuite) TestPingList_WithCustomTags() { - stream, err := s.Client.PingList(s.SimpleCtx(), goodPing) + stream, err := s.Client.PingList(s.SimpleCtx(), testpb.GoodPingList) require.NoError(s.T(), err, "should not fail on establishing the stream") for { resp, err := stream.Recv() @@ -153,8 +145,8 @@ func TestTaggingOnInitialRequestSuite(t *testing.T) { // the case of unary and server-streamed calls s := &ClientStreamedTaggingSuite{ TaggingSuite: &TaggingSuite{ - InterceptorTestSuite: &grpctesting.InterceptorTestSuite{ - TestService: &tagPingBack{&grpctesting.TestPingService{T: t}}, + InterceptorTestSuite: &testpb.InterceptorTestSuite{ + TestService: &tagPingBack{&testpb.TestPingService{T: t}}, ServerOpts: []grpc.ServerOption{ grpc.StreamInterceptor(tags.StreamServerInterceptor(opts...)), grpc.UnaryInterceptor(tags.UnaryServerInterceptor(opts...)), @@ -177,9 +169,9 @@ func (s *ClientStreamedTaggingSuite) TestPingStream_WithCustomTagsFirstRequest() for { switch { case count == 0: - err = stream.Send(goodPing) + err = stream.Send(testpb.GoodPingStream) case count < 3: - err = stream.Send(anotherPing) + err = stream.Send(&testpb.PingStreamRequest{Value: "another", SleepTimeMs: 9999}) default: err = stream.CloseSend() } diff --git a/interceptors/tracing/interceptors_test.go b/interceptors/tracing/interceptors_test.go index 894634833..71d9bdda8 100644 --- a/interceptors/tracing/interceptors_test.go +++ b/interceptors/tracing/interceptors_test.go @@ -21,14 +21,12 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/codes" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting/testpb" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tags" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tracing" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/testing/testpb" ) var ( - goodPing = &testpb.PingRequest{Value: "something", SleepTimeMs: 9999} fakeInboundTraceId = 1337 fakeInboundSpanId = 999 traceHeaderName = "uber-trace-id" @@ -49,12 +47,12 @@ func (s *tracingAssertService) Ping(ctx context.Context, ping *testpb.PingReques return s.TestServiceServer.Ping(ctx, ping) } -func (s *tracingAssertService) PingError(ctx context.Context, ping *testpb.PingRequest) (*testpb.Empty, error) { +func (s *tracingAssertService) PingError(ctx context.Context, ping *testpb.PingErrorRequest) (*testpb.PingErrorResponse, error) { assert.NotNil(s.T, opentracing.SpanFromContext(ctx), "handlers must have the spancontext in their context, otherwise propagation will fail") return s.TestServiceServer.PingError(ctx, ping) } -func (s *tracingAssertService) PingList(ping *testpb.PingRequest, stream testpb.TestService_PingListServer) error { +func (s *tracingAssertService) PingList(ping *testpb.PingListRequest, stream testpb.TestService_PingListServer) error { assert.NotNil(s.T, opentracing.SpanFromContext(stream.Context()), "handlers must have the spancontext in their context, otherwise propagation will fail") tags := tags.Extract(stream.Context()) assert.True(s.T, tags.Has(tracing.TagTraceId), "tags must contain traceid") @@ -64,7 +62,7 @@ func (s *tracingAssertService) PingList(ping *testpb.PingRequest, stream testpb. return s.TestServiceServer.PingList(ping, stream) } -func (s *tracingAssertService) PingEmpty(ctx context.Context, empty *testpb.Empty) (*testpb.PingResponse, error) { +func (s *tracingAssertService) PingEmpty(ctx context.Context, empty *testpb.PingEmptyRequest) (*testpb.PingEmptyResponse, error) { assert.NotNil(s.T, opentracing.SpanFromContext(ctx), "handlers must have the spancontext in their context, otherwise propagation will fail") tags := tags.Extract(ctx) assert.True(s.T, tags.Has(tracing.TagTraceId), "tags must contain traceid") @@ -101,9 +99,9 @@ func TestTaggingSuiteJaeger(t *testing.T) { suite.Run(t, s) } -func makeInterceptorTestSuite(t *testing.T, opts []tracing.Option) *grpctesting.InterceptorTestSuite { - return &grpctesting.InterceptorTestSuite{ - TestService: &tracingAssertService{TestServiceServer: &grpctesting.TestPingService{T: t}, T: t}, +func makeInterceptorTestSuite(t *testing.T, opts []tracing.Option) *testpb.InterceptorTestSuite { + return &testpb.InterceptorTestSuite{ + TestService: &tracingAssertService{TestServiceServer: &testpb.TestPingService{T: t}, T: t}, ClientOpts: []grpc.DialOption{ grpc.WithUnaryInterceptor(tracing.UnaryClientInterceptor(opts...)), grpc.WithStreamInterceptor(tracing.StreamClientInterceptor(opts...)), @@ -120,7 +118,7 @@ func makeInterceptorTestSuite(t *testing.T, opts []tracing.Option) *grpctesting. } type OpentracingSuite struct { - *grpctesting.InterceptorTestSuite + *testpb.InterceptorTestSuite mockTracer *mocktracer.MockTracer } @@ -178,7 +176,7 @@ func (s *OpentracingSuite) assertTracesCreated(methodName string) (clientSpan *m func (s *OpentracingSuite) TestPing_PropagatesTraces() { ctx := s.createContextFromFakeHttpRequestParent(s.SimpleCtx(), true) - _, err := s.Client.Ping(ctx, goodPing) + _, err := s.Client.Ping(ctx, testpb.GoodPing) require.NoError(s.T(), err, "there must be not be an on a successful call") s.assertTracesCreated("/" + testpb.TestServiceFullName + "/Ping") } @@ -190,7 +188,7 @@ func (s *OpentracingSuite) TestPing_ClientContextTags() { opentracing.Tags{name: ""}, ) - _, err := s.Client.Ping(ctx, goodPing) + _, err := s.Client.Ping(ctx, testpb.GoodPing) require.NoError(s.T(), err, "there must be not be an on a successful call") for _, span := range s.mockTracer.FinishedSpans() { @@ -205,7 +203,7 @@ func (s *OpentracingSuite) TestPing_ClientContextTags() { func (s *OpentracingSuite) TestPingList_PropagatesTraces() { ctx := s.createContextFromFakeHttpRequestParent(s.SimpleCtx(), true) - stream, err := s.Client.PingList(ctx, goodPing) + stream, err := s.Client.PingList(ctx, testpb.GoodPingList) require.NoError(s.T(), err, "should not fail on establishing the stream") for { _, err := stream.Recv() @@ -219,8 +217,7 @@ func (s *OpentracingSuite) TestPingList_PropagatesTraces() { func (s *OpentracingSuite) TestPingError_PropagatesTraces() { ctx := s.createContextFromFakeHttpRequestParent(s.SimpleCtx(), true) - erroringPing := &testpb.PingRequest{Value: "something", ErrorCodeReturned: uint32(codes.OutOfRange)} - _, err := s.Client.PingError(ctx, erroringPing) + _, err := s.Client.PingError(ctx, &testpb.PingErrorRequest{Value: "something", ErrorCodeReturned: uint32(codes.OutOfRange)}) require.Error(s.T(), err, "there must be an error returned here") clientSpan, serverSpan := s.assertTracesCreated("/" + testpb.TestServiceFullName + "/PingError") assert.Equal(s.T(), true, clientSpan.Tag("error"), "client span needs to be marked as an error") @@ -229,7 +226,7 @@ func (s *OpentracingSuite) TestPingError_PropagatesTraces() { func (s *OpentracingSuite) TestPingEmpty_NotSampleTraces() { ctx := s.createContextFromFakeHttpRequestParent(s.SimpleCtx(), false) - _, err := s.Client.PingEmpty(ctx, &testpb.Empty{}) + _, err := s.Client.PingEmpty(ctx, &testpb.PingEmptyRequest{}) require.NoError(s.T(), err, "there must be not be an on a successful call") } diff --git a/interceptors/validator/validator_test.go b/interceptors/validator/validator_test.go index 39fb846c2..4154a1c8c 100644 --- a/interceptors/validator/validator_test.go +++ b/interceptors/validator/validator_test.go @@ -14,20 +14,13 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting/testpb" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/validator" -) - -var ( - // See test.manual_validator.pb.go for the validator check of SleepTimeMs. - goodPing = &testpb.PingRequest{Value: "something", SleepTimeMs: 9999} - badPing = &testpb.PingRequest{Value: "something", SleepTimeMs: 10001} + "github.com/grpc-ecosystem/go-grpc-middleware/v2/testing/testpb" ) func TestValidatorTestSuite(t *testing.T) { s := &ValidatorTestSuite{ - InterceptorTestSuite: &grpctesting.InterceptorTestSuite{ + InterceptorTestSuite: &testpb.InterceptorTestSuite{ ServerOpts: []grpc.ServerOption{ grpc.StreamInterceptor(validator.StreamServerInterceptor()), grpc.UnaryInterceptor(validator.UnaryServerInterceptor()), @@ -37,7 +30,7 @@ func TestValidatorTestSuite(t *testing.T) { suite.Run(t, s) cs := &ClientValidatorTestSuite{ - InterceptorTestSuite: &grpctesting.InterceptorTestSuite{ + InterceptorTestSuite: &testpb.InterceptorTestSuite{ ClientOpts: []grpc.DialOption{ grpc.WithUnaryInterceptor(validator.UnaryClientInterceptor()), }, @@ -47,22 +40,22 @@ func TestValidatorTestSuite(t *testing.T) { } type ValidatorTestSuite struct { - *grpctesting.InterceptorTestSuite + *testpb.InterceptorTestSuite } func (s *ValidatorTestSuite) TestValidPasses_Unary() { - _, err := s.Client.Ping(s.SimpleCtx(), goodPing) + _, err := s.Client.Ping(s.SimpleCtx(), testpb.GoodPing) assert.NoError(s.T(), err, "no error expected") } func (s *ValidatorTestSuite) TestInvalidErrors_Unary() { - _, err := s.Client.Ping(s.SimpleCtx(), badPing) + _, err := s.Client.Ping(s.SimpleCtx(), testpb.BadPing) assert.Error(s.T(), err, "no error expected") assert.Equal(s.T(), codes.InvalidArgument, status.Code(err), "gRPC status must be InvalidArgument") } func (s *ValidatorTestSuite) TestValidPasses_ServerStream() { - stream, err := s.Client.PingList(s.SimpleCtx(), goodPing) + stream, err := s.Client.PingList(s.SimpleCtx(), testpb.GoodPingList) require.NoError(s.T(), err, "no error on stream establishment expected") for { _, err := stream.Recv() @@ -74,7 +67,7 @@ func (s *ValidatorTestSuite) TestValidPasses_ServerStream() { } func (s *ValidatorTestSuite) TestInvalidErrors_ServerStream() { - stream, err := s.Client.PingList(s.SimpleCtx(), badPing) + stream, err := s.Client.PingList(s.SimpleCtx(), testpb.BadPingList) require.NoError(s.T(), err, "no error on stream establishment expected") _, err = stream.Recv() assert.Error(s.T(), err, "error should be received on first message") @@ -85,16 +78,16 @@ func (s *ValidatorTestSuite) TestInvalidErrors_BidiStream() { stream, err := s.Client.PingStream(s.SimpleCtx()) require.NoError(s.T(), err, "no error on stream establishment expected") - require.NoError(s.T(), stream.Send(goodPing)) + require.NoError(s.T(), stream.Send(testpb.GoodPingStream)) _, err = stream.Recv() assert.NoError(s.T(), err, "receiving a good ping should return a good pong") - require.NoError(s.T(), stream.Send(goodPing)) + require.NoError(s.T(), stream.Send(testpb.GoodPingStream)) _, err = stream.Recv() assert.NoError(s.T(), err, "receiving a good ping should return a good pong") - require.NoError(s.T(), stream.Send(badPing)) + require.NoError(s.T(), stream.Send(testpb.BadPingStream)) _, err = stream.Recv() - assert.Error(s.T(), err, "receiving a good ping should return a good pong") + assert.Error(s.T(), err, "receiving a bad ping should return a bad pong") assert.Equal(s.T(), codes.InvalidArgument, status.Code(err), "gRPC status must be InvalidArgument") err = stream.CloseSend() @@ -102,16 +95,16 @@ func (s *ValidatorTestSuite) TestInvalidErrors_BidiStream() { } type ClientValidatorTestSuite struct { - *grpctesting.InterceptorTestSuite + *testpb.InterceptorTestSuite } func (s *ClientValidatorTestSuite) TestValidPasses_Unary() { - _, err := s.Client.Ping(s.SimpleCtx(), goodPing) + _, err := s.Client.Ping(s.SimpleCtx(), testpb.GoodPing) assert.NoError(s.T(), err, "no error expected") } func (s *ClientValidatorTestSuite) TestInvalidErrors_Unary() { - _, err := s.Client.Ping(s.SimpleCtx(), badPing) + _, err := s.Client.Ping(s.SimpleCtx(), testpb.BadPing) assert.Error(s.T(), err, "error expected") assert.Equal(s.T(), codes.InvalidArgument, status.Code(err), "gRPC status must be InvalidArgument") } diff --git a/scripts/genproto.sh b/scripts/genproto.sh deleted file mode 100755 index a3964d97b..000000000 --- a/scripts/genproto.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env bash -# -# Generate all protobuf bindings. -# Run from repository root. -set -e -set -u - -PROTOC_BIN=${PROTOC_BIN:-protoc} -GOIMPORTS_BIN=${GOIMPORTS_BIN:-goimports} -PROTOC_GEN_GO_BIN=${PROTOC_GEN_GO_BIN:-protoc-gen-go} -PROTOC_GEN_GO_GRPC_BIN=${PROTOC_GEN_GO_GRPC_BIN:-protoc-gen-go-grpc} - -if ! [[ "$0" =~ "scripts/genproto.sh" ]]; then - echo "must be run from repository root" - exit 255 -fi - -OLDPATH=${PATH} - -mkdir -p /tmp/protobin/ -cp ${PROTOC_GEN_GO_BIN} /tmp/protobin/protoc-gen-go -cp ${PROTOC_GEN_GO_GRPC_BIN} /tmp/protobin/protoc-gen-go-grpc -PATH=${OLDPATH}:/tmp/protobin - -DIRS="grpctesting/testpb" -echo "generating protobuf code" -for dir in ${DIRS}; do - pushd ${dir} - ${PROTOC_BIN} --go_out=. --go-grpc_out=.\ - -I=. \ - *.proto - - ${GOIMPORTS_BIN} -w *.pb.go - popd -done diff --git a/scripts/installprotoc.sh b/scripts/installprotoc.sh deleted file mode 100755 index 1ca843c6c..000000000 --- a/scripts/installprotoc.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/env bash -# -# Install the standard protocol buffer implementation - protoc. -set -e -set -u - -PROTOC_VERSION=${PROTOC_VERSION:-3.4.0} -TMP_GOPATH=${TMP_GOPATH:-/tmp/thanos-go} -PROTOC_DOWNLOAD_URL="https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}" - -OS=$(go env GOOS) -ARCH=$(go env GOARCH) -PLATFORM="${OS}/${ARCH}" - -is_supported_platform() { - platform=$1 - found=1 - case "$platform" in - darwin/amd64) found=0 ;; - darwin/i386) found=0 ;; - linux/amd64) found=0 ;; - linux/i386) found=0 ;; - linux/arm64) found=0 ;; - esac - return $found -} - -adjust_os() { - case ${OS} in - darwin) OS=osx ;; - esac - true -} - -adjust_arch() { - case ${ARCH} in - amd64) ARCH=x86_64 ;; - i386) ARCH=x86_32 ;; - arm64) ARCH=aarch_64 ;; - esac - true -} - -mkdir -p ${TMP_GOPATH} - -is_supported_platform "$PLATFORM" -if [[ $? -eq 1 ]]; then - echo "platform $PLATFORM is not supported. See https://github.com/protocolbuffers/protobuf/releases for details" - exit 1 -fi - -adjust_os - -adjust_arch - -PACKAGE="protoc-${PROTOC_VERSION}-${OS}-${ARCH}.zip" -PACKAGE_DOWNLOAD_URL="${PROTOC_DOWNLOAD_URL}/${PACKAGE}" -curl -LSs ${PACKAGE_DOWNLOAD_URL} -o ${TMP_GOPATH}/${PACKAGE} -unzip -qqj ${TMP_GOPATH}/${PACKAGE} "bin/protoc" -d "${TMP_GOPATH}/bin/" diff --git a/grpctesting/interceptor_suite.go b/testing/testpb/interceptor_suite.go similarity index 94% rename from grpctesting/interceptor_suite.go rename to testing/testpb/interceptor_suite.go index cbfefc049..c46dd49cc 100644 --- a/grpctesting/interceptor_suite.go +++ b/testing/testpb/interceptor_suite.go @@ -1,7 +1,7 @@ // Copyright 2016 Michal Witkowski. All Rights Reserved. // See LICENSE for licensing terms. -package grpctesting +package testpb import ( "context" @@ -21,8 +21,6 @@ import ( "github.com/stretchr/testify/suite" "google.golang.org/grpc" "google.golang.org/grpc/credentials" - - "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting/testpb" ) var ( @@ -36,7 +34,7 @@ var ( type InterceptorTestSuite struct { suite.Suite - TestService testpb.TestServiceServer + TestService TestServiceServer ServerOpts []grpc.ServerOption ClientOpts []grpc.DialOption @@ -44,7 +42,7 @@ type InterceptorTestSuite struct { ServerListener net.Listener Server *grpc.Server clientConn *grpc.ClientConn - Client testpb.TestServiceClient + Client TestServiceClient restartServerWithDelayedStart chan time.Duration serverRunning chan bool @@ -79,7 +77,7 @@ func (s *InterceptorTestSuite) SetupSuite() { if s.TestService == nil { s.TestService = &TestPingService{T: s.T()} } - testpb.RegisterTestServiceServer(s.Server, s.TestService) + RegisterTestServiceServer(s.Server, s.TestService) w := sync.WaitGroup{} w.Add(1) @@ -113,7 +111,7 @@ func (s *InterceptorTestSuite) RestartServer(delayedStart time.Duration) <-chan return s.serverRunning } -func (s *InterceptorTestSuite) NewClient(dialOpts ...grpc.DialOption) testpb.TestServiceClient { +func (s *InterceptorTestSuite) NewClient(dialOpts ...grpc.DialOption) TestServiceClient { newDialOpts := append(dialOpts, grpc.WithBlock()) if *flagTls { cp := x509.NewCertPool() @@ -129,7 +127,7 @@ func (s *InterceptorTestSuite) NewClient(dialOpts ...grpc.DialOption) testpb.Tes defer cancel() clientConn, err := grpc.DialContext(ctx, s.ServerAddr(), newDialOpts...) require.NoError(s.T(), err, "must not error on client Dial") - return testpb.NewTestServiceClient(clientConn) + return NewTestServiceClient(clientConn) } func (s *InterceptorTestSuite) ServerAddr() string { diff --git a/testing/testpb/pingservice.go b/testing/testpb/pingservice.go new file mode 100644 index 000000000..4107a4c91 --- /dev/null +++ b/testing/testpb/pingservice.go @@ -0,0 +1,78 @@ +// Copyright 2016 Michal Witkowski. All Rights Reserved. +// See LICENSE for licensing terms. + +/* +Package `grpc_testing` provides helper functions for testing validators in this package. +*/ + +package testpb + +import ( + "context" + "io" + "testing" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +const ( + // ListResponseCount is the expected number of responses to PingList + ListResponseCount = 100 +) + +// Interface implementation assert. +var _ TestServiceServer = &TestPingService{} + +type TestPingService struct { + UnimplementedTestServiceServer + + T *testing.T +} + +func (s *TestPingService) PingEmpty(_ context.Context, _ *PingEmptyRequest) (*PingEmptyResponse, error) { + return &PingEmptyResponse{}, nil +} + +func (s *TestPingService) Ping(_ context.Context, ping *PingRequest) (*PingResponse, error) { + // Send user trailers and headers. + return &PingResponse{Value: ping.Value, Counter: 0}, nil +} + +func (s *TestPingService) PingError(_ context.Context, ping *PingErrorRequest) (*PingErrorResponse, error) { + code := codes.Code(ping.ErrorCodeReturned) + return nil, status.Errorf(code, "Userspace error.") +} + +func (s *TestPingService) PingList(ping *PingListRequest, stream TestService_PingListServer) error { + if ping.ErrorCodeReturned != 0 { + return status.Errorf(codes.Code(ping.ErrorCodeReturned), "foobar") + } + + // Send user trailers and headers. + for i := 0; i < ListResponseCount; i++ { + if err := stream.Send(&PingListResponse{Value: ping.Value, Counter: int32(i)}); err != nil { + return err + } + } + return nil +} + +func (s *TestPingService) PingStream(stream TestService_PingStreamServer) error { + count := 0 + for { + ping, err := stream.Recv() + if err == io.EOF { + break + } + if err != nil { + return err + } + if err := stream.Send(&PingStreamResponse{Value: ping.Value, Counter: int32(count)}); err != nil { + return err + } + + count += 1 + } + return nil +} diff --git a/grpctesting/pingservice_test.go b/testing/testpb/pingservice_test.go similarity index 70% rename from grpctesting/pingservice_test.go rename to testing/testpb/pingservice_test.go index 5efe0f8fa..4e220755b 100644 --- a/grpctesting/pingservice_test.go +++ b/testing/testpb/pingservice_test.go @@ -1,4 +1,4 @@ -package grpctesting +package testpb import ( "context" @@ -9,8 +9,6 @@ import ( "github.com/stretchr/testify/require" "google.golang.org/grpc" - - "github.com/grpc-ecosystem/go-grpc-middleware/v2/grpctesting/testpb" ) func TestPingServiceOnWire(t *testing.T) { @@ -19,7 +17,7 @@ func TestPingServiceOnWire(t *testing.T) { require.NoError(t, err, "must be able to allocate a port for serverListener") server := grpc.NewServer() - testpb.RegisterTestServiceServer(server, &TestPingService{T: t}) + RegisterTestServiceServer(server, &TestPingService{T: t}) go func() { defer close(stopped) @@ -42,27 +40,26 @@ func TestPingServiceOnWire(t *testing.T) { ) require.NoError(t, err, "must not error on client Dial") - testClient := testpb.NewTestServiceClient(clientConn) + testClient := NewTestServiceClient(clientConn) select { case err := <-stopped: t.Fatal("gRPC server stopped prematurely", err) default: } - r, err := testClient.PingEmpty(context.Background(), &testpb.Empty{}) + r, err := testClient.PingEmpty(context.Background(), &PingEmptyRequest{}) require.NoError(t, err) - require.Equal(t, "default_response_value", r.Value) - require.Equal(t, int32(0), r.Counter) + require.NotNil(t, r) - r2, err := testClient.Ping(context.Background(), &testpb.PingRequest{Value: "24"}) + r2, err := testClient.Ping(context.Background(), &PingRequest{Value: "24"}) require.NoError(t, err) require.Equal(t, "24", r2.Value) require.Equal(t, int32(0), r2.Counter) - _, err = testClient.PingError(context.Background(), &testpb.PingRequest{Value: "24"}) + _, err = testClient.PingError(context.Background(), &PingErrorRequest{Value: "24"}) require.Error(t, err) - l, err := testClient.PingList(context.Background(), &testpb.PingRequest{Value: "24"}) + l, err := testClient.PingList(context.Background(), &PingListRequest{Value: "24"}) require.NoError(t, err) for i := 0; i < ListResponseCount; i++ { r, err := l.Recv() @@ -74,7 +71,7 @@ func TestPingServiceOnWire(t *testing.T) { s, err := testClient.PingStream(context.Background()) require.NoError(t, err) for i := 0; i < ListResponseCount; i++ { - require.NoError(t, s.Send(&testpb.PingRequest{Value: fmt.Sprintf("%v", i)})) + require.NoError(t, s.Send(&PingStreamRequest{Value: fmt.Sprintf("%v", i)})) r, err := s.Recv() require.NoError(t, err) diff --git a/testing/testpb/test.manual_extractfields.pb.go b/testing/testpb/test.manual_extractfields.pb.go new file mode 100644 index 000000000..7006fa466 --- /dev/null +++ b/testing/testpb/test.manual_extractfields.pb.go @@ -0,0 +1,25 @@ +// Manual code for logging field extraction tests. + +package testpb + +const TestServiceFullName = "testing.testpb.v1.TestService" + +// This is implementing tags.requestFieldsExtractor +func (x *PingRequest) ExtractRequestFields(appendToMap map[string]string) { + appendToMap["value"] = x.Value +} + +// This is implementing tags.requestFieldsExtractor +func (x *PingErrorRequest) ExtractRequestFields(appendToMap map[string]string) { + appendToMap["value"] = x.Value +} + +// This is implementing tags.requestFieldsExtractor +func (x *PingListRequest) ExtractRequestFields(appendToMap map[string]string) { + appendToMap["value"] = x.Value +} + +// This is implementing tags.requestFieldsExtractor +func (x *PingStreamRequest) ExtractRequestFields(appendToMap map[string]string) { + appendToMap["value"] = x.Value +} diff --git a/testing/testpb/test.manual_validator.pb.go b/testing/testpb/test.manual_validator.pb.go new file mode 100644 index 000000000..a2d438b2f --- /dev/null +++ b/testing/testpb/test.manual_validator.pb.go @@ -0,0 +1,45 @@ +// Manual code for validation tests. + +package testpb + +import "github.com/pkg/errors" + +func (x *PingRequest) Validate() error { + if x.SleepTimeMs > 10000 { + return errors.New("cannot sleep for more than 10s") + } + return nil +} + +func (x *PingErrorRequest) Validate() error { + if x.SleepTimeMs > 10000 { + return errors.New("cannot sleep for more than 10s") + } + return nil +} + +func (x *PingListRequest) Validate() error { + if x.SleepTimeMs > 10000 { + return errors.New("cannot sleep for more than 10s") + } + return nil +} + +func (x *PingStreamRequest) Validate() error { + if x.SleepTimeMs > 10000 { + return errors.New("cannot sleep for more than 10s") + } + return nil +} + +var ( + GoodPing = &PingRequest{Value: "something", SleepTimeMs: 9999} + GoodPingError = &PingErrorRequest{Value: "something", SleepTimeMs: 9999} + GoodPingList = &PingListRequest{Value: "something", SleepTimeMs: 9999} + GoodPingStream = &PingStreamRequest{Value: "something", SleepTimeMs: 9999} + + BadPing = &PingRequest{Value: "something", SleepTimeMs: 10001} + BadPingError = &PingErrorRequest{Value: "something", SleepTimeMs: 10001} + BadPingList = &PingListRequest{Value: "something", SleepTimeMs: 10001} + BadPingStream = &PingStreamRequest{Value: "something", SleepTimeMs: 10001} +) diff --git a/testing/testpb/test.pb.go b/testing/testpb/test.pb.go new file mode 100644 index 000000000..c944d73cb --- /dev/null +++ b/testing/testpb/test.pb.go @@ -0,0 +1,853 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.25.0 +// protoc v3.13.0 +// source: test.proto + +package testpb + +import ( + reflect "reflect" + sync "sync" + + proto "github.com/golang/protobuf/proto" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// This is a compile-time assertion that a sufficiently up-to-date version +// of the legacy proto package is being used. +const _ = proto.ProtoPackageIsVersion4 + +type PingEmptyRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *PingEmptyRequest) Reset() { + *x = PingEmptyRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PingEmptyRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PingEmptyRequest) ProtoMessage() {} + +func (x *PingEmptyRequest) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PingEmptyRequest.ProtoReflect.Descriptor instead. +func (*PingEmptyRequest) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{0} +} + +type PingEmptyResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *PingEmptyResponse) Reset() { + *x = PingEmptyResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PingEmptyResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PingEmptyResponse) ProtoMessage() {} + +func (x *PingEmptyResponse) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PingEmptyResponse.ProtoReflect.Descriptor instead. +func (*PingEmptyResponse) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{1} +} + +type PingRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` + SleepTimeMs int32 `protobuf:"varint,2,opt,name=sleep_time_ms,json=sleepTimeMs,proto3" json:"sleep_time_ms,omitempty"` + ErrorCodeReturned uint32 `protobuf:"varint,3,opt,name=error_code_returned,json=errorCodeReturned,proto3" json:"error_code_returned,omitempty"` +} + +func (x *PingRequest) Reset() { + *x = PingRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PingRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PingRequest) ProtoMessage() {} + +func (x *PingRequest) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PingRequest.ProtoReflect.Descriptor instead. +func (*PingRequest) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{2} +} + +func (x *PingRequest) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +func (x *PingRequest) GetSleepTimeMs() int32 { + if x != nil { + return x.SleepTimeMs + } + return 0 +} + +func (x *PingRequest) GetErrorCodeReturned() uint32 { + if x != nil { + return x.ErrorCodeReturned + } + return 0 +} + +type PingResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` + Counter int32 `protobuf:"varint,2,opt,name=counter,proto3" json:"counter,omitempty"` +} + +func (x *PingResponse) Reset() { + *x = PingResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PingResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PingResponse) ProtoMessage() {} + +func (x *PingResponse) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PingResponse.ProtoReflect.Descriptor instead. +func (*PingResponse) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{3} +} + +func (x *PingResponse) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +func (x *PingResponse) GetCounter() int32 { + if x != nil { + return x.Counter + } + return 0 +} + +type PingErrorRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` + SleepTimeMs int32 `protobuf:"varint,2,opt,name=sleep_time_ms,json=sleepTimeMs,proto3" json:"sleep_time_ms,omitempty"` + ErrorCodeReturned uint32 `protobuf:"varint,3,opt,name=error_code_returned,json=errorCodeReturned,proto3" json:"error_code_returned,omitempty"` +} + +func (x *PingErrorRequest) Reset() { + *x = PingErrorRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PingErrorRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PingErrorRequest) ProtoMessage() {} + +func (x *PingErrorRequest) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PingErrorRequest.ProtoReflect.Descriptor instead. +func (*PingErrorRequest) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{4} +} + +func (x *PingErrorRequest) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +func (x *PingErrorRequest) GetSleepTimeMs() int32 { + if x != nil { + return x.SleepTimeMs + } + return 0 +} + +func (x *PingErrorRequest) GetErrorCodeReturned() uint32 { + if x != nil { + return x.ErrorCodeReturned + } + return 0 +} + +type PingErrorResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` + Counter int32 `protobuf:"varint,2,opt,name=counter,proto3" json:"counter,omitempty"` +} + +func (x *PingErrorResponse) Reset() { + *x = PingErrorResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PingErrorResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PingErrorResponse) ProtoMessage() {} + +func (x *PingErrorResponse) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PingErrorResponse.ProtoReflect.Descriptor instead. +func (*PingErrorResponse) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{5} +} + +func (x *PingErrorResponse) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +func (x *PingErrorResponse) GetCounter() int32 { + if x != nil { + return x.Counter + } + return 0 +} + +type PingListRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` + SleepTimeMs int32 `protobuf:"varint,2,opt,name=sleep_time_ms,json=sleepTimeMs,proto3" json:"sleep_time_ms,omitempty"` + ErrorCodeReturned uint32 `protobuf:"varint,3,opt,name=error_code_returned,json=errorCodeReturned,proto3" json:"error_code_returned,omitempty"` +} + +func (x *PingListRequest) Reset() { + *x = PingListRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PingListRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PingListRequest) ProtoMessage() {} + +func (x *PingListRequest) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PingListRequest.ProtoReflect.Descriptor instead. +func (*PingListRequest) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{6} +} + +func (x *PingListRequest) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +func (x *PingListRequest) GetSleepTimeMs() int32 { + if x != nil { + return x.SleepTimeMs + } + return 0 +} + +func (x *PingListRequest) GetErrorCodeReturned() uint32 { + if x != nil { + return x.ErrorCodeReturned + } + return 0 +} + +type PingListResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` + Counter int32 `protobuf:"varint,2,opt,name=counter,proto3" json:"counter,omitempty"` +} + +func (x *PingListResponse) Reset() { + *x = PingListResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PingListResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PingListResponse) ProtoMessage() {} + +func (x *PingListResponse) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PingListResponse.ProtoReflect.Descriptor instead. +func (*PingListResponse) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{7} +} + +func (x *PingListResponse) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +func (x *PingListResponse) GetCounter() int32 { + if x != nil { + return x.Counter + } + return 0 +} + +type PingStreamRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` + SleepTimeMs int32 `protobuf:"varint,2,opt,name=sleep_time_ms,json=sleepTimeMs,proto3" json:"sleep_time_ms,omitempty"` + ErrorCodeReturned uint32 `protobuf:"varint,3,opt,name=error_code_returned,json=errorCodeReturned,proto3" json:"error_code_returned,omitempty"` +} + +func (x *PingStreamRequest) Reset() { + *x = PingStreamRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PingStreamRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PingStreamRequest) ProtoMessage() {} + +func (x *PingStreamRequest) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PingStreamRequest.ProtoReflect.Descriptor instead. +func (*PingStreamRequest) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{8} +} + +func (x *PingStreamRequest) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +func (x *PingStreamRequest) GetSleepTimeMs() int32 { + if x != nil { + return x.SleepTimeMs + } + return 0 +} + +func (x *PingStreamRequest) GetErrorCodeReturned() uint32 { + if x != nil { + return x.ErrorCodeReturned + } + return 0 +} + +type PingStreamResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` + Counter int32 `protobuf:"varint,2,opt,name=counter,proto3" json:"counter,omitempty"` +} + +func (x *PingStreamResponse) Reset() { + *x = PingStreamResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PingStreamResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PingStreamResponse) ProtoMessage() {} + +func (x *PingStreamResponse) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PingStreamResponse.ProtoReflect.Descriptor instead. +func (*PingStreamResponse) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{9} +} + +func (x *PingStreamResponse) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +func (x *PingStreamResponse) GetCounter() int32 { + if x != nil { + return x.Counter + } + return 0 +} + +var File_test_proto protoreflect.FileDescriptor + +var file_test_proto_rawDesc = []byte{ + 0x0a, 0x0a, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x11, 0x74, 0x65, + 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x76, 0x31, 0x22, + 0x12, 0x0a, 0x10, 0x50, 0x69, 0x6e, 0x67, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x22, 0x13, 0x0a, 0x11, 0x50, 0x69, 0x6e, 0x67, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x77, 0x0a, 0x0b, 0x50, 0x69, 0x6e, 0x67, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x22, 0x0a, + 0x0d, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x54, 0x69, 0x6d, 0x65, 0x4d, + 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x5f, + 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x65, + 0x64, 0x22, 0x3e, 0x0a, 0x0c, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, + 0x72, 0x22, 0x7c, 0x0a, 0x10, 0x50, 0x69, 0x6e, 0x67, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x73, + 0x6c, 0x65, 0x65, 0x70, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x0b, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x12, + 0x2e, 0x0a, 0x13, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x72, 0x65, + 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x22, + 0x43, 0x0a, 0x11, 0x50, 0x69, 0x6e, 0x67, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x65, 0x72, 0x22, 0x7b, 0x0a, 0x0f, 0x50, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x22, 0x0a, + 0x0d, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x54, 0x69, 0x6d, 0x65, 0x4d, + 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x5f, + 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x65, + 0x64, 0x22, 0x42, 0x0a, 0x10, 0x50, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x65, 0x72, 0x22, 0x7d, 0x0a, 0x11, 0x50, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x72, + 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x12, 0x22, 0x0a, 0x0d, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, + 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x54, 0x69, + 0x6d, 0x65, 0x4d, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x63, 0x6f, + 0x64, 0x65, 0x5f, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x11, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x74, 0x75, + 0x72, 0x6e, 0x65, 0x64, 0x22, 0x44, 0x0a, 0x12, 0x50, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x72, 0x65, + 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x32, 0xc6, 0x03, 0x0a, 0x0b, 0x54, + 0x65, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x58, 0x0a, 0x09, 0x50, 0x69, + 0x6e, 0x67, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x23, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, + 0x67, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x74, + 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x76, 0x31, + 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x49, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x1e, 0x2e, 0x74, + 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x76, 0x31, + 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x74, + 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x76, 0x31, + 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x58, 0x0a, 0x09, 0x50, 0x69, 0x6e, 0x67, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x23, 0x2e, 0x74, + 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x76, 0x31, + 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x24, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x74, 0x65, 0x73, 0x74, + 0x70, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x57, 0x0a, 0x08, 0x50, 0x69, 0x6e, + 0x67, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x22, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, + 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x4c, 0x69, + 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x74, 0x65, 0x73, 0x74, + 0x69, 0x6e, 0x67, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, + 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x30, 0x01, 0x12, 0x5f, 0x0a, 0x0a, 0x50, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, + 0x12, 0x24, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, + 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, + 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x53, + 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, + 0x01, 0x30, 0x01, 0x42, 0x0a, 0x5a, 0x08, 0x2e, 0x3b, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_test_proto_rawDescOnce sync.Once + file_test_proto_rawDescData = file_test_proto_rawDesc +) + +func file_test_proto_rawDescGZIP() []byte { + file_test_proto_rawDescOnce.Do(func() { + file_test_proto_rawDescData = protoimpl.X.CompressGZIP(file_test_proto_rawDescData) + }) + return file_test_proto_rawDescData +} + +var file_test_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_test_proto_goTypes = []interface{}{ + (*PingEmptyRequest)(nil), // 0: testing.testpb.v1.PingEmptyRequest + (*PingEmptyResponse)(nil), // 1: testing.testpb.v1.PingEmptyResponse + (*PingRequest)(nil), // 2: testing.testpb.v1.PingRequest + (*PingResponse)(nil), // 3: testing.testpb.v1.PingResponse + (*PingErrorRequest)(nil), // 4: testing.testpb.v1.PingErrorRequest + (*PingErrorResponse)(nil), // 5: testing.testpb.v1.PingErrorResponse + (*PingListRequest)(nil), // 6: testing.testpb.v1.PingListRequest + (*PingListResponse)(nil), // 7: testing.testpb.v1.PingListResponse + (*PingStreamRequest)(nil), // 8: testing.testpb.v1.PingStreamRequest + (*PingStreamResponse)(nil), // 9: testing.testpb.v1.PingStreamResponse +} +var file_test_proto_depIdxs = []int32{ + 0, // 0: testing.testpb.v1.TestService.PingEmpty:input_type -> testing.testpb.v1.PingEmptyRequest + 2, // 1: testing.testpb.v1.TestService.Ping:input_type -> testing.testpb.v1.PingRequest + 4, // 2: testing.testpb.v1.TestService.PingError:input_type -> testing.testpb.v1.PingErrorRequest + 6, // 3: testing.testpb.v1.TestService.PingList:input_type -> testing.testpb.v1.PingListRequest + 8, // 4: testing.testpb.v1.TestService.PingStream:input_type -> testing.testpb.v1.PingStreamRequest + 1, // 5: testing.testpb.v1.TestService.PingEmpty:output_type -> testing.testpb.v1.PingEmptyResponse + 3, // 6: testing.testpb.v1.TestService.Ping:output_type -> testing.testpb.v1.PingResponse + 5, // 7: testing.testpb.v1.TestService.PingError:output_type -> testing.testpb.v1.PingErrorResponse + 7, // 8: testing.testpb.v1.TestService.PingList:output_type -> testing.testpb.v1.PingListResponse + 9, // 9: testing.testpb.v1.TestService.PingStream:output_type -> testing.testpb.v1.PingStreamResponse + 5, // [5:10] is the sub-list for method output_type + 0, // [0:5] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_test_proto_init() } +func file_test_proto_init() { + if File_test_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_test_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PingEmptyRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PingEmptyResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PingRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PingResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PingErrorRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PingErrorResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PingListRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PingListResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PingStreamRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PingStreamResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_test_proto_rawDesc, + NumEnums: 0, + NumMessages: 10, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_test_proto_goTypes, + DependencyIndexes: file_test_proto_depIdxs, + MessageInfos: file_test_proto_msgTypes, + }.Build() + File_test_proto = out.File + file_test_proto_rawDesc = nil + file_test_proto_goTypes = nil + file_test_proto_depIdxs = nil +} diff --git a/grpctesting/testpb/test_grpc.pb.go b/testing/testpb/test_grpc.pb.go similarity index 73% rename from grpctesting/testpb/test_grpc.pb.go rename to testing/testpb/test_grpc.pb.go index 148471a4e..effb0e2a4 100644 --- a/grpctesting/testpb/test_grpc.pb.go +++ b/testing/testpb/test_grpc.pb.go @@ -18,10 +18,10 @@ const _ = grpc.SupportPackageIsVersion6 // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. type TestServiceClient interface { - PingEmpty(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*PingResponse, error) + PingEmpty(ctx context.Context, in *PingEmptyRequest, opts ...grpc.CallOption) (*PingEmptyResponse, error) Ping(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*PingResponse, error) - PingError(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*Empty, error) - PingList(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (TestService_PingListClient, error) + PingError(ctx context.Context, in *PingErrorRequest, opts ...grpc.CallOption) (*PingErrorResponse, error) + PingList(ctx context.Context, in *PingListRequest, opts ...grpc.CallOption) (TestService_PingListClient, error) PingStream(ctx context.Context, opts ...grpc.CallOption) (TestService_PingStreamClient, error) } @@ -33,9 +33,9 @@ func NewTestServiceClient(cc grpc.ClientConnInterface) TestServiceClient { return &testServiceClient{cc} } -func (c *testServiceClient) PingEmpty(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*PingResponse, error) { - out := new(PingResponse) - err := c.cc.Invoke(ctx, "/grpc_middleware.testpb.TestService/PingEmpty", in, out, opts...) +func (c *testServiceClient) PingEmpty(ctx context.Context, in *PingEmptyRequest, opts ...grpc.CallOption) (*PingEmptyResponse, error) { + out := new(PingEmptyResponse) + err := c.cc.Invoke(ctx, "/testing.testpb.v1.TestService/PingEmpty", in, out, opts...) if err != nil { return nil, err } @@ -44,24 +44,24 @@ func (c *testServiceClient) PingEmpty(ctx context.Context, in *Empty, opts ...gr func (c *testServiceClient) Ping(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*PingResponse, error) { out := new(PingResponse) - err := c.cc.Invoke(ctx, "/grpc_middleware.testpb.TestService/Ping", in, out, opts...) + err := c.cc.Invoke(ctx, "/testing.testpb.v1.TestService/Ping", in, out, opts...) if err != nil { return nil, err } return out, nil } -func (c *testServiceClient) PingError(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*Empty, error) { - out := new(Empty) - err := c.cc.Invoke(ctx, "/grpc_middleware.testpb.TestService/PingError", in, out, opts...) +func (c *testServiceClient) PingError(ctx context.Context, in *PingErrorRequest, opts ...grpc.CallOption) (*PingErrorResponse, error) { + out := new(PingErrorResponse) + err := c.cc.Invoke(ctx, "/testing.testpb.v1.TestService/PingError", in, out, opts...) if err != nil { return nil, err } return out, nil } -func (c *testServiceClient) PingList(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (TestService_PingListClient, error) { - stream, err := c.cc.NewStream(ctx, &_TestService_serviceDesc.Streams[0], "/grpc_middleware.testpb.TestService/PingList", opts...) +func (c *testServiceClient) PingList(ctx context.Context, in *PingListRequest, opts ...grpc.CallOption) (TestService_PingListClient, error) { + stream, err := c.cc.NewStream(ctx, &_TestService_serviceDesc.Streams[0], "/testing.testpb.v1.TestService/PingList", opts...) if err != nil { return nil, err } @@ -76,7 +76,7 @@ func (c *testServiceClient) PingList(ctx context.Context, in *PingRequest, opts } type TestService_PingListClient interface { - Recv() (*PingResponse, error) + Recv() (*PingListResponse, error) grpc.ClientStream } @@ -84,8 +84,8 @@ type testServicePingListClient struct { grpc.ClientStream } -func (x *testServicePingListClient) Recv() (*PingResponse, error) { - m := new(PingResponse) +func (x *testServicePingListClient) Recv() (*PingListResponse, error) { + m := new(PingListResponse) if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err } @@ -93,7 +93,7 @@ func (x *testServicePingListClient) Recv() (*PingResponse, error) { } func (c *testServiceClient) PingStream(ctx context.Context, opts ...grpc.CallOption) (TestService_PingStreamClient, error) { - stream, err := c.cc.NewStream(ctx, &_TestService_serviceDesc.Streams[1], "/grpc_middleware.testpb.TestService/PingStream", opts...) + stream, err := c.cc.NewStream(ctx, &_TestService_serviceDesc.Streams[1], "/testing.testpb.v1.TestService/PingStream", opts...) if err != nil { return nil, err } @@ -102,8 +102,8 @@ func (c *testServiceClient) PingStream(ctx context.Context, opts ...grpc.CallOpt } type TestService_PingStreamClient interface { - Send(*PingRequest) error - Recv() (*PingResponse, error) + Send(*PingStreamRequest) error + Recv() (*PingStreamResponse, error) grpc.ClientStream } @@ -111,12 +111,12 @@ type testServicePingStreamClient struct { grpc.ClientStream } -func (x *testServicePingStreamClient) Send(m *PingRequest) error { +func (x *testServicePingStreamClient) Send(m *PingStreamRequest) error { return x.ClientStream.SendMsg(m) } -func (x *testServicePingStreamClient) Recv() (*PingResponse, error) { - m := new(PingResponse) +func (x *testServicePingStreamClient) Recv() (*PingStreamResponse, error) { + m := new(PingStreamResponse) if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err } @@ -127,10 +127,10 @@ func (x *testServicePingStreamClient) Recv() (*PingResponse, error) { // All implementations must embed UnimplementedTestServiceServer // for forward compatibility type TestServiceServer interface { - PingEmpty(context.Context, *Empty) (*PingResponse, error) + PingEmpty(context.Context, *PingEmptyRequest) (*PingEmptyResponse, error) Ping(context.Context, *PingRequest) (*PingResponse, error) - PingError(context.Context, *PingRequest) (*Empty, error) - PingList(*PingRequest, TestService_PingListServer) error + PingError(context.Context, *PingErrorRequest) (*PingErrorResponse, error) + PingList(*PingListRequest, TestService_PingListServer) error PingStream(TestService_PingStreamServer) error mustEmbedUnimplementedTestServiceServer() } @@ -139,16 +139,16 @@ type TestServiceServer interface { type UnimplementedTestServiceServer struct { } -func (*UnimplementedTestServiceServer) PingEmpty(context.Context, *Empty) (*PingResponse, error) { +func (*UnimplementedTestServiceServer) PingEmpty(context.Context, *PingEmptyRequest) (*PingEmptyResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method PingEmpty not implemented") } func (*UnimplementedTestServiceServer) Ping(context.Context, *PingRequest) (*PingResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Ping not implemented") } -func (*UnimplementedTestServiceServer) PingError(context.Context, *PingRequest) (*Empty, error) { +func (*UnimplementedTestServiceServer) PingError(context.Context, *PingErrorRequest) (*PingErrorResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method PingError not implemented") } -func (*UnimplementedTestServiceServer) PingList(*PingRequest, TestService_PingListServer) error { +func (*UnimplementedTestServiceServer) PingList(*PingListRequest, TestService_PingListServer) error { return status.Errorf(codes.Unimplemented, "method PingList not implemented") } func (*UnimplementedTestServiceServer) PingStream(TestService_PingStreamServer) error { @@ -161,7 +161,7 @@ func RegisterTestServiceServer(s *grpc.Server, srv TestServiceServer) { } func _TestService_PingEmpty_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) + in := new(PingEmptyRequest) if err := dec(in); err != nil { return nil, err } @@ -170,10 +170,10 @@ func _TestService_PingEmpty_Handler(srv interface{}, ctx context.Context, dec fu } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/grpc_middleware.testpb.TestService/PingEmpty", + FullMethod: "/testing.testpb.v1.TestService/PingEmpty", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(TestServiceServer).PingEmpty(ctx, req.(*Empty)) + return srv.(TestServiceServer).PingEmpty(ctx, req.(*PingEmptyRequest)) } return interceptor(ctx, in, info, handler) } @@ -188,7 +188,7 @@ func _TestService_Ping_Handler(srv interface{}, ctx context.Context, dec func(in } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/grpc_middleware.testpb.TestService/Ping", + FullMethod: "/testing.testpb.v1.TestService/Ping", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(TestServiceServer).Ping(ctx, req.(*PingRequest)) @@ -197,7 +197,7 @@ func _TestService_Ping_Handler(srv interface{}, ctx context.Context, dec func(in } func _TestService_PingError_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(PingRequest) + in := new(PingErrorRequest) if err := dec(in); err != nil { return nil, err } @@ -206,16 +206,16 @@ func _TestService_PingError_Handler(srv interface{}, ctx context.Context, dec fu } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/grpc_middleware.testpb.TestService/PingError", + FullMethod: "/testing.testpb.v1.TestService/PingError", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(TestServiceServer).PingError(ctx, req.(*PingRequest)) + return srv.(TestServiceServer).PingError(ctx, req.(*PingErrorRequest)) } return interceptor(ctx, in, info, handler) } func _TestService_PingList_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(PingRequest) + m := new(PingListRequest) if err := stream.RecvMsg(m); err != nil { return err } @@ -223,7 +223,7 @@ func _TestService_PingList_Handler(srv interface{}, stream grpc.ServerStream) er } type TestService_PingListServer interface { - Send(*PingResponse) error + Send(*PingListResponse) error grpc.ServerStream } @@ -231,7 +231,7 @@ type testServicePingListServer struct { grpc.ServerStream } -func (x *testServicePingListServer) Send(m *PingResponse) error { +func (x *testServicePingListServer) Send(m *PingListResponse) error { return x.ServerStream.SendMsg(m) } @@ -240,8 +240,8 @@ func _TestService_PingStream_Handler(srv interface{}, stream grpc.ServerStream) } type TestService_PingStreamServer interface { - Send(*PingResponse) error - Recv() (*PingRequest, error) + Send(*PingStreamResponse) error + Recv() (*PingStreamRequest, error) grpc.ServerStream } @@ -249,12 +249,12 @@ type testServicePingStreamServer struct { grpc.ServerStream } -func (x *testServicePingStreamServer) Send(m *PingResponse) error { +func (x *testServicePingStreamServer) Send(m *PingStreamResponse) error { return x.ServerStream.SendMsg(m) } -func (x *testServicePingStreamServer) Recv() (*PingRequest, error) { - m := new(PingRequest) +func (x *testServicePingStreamServer) Recv() (*PingStreamRequest, error) { + m := new(PingStreamRequest) if err := x.ServerStream.RecvMsg(m); err != nil { return nil, err } @@ -262,7 +262,7 @@ func (x *testServicePingStreamServer) Recv() (*PingRequest, error) { } var _TestService_serviceDesc = grpc.ServiceDesc{ - ServiceName: "grpc_middleware.testpb.TestService", + ServiceName: "testing.testpb.v1.TestService", HandlerType: (*TestServiceServer)(nil), Methods: []grpc.MethodDesc{ { diff --git a/testing/testpb/v1/test.proto b/testing/testpb/v1/test.proto new file mode 100644 index 000000000..64bc4bd83 --- /dev/null +++ b/testing/testpb/v1/test.proto @@ -0,0 +1,68 @@ +syntax = "proto3"; + +package testing.testpb.v1; + +option go_package = ".;testpb"; + +message PingEmptyRequest { +} + +message PingEmptyResponse { +} + +message PingRequest { + string value = 1; + int32 sleep_time_ms = 2; + uint32 error_code_returned = 3; +} + +message PingResponse { + string value = 1; + int32 counter = 2; +} + +message PingErrorRequest { + string value = 1; + int32 sleep_time_ms = 2; + uint32 error_code_returned = 3; +} + +message PingErrorResponse { + string value = 1; + int32 counter = 2; +} + +message PingListRequest { + string value = 1; + int32 sleep_time_ms = 2; + uint32 error_code_returned = 3; +} + +message PingListResponse { + string value = 1; + int32 counter = 2; +} + +message PingStreamRequest { + string value = 1; + int32 sleep_time_ms = 2; + uint32 error_code_returned = 3; +} + +message PingStreamResponse { + string value = 1; + int32 counter = 2; +} + +service TestService { + rpc PingEmpty(PingEmptyRequest) returns (PingEmptyResponse) {} + + rpc Ping(PingRequest) returns (PingResponse) {} + + rpc PingError(PingErrorRequest) returns (PingErrorResponse) {} + + rpc PingList(PingListRequest) returns (stream PingListResponse) {} + + rpc PingStream(stream PingStreamRequest) returns (stream PingStreamResponse) {} + +} From 3ff779b52992f59c378833b2dfe57296944f5b99 Mon Sep 17 00:00:00 2001 From: Yash Sharma Date: Thu, 28 Jan 2021 16:45:00 +0530 Subject: [PATCH 16/27] Added a timer interface (#387) Signed-off-by: Yash Sharma --- interceptors/reporter.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/interceptors/reporter.go b/interceptors/reporter.go index 210134e83..dd1bdf332 100644 --- a/interceptors/reporter.go +++ b/interceptors/reporter.go @@ -14,6 +14,23 @@ import ( type GRPCType string +// Timer is a helper interface to time functions. +// Useful for interceptors to record the total +// time elapsed since completion of a call. +type Timer interface { + ObserveDuration() time.Duration +} + +// zeroTimer. +type zeroTimer struct { +} + +func (zeroTimer) ObserveDuration() time.Duration { + return 0 +} + +var EmptyTimer = &zeroTimer{} + const ( Unary GRPCType = "unary" ClientStream GRPCType = "client_stream" From 20b28252aa21191c1efc83a1e4b98bf40364f567 Mon Sep 17 00:00:00 2001 From: Dario Maiocchi Date: Fri, 29 Jan 2021 13:09:09 +0100 Subject: [PATCH 17/27] [Rate-limit provider]: Add token bucket implementation of rate-limiter (#386) * Add tocken bucket implementation of rate-limiter Use tockenbucket provider Signed-off-by: dmaiocchi * Update providers/tokenbucket/limiter.go Co-authored-by: Yash Sharma * Update providers/tokenbucket/examples_test.go Co-authored-by: Yash Sharma * Update providers/tokenbucket/limiter.go Co-authored-by: Yash Sharma * Update providers/tokenbucket/limiter.go Co-authored-by: Yash Sharma * Update providers/tokenbucket/doc.go Co-authored-by: Yash Sharma * Update providers/tokenbucket/limiter.go Co-authored-by: Yash Sharma * Update providers/tokenbucket/examples_test.go Co-authored-by: Yash Sharma * Fix word and minor changes Signed-off-by: dmaiocchi Co-authored-by: Yash Sharma --- go.sum | 1 - providers/tokenbucket/doc.go | 6 ++ providers/tokenbucket/examples_test.go | 30 +++++++ providers/tokenbucket/go.mod | 9 ++ providers/tokenbucket/go.sum | 112 +++++++++++++++++++++++++ providers/tokenbucket/limiter.go | 29 +++++++ 6 files changed, 186 insertions(+), 1 deletion(-) create mode 100644 providers/tokenbucket/doc.go create mode 100644 providers/tokenbucket/examples_test.go create mode 100644 providers/tokenbucket/go.mod create mode 100644 providers/tokenbucket/go.sum create mode 100644 providers/tokenbucket/limiter.go diff --git a/go.sum b/go.sum index e1d0ddb5a..42190ddfa 100644 --- a/go.sum +++ b/go.sum @@ -30,7 +30,6 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 h1:FlFbCRLd5Jr4iYXZufAvgWN6Ao0JrI5chLINnUXDDr0= github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= diff --git a/providers/tokenbucket/doc.go b/providers/tokenbucket/doc.go new file mode 100644 index 000000000..a04f8691c --- /dev/null +++ b/providers/tokenbucket/doc.go @@ -0,0 +1,6 @@ +package tokenbucket + +/* +`tokenbucket` provides a small adapter required to use juju TockenBucket rate limiter for gRPC middlewares. + Please see examples for examples of use. +*/ diff --git a/providers/tokenbucket/examples_test.go b/providers/tokenbucket/examples_test.go new file mode 100644 index 000000000..eb5e4ffeb --- /dev/null +++ b/providers/tokenbucket/examples_test.go @@ -0,0 +1,30 @@ +package tokenbucket + +import ( + grpc_ratelimit "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/ratelimit" + "github.com/juju/ratelimit" + "google.golang.org/grpc" +) + +// Hard-coded for simplicity sake, but make this configurable in your application. +const ( + // Add 5 token per seconds. + rate = 5 + // Capacity of bucket. allow only 40 requests. + tokenCapacity = 40 +) + +// Simple example of server initialization code. +func Example() { + limiter := TokenBucketInterceptor{} + limiter.tokenBucket = ratelimit.NewBucket(rate, int64(tokenCapacity)) + + _ = grpc.NewServer( + grpc.ChainUnaryInterceptor( + grpc_ratelimit.UnaryServerInterceptor(&limiter), + ), + grpc.ChainStreamInterceptor( + grpc_ratelimit.StreamServerInterceptor(&limiter), + ), + ) +} diff --git a/providers/tokenbucket/go.mod b/providers/tokenbucket/go.mod new file mode 100644 index 000000000..ec5c3d18b --- /dev/null +++ b/providers/tokenbucket/go.mod @@ -0,0 +1,9 @@ +module github.com/grpc-ecosystem/go-grpc-middleware/providers/tockenbucket/v2 + +go 1.15 + +require ( + github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20210122204322-468f61573a34 + github.com/juju/ratelimit v1.0.1 + google.golang.org/grpc v1.35.0 +) diff --git a/providers/tokenbucket/go.sum b/providers/tokenbucket/go.sum new file mode 100644 index 000000000..9f8a91f8e --- /dev/null +++ b/providers/tokenbucket/go.sum @@ -0,0 +1,112 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20210122204322-468f61573a34 h1:JCFKONF4wZWg7iO0mjclgZQqGH4H73/R9nUpcREPBhs= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20210122204322-468f61573a34/go.mod h1:fG+XdHpfvMfdBQ9GTIRX0nXjb+VHaMWV5o9OCgw6Qi8= +github.com/juju/ratelimit v1.0.1 h1:+7AIFJVQ0EQgq/K9+0Krm7m530Du7tIz0METWzN0RgY= +github.com/juju/ratelimit v1.0.1/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +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-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +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/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200624020401-64a14ca9d1ad h1:uAwc13+y0Y8QZLTYhLCu6lHhnG99ecQU5FYTj8zxAng= +google.golang.org/genproto v0.0.0-20200624020401-64a14ca9d1ad/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.30.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.35.0 h1:TwIQcH3es+MojMVojxxfQ3l3OF2KzlRxML2xZq0kRo8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc/examples v0.0.0-20200723182653-9106c3fff523/go.mod h1:5j1uub0jRGhRiSghIlrThmBUgcgLXOVJQ/l1getT4uo= +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= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/providers/tokenbucket/limiter.go b/providers/tokenbucket/limiter.go new file mode 100644 index 000000000..7a464e787 --- /dev/null +++ b/providers/tokenbucket/limiter.go @@ -0,0 +1,29 @@ +package tokenbucket + +// Implement Limiter interface. + +import ( + "context" + "fmt" + + "github.com/juju/ratelimit" +) + +// TokenBucketInterceptor implement token bucket algorithm. +type TokenBucketInterceptor struct { + tokenBucket *ratelimit.Bucket +} + +// Limit implements Limiter interface. +func (r *TokenBucketInterceptor) Limit(_ context.Context) error { + // Take one token per request. This call doesn't block. + tokenRes := r.tokenBucket.TakeAvailable(1) + + // When rate limit reached, return specific error for the clients. + if tokenRes == 0 { + return fmt.Errorf("APP-XXX: reached Rate-Limiting %d", r.tokenBucket.Available()) + } + + // Rate limit isn't reached. + return nil +} From 215af813c95e0f11477e603edf25f6da4f02d413 Mon Sep 17 00:00:00 2001 From: Yash Sharma Date: Sat, 30 Jan 2021 02:33:47 +0530 Subject: [PATCH 18/27] Add OpenMetrics(Prometheus) in the provider module (#379) * Added a prometheus provider Signed-off-by: Yash Sharma * Moved the constants to interceptor package Signed-off-by: Yash Sharma * renamed prometheus to open metrics Signed-off-by: Yash Sharma * changed the interface of StartTimeCall to previous interface, and use reporter to utilise the timer call function of open metrics Signed-off-by: Yash Sharma * Added options for open metrics Signed-off-by: Yash Sharma * changed prom client to openmetrics for nomenclature Signed-off-by: Yash Sharma * modified go sum Signed-off-by: Yash Sharma * changed register to mustregister, so that code panics if registry is incorrect, also added some nits Signed-off-by: Yash Sharma * Added tests for openmetrics provider Signed-off-by: Yash Sharma * Added buf suggested proto structuring of proto files for testing in openmetrics Signed-off-by: Yash Sharma * nitpickings due to buf suggesting changes Signed-off-by: Yash Sharma * modified openmetrics gomod Signed-off-by: Yash Sharma * Add custom registry support for Prometheus Signed-off-by: Yash Sharma * linting changes Signed-off-by: Yash Sharma * added a function for custom registered metrics object Signed-off-by: Yash Sharma * Added a function to remove the global metrics object, and return a server/client metrics object with some default metrics initialisation Signed-off-by: Yash Sharma --- interceptors/reporter.go | 1 - providers/openmetrics/client_interceptor.go | 35 + providers/openmetrics/client_metrics.go | 187 +++++ providers/openmetrics/client_test.go | 148 ++++ providers/openmetrics/constants.go | 20 + providers/openmetrics/go.mod | 13 + providers/openmetrics/go.sum | 444 +++++++++++ providers/openmetrics/options.go | 63 ++ providers/openmetrics/reporter.go | 114 +++ providers/openmetrics/server_interceptor.go | 35 + providers/openmetrics/server_metrics.go | 145 ++++ providers/openmetrics/server_test.go | 350 +++++++++ .../openmetrics/testproto/v1/run_protoc.sh | 1 + providers/openmetrics/testproto/v1/test.pb.go | 697 ++++++++++++++++++ providers/openmetrics/testproto/v1/test.proto | 54 ++ .../openmetrics/testproto/v1/test_grpc.pb.go | 232 ++++++ 16 files changed, 2538 insertions(+), 1 deletion(-) create mode 100644 providers/openmetrics/client_interceptor.go create mode 100644 providers/openmetrics/client_metrics.go create mode 100644 providers/openmetrics/client_test.go create mode 100644 providers/openmetrics/constants.go create mode 100644 providers/openmetrics/go.mod create mode 100644 providers/openmetrics/go.sum create mode 100644 providers/openmetrics/options.go create mode 100644 providers/openmetrics/reporter.go create mode 100644 providers/openmetrics/server_interceptor.go create mode 100644 providers/openmetrics/server_metrics.go create mode 100644 providers/openmetrics/server_test.go create mode 100755 providers/openmetrics/testproto/v1/run_protoc.sh create mode 100644 providers/openmetrics/testproto/v1/test.pb.go create mode 100644 providers/openmetrics/testproto/v1/test.proto create mode 100644 providers/openmetrics/testproto/v1/test_grpc.pb.go diff --git a/interceptors/reporter.go b/interceptors/reporter.go index dd1bdf332..1f5391de2 100644 --- a/interceptors/reporter.go +++ b/interceptors/reporter.go @@ -69,7 +69,6 @@ type ServerReportable interface { type Reporter interface { PostCall(err error, rpcDuration time.Duration) - PostMsgSend(reqProto interface{}, err error, sendDuration time.Duration) PostMsgReceive(replyProto interface{}, err error, recvDuration time.Duration) } diff --git a/providers/openmetrics/client_interceptor.go b/providers/openmetrics/client_interceptor.go new file mode 100644 index 000000000..a16126e8b --- /dev/null +++ b/providers/openmetrics/client_interceptor.go @@ -0,0 +1,35 @@ +package metrics + +import ( + openmetrics "github.com/prometheus/client_golang/prometheus" + "google.golang.org/grpc" + + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors" +) + +// RegisterClientMetrics returns a custom ClientMetrics object registered +// with the user's registry, and registers some common metrics associated +// with every instance. +func RegisterClientMetrics(registry openmetrics.Registerer) *ClientMetrics { + customClientMetrics := NewClientMetrics(registry) + customClientMetrics.MustRegister(customClientMetrics.clientStartedCounter) + customClientMetrics.MustRegister(customClientMetrics.clientHandledCounter) + customClientMetrics.MustRegister(customClientMetrics.clientStreamMsgReceived) + customClientMetrics.MustRegister(customClientMetrics.clientStreamMsgSent) + + return customClientMetrics +} + +// UnaryClientInterceptor is a gRPC client-side interceptor that provides Prometheus monitoring for Unary RPCs. +func UnaryClientInterceptor(clientRegister openmetrics.Registerer) grpc.UnaryClientInterceptor { + return interceptors.UnaryClientInterceptor(&reportable{ + registry: clientRegister, + }) +} + +// StreamClientInterceptor is a gRPC client-side interceptor that provides Prometheus monitoring for Streaming RPCs. +func StreamClientInterceptor(clientRegister openmetrics.Registerer) grpc.StreamClientInterceptor { + return interceptors.StreamClientInterceptor(&reportable{ + registry: clientRegister, + }) +} diff --git a/providers/openmetrics/client_metrics.go b/providers/openmetrics/client_metrics.go new file mode 100644 index 000000000..0a0477aea --- /dev/null +++ b/providers/openmetrics/client_metrics.go @@ -0,0 +1,187 @@ +package metrics + +import ( + "github.com/prometheus/client_golang/prometheus" + openmetrics "github.com/prometheus/client_golang/prometheus" +) + +// ClientMetrics represents a collection of metrics to be registered on a +// Prometheus metrics registry for a gRPC client. +type ClientMetrics struct { + clientRegister openmetrics.Registerer + + clientStartedCounter *openmetrics.CounterVec + clientHandledCounter *openmetrics.CounterVec + clientStreamMsgReceived *openmetrics.CounterVec + clientStreamMsgSent *openmetrics.CounterVec + + clientHandledHistogramEnabled bool + clientHandledHistogramOpts openmetrics.HistogramOpts + clientHandledHistogram *openmetrics.HistogramVec + + clientStreamRecvHistogramEnabled bool + clientStreamRecvHistogramOpts openmetrics.HistogramOpts + clientStreamRecvHistogram *openmetrics.HistogramVec + + clientStreamSendHistogramEnabled bool + clientStreamSendHistogramOpts openmetrics.HistogramOpts + clientStreamSendHistogram *openmetrics.HistogramVec +} + +// NewClientMetrics returns a ClientMetrics object. Use a new instance of +// ClientMetrics when not using the default Prometheus metrics registry, for +// example when wanting to control which metrics are added to a registry as +// opposed to automatically adding metrics via init functions. +func NewClientMetrics(clientRegistry prometheus.Registerer, counterOpts ...CounterOption) *ClientMetrics { + opts := counterOptions(counterOpts) + return &ClientMetrics{ + clientRegister: clientRegistry, + clientStartedCounter: openmetrics.NewCounterVec( + opts.apply(openmetrics.CounterOpts{ + Name: "grpc_client_started_total", + Help: "Total number of RPCs started on the client.", + }), []string{"grpc_type", "grpc_service", "grpc_method"}), + + clientHandledCounter: openmetrics.NewCounterVec( + opts.apply(openmetrics.CounterOpts{ + Name: "grpc_client_handled_total", + Help: "Total number of RPCs completed by the client, regardless of success or failure.", + }), []string{"grpc_type", "grpc_service", "grpc_method", "grpc_code"}), + + clientStreamMsgReceived: openmetrics.NewCounterVec( + opts.apply(openmetrics.CounterOpts{ + Name: "grpc_client_msg_received_total", + Help: "Total number of RPC stream messages received by the client.", + }), []string{"grpc_type", "grpc_service", "grpc_method"}), + + clientStreamMsgSent: openmetrics.NewCounterVec( + opts.apply(openmetrics.CounterOpts{ + Name: "grpc_client_msg_sent_total", + Help: "Total number of gRPC stream messages sent by the client.", + }), []string{"grpc_type", "grpc_service", "grpc_method"}), + + clientHandledHistogramEnabled: false, + clientHandledHistogramOpts: openmetrics.HistogramOpts{ + Name: "grpc_client_handling_seconds", + Help: "Histogram of response latency (seconds) of the gRPC until it is finished by the application.", + Buckets: openmetrics.DefBuckets, + }, + clientHandledHistogram: nil, + clientStreamRecvHistogramEnabled: false, + clientStreamRecvHistogramOpts: openmetrics.HistogramOpts{ + Name: "grpc_client_msg_recv_handling_seconds", + Help: "Histogram of response latency (seconds) of the gRPC single message receive.", + Buckets: openmetrics.DefBuckets, + }, + clientStreamRecvHistogram: nil, + clientStreamSendHistogramEnabled: false, + clientStreamSendHistogramOpts: openmetrics.HistogramOpts{ + Name: "grpc_client_msg_send_handling_seconds", + Help: "Histogram of response latency (seconds) of the gRPC single message send.", + Buckets: openmetrics.DefBuckets, + }, + clientStreamSendHistogram: nil, + } +} + +// Register registers the provided Collector with the custom register. +// returns error much like DefaultRegisterer of Prometheus. +func (m *ClientMetrics) Register(c openmetrics.Collector) error { + return m.clientRegister.Register(c) +} + +// MustRegister registers the provided Collectors with the custom Registerer +// and panics if any error occurs much like DefaultRegisterer of Prometheus. +func (m *ClientMetrics) MustRegister(c openmetrics.Collector) { + m.clientRegister.MustRegister(c) +} + +// Describe sends the super-set of all possible descriptors of metrics +// collected by this Collector to the provided channel and returns once +// the last descriptor has been sent. +func (m *ClientMetrics) Describe(ch chan<- *openmetrics.Desc) { + m.clientStartedCounter.Describe(ch) + m.clientHandledCounter.Describe(ch) + m.clientStreamMsgReceived.Describe(ch) + m.clientStreamMsgSent.Describe(ch) + if m.clientHandledHistogramEnabled { + m.clientHandledHistogram.Describe(ch) + } + if m.clientStreamRecvHistogramEnabled { + m.clientStreamRecvHistogram.Describe(ch) + } + if m.clientStreamSendHistogramEnabled { + m.clientStreamSendHistogram.Describe(ch) + } +} + +// Collect is called by the Prometheus registry when collecting +// metrics. The implementation sends each collected metric via the +// provided channel and returns once the last metric has been sent. +func (m *ClientMetrics) Collect(ch chan<- openmetrics.Metric) { + m.clientStartedCounter.Collect(ch) + m.clientHandledCounter.Collect(ch) + m.clientStreamMsgReceived.Collect(ch) + m.clientStreamMsgSent.Collect(ch) + if m.clientHandledHistogramEnabled { + m.clientHandledHistogram.Collect(ch) + } + if m.clientStreamRecvHistogramEnabled { + m.clientStreamRecvHistogram.Collect(ch) + } + if m.clientStreamSendHistogramEnabled { + m.clientStreamSendHistogram.Collect(ch) + } +} + +// EnableClientHandlingTimeHistogram turns on recording of handling time of RPCs. +// Histogram metrics can be very expensive for Prometheus to retain and query. +func (m *ClientMetrics) EnableClientHandlingTimeHistogram(opts ...HistogramOption) error { + for _, o := range opts { + o(&m.clientHandledHistogramOpts) + } + if !m.clientHandledHistogramEnabled { + m.clientHandledHistogram = openmetrics.NewHistogramVec( + m.clientHandledHistogramOpts, + []string{"grpc_type", "grpc_service", "grpc_method"}, + ) + } + m.clientHandledHistogramEnabled = true + return m.clientRegister.Register(m.clientHandledHistogram) +} + +// EnableClientStreamReceiveTimeHistogram turns on recording of single message receive time of streaming RPCs. +// Histogram metrics can be very expensive for Prometheus to retain and query. +func (m *ClientMetrics) EnableClientStreamReceiveTimeHistogram(opts ...HistogramOption) error { + for _, o := range opts { + o(&m.clientStreamRecvHistogramOpts) + } + + if !m.clientStreamRecvHistogramEnabled { + m.clientStreamRecvHistogram = openmetrics.NewHistogramVec( + m.clientStreamRecvHistogramOpts, + []string{"grpc_type", "grpc_service", "grpc_method"}, + ) + } + + m.clientStreamRecvHistogramEnabled = true + return m.clientRegister.Register(m.clientStreamRecvHistogram) +} + +// EnableClientStreamSendTimeHistogram turns on recording of single message send time of streaming RPCs. +// Histogram metrics can be very expensive for Prometheus to retain and query. +func (m *ClientMetrics) EnableClientStreamSendTimeHistogram(opts ...HistogramOption) error { + for _, o := range opts { + o(&m.clientStreamSendHistogramOpts) + } + + if !m.clientStreamSendHistogramEnabled { + m.clientStreamSendHistogram = openmetrics.NewHistogramVec( + m.clientStreamSendHistogramOpts, + []string{"grpc_type", "grpc_service", "grpc_method"}, + ) + } + + m.clientStreamSendHistogramEnabled = true + return m.clientRegister.Register(m.clientStreamSendHistogram) +} diff --git a/providers/openmetrics/client_test.go b/providers/openmetrics/client_test.go new file mode 100644 index 000000000..c6b0c9602 --- /dev/null +++ b/providers/openmetrics/client_test.go @@ -0,0 +1,148 @@ +package metrics + +import ( + "context" + "io" + "net" + "testing" + "time" + + pb_testproto "github.com/grpc-ecosystem/go-grpc-middleware/providers/openmetrics/v2/testproto/v1" + "github.com/prometheus/client_golang/prometheus" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +var ( + DefaultClientMetrics *ClientMetrics = NewClientMetrics(prometheus.DefaultRegisterer) +) + +func TestClientInterceptorSuite(t *testing.T) { + suite.Run(t, &ClientInterceptorTestSuite{}) +} + +type ClientInterceptorTestSuite struct { + suite.Suite + + serverListener net.Listener + server *grpc.Server + clientConn *grpc.ClientConn + testClient pb_testproto.TestServiceClient + ctx context.Context + cancel context.CancelFunc +} + +func (s *ClientInterceptorTestSuite) SetupSuite() { + var err error + + DefaultClientMetrics.EnableClientHandlingTimeHistogram() + + s.serverListener, err = net.Listen("tcp", "127.0.0.1:0") + require.NoError(s.T(), err, "must be able to allocate a port for serverListener") + + // This is the point where we hook up the interceptor + s.server = grpc.NewServer() + pb_testproto.RegisterTestServiceServer(s.server, &testService{t: s.T()}) + + go func() { + s.server.Serve(s.serverListener) + }() + + s.clientConn, err = grpc.Dial( + s.serverListener.Addr().String(), + grpc.WithInsecure(), + grpc.WithBlock(), + grpc.WithUnaryInterceptor(UnaryClientInterceptor(prometheus.DefaultRegisterer)), + grpc.WithStreamInterceptor(StreamClientInterceptor(prometheus.DefaultRegisterer)), + grpc.WithTimeout(2*time.Second)) + require.NoError(s.T(), err, "must not error on client Dial") + s.testClient = pb_testproto.NewTestServiceClient(s.clientConn) +} + +func (s *ClientInterceptorTestSuite) SetupTest() { + // Make all RPC calls last at most 2 sec, meaning all async issues or deadlock will not kill tests. + s.ctx, s.cancel = context.WithTimeout(context.TODO(), 2*time.Second) + + // Make sure every test starts with same fresh, intialized metric state. + DefaultClientMetrics.clientStartedCounter.Reset() + DefaultClientMetrics.clientHandledCounter.Reset() + DefaultClientMetrics.clientHandledHistogram.Reset() + DefaultClientMetrics.clientStreamMsgReceived.Reset() + DefaultClientMetrics.clientStreamMsgSent.Reset() +} + +func (s *ClientInterceptorTestSuite) TearDownSuite() { + if s.serverListener != nil { + s.server.Stop() + s.T().Logf("stopped grpc.Server at: %v", s.serverListener.Addr().String()) + s.serverListener.Close() + + } + if s.clientConn != nil { + s.clientConn.Close() + } +} + +func (s *ClientInterceptorTestSuite) TearDownTest() { + s.cancel() +} + +func (s *ClientInterceptorTestSuite) TestUnaryIncrementsMetrics() { + _, err := s.testClient.PingEmpty(s.ctx, &pb_testproto.PingEmptyRequest{}) // should return with code=OK + require.NoError(s.T(), err) + requireValue(s.T(), 1, DefaultClientMetrics.clientStartedCounter.WithLabelValues("unary", "mwitkow.testproto.TestService", "PingEmpty")) + requireValue(s.T(), 1, DefaultClientMetrics.clientHandledCounter.WithLabelValues("unary", "mwitkow.testproto.TestService", "PingEmpty", "OK")) + requireValueHistCount(s.T(), 1, DefaultClientMetrics.clientHandledHistogram.WithLabelValues("unary", "mwitkow.testproto.TestService", "PingEmpty")) + + _, err = s.testClient.PingError(s.ctx, &pb_testproto.PingErrorRequest{ErrorCodeReturned: uint32(codes.FailedPrecondition)}) // should return with code=FailedPrecondition + require.Error(s.T(), err) + requireValue(s.T(), 1, DefaultClientMetrics.clientStartedCounter.WithLabelValues("unary", "mwitkow.testproto.TestService", "PingError")) + requireValue(s.T(), 1, DefaultClientMetrics.clientHandledCounter.WithLabelValues("unary", "mwitkow.testproto.TestService", "PingError", "FailedPrecondition")) + requireValueHistCount(s.T(), 1, DefaultClientMetrics.clientHandledHistogram.WithLabelValues("unary", "mwitkow.testproto.TestService", "PingError")) +} + +func (s *ClientInterceptorTestSuite) TestStartedStreamingIncrementsStarted() { + _, err := s.testClient.PingList(s.ctx, &pb_testproto.PingListRequest{}) + require.NoError(s.T(), err) + requireValue(s.T(), 1, DefaultClientMetrics.clientStartedCounter.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList")) + + _, err = s.testClient.PingList(s.ctx, &pb_testproto.PingListRequest{ErrorCodeReturned: uint32(codes.FailedPrecondition)}) // should return with code=FailedPrecondition + require.NoError(s.T(), err, "PingList must not fail immediately") + requireValue(s.T(), 2, DefaultClientMetrics.clientStartedCounter.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList")) +} + +func (s *ClientInterceptorTestSuite) TestStreamingIncrementsMetrics() { + ss, _ := s.testClient.PingList(s.ctx, &pb_testproto.PingListRequest{}) // should return with code=OK + // Do a read, just for kicks. + count := 0 + for { + _, err := ss.Recv() + if err == io.EOF { + break + } + require.NoError(s.T(), err, "reading pingList shouldn't fail") + count++ + } + require.EqualValues(s.T(), countListResponses, count, "Number of received msg on the wire must match") + + requireValue(s.T(), 1, DefaultClientMetrics.clientStartedCounter.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList")) + requireValue(s.T(), 1, DefaultClientMetrics.clientHandledCounter.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList", "OK")) + requireValue(s.T(), countListResponses, DefaultClientMetrics.clientStreamMsgReceived.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList")) + requireValue(s.T(), 1, DefaultClientMetrics.clientStreamMsgSent.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList")) + requireValueHistCount(s.T(), 1, DefaultClientMetrics.clientHandledHistogram.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList")) + + ss, err := s.testClient.PingList(s.ctx, &pb_testproto.PingListRequest{ErrorCodeReturned: uint32(codes.FailedPrecondition)}) // should return with code=FailedPrecondition + require.NoError(s.T(), err, "PingList must not fail immediately") + + // Do a read, just to progate errors. + _, err = ss.Recv() + st, _ := status.FromError(err) + require.Equal(s.T(), codes.FailedPrecondition, st.Code(), "Recv must return FailedPrecondition, otherwise the test is wrong") + + requireValue(s.T(), 2, DefaultClientMetrics.clientStartedCounter.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList")) + requireValue(s.T(), 1, DefaultClientMetrics.clientHandledCounter.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList", "FailedPrecondition")) + requireValueHistCount(s.T(), 2, DefaultClientMetrics.clientHandledHistogram.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList")) +} diff --git a/providers/openmetrics/constants.go b/providers/openmetrics/constants.go new file mode 100644 index 000000000..c05d05d6f --- /dev/null +++ b/providers/openmetrics/constants.go @@ -0,0 +1,20 @@ +package metrics + +type grpcType string + +// grpcType describes all types of grpc connection. +const ( + Unary grpcType = "unary" + ClientStream grpcType = "client_stream" + ServerStream grpcType = "server_stream" + BidiStream grpcType = "bidi_stream" +) + +// Kind describes whether interceptor is a client or server type. +type Kind string + +// Enum for Client and Server Kind. +const ( + KindClient Kind = "client" + KindServer Kind = "server" +) diff --git a/providers/openmetrics/go.mod b/providers/openmetrics/go.mod new file mode 100644 index 000000000..81d646e5d --- /dev/null +++ b/providers/openmetrics/go.mod @@ -0,0 +1,13 @@ +module github.com/grpc-ecosystem/go-grpc-middleware/providers/openmetrics/v2 + +go 1.15 + +require ( + github.com/golang/protobuf v1.4.3 + github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20210128111500-3ff779b52992 + github.com/prometheus/client_golang v1.9.0 + github.com/prometheus/client_model v0.2.0 + github.com/stretchr/testify v1.7.0 + google.golang.org/grpc v1.35.0 + google.golang.org/protobuf v1.25.0 +) diff --git a/providers/openmetrics/go.sum b/providers/openmetrics/go.sum new file mode 100644 index 000000000..b557e49e6 --- /dev/null +++ b/providers/openmetrics/go.sum @@ -0,0 +1,444 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 h1:z53tR0945TRRQO/fLEVPI6SMv7ZflF0TEaTAoU7tOzg= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20210128111500-3ff779b52992 h1:zQBrssA5h0QjXbr/d560qCC1L48fFjCxx6Ld1r4d+J4= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20210128111500-3ff779b52992/go.mod h1:fG+XdHpfvMfdBQ9GTIRX0nXjb+VHaMWV5o9OCgw6Qi8= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.9.0 h1:Rrch9mh17XcxvEu9D9DEpb4isxjGBtcevQjKvxPRQIU= +github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.15.0 h1:4fgOnadei3EZvgRwxJ7RMpG1k1pOZth5Pc13tyspaKM= +github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4= +github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/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= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e h1:AyodaIpKjppX+cBfTASF2E1US3H2JFBj920Ot3rtDjs= +golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200624020401-64a14ca9d1ad h1:uAwc13+y0Y8QZLTYhLCu6lHhnG99ecQU5FYTj8zxAng= +google.golang.org/genproto v0.0.0-20200624020401-64a14ca9d1ad/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.30.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.35.0 h1:TwIQcH3es+MojMVojxxfQ3l3OF2KzlRxML2xZq0kRo8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc/examples v0.0.0-20200723182653-9106c3fff523/go.mod h1:5j1uub0jRGhRiSghIlrThmBUgcgLXOVJQ/l1getT4uo= +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= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/providers/openmetrics/options.go b/providers/openmetrics/options.go new file mode 100644 index 000000000..3efe38ad6 --- /dev/null +++ b/providers/openmetrics/options.go @@ -0,0 +1,63 @@ +package metrics + +import ( + openmetrics "github.com/prometheus/client_golang/prometheus" + "google.golang.org/grpc" + "google.golang.org/grpc/status" +) + +// FromError returns a grpc status if error code is a valid grpc status. +func FromError(err error) (s *status.Status, ok bool) { + return status.FromError(err) + + // TODO: @yashrsharma44 - discuss if we require more error handling from the previous package +} + +// A CounterOption lets you add options to Counter metrics using With* funcs. +type CounterOption func(*openmetrics.CounterOpts) + +type counterOptions []CounterOption + +func (co counterOptions) apply(o openmetrics.CounterOpts) openmetrics.CounterOpts { + for _, f := range co { + f(&o) + } + return o +} + +// WithConstLabels allows you to add ConstLabels to Counter metrics. +func WithConstLabels(labels openmetrics.Labels) CounterOption { + return func(o *openmetrics.CounterOpts) { + o.ConstLabels = labels + } +} + +// A HistogramOption lets you add options to Histogram metrics using With* +// funcs. +type HistogramOption func(*openmetrics.HistogramOpts) + +// WithHistogramBuckets allows you to specify custom bucket ranges for histograms if EnableHandlingTimeHistogram is on. +func WithHistogramBuckets(buckets []float64) HistogramOption { + return func(o *openmetrics.HistogramOpts) { o.Buckets = buckets } +} + +// WithHistogramConstLabels allows you to add custom ConstLabels to +// histograms metrics. +func WithHistogramConstLabels(labels openmetrics.Labels) HistogramOption { + return func(o *openmetrics.HistogramOpts) { + o.ConstLabels = labels + } +} + +func typeFromMethodInfo(mInfo *grpc.MethodInfo) grpcType { + if !mInfo.IsClientStream && !mInfo.IsServerStream { + return Unary + } + if mInfo.IsClientStream && !mInfo.IsServerStream { + return ClientStream + } + if !mInfo.IsClientStream && mInfo.IsServerStream { + return ServerStream + } + return BidiStream +} diff --git a/providers/openmetrics/reporter.go b/providers/openmetrics/reporter.go new file mode 100644 index 000000000..b526d8c38 --- /dev/null +++ b/providers/openmetrics/reporter.go @@ -0,0 +1,114 @@ +package metrics + +import ( + "context" + "time" + + openmetrics "github.com/prometheus/client_golang/prometheus" + + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors" +) + +type reporter struct { + clientMetrics *ClientMetrics + serverMetrics *ServerMetrics + typ interceptors.GRPCType + service, method string + startTime time.Time + kind Kind + sendTimer, receiveTimer interceptors.Timer +} + +func (r *reporter) PostCall(err error, duration time.Duration) { + // get status code from error + status, _ := FromError(err) + code := status.Code() + + // perform handling of metrics from code + switch r.kind { + case KindServer: + r.serverMetrics.serverHandledCounter.WithLabelValues(string(r.typ), r.service, r.method, code.String()).Inc() + if r.serverMetrics.serverHandledHistogramEnabled { + r.serverMetrics.serverHandledHistogram.WithLabelValues(string(r.typ), r.service, r.method).Observe(time.Since(r.startTime).Seconds()) + } + + case KindClient: + r.clientMetrics.clientHandledCounter.WithLabelValues(string(r.typ), r.service, r.method, code.String()).Inc() + if r.clientMetrics.clientHandledHistogramEnabled { + r.clientMetrics.clientHandledHistogram.WithLabelValues(string(r.typ), r.service, r.method).Observe(time.Since(r.startTime).Seconds()) + } + } +} + +func (r *reporter) PostMsgSend(_ interface{}, _ error, _ time.Duration) { + switch r.kind { + case KindServer: + r.serverMetrics.serverStreamMsgSent.WithLabelValues(string(r.typ), r.service, r.method).Inc() + case KindClient: + r.clientMetrics.clientStreamMsgSent.WithLabelValues(string(r.typ), r.service, r.method).Inc() + r.sendTimer.ObserveDuration() + } +} + +func (r *reporter) PostMsgReceive(_ interface{}, _ error, _ time.Duration) { + switch r.kind { + case KindServer: + r.serverMetrics.serverStreamMsgReceived.WithLabelValues(string(r.typ), r.service, r.method).Inc() + case KindClient: + r.clientMetrics.clientStreamMsgReceived.WithLabelValues(string(r.typ), r.service, r.method).Inc() + r.receiveTimer.ObserveDuration() + } +} + +type reportable struct { + registry openmetrics.Registerer +} + +func (rep *reportable) ServerReporter(ctx context.Context, _ interface{}, typ interceptors.GRPCType, service string, method string) (interceptors.Reporter, context.Context) { + m := NewServerMetrics(rep.registry) + return rep.reporter(m, nil, typ, service, method, KindServer) +} + +func (rep *reportable) ClientReporter(ctx context.Context, _ interface{}, typ interceptors.GRPCType, service string, method string) (interceptors.Reporter, context.Context) { + m := NewClientMetrics(rep.registry) + return rep.reporter(nil, m, typ, service, method, KindClient) +} + +func (rep *reportable) reporter(sm *ServerMetrics, cm *ClientMetrics, rpcType interceptors.GRPCType, service, method string, kind Kind) (interceptors.Reporter, context.Context) { + r := &reporter{ + clientMetrics: cm, + serverMetrics: sm, + typ: rpcType, + service: service, + method: method, + kind: kind, + sendTimer: interceptors.EmptyTimer, + receiveTimer: interceptors.EmptyTimer, + } + + switch kind { + case KindClient: + if r.clientMetrics.clientHandledHistogramEnabled { + r.startTime = time.Now() + } + r.clientMetrics.clientStartedCounter.WithLabelValues(string(r.typ), r.service, r.method).Inc() + + if r.clientMetrics.clientStreamSendHistogramEnabled { + hist := r.clientMetrics.clientStreamSendHistogram.WithLabelValues(string(r.typ), r.service, r.method) + r.sendTimer = openmetrics.NewTimer(hist) + } + + if r.clientMetrics.clientStreamRecvHistogramEnabled { + hist := r.clientMetrics.clientStreamRecvHistogram.WithLabelValues(string(r.typ), r.service, r.method) + r.receiveTimer = openmetrics.NewTimer(hist) + } + case KindServer: + if r.serverMetrics.serverHandledHistogramEnabled { + r.startTime = time.Now() + } + r.serverMetrics.serverStartedCounter.WithLabelValues(string(r.typ), r.service, r.method).Inc() + } + + // TODO: @yashrsharma44 - What should we use instead of the context.Background()? + return r, context.Background() +} diff --git a/providers/openmetrics/server_interceptor.go b/providers/openmetrics/server_interceptor.go new file mode 100644 index 000000000..ca3ed3b6c --- /dev/null +++ b/providers/openmetrics/server_interceptor.go @@ -0,0 +1,35 @@ +package metrics + +import ( + openmetrics "github.com/prometheus/client_golang/prometheus" + "google.golang.org/grpc" + + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors" +) + +// RegisterServerMetrics returns a custom ServerMetrics object registered +// with the user's registry, and registers some common metrics associated +// with every instance. +func RegisterServerMetrics(registry openmetrics.Registerer) *ServerMetrics { + customServerMetrics := NewServerMetrics(registry) + customServerMetrics.MustRegister(customServerMetrics.serverStartedCounter) + customServerMetrics.MustRegister(customServerMetrics.serverHandledCounter) + customServerMetrics.MustRegister(customServerMetrics.serverStreamMsgReceived) + customServerMetrics.MustRegister(customServerMetrics.serverStreamMsgSent) + + return customServerMetrics +} + +// UnaryServerInterceptor is a gRPC server-side interceptor that provides Prometheus monitoring for Unary RPCs. +func UnaryServerInterceptor(serverRegister openmetrics.Registerer) grpc.UnaryServerInterceptor { + return interceptors.UnaryServerInterceptor(&reportable{ + registry: serverRegister, + }) +} + +// StreamServerInterceptor is a gRPC server-side interceptor that provides Prometheus monitoring for Streaming RPCs. +func StreamServerInterceptor(serverRegister openmetrics.Registerer) grpc.StreamServerInterceptor { + return interceptors.StreamServerInterceptor(&reportable{ + registry: serverRegister, + }) +} diff --git a/providers/openmetrics/server_metrics.go b/providers/openmetrics/server_metrics.go new file mode 100644 index 000000000..976338414 --- /dev/null +++ b/providers/openmetrics/server_metrics.go @@ -0,0 +1,145 @@ +package metrics + +import ( + openmetrics "github.com/prometheus/client_golang/prometheus" + + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors" + + "google.golang.org/grpc" +) + +// ServerMetrics represents a collection of metrics to be registered on a +// Prometheus metrics registry for a gRPC server. +type ServerMetrics struct { + serverRegister openmetrics.Registerer + + serverStartedCounter *openmetrics.CounterVec + serverHandledCounter *openmetrics.CounterVec + serverStreamMsgReceived *openmetrics.CounterVec + serverStreamMsgSent *openmetrics.CounterVec + serverHandledHistogramEnabled bool + serverHandledHistogramOpts openmetrics.HistogramOpts + serverHandledHistogram *openmetrics.HistogramVec +} + +// NewServerMetrics returns a ServerMetrics object. Use a new instance of +// ServerMetrics when not using the default Prometheus metrics registry, for +// example when wanting to control which metrics are added to a registry as +// opposed to automatically adding metrics via init functions. +func NewServerMetrics(serverRegistry openmetrics.Registerer, counterOpts ...CounterOption) *ServerMetrics { + opts := counterOptions(counterOpts) + return &ServerMetrics{ + serverRegister: serverRegistry, + serverStartedCounter: openmetrics.NewCounterVec( + opts.apply(openmetrics.CounterOpts{ + Name: "grpc_server_started_total", + Help: "Total number of RPCs started on the server.", + }), []string{"grpc_type", "grpc_service", "grpc_method"}), + serverHandledCounter: openmetrics.NewCounterVec( + opts.apply(openmetrics.CounterOpts{ + Name: "grpc_server_handled_total", + Help: "Total number of RPCs completed on the server, regardless of success or failure.", + }), []string{"grpc_type", "grpc_service", "grpc_method", "grpc_code"}), + serverStreamMsgReceived: openmetrics.NewCounterVec( + opts.apply(openmetrics.CounterOpts{ + Name: "grpc_server_msg_received_total", + Help: "Total number of RPC stream messages received on the server.", + }), []string{"grpc_type", "grpc_service", "grpc_method"}), + serverStreamMsgSent: openmetrics.NewCounterVec( + opts.apply(openmetrics.CounterOpts{ + Name: "grpc_server_msg_sent_total", + Help: "Total number of gRPC stream messages sent by the server.", + }), []string{"grpc_type", "grpc_service", "grpc_method"}), + serverHandledHistogramEnabled: false, + serverHandledHistogramOpts: openmetrics.HistogramOpts{ + Name: "grpc_server_handling_seconds", + Help: "Histogram of response latency (seconds) of gRPC that had been application-level handled by the server.", + Buckets: openmetrics.DefBuckets, + }, + serverHandledHistogram: nil, + } +} + +// Register registers the provided Collector with the custom register. +// returns error much like DefaultRegisterer of Prometheus. +func (m *ServerMetrics) Register(c openmetrics.Collector) error { + return m.serverRegister.Register(c) +} + +// MustRegister registers the provided Collectors with the custom Registerer +// and panics if any error occurs much like DefaultRegisterer of Prometheus. +func (m *ServerMetrics) MustRegister(c openmetrics.Collector) { + m.serverRegister.MustRegister(c) +} + +// EnableHandlingTimeHistogram turns on recording of handling time +// of RPCs. Histogram metrics can be very expensive for Prometheus +// to retain and query.It takes options to configure histogram +// options such as the defined buckets. +func (m *ServerMetrics) EnableHandlingTimeHistogram(opts ...HistogramOption) error { + for _, o := range opts { + o(&m.serverHandledHistogramOpts) + } + if !m.serverHandledHistogramEnabled { + m.serverHandledHistogram = openmetrics.NewHistogramVec( + m.serverHandledHistogramOpts, + []string{"grpc_type", "grpc_service", "grpc_method"}, + ) + } + m.serverHandledHistogramEnabled = true + return m.serverRegister.Register(m.serverHandledHistogram) +} + +// Describe sends the super-set of all possible descriptors of metrics +// collected by this Collector to the provided channel and returns once +// the last descriptor has been sent. +func (m *ServerMetrics) Describe(ch chan<- *openmetrics.Desc) { + m.serverStartedCounter.Describe(ch) + m.serverHandledCounter.Describe(ch) + m.serverStreamMsgReceived.Describe(ch) + m.serverStreamMsgSent.Describe(ch) + if m.serverHandledHistogramEnabled { + m.serverHandledHistogram.Describe(ch) + } +} + +// Collect is called by the Prometheus registry when collecting +// metrics. The implementation sends each collected metric via the +// provided channel and returns once the last metric has been sent. +func (m *ServerMetrics) Collect(ch chan<- openmetrics.Metric) { + m.serverStartedCounter.Collect(ch) + m.serverHandledCounter.Collect(ch) + m.serverStreamMsgReceived.Collect(ch) + m.serverStreamMsgSent.Collect(ch) + if m.serverHandledHistogramEnabled { + m.serverHandledHistogram.Collect(ch) + } +} + +// InitializeMetrics initializes all metrics, with their appropriate null +// value, for all gRPC methods registered on a gRPC server. This is useful, to +// ensure that all metrics exist when collecting and querying. +func (m *ServerMetrics) InitializeMetrics(server *grpc.Server) { + serviceInfo := server.GetServiceInfo() + for serviceName, info := range serviceInfo { + for _, mInfo := range info.Methods { + m.preRegisterMethod(serviceName, &mInfo) + } + } +} + +// preRegisterMethod is invoked on Register of a Server, allowing all gRPC services labels to be pre-populated. +func (m *ServerMetrics) preRegisterMethod(serviceName string, mInfo *grpc.MethodInfo) { + methodName := mInfo.Name + methodType := string(typeFromMethodInfo(mInfo)) + // These are just references (no increments), as just referencing will create the labels but not set values. + m.serverStartedCounter.GetMetricWithLabelValues(methodType, serviceName, methodName) + m.serverStreamMsgReceived.GetMetricWithLabelValues(methodType, serviceName, methodName) + m.serverStreamMsgSent.GetMetricWithLabelValues(methodType, serviceName, methodName) + if m.serverHandledHistogramEnabled { + m.serverHandledHistogram.GetMetricWithLabelValues(methodType, serviceName, methodName) + } + for _, code := range interceptors.AllCodes { + m.serverHandledCounter.GetMetricWithLabelValues(methodType, serviceName, methodName, code.String()) + } +} diff --git a/providers/openmetrics/server_test.go b/providers/openmetrics/server_test.go new file mode 100644 index 000000000..13c8cd26c --- /dev/null +++ b/providers/openmetrics/server_test.go @@ -0,0 +1,350 @@ +package metrics + +import ( + "bufio" + "context" + "fmt" + "io" + "net" + "net/http" + "net/http/httptest" + "reflect" + "strings" + "testing" + "time" + + "github.com/prometheus/client_golang/prometheus/promhttp" + "github.com/prometheus/client_golang/prometheus/testutil" + + pb_testproto "github.com/grpc-ecosystem/go-grpc-middleware/providers/openmetrics/v2/testproto/v1" + "github.com/prometheus/client_golang/prometheus" + dto "github.com/prometheus/client_model/go" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +var ( + DefaultServerMetrics = RegisterServerMetrics(prometheus.DefaultRegisterer) +) + +const ( + pingDefaultValue = "I like kittens." + countListResponses = 20 +) + +func TestServerInterceptorSuite(t *testing.T) { + suite.Run(t, &ServerInterceptorTestSuite{}) +} + +type ServerInterceptorTestSuite struct { + suite.Suite + + serverListener net.Listener + server *grpc.Server + clientConn *grpc.ClientConn + testClient pb_testproto.TestServiceClient + ctx context.Context + cancel context.CancelFunc +} + +func (s *ServerInterceptorTestSuite) SetupSuite() { + var err error + + DefaultServerMetrics.EnableHandlingTimeHistogram() + + s.serverListener, err = net.Listen("tcp", "127.0.0.1:0") + require.NoError(s.T(), err, "must be able to allocate a port for serverListener") + + // This is the point where we hook up the interceptor + s.server = grpc.NewServer( + grpc.StreamInterceptor(StreamServerInterceptor(prometheus.DefaultRegisterer)), + grpc.UnaryInterceptor(UnaryServerInterceptor(prometheus.DefaultRegisterer)), + ) + pb_testproto.RegisterTestServiceServer(s.server, &testService{t: s.T()}) + + go func() { + s.server.Serve(s.serverListener) + }() + + s.clientConn, err = grpc.Dial(s.serverListener.Addr().String(), grpc.WithInsecure(), grpc.WithBlock(), grpc.WithTimeout(2*time.Second)) + require.NoError(s.T(), err, "must not error on client Dial") + s.testClient = pb_testproto.NewTestServiceClient(s.clientConn) +} + +func (s *ServerInterceptorTestSuite) SetupTest() { + // Make all RPC calls last at most 2 sec, meaning all async issues or deadlock will not kill tests. + s.ctx, s.cancel = context.WithTimeout(context.TODO(), 2*time.Second) + + // Make sure every test starts with same fresh, intialized metric state. + DefaultServerMetrics.serverStartedCounter.Reset() + DefaultServerMetrics.serverHandledCounter.Reset() + DefaultServerMetrics.serverHandledHistogram.Reset() + DefaultServerMetrics.serverStreamMsgReceived.Reset() + DefaultServerMetrics.serverStreamMsgSent.Reset() + DefaultServerMetrics.InitializeMetrics(s.server) +} + +func (s *ServerInterceptorTestSuite) TearDownSuite() { + if s.serverListener != nil { + s.server.Stop() + s.T().Logf("stopped grpc.Server at: %v", s.serverListener.Addr().String()) + s.serverListener.Close() + + } + if s.clientConn != nil { + s.clientConn.Close() + } +} + +func (s *ServerInterceptorTestSuite) TearDownTest() { + s.cancel() +} + +func (s *ServerInterceptorTestSuite) TestRegisterPresetsStuff() { + for testID, testCase := range []struct { + metricName string + existingLabels []string + }{ + // Order of label is irrelevant. + {"grpc_server_started_total", []string{"mwitkow.testproto.TestService", "PingEmpty", "unary"}}, + {"grpc_server_started_total", []string{"mwitkow.testproto.TestService", "PingList", "server_stream"}}, + {"grpc_server_msg_received_total", []string{"mwitkow.testproto.TestService", "PingList", "server_stream"}}, + {"grpc_server_msg_sent_total", []string{"mwitkow.testproto.TestService", "PingEmpty", "unary"}}, + {"grpc_server_handling_seconds_sum", []string{"mwitkow.testproto.TestService", "PingEmpty", "unary"}}, + {"grpc_server_handling_seconds_count", []string{"mwitkow.testproto.TestService", "PingList", "server_stream"}}, + {"grpc_server_handled_total", []string{"mwitkow.testproto.TestService", "PingList", "server_stream", "OutOfRange"}}, + {"grpc_server_handled_total", []string{"mwitkow.testproto.TestService", "PingList", "server_stream", "Aborted"}}, + {"grpc_server_handled_total", []string{"mwitkow.testproto.TestService", "PingEmpty", "unary", "FailedPrecondition"}}, + {"grpc_server_handled_total", []string{"mwitkow.testproto.TestService", "PingEmpty", "unary", "ResourceExhausted"}}, + } { + lineCount := len(fetchPrometheusLines(s.T(), testCase.metricName, testCase.existingLabels...)) + assert.NotEqual(s.T(), 0, lineCount, "metrics must exist for test case %d", testID) + } +} + +func (s *ServerInterceptorTestSuite) TestUnaryIncrementsMetrics() { + _, err := s.testClient.PingEmpty(s.ctx, &pb_testproto.PingEmptyRequest{}) // should return with code=OK + require.NoError(s.T(), err) + requireValue(s.T(), 1, DefaultServerMetrics.serverStartedCounter.WithLabelValues("unary", "mwitkow.testproto.TestService", "PingEmpty")) + requireValue(s.T(), 1, DefaultServerMetrics.serverHandledCounter.WithLabelValues("unary", "mwitkow.testproto.TestService", "PingEmpty", "OK")) + requireValueHistCount(s.T(), 1, DefaultServerMetrics.serverHandledHistogram.WithLabelValues("unary", "mwitkow.testproto.TestService", "PingEmpty")) + + _, err = s.testClient.PingError(s.ctx, &pb_testproto.PingErrorRequest{ErrorCodeReturned: uint32(codes.FailedPrecondition)}) // should return with code=FailedPrecondition + require.Error(s.T(), err) + requireValue(s.T(), 1, DefaultServerMetrics.serverStartedCounter.WithLabelValues("unary", "mwitkow.testproto.TestService", "PingError")) + requireValue(s.T(), 1, DefaultServerMetrics.serverHandledCounter.WithLabelValues("unary", "mwitkow.testproto.TestService", "PingError", "FailedPrecondition")) + requireValueHistCount(s.T(), 1, DefaultServerMetrics.serverHandledHistogram.WithLabelValues("unary", "mwitkow.testproto.TestService", "PingError")) +} + +func (s *ServerInterceptorTestSuite) TestStartedStreamingIncrementsStarted() { + _, err := s.testClient.PingList(s.ctx, &pb_testproto.PingListRequest{}) + require.NoError(s.T(), err) + requireValueWithRetry(s.ctx, s.T(), 1, + DefaultServerMetrics.serverStartedCounter.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList")) + + _, err = s.testClient.PingList(s.ctx, &pb_testproto.PingListRequest{ErrorCodeReturned: uint32(codes.FailedPrecondition)}) // should return with code=FailedPrecondition + require.NoError(s.T(), err, "PingList must not fail immediately") + requireValueWithRetry(s.ctx, s.T(), 2, + DefaultServerMetrics.serverStartedCounter.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList")) +} + +func (s *ServerInterceptorTestSuite) TestStreamingIncrementsMetrics() { + ss, _ := s.testClient.PingList(s.ctx, &pb_testproto.PingListRequest{}) // should return with code=OK + // Do a read, just for kicks. + count := 0 + for { + _, err := ss.Recv() + if err == io.EOF { + break + } + require.NoError(s.T(), err, "reading pingList shouldn't fail") + count++ + } + require.EqualValues(s.T(), countListResponses, count, "Number of received msg on the wire must match") + + requireValueWithRetry(s.ctx, s.T(), 1, + DefaultServerMetrics.serverStartedCounter.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList")) + requireValueWithRetry(s.ctx, s.T(), 1, + DefaultServerMetrics.serverHandledCounter.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList", "OK")) + requireValueWithRetry(s.ctx, s.T(), countListResponses, + DefaultServerMetrics.serverStreamMsgSent.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList")) + requireValueWithRetry(s.ctx, s.T(), 1, + DefaultServerMetrics.serverStreamMsgReceived.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList")) + requireValueWithRetryHistCount(s.ctx, s.T(), 1, + DefaultServerMetrics.serverHandledHistogram.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList")) + + _, err := s.testClient.PingList(s.ctx, &pb_testproto.PingListRequest{ErrorCodeReturned: uint32(codes.FailedPrecondition)}) // should return with code=FailedPrecondition + require.NoError(s.T(), err, "PingList must not fail immediately") + + requireValueWithRetry(s.ctx, s.T(), 2, + DefaultServerMetrics.serverStartedCounter.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList")) + requireValueWithRetry(s.ctx, s.T(), 1, + DefaultServerMetrics.serverHandledCounter.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList", "FailedPrecondition")) + requireValueWithRetryHistCount(s.ctx, s.T(), 2, + DefaultServerMetrics.serverHandledHistogram.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList")) +} + +// fetchPrometheusLines does mocked HTTP GET request against real prometheus handler to get the same view that Prometheus +// would have while scraping this endpoint. +// Order of matching label vales does not matter. +func fetchPrometheusLines(t *testing.T, metricName string, matchingLabelValues ...string) []string { + resp := httptest.NewRecorder() + req, err := http.NewRequest("GET", "/", nil) + require.NoError(t, err, "failed creating request for Prometheus handler") + + promhttp.Handler().ServeHTTP(resp, req) + reader := bufio.NewReader(resp.Body) + + var ret []string + for { + line, err := reader.ReadString('\n') + if err == io.EOF { + break + } else { + require.NoError(t, err, "error reading stuff") + } + if !strings.HasPrefix(line, metricName) { + continue + } + matches := true + for _, labelValue := range matchingLabelValues { + if !strings.Contains(line, `"`+labelValue+`"`) { + matches = false + } + } + if matches { + ret = append(ret, line) + } + + } + return ret +} + +type testService struct { + t *testing.T +} + +func (s *testService) PingEmpty(ctx context.Context, _ *pb_testproto.PingEmptyRequest) (*pb_testproto.PingEmptyResponse, error) { + return &pb_testproto.PingEmptyResponse{Value: pingDefaultValue, Counter: 42}, nil +} + +func (s *testService) Ping(ctx context.Context, ping *pb_testproto.PingRequest) (*pb_testproto.PingResponse, error) { + // Send user trailers and headers. + return &pb_testproto.PingResponse{Value: ping.Value, Counter: 42}, nil +} + +func (s *testService) PingError(ctx context.Context, ping *pb_testproto.PingErrorRequest) (*pb_testproto.PingErrorResponse, error) { + code := codes.Code(ping.ErrorCodeReturned) + return nil, status.Errorf(code, "Userspace error.") +} + +func (s *testService) PingList(ping *pb_testproto.PingListRequest, stream pb_testproto.TestService_PingListServer) error { + if ping.ErrorCodeReturned != 0 { + return status.Errorf(codes.Code(ping.ErrorCodeReturned), "foobar") + } + // Send user trailers and headers. + for i := 0; i < countListResponses; i++ { + stream.Send(&pb_testproto.PingListResponse{Value: ping.Value, Counter: int32(i)}) + } + return nil +} + +// toFloat64HistCount does the same thing as prometheus go client testutil.ToFloat64, but for histograms. +// TODO(bwplotka): Upstream this function to prometheus client. +func toFloat64HistCount(h prometheus.Observer) uint64 { + var ( + m prometheus.Metric + mCount int + mChan = make(chan prometheus.Metric) + done = make(chan struct{}) + ) + + go func() { + for m = range mChan { + mCount++ + } + close(done) + }() + + c, ok := h.(prometheus.Collector) + if !ok { + panic(fmt.Errorf("observer is not a collector; got: %T", h)) + } + + c.Collect(mChan) + close(mChan) + <-done + + if mCount != 1 { + panic(fmt.Errorf("collected %d metrics instead of exactly 1", mCount)) + } + + pb := &dto.Metric{} + m.Write(pb) + if pb.Histogram != nil { + return pb.Histogram.GetSampleCount() + } + panic(fmt.Errorf("collected a non-histogram metric: %s", pb)) +} + +func requireValue(t *testing.T, expect int, c prometheus.Collector) { + v := int(testutil.ToFloat64(c)) + if v == expect { + return + } + + metricFullName := reflect.ValueOf(*c.(prometheus.Metric).Desc()).FieldByName("fqName").String() + t.Errorf("expected %d %s value; got %d; ", expect, metricFullName, v) + t.Fail() +} + +func requireValueHistCount(t *testing.T, expect int, o prometheus.Observer) { + v := int(toFloat64HistCount(o)) + if v == expect { + return + } + + metricFullName := reflect.ValueOf(*o.(prometheus.Metric).Desc()).FieldByName("fqName").String() + t.Errorf("expected %d %s value; got %d; ", expect, metricFullName, v) + t.Fail() +} + +func requireValueWithRetry(ctx context.Context, t *testing.T, expect int, c prometheus.Collector) { + for { + v := int(testutil.ToFloat64(c)) + if v == expect { + return + } + + select { + case <-ctx.Done(): + metricFullName := reflect.ValueOf(*c.(prometheus.Metric).Desc()).FieldByName("fqName").String() + t.Errorf("timeout while expecting %d %s value; got %d; ", expect, metricFullName, v) + t.Fail() + return + case <-time.After(100 * time.Millisecond): + } + } +} + +func requireValueWithRetryHistCount(ctx context.Context, t *testing.T, expect int, o prometheus.Observer) { + for { + v := int(toFloat64HistCount(o)) + if v == expect { + return + } + + select { + case <-ctx.Done(): + metricFullName := reflect.ValueOf(*o.(prometheus.Metric).Desc()).FieldByName("fqName").String() + t.Errorf("timeout while expecting %d %s histogram count value; got %d; ", expect, metricFullName, v) + t.Fail() + return + case <-time.After(100 * time.Millisecond): + } + } +} diff --git a/providers/openmetrics/testproto/v1/run_protoc.sh b/providers/openmetrics/testproto/v1/run_protoc.sh new file mode 100755 index 000000000..736549587 --- /dev/null +++ b/providers/openmetrics/testproto/v1/run_protoc.sh @@ -0,0 +1 @@ +protoc --go_out=. --go-grpc_opt=require_unimplemented_servers=false --go-grpc_out=. test.proto \ No newline at end of file diff --git a/providers/openmetrics/testproto/v1/test.pb.go b/providers/openmetrics/testproto/v1/test.pb.go new file mode 100644 index 000000000..d2556038b --- /dev/null +++ b/providers/openmetrics/testproto/v1/test.pb.go @@ -0,0 +1,697 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.25.0 +// protoc v3.13.0 +// source: test.proto + +package providers_openmetrics_testproto_v1 + +import ( + reflect "reflect" + sync "sync" + + proto "github.com/golang/protobuf/proto" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// This is a compile-time assertion that a sufficiently up-to-date version +// of the legacy proto package is being used. +const _ = proto.ProtoPackageIsVersion4 + +type PingEmptyRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *PingEmptyRequest) Reset() { + *x = PingEmptyRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PingEmptyRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PingEmptyRequest) ProtoMessage() {} + +func (x *PingEmptyRequest) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PingEmptyRequest.ProtoReflect.Descriptor instead. +func (*PingEmptyRequest) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{0} +} + +type PingEmptyResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` + Counter int32 `protobuf:"varint,2,opt,name=counter,proto3" json:"counter,omitempty"` +} + +func (x *PingEmptyResponse) Reset() { + *x = PingEmptyResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PingEmptyResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PingEmptyResponse) ProtoMessage() {} + +func (x *PingEmptyResponse) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PingEmptyResponse.ProtoReflect.Descriptor instead. +func (*PingEmptyResponse) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{1} +} + +func (x *PingEmptyResponse) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +func (x *PingEmptyResponse) GetCounter() int32 { + if x != nil { + return x.Counter + } + return 0 +} + +type PingRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` + SleepTimeMs int32 `protobuf:"varint,2,opt,name=sleep_time_ms,json=sleepTimeMs,proto3" json:"sleep_time_ms,omitempty"` + ErrorCodeReturned uint32 `protobuf:"varint,3,opt,name=error_code_returned,json=errorCodeReturned,proto3" json:"error_code_returned,omitempty"` +} + +func (x *PingRequest) Reset() { + *x = PingRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PingRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PingRequest) ProtoMessage() {} + +func (x *PingRequest) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PingRequest.ProtoReflect.Descriptor instead. +func (*PingRequest) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{2} +} + +func (x *PingRequest) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +func (x *PingRequest) GetSleepTimeMs() int32 { + if x != nil { + return x.SleepTimeMs + } + return 0 +} + +func (x *PingRequest) GetErrorCodeReturned() uint32 { + if x != nil { + return x.ErrorCodeReturned + } + return 0 +} + +type PingResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` + Counter int32 `protobuf:"varint,2,opt,name=counter,proto3" json:"counter,omitempty"` +} + +func (x *PingResponse) Reset() { + *x = PingResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PingResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PingResponse) ProtoMessage() {} + +func (x *PingResponse) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PingResponse.ProtoReflect.Descriptor instead. +func (*PingResponse) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{3} +} + +func (x *PingResponse) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +func (x *PingResponse) GetCounter() int32 { + if x != nil { + return x.Counter + } + return 0 +} + +type PingErrorRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` + SleepTimeMs int32 `protobuf:"varint,2,opt,name=sleep_time_ms,json=sleepTimeMs,proto3" json:"sleep_time_ms,omitempty"` + ErrorCodeReturned uint32 `protobuf:"varint,3,opt,name=error_code_returned,json=errorCodeReturned,proto3" json:"error_code_returned,omitempty"` +} + +func (x *PingErrorRequest) Reset() { + *x = PingErrorRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PingErrorRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PingErrorRequest) ProtoMessage() {} + +func (x *PingErrorRequest) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PingErrorRequest.ProtoReflect.Descriptor instead. +func (*PingErrorRequest) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{4} +} + +func (x *PingErrorRequest) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +func (x *PingErrorRequest) GetSleepTimeMs() int32 { + if x != nil { + return x.SleepTimeMs + } + return 0 +} + +func (x *PingErrorRequest) GetErrorCodeReturned() uint32 { + if x != nil { + return x.ErrorCodeReturned + } + return 0 +} + +type PingErrorResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *PingErrorResponse) Reset() { + *x = PingErrorResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PingErrorResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PingErrorResponse) ProtoMessage() {} + +func (x *PingErrorResponse) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PingErrorResponse.ProtoReflect.Descriptor instead. +func (*PingErrorResponse) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{5} +} + +type PingListRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` + SleepTimeMs int32 `protobuf:"varint,2,opt,name=sleep_time_ms,json=sleepTimeMs,proto3" json:"sleep_time_ms,omitempty"` + ErrorCodeReturned uint32 `protobuf:"varint,3,opt,name=error_code_returned,json=errorCodeReturned,proto3" json:"error_code_returned,omitempty"` +} + +func (x *PingListRequest) Reset() { + *x = PingListRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PingListRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PingListRequest) ProtoMessage() {} + +func (x *PingListRequest) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PingListRequest.ProtoReflect.Descriptor instead. +func (*PingListRequest) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{6} +} + +func (x *PingListRequest) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +func (x *PingListRequest) GetSleepTimeMs() int32 { + if x != nil { + return x.SleepTimeMs + } + return 0 +} + +func (x *PingListRequest) GetErrorCodeReturned() uint32 { + if x != nil { + return x.ErrorCodeReturned + } + return 0 +} + +type PingListResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` + Counter int32 `protobuf:"varint,2,opt,name=counter,proto3" json:"counter,omitempty"` +} + +func (x *PingListResponse) Reset() { + *x = PingListResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PingListResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PingListResponse) ProtoMessage() {} + +func (x *PingListResponse) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PingListResponse.ProtoReflect.Descriptor instead. +func (*PingListResponse) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{7} +} + +func (x *PingListResponse) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +func (x *PingListResponse) GetCounter() int32 { + if x != nil { + return x.Counter + } + return 0 +} + +var File_test_proto protoreflect.FileDescriptor + +var file_test_proto_rawDesc = []byte{ + 0x0a, 0x0a, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x22, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x6d, 0x65, 0x74, 0x72, + 0x69, 0x63, 0x73, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, + 0x22, 0x12, 0x0a, 0x10, 0x50, 0x69, 0x6e, 0x67, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x22, 0x43, 0x0a, 0x11, 0x50, 0x69, 0x6e, 0x67, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, + 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x22, 0x77, 0x0a, 0x0b, 0x50, 0x69, 0x6e, + 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x22, + 0x0a, 0x0d, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x54, 0x69, 0x6d, 0x65, + 0x4d, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x63, 0x6f, 0x64, 0x65, + 0x5f, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x11, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, + 0x65, 0x64, 0x22, 0x3e, 0x0a, 0x0c, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x65, 0x72, 0x22, 0x7c, 0x0a, 0x10, 0x50, 0x69, 0x6e, 0x67, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x22, 0x0a, 0x0d, + 0x73, 0x6c, 0x65, 0x65, 0x70, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x0b, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, + 0x12, 0x2e, 0x0a, 0x13, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x72, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, + 0x22, 0x13, 0x0a, 0x11, 0x50, 0x69, 0x6e, 0x67, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x7b, 0x0a, 0x0f, 0x50, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x22, + 0x0a, 0x0d, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x54, 0x69, 0x6d, 0x65, + 0x4d, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x63, 0x6f, 0x64, 0x65, + 0x5f, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x11, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, + 0x65, 0x64, 0x22, 0x42, 0x0a, 0x10, 0x50, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x18, 0x0a, 0x07, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x32, 0xed, 0x03, 0x0a, 0x0b, 0x54, 0x65, 0x73, 0x74, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x7a, 0x0a, 0x09, 0x50, 0x69, 0x6e, 0x67, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x12, 0x34, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x2e, + 0x6f, 0x70, 0x65, 0x6e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x74, 0x65, 0x73, 0x74, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x70, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x73, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, + 0x73, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x50, + 0x69, 0x6e, 0x67, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x00, 0x12, 0x6b, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x2f, 0x2e, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x6d, 0x65, 0x74, 0x72, 0x69, + 0x63, 0x73, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, + 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x6d, 0x65, 0x74, 0x72, + 0x69, 0x63, 0x73, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, + 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x7a, 0x0a, 0x09, 0x50, 0x69, 0x6e, 0x67, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x34, 0x2e, 0x70, + 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x6d, 0x65, 0x74, + 0x72, 0x69, 0x63, 0x73, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, + 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x2e, 0x6f, + 0x70, 0x65, 0x6e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x45, 0x72, 0x72, 0x6f, + 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x79, 0x0a, 0x08, 0x50, + 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x33, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, + 0x65, 0x72, 0x73, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, + 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, + 0x67, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x70, + 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x6d, 0x65, 0x74, + 0x72, 0x69, 0x63, 0x73, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, + 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_test_proto_rawDescOnce sync.Once + file_test_proto_rawDescData = file_test_proto_rawDesc +) + +func file_test_proto_rawDescGZIP() []byte { + file_test_proto_rawDescOnce.Do(func() { + file_test_proto_rawDescData = protoimpl.X.CompressGZIP(file_test_proto_rawDescData) + }) + return file_test_proto_rawDescData +} + +var file_test_proto_msgTypes = make([]protoimpl.MessageInfo, 8) +var file_test_proto_goTypes = []interface{}{ + (*PingEmptyRequest)(nil), // 0: providers.openmetrics.testproto.v1.PingEmptyRequest + (*PingEmptyResponse)(nil), // 1: providers.openmetrics.testproto.v1.PingEmptyResponse + (*PingRequest)(nil), // 2: providers.openmetrics.testproto.v1.PingRequest + (*PingResponse)(nil), // 3: providers.openmetrics.testproto.v1.PingResponse + (*PingErrorRequest)(nil), // 4: providers.openmetrics.testproto.v1.PingErrorRequest + (*PingErrorResponse)(nil), // 5: providers.openmetrics.testproto.v1.PingErrorResponse + (*PingListRequest)(nil), // 6: providers.openmetrics.testproto.v1.PingListRequest + (*PingListResponse)(nil), // 7: providers.openmetrics.testproto.v1.PingListResponse +} +var file_test_proto_depIdxs = []int32{ + 0, // 0: providers.openmetrics.testproto.v1.TestService.PingEmpty:input_type -> providers.openmetrics.testproto.v1.PingEmptyRequest + 2, // 1: providers.openmetrics.testproto.v1.TestService.Ping:input_type -> providers.openmetrics.testproto.v1.PingRequest + 4, // 2: providers.openmetrics.testproto.v1.TestService.PingError:input_type -> providers.openmetrics.testproto.v1.PingErrorRequest + 6, // 3: providers.openmetrics.testproto.v1.TestService.PingList:input_type -> providers.openmetrics.testproto.v1.PingListRequest + 1, // 4: providers.openmetrics.testproto.v1.TestService.PingEmpty:output_type -> providers.openmetrics.testproto.v1.PingEmptyResponse + 3, // 5: providers.openmetrics.testproto.v1.TestService.Ping:output_type -> providers.openmetrics.testproto.v1.PingResponse + 5, // 6: providers.openmetrics.testproto.v1.TestService.PingError:output_type -> providers.openmetrics.testproto.v1.PingErrorResponse + 7, // 7: providers.openmetrics.testproto.v1.TestService.PingList:output_type -> providers.openmetrics.testproto.v1.PingListResponse + 4, // [4:8] is the sub-list for method output_type + 0, // [0:4] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_test_proto_init() } +func file_test_proto_init() { + if File_test_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_test_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PingEmptyRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PingEmptyResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PingRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PingResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PingErrorRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PingErrorResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PingListRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PingListResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_test_proto_rawDesc, + NumEnums: 0, + NumMessages: 8, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_test_proto_goTypes, + DependencyIndexes: file_test_proto_depIdxs, + MessageInfos: file_test_proto_msgTypes, + }.Build() + File_test_proto = out.File + file_test_proto_rawDesc = nil + file_test_proto_goTypes = nil + file_test_proto_depIdxs = nil +} diff --git a/providers/openmetrics/testproto/v1/test.proto b/providers/openmetrics/testproto/v1/test.proto new file mode 100644 index 000000000..b4bc54204 --- /dev/null +++ b/providers/openmetrics/testproto/v1/test.proto @@ -0,0 +1,54 @@ + +syntax = "proto3"; + +package providers.openmetrics.testproto.v1; + +message PingEmptyRequest { +} + +message PingEmptyResponse { + string value = 1; + int32 counter = 2; +} + +message PingRequest { + string value = 1; + int32 sleep_time_ms = 2; + uint32 error_code_returned = 3; +} + +message PingResponse { + string value = 1; + int32 counter = 2; +} + +message PingErrorRequest { + string value = 1; + int32 sleep_time_ms = 2; + uint32 error_code_returned = 3; +} + +message PingErrorResponse { +} + +message PingListRequest { + string value = 1; + int32 sleep_time_ms = 2; + uint32 error_code_returned = 3; +} + +message PingListResponse { + string value = 1; + int32 counter = 2; +} + + +service TestService { + rpc PingEmpty(PingEmptyRequest) returns (PingEmptyResponse) {} + + rpc Ping(PingRequest) returns (PingResponse) {} + + rpc PingError(PingErrorRequest) returns (PingErrorResponse) {} + + rpc PingList(PingListRequest) returns (stream PingListResponse) {} +} \ No newline at end of file diff --git a/providers/openmetrics/testproto/v1/test_grpc.pb.go b/providers/openmetrics/testproto/v1/test_grpc.pb.go new file mode 100644 index 000000000..b1d083ce9 --- /dev/null +++ b/providers/openmetrics/testproto/v1/test_grpc.pb.go @@ -0,0 +1,232 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. + +package providers_openmetrics_testproto_v1 + +import ( + context "context" + + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion7 + +// TestServiceClient is the client API for TestService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type TestServiceClient interface { + PingEmpty(ctx context.Context, in *PingEmptyRequest, opts ...grpc.CallOption) (*PingEmptyResponse, error) + Ping(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*PingResponse, error) + PingError(ctx context.Context, in *PingErrorRequest, opts ...grpc.CallOption) (*PingErrorResponse, error) + PingList(ctx context.Context, in *PingListRequest, opts ...grpc.CallOption) (TestService_PingListClient, error) +} + +type testServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewTestServiceClient(cc grpc.ClientConnInterface) TestServiceClient { + return &testServiceClient{cc} +} + +func (c *testServiceClient) PingEmpty(ctx context.Context, in *PingEmptyRequest, opts ...grpc.CallOption) (*PingEmptyResponse, error) { + out := new(PingEmptyResponse) + err := c.cc.Invoke(ctx, "/providers.openmetrics.testproto.v1.TestService/PingEmpty", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *testServiceClient) Ping(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*PingResponse, error) { + out := new(PingResponse) + err := c.cc.Invoke(ctx, "/providers.openmetrics.testproto.v1.TestService/Ping", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *testServiceClient) PingError(ctx context.Context, in *PingErrorRequest, opts ...grpc.CallOption) (*PingErrorResponse, error) { + out := new(PingErrorResponse) + err := c.cc.Invoke(ctx, "/providers.openmetrics.testproto.v1.TestService/PingError", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *testServiceClient) PingList(ctx context.Context, in *PingListRequest, opts ...grpc.CallOption) (TestService_PingListClient, error) { + stream, err := c.cc.NewStream(ctx, &_TestService_serviceDesc.Streams[0], "/providers.openmetrics.testproto.v1.TestService/PingList", opts...) + if err != nil { + return nil, err + } + x := &testServicePingListClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type TestService_PingListClient interface { + Recv() (*PingListResponse, error) + grpc.ClientStream +} + +type testServicePingListClient struct { + grpc.ClientStream +} + +func (x *testServicePingListClient) Recv() (*PingListResponse, error) { + m := new(PingListResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// TestServiceServer is the server API for TestService service. +// All implementations should embed UnimplementedTestServiceServer +// for forward compatibility +type TestServiceServer interface { + PingEmpty(context.Context, *PingEmptyRequest) (*PingEmptyResponse, error) + Ping(context.Context, *PingRequest) (*PingResponse, error) + PingError(context.Context, *PingErrorRequest) (*PingErrorResponse, error) + PingList(*PingListRequest, TestService_PingListServer) error +} + +// UnimplementedTestServiceServer should be embedded to have forward compatible implementations. +type UnimplementedTestServiceServer struct { +} + +func (UnimplementedTestServiceServer) PingEmpty(context.Context, *PingEmptyRequest) (*PingEmptyResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method PingEmpty not implemented") +} +func (UnimplementedTestServiceServer) Ping(context.Context, *PingRequest) (*PingResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Ping not implemented") +} +func (UnimplementedTestServiceServer) PingError(context.Context, *PingErrorRequest) (*PingErrorResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method PingError not implemented") +} +func (UnimplementedTestServiceServer) PingList(*PingListRequest, TestService_PingListServer) error { + return status.Errorf(codes.Unimplemented, "method PingList not implemented") +} + +// UnsafeTestServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to TestServiceServer will +// result in compilation errors. +type UnsafeTestServiceServer interface { + mustEmbedUnimplementedTestServiceServer() +} + +func RegisterTestServiceServer(s grpc.ServiceRegistrar, srv TestServiceServer) { + s.RegisterService(&_TestService_serviceDesc, srv) +} + +func _TestService_PingEmpty_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PingEmptyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TestServiceServer).PingEmpty(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/providers.openmetrics.testproto.v1.TestService/PingEmpty", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TestServiceServer).PingEmpty(ctx, req.(*PingEmptyRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _TestService_Ping_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PingRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TestServiceServer).Ping(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/providers.openmetrics.testproto.v1.TestService/Ping", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TestServiceServer).Ping(ctx, req.(*PingRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _TestService_PingError_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PingErrorRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TestServiceServer).PingError(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/providers.openmetrics.testproto.v1.TestService/PingError", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TestServiceServer).PingError(ctx, req.(*PingErrorRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _TestService_PingList_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(PingListRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(TestServiceServer).PingList(m, &testServicePingListServer{stream}) +} + +type TestService_PingListServer interface { + Send(*PingListResponse) error + grpc.ServerStream +} + +type testServicePingListServer struct { + grpc.ServerStream +} + +func (x *testServicePingListServer) Send(m *PingListResponse) error { + return x.ServerStream.SendMsg(m) +} + +var _TestService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "providers.openmetrics.testproto.v1.TestService", + HandlerType: (*TestServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "PingEmpty", + Handler: _TestService_PingEmpty_Handler, + }, + { + MethodName: "Ping", + Handler: _TestService_Ping_Handler, + }, + { + MethodName: "PingError", + Handler: _TestService_PingError_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "PingList", + Handler: _TestService_PingList_Handler, + ServerStreams: true, + }, + }, + Metadata: "test.proto", +} From 524ce8f5844d320bc6fd070eed5e9b2bb14a96f7 Mon Sep 17 00:00:00 2001 From: instabledesign Date: Fri, 26 Mar 2021 23:27:24 +0100 Subject: [PATCH 19/27] v2: Client unary interceptor timeout on v2 branch (#330) * Client unary interceptor timeout on v2 branch * change fmt.println with log.Println in example (linter fix) * fix test * Update interceptors/timeout/examples_test.go Co-authored-by: Johan Brandhorst-Satzkorn * fixup example linter * fix when context already has timeout * fixup trailing period * try increase timing * delete deadline check * update comment * add readme timeout note * fixup test Co-authored-by: Johan Brandhorst-Satzkorn --- README.md | 1 + interceptors/timeout/doc.go | 8 +++++ interceptors/timeout/examples_test.go | 35 ++++++++++++++++++ interceptors/timeout/timeout.go | 17 +++++++++ interceptors/timeout/timeout_test.go | 52 +++++++++++++++++++++++++++ 5 files changed, 113 insertions(+) create mode 100644 interceptors/timeout/doc.go create mode 100644 interceptors/timeout/examples_test.go create mode 100644 interceptors/timeout/timeout.go create mode 100644 interceptors/timeout/timeout_test.go diff --git a/README.md b/README.md index dfeb8d370..99c838708 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,7 @@ myServer := grpc.NewServer( #### Client * [`retry`](interceptors/retry) - a generic gRPC response code retry mechanism, client-side middleware + * [`timeout`](interceptors/timeout) - a generic gRPC request timeout, client-side middleware #### Server * [`validator`](interceptors/validator) - codegen inbound message validation from `.proto` options diff --git a/interceptors/timeout/doc.go b/interceptors/timeout/doc.go new file mode 100644 index 000000000..2dcca58a6 --- /dev/null +++ b/interceptors/timeout/doc.go @@ -0,0 +1,8 @@ +/* +`grpc_timeout` are interceptors that timeout for gRPC client calls. + +Client Side Timeout Middleware + +Please see examples for simple examples of use. +*/ +package timeout diff --git a/interceptors/timeout/examples_test.go b/interceptors/timeout/examples_test.go new file mode 100644 index 000000000..ae9f5d826 --- /dev/null +++ b/interceptors/timeout/examples_test.go @@ -0,0 +1,35 @@ +package timeout_test + +import ( + "context" + "log" + "time" + + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/timeout" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/testing/testpb" + "google.golang.org/grpc" +) + +// Initialization shows an initialization sequence with a custom client request timeout. +func Example_initialization() { + clientConn, err := grpc.Dial( + "ServerAddr", + grpc.WithUnaryInterceptor( + // Set your client request timeout. + timeout.TimeoutUnaryClientInterceptor(20*time.Millisecond), + ), + ) + if err != nil { + log.Fatal(err) + } + + // Initialize your grpc service with connection. + testServiceClient := testpb.NewTestServiceClient(clientConn) + resp, err := testServiceClient.Ping(context.TODO(), &testpb.PingRequest{Value: "my_example_value"}) + if err != nil { + log.Fatal(err) + } + + // Use grpc response value. + log.Println(resp.Value) +} diff --git a/interceptors/timeout/timeout.go b/interceptors/timeout/timeout.go new file mode 100644 index 000000000..1b156e94a --- /dev/null +++ b/interceptors/timeout/timeout.go @@ -0,0 +1,17 @@ +package timeout + +import ( + "context" + "time" + + "google.golang.org/grpc" +) + +// TimeoutUnaryClientInterceptor returns a new unary client interceptor that sets a timeout on the request context. +func TimeoutUnaryClientInterceptor(timeout time.Duration) grpc.UnaryClientInterceptor { + return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { + timedCtx, cancel := context.WithTimeout(ctx, timeout) + defer cancel() + return invoker(timedCtx, method, req, reply, cc, opts...) + } +} diff --git a/interceptors/timeout/timeout_test.go b/interceptors/timeout/timeout_test.go new file mode 100644 index 000000000..0589f974e --- /dev/null +++ b/interceptors/timeout/timeout_test.go @@ -0,0 +1,52 @@ +package timeout_test + +import ( + "context" + "testing" + "time" + + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/timeout" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/testing/testpb" + "github.com/stretchr/testify/assert" + "google.golang.org/grpc" +) + +type TimeoutTestServiceServer struct { + sleepTime time.Duration + testpb.TestPingService +} + +func (t *TimeoutTestServiceServer) Ping(ctx context.Context, req *testpb.PingRequest) (*testpb.PingResponse, error) { + if t.sleepTime > 0 { + time.Sleep(t.sleepTime) + } + return t.TestPingService.Ping(ctx, req) +} + +func TestTimeoutUnaryClientInterceptor(t *testing.T) { + server := &TimeoutTestServiceServer{} + + its := &testpb.InterceptorTestSuite{ + ClientOpts: []grpc.DialOption{ + grpc.WithUnaryInterceptor(timeout.TimeoutUnaryClientInterceptor(100 * time.Millisecond)), + }, + TestService: server, + } + its.Suite.SetT(t) + its.SetupSuite() + defer its.TearDownSuite() + + // This call will take 0/100ms for respond, so the client timeout NOT exceed. + resp, err := its.Client.Ping(context.TODO(), &testpb.PingRequest{Value: "default_response_value"}) + assert.NoError(t, err) + assert.NotNil(t, resp) + assert.Equal(t, "default_response_value", resp.Value) + + // server will sleep 300ms before respond + server.sleepTime = 300 * time.Millisecond + + // This call will take 300/100ms for respond, so the client timeout exceed. + resp2, err2 := its.Client.Ping(context.TODO(), &testpb.PingRequest{}) + assert.Nil(t, resp2) + assert.EqualError(t, err2, "rpc error: code = DeadlineExceeded desc = context deadline exceeded") +} From 0df73fc576befff7acf6f397634a64c54aa4ad11 Mon Sep 17 00:00:00 2001 From: Alex Simenduev Date: Sat, 3 Apr 2021 17:26:55 +0300 Subject: [PATCH 20/27] add onRetryCallback callback function (#405) * add onRetryCallback callback function * use only one OnRetryCallback function, instead of one with and one without context * move retry attempt trace log to be the default onRetryCallback behaviour * use parentCtx when calling onRetryCallback function --- interceptors/retry/options.go | 26 +++++++++++++++++++++----- interceptors/retry/retry.go | 6 +++--- interceptors/retry/retry_test.go | 30 ++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 8 deletions(-) diff --git a/interceptors/retry/options.go b/interceptors/retry/options.go index baa4e06f7..6f147c673 100644 --- a/interceptors/retry/options.go +++ b/interceptors/retry/options.go @@ -26,6 +26,9 @@ var ( backoffFunc: BackoffFuncContext(func(ctx context.Context, attempt uint) time.Duration { return BackoffLinearWithJitter(50*time.Millisecond /*jitter*/, 0.10)(attempt) }), + onRetryCallback: OnRetryCallback(func(ctx context.Context, attempt uint, err error) { + logTrace(ctx, "grpc_retry attempt: %d, backoff for %v", attempt, err) + }), } ) @@ -45,6 +48,9 @@ type BackoffFunc func(attempt uint) time.Duration // with the next iteration. The context can be used to extract request scoped metadata and context values. type BackoffFuncContext func(ctx context.Context, attempt uint) time.Duration +// OnRetryCallback is the type of function called when a retry occurs. +type OnRetryCallback func(ctx context.Context, attempt uint, err error) + // Disable disables the retry behaviour on this call, or this interceptor. // // Its semantically the same to `WithMax` @@ -75,6 +81,15 @@ func WithBackoffContext(bf BackoffFuncContext) CallOption { }} } +// WithOnRetryCallback sets the callback to use when a retry occurs. +// +// By default, when no callback function provided, we will just print a log to trace +func WithOnRetryCallback(fn OnRetryCallback) CallOption { + return CallOption{applyFunc: func(o *options) { + o.onRetryCallback = fn + }} +} + // WithCodes sets which codes should be retried. // // Please *use with care*, as you may be retrying non-idempotent calls. @@ -105,11 +120,12 @@ func WithPerRetryTimeout(timeout time.Duration) CallOption { } type options struct { - max uint - perCallTimeout time.Duration - includeHeader bool - codes []codes.Code - backoffFunc BackoffFuncContext + max uint + perCallTimeout time.Duration + includeHeader bool + codes []codes.Code + backoffFunc BackoffFuncContext + onRetryCallback OnRetryCallback } // CallOption is a grpc.CallOption that is local to grpc_retry. diff --git a/interceptors/retry/retry.go b/interceptors/retry/retry.go index 9f98afc27..2445fc30a 100644 --- a/interceptors/retry/retry.go +++ b/interceptors/retry/retry.go @@ -48,7 +48,7 @@ func UnaryClientInterceptor(optFuncs ...CallOption) grpc.UnaryClientInterceptor if lastErr == nil { return nil } - logTrace(parentCtx, "grpc_retry attempt: %d, got err: %v", attempt, lastErr) + callOpts.onRetryCallback(parentCtx, attempt, lastErr) if isContextError(lastErr) { if parentCtx.Err() != nil { logTrace(parentCtx, "grpc_retry attempt: %d, parent context error: %v", attempt, parentCtx.Err()) @@ -110,8 +110,7 @@ func StreamClientInterceptor(optFuncs ...CallOption) grpc.StreamClientIntercepto } return retryingStreamer, nil } - - logTrace(parentCtx, "grpc_retry attempt: %d, got err: %v", attempt, lastErr) + callOpts.onRetryCallback(parentCtx, attempt, lastErr) if isContextError(lastErr) { if parentCtx.Err() != nil { logTrace(parentCtx, "grpc_retry attempt: %d, parent context error: %v", attempt, parentCtx.Err()) @@ -189,6 +188,7 @@ func (s *serverStreamingRetryingStream) RecvMsg(m interface{}) error { if err := waitRetryBackoff(attempt, s.parentCtx, s.callOpts); err != nil { return err } + s.callOpts.onRetryCallback(s.parentCtx, attempt, lastErr) // TODO(bwplotka): Close cancel as it might leak some resources. callCtx, _ := perCallContext(s.parentCtx, s.callOpts, attempt) //nolint newStream, err := s.reestablishStreamAndResendBuffer(callCtx) diff --git a/interceptors/retry/retry_test.go b/interceptors/retry/retry_test.go index d3372f7f8..c5501b831 100644 --- a/interceptors/retry/retry_test.go +++ b/interceptors/retry/retry_test.go @@ -215,6 +215,21 @@ func (s *RetrySuite) TestUnary_PerCallDeadline_FailsOnParent() { require.Equal(s.T(), codes.DeadlineExceeded, status.Code(err), "failre code must be a gRPC error of Deadline class") } +func (s *RetrySuite) TestUnary_OnRetryCallbackCalled() { + retryCallbackCount := 0 + + s.srv.resetFailingConfiguration(3, codes.Unavailable, noSleep) // see retriable_errors + out, err := s.Client.Ping(s.SimpleCtx(), testpb.GoodPing, + retry.WithOnRetryCallback(func(ctx context.Context, attempt uint, err error) { + retryCallbackCount++ + }), + ) + + require.NoError(s.T(), err, "the third invocation should succeed") + require.NotNil(s.T(), out, "Pong must be not nil") + require.EqualValues(s.T(), 2, retryCallbackCount, "two retry callbacks should be called") +} + func (s *RetrySuite) TestServerStream_SucceedsOnRetriableError() { s.srv.resetFailingConfiguration(3, codes.DataLoss, noSleep) // see retriable_errors stream, err := s.Client.PingList(s.SimpleCtx(), testpb.GoodPingList) @@ -266,6 +281,21 @@ func (s *RetrySuite) TestServerStream_PerCallDeadline_FailsOnParent() { require.Equal(s.T(), codes.DeadlineExceeded, status.Code(err), "failre code must be a gRPC error of Deadline class") } +func (s *RetrySuite) TestServerStream_OnRetryCallbackCalled() { + retryCallbackCount := 0 + + s.srv.resetFailingConfiguration(3, codes.Unavailable, noSleep) // see retriable_errors + stream, err := s.Client.PingList(s.SimpleCtx(), testpb.GoodPingList, + retry.WithOnRetryCallback(func(ctx context.Context, attempt uint, err error) { + retryCallbackCount++ + }), + ) + + require.NoError(s.T(), err, "establishing the connection must always succeed") + s.assertPingListWasCorrect(stream) + require.EqualValues(s.T(), 2, retryCallbackCount, "two retry callbacks should be called") +} + func (s *RetrySuite) TestServerStream_CallFailsOnOutOfRetries() { restarted := s.RestartServer(3 * retryTimeout) _, err := s.Client.PingList(s.SimpleCtx(), testpb.GoodPingList) From 0c9d2580269cb45ee81f11132b087bb9b1c2a101 Mon Sep 17 00:00:00 2001 From: Daniel Hochman Date: Fri, 23 Apr 2021 12:46:12 -0500 Subject: [PATCH 21/27] port to v2 (#418) --- interceptors/validator/validator.go | 41 +++++++++++++++------- interceptors/validator/validator_test.go | 17 ++++++--- testing/testpb/test.manual_validator.pb.go | 25 ++++++++++--- 3 files changed, 61 insertions(+), 22 deletions(-) diff --git a/interceptors/validator/validator.go b/interceptors/validator/validator.go index 958830383..164d201e0 100644 --- a/interceptors/validator/validator.go +++ b/interceptors/validator/validator.go @@ -11,19 +11,40 @@ import ( "google.golang.org/grpc/status" ) +// The validate interface starting with protoc-gen-validate v0.6.0. +// See https://github.com/envoyproxy/protoc-gen-validate/pull/455. type validator interface { + Validate(all bool) error +} + +// The validate interface prior to protoc-gen-validate v0.6.0. +type validatorLegacy interface { Validate() error } +// Calls the Validate function on a proto message using either the current or legacy interface if the Validate function +// is present. If validation fails, the error is wrapped with `InvalidArgument` and returned. +func validate(req interface{}) error { + switch v := req.(type) { + case validatorLegacy: + if err := v.Validate(); err != nil { + return status.Error(codes.InvalidArgument, err.Error()) + } + case validator: + if err := v.Validate(false); err != nil { + return status.Error(codes.InvalidArgument, err.Error()) + } + } + return nil +} + // UnaryServerInterceptor returns a new unary server interceptor that validates incoming messages. // // Invalid messages will be rejected with `InvalidArgument` before reaching any userspace handlers. func UnaryServerInterceptor() grpc.UnaryServerInterceptor { return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { - if v, ok := req.(validator); ok { - if err := v.Validate(); err != nil { - return nil, status.Errorf(codes.InvalidArgument, err.Error()) - } + if err := validate(req); err != nil { + return nil, err } return handler(ctx, req) } @@ -34,10 +55,8 @@ func UnaryServerInterceptor() grpc.UnaryServerInterceptor { // Invalid messages will be rejected with `InvalidArgument` before sending the request to server. func UnaryClientInterceptor() grpc.UnaryClientInterceptor { return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { - if v, ok := req.(validator); ok { - if err := v.Validate(); err != nil { - return status.Errorf(codes.InvalidArgument, err.Error()) - } + if err := validate(req); err != nil { + return err } return invoker(ctx, method, req, reply, cc, opts...) } @@ -64,10 +83,8 @@ func (s *recvWrapper) RecvMsg(m interface{}) error { if err := s.ServerStream.RecvMsg(m); err != nil { return err } - if v, ok := m.(validator); ok { - if err := v.Validate(); err != nil { - return status.Errorf(codes.InvalidArgument, err.Error()) - } + if err := validate(m); err != nil { + return err } return nil } diff --git a/interceptors/validator/validator_test.go b/interceptors/validator/validator_test.go index 4154a1c8c..3a8bf7933 100644 --- a/interceptors/validator/validator_test.go +++ b/interceptors/validator/validator_test.go @@ -1,7 +1,7 @@ // Copyright 2016 Michal Witkowski. All Rights Reserved. // See LICENSE for licensing terms. -package validator_test +package validator import ( "io" @@ -14,16 +14,23 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/validator" "github.com/grpc-ecosystem/go-grpc-middleware/v2/testing/testpb" ) +func TestValidateWrapper(t *testing.T) { + assert.NoError(t, validate(testpb.GoodPing)) + assert.Error(t, validate(testpb.BadPing)) + + assert.NoError(t, validate(testpb.GoodPingResponse)) + assert.Error(t, validate(testpb.BadPingResponse)) +} + func TestValidatorTestSuite(t *testing.T) { s := &ValidatorTestSuite{ InterceptorTestSuite: &testpb.InterceptorTestSuite{ ServerOpts: []grpc.ServerOption{ - grpc.StreamInterceptor(validator.StreamServerInterceptor()), - grpc.UnaryInterceptor(validator.UnaryServerInterceptor()), + grpc.StreamInterceptor(StreamServerInterceptor()), + grpc.UnaryInterceptor(UnaryServerInterceptor()), }, }, } @@ -32,7 +39,7 @@ func TestValidatorTestSuite(t *testing.T) { cs := &ClientValidatorTestSuite{ InterceptorTestSuite: &testpb.InterceptorTestSuite{ ClientOpts: []grpc.DialOption{ - grpc.WithUnaryInterceptor(validator.UnaryClientInterceptor()), + grpc.WithUnaryInterceptor(UnaryClientInterceptor()), }, }, } diff --git a/testing/testpb/test.manual_validator.pb.go b/testing/testpb/test.manual_validator.pb.go index a2d438b2f..6bbf3147f 100644 --- a/testing/testpb/test.manual_validator.pb.go +++ b/testing/testpb/test.manual_validator.pb.go @@ -2,36 +2,48 @@ package testpb -import "github.com/pkg/errors" +import ( + "math" -func (x *PingRequest) Validate() error { + "github.com/pkg/errors" +) + +func (x *PingRequest) Validate(bool) error { if x.SleepTimeMs > 10000 { return errors.New("cannot sleep for more than 10s") } return nil } -func (x *PingErrorRequest) Validate() error { +func (x *PingErrorRequest) Validate(bool) error { if x.SleepTimeMs > 10000 { return errors.New("cannot sleep for more than 10s") } return nil } -func (x *PingListRequest) Validate() error { +func (x *PingListRequest) Validate(bool) error { if x.SleepTimeMs > 10000 { return errors.New("cannot sleep for more than 10s") } return nil } -func (x *PingStreamRequest) Validate() error { +func (x *PingStreamRequest) Validate(bool) error { if x.SleepTimeMs > 10000 { return errors.New("cannot sleep for more than 10s") } return nil } +// Implements the legacy validation interface from protoc-gen-validate. +func (x *PingResponse) Validate() error { + if x.Counter > math.MaxInt16 { + return errors.New("ping allocation exceeded") + } + return nil +} + var ( GoodPing = &PingRequest{Value: "something", SleepTimeMs: 9999} GoodPingError = &PingErrorRequest{Value: "something", SleepTimeMs: 9999} @@ -42,4 +54,7 @@ var ( BadPingError = &PingErrorRequest{Value: "something", SleepTimeMs: 10001} BadPingList = &PingListRequest{Value: "something", SleepTimeMs: 10001} BadPingStream = &PingStreamRequest{Value: "something", SleepTimeMs: 10001} + + GoodPingResponse = &PingResponse{Counter: 100} + BadPingResponse = &PingResponse{Counter: math.MaxInt16 + 1} ) From f60016a9530e47b91eedf1833f65e21e591ed769 Mon Sep 17 00:00:00 2001 From: Mikhail Mazurskiy <126021+ash2k@users.noreply.github.com> Date: Sat, 24 Apr 2021 04:48:10 +1000 Subject: [PATCH 22/27] Refactor metrics interceptor and fix tests (#413) --- interceptors/client.go | 8 +- interceptors/client_test.go | 12 +- providers/openmetrics/client_interceptor.go | 22 +-- providers/openmetrics/client_metrics.go | 172 +++++++------------- providers/openmetrics/client_options.go | 74 +++++++++ providers/openmetrics/client_test.go | 69 ++++---- providers/openmetrics/go.mod | 2 + providers/openmetrics/go.sum | 7 - providers/openmetrics/options.go | 9 + providers/openmetrics/reporter.go | 21 ++- providers/openmetrics/server_interceptor.go | 22 +-- providers/openmetrics/server_metrics.go | 100 ++++++------ providers/openmetrics/server_options.go | 40 +++++ providers/openmetrics/server_test.go | 107 ++++++------ 14 files changed, 355 insertions(+), 310 deletions(-) create mode 100644 providers/openmetrics/client_options.go create mode 100644 providers/openmetrics/server_options.go diff --git a/interceptors/client.go b/interceptors/client.go index 051c92c7f..df29ef1ea 100644 --- a/interceptors/client.go +++ b/interceptors/client.go @@ -7,6 +7,7 @@ package interceptors import ( "context" + "io" "time" "google.golang.org/grpc" @@ -74,7 +75,10 @@ func (s *monitoredClientStream) RecvMsg(m interface{}) error { if err == nil { return nil } - - s.reporter.PostCall(err, time.Since(s.startTime)) + var postErr error + if err != io.EOF { + postErr = err + } + s.reporter.PostCall(postErr, time.Since(s.startTime)) return err } diff --git a/interceptors/client_test.go b/interceptors/client_test.go index 84a48830c..b90953cc3 100644 --- a/interceptors/client_test.go +++ b/interceptors/client_test.go @@ -50,7 +50,7 @@ func (m *mockReportable) Equal(t *testing.T, expected []*mockReport) { require.NoError(t, err) continue } - require.Equal(t, expected[i].postCalls[k].Error(), err.Error(), "%v %v", i, k) + require.EqualError(t, err, expected[i].postCalls[k].Error(), "%v %v", i, k) } require.Len(t, expected[i].postMsgSends, len(e.postMsgSends), "%v", i) for k, err := range e.postMsgSends { @@ -276,7 +276,7 @@ func (s *ClientInterceptorTestSuite) TestListReporting() { typ: ServerStream, svcName: testpb.TestServiceFullName, methodName: "PingList", - postCalls: []error{io.EOF}, + postCalls: []error{nil}, postMsgReceives: append(make([]error, testpb.ListResponseCount), io.EOF), postMsgSends: []error{nil}, }}) @@ -329,7 +329,9 @@ func (s *ClientInterceptorTestSuite) TestBiStreamingReporting() { if err == io.EOF { break } - require.NoError(s.T(), err, "reading pingStream shouldn't fail") + if !s.Assert().NoError(err, "reading pingStream shouldn't fail") { + break + } count++ } }() @@ -340,12 +342,12 @@ func (s *ClientInterceptorTestSuite) TestBiStreamingReporting() { require.NoError(s.T(), ss.CloseSend()) wg.Wait() - require.EqualValues(s.T(), count, 100, "Number of received msg on the wire must match") + require.EqualValues(s.T(), 100, count, "Number of received msg on the wire must match") s.mock.Equal(s.T(), []*mockReport{{ typ: BidiStream, svcName: testpb.TestServiceFullName, methodName: "PingStream", - postCalls: []error{io.EOF}, + postCalls: []error{nil}, postMsgReceives: append(make([]error, 100), io.EOF), postMsgSends: make([]error, 100), }}) diff --git a/providers/openmetrics/client_interceptor.go b/providers/openmetrics/client_interceptor.go index a16126e8b..1ce779f36 100644 --- a/providers/openmetrics/client_interceptor.go +++ b/providers/openmetrics/client_interceptor.go @@ -1,35 +1,21 @@ package metrics import ( - openmetrics "github.com/prometheus/client_golang/prometheus" "google.golang.org/grpc" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors" ) -// RegisterClientMetrics returns a custom ClientMetrics object registered -// with the user's registry, and registers some common metrics associated -// with every instance. -func RegisterClientMetrics(registry openmetrics.Registerer) *ClientMetrics { - customClientMetrics := NewClientMetrics(registry) - customClientMetrics.MustRegister(customClientMetrics.clientStartedCounter) - customClientMetrics.MustRegister(customClientMetrics.clientHandledCounter) - customClientMetrics.MustRegister(customClientMetrics.clientStreamMsgReceived) - customClientMetrics.MustRegister(customClientMetrics.clientStreamMsgSent) - - return customClientMetrics -} - // UnaryClientInterceptor is a gRPC client-side interceptor that provides Prometheus monitoring for Unary RPCs. -func UnaryClientInterceptor(clientRegister openmetrics.Registerer) grpc.UnaryClientInterceptor { +func UnaryClientInterceptor(clientMetrics *ClientMetrics) grpc.UnaryClientInterceptor { return interceptors.UnaryClientInterceptor(&reportable{ - registry: clientRegister, + clientMetrics: clientMetrics, }) } // StreamClientInterceptor is a gRPC client-side interceptor that provides Prometheus monitoring for Streaming RPCs. -func StreamClientInterceptor(clientRegister openmetrics.Registerer) grpc.StreamClientInterceptor { +func StreamClientInterceptor(clientMetrics *ClientMetrics) grpc.StreamClientInterceptor { return interceptors.StreamClientInterceptor(&reportable{ - registry: clientRegister, + clientMetrics: clientMetrics, }) } diff --git a/providers/openmetrics/client_metrics.go b/providers/openmetrics/client_metrics.go index 0a0477aea..e50025316 100644 --- a/providers/openmetrics/client_metrics.go +++ b/providers/openmetrics/client_metrics.go @@ -1,99 +1,103 @@ package metrics import ( - "github.com/prometheus/client_golang/prometheus" openmetrics "github.com/prometheus/client_golang/prometheus" ) // ClientMetrics represents a collection of metrics to be registered on a // Prometheus metrics registry for a gRPC client. type ClientMetrics struct { - clientRegister openmetrics.Registerer - clientStartedCounter *openmetrics.CounterVec clientHandledCounter *openmetrics.CounterVec clientStreamMsgReceived *openmetrics.CounterVec clientStreamMsgSent *openmetrics.CounterVec - clientHandledHistogramEnabled bool - clientHandledHistogramOpts openmetrics.HistogramOpts - clientHandledHistogram *openmetrics.HistogramVec - - clientStreamRecvHistogramEnabled bool - clientStreamRecvHistogramOpts openmetrics.HistogramOpts - clientStreamRecvHistogram *openmetrics.HistogramVec - - clientStreamSendHistogramEnabled bool - clientStreamSendHistogramOpts openmetrics.HistogramOpts - clientStreamSendHistogram *openmetrics.HistogramVec + // clientHandledHistogram can be nil + clientHandledHistogram *openmetrics.HistogramVec + // clientStreamRecvHistogram can be nil + clientStreamRecvHistogram *openmetrics.HistogramVec + // clientStreamSendHistogram can be nil + clientStreamSendHistogram *openmetrics.HistogramVec } -// NewClientMetrics returns a ClientMetrics object. Use a new instance of -// ClientMetrics when not using the default Prometheus metrics registry, for -// example when wanting to control which metrics are added to a registry as -// opposed to automatically adding metrics via init functions. -func NewClientMetrics(clientRegistry prometheus.Registerer, counterOpts ...CounterOption) *ClientMetrics { - opts := counterOptions(counterOpts) +// NewClientMetrics returns a new ClientMetrics object. +func NewClientMetrics(opts ...ClientMetricsOption) *ClientMetrics { + var config clientMetricsConfig + config.apply(opts) return &ClientMetrics{ - clientRegister: clientRegistry, clientStartedCounter: openmetrics.NewCounterVec( - opts.apply(openmetrics.CounterOpts{ + config.counterOpts.apply(openmetrics.CounterOpts{ Name: "grpc_client_started_total", Help: "Total number of RPCs started on the client.", }), []string{"grpc_type", "grpc_service", "grpc_method"}), clientHandledCounter: openmetrics.NewCounterVec( - opts.apply(openmetrics.CounterOpts{ + config.counterOpts.apply(openmetrics.CounterOpts{ Name: "grpc_client_handled_total", Help: "Total number of RPCs completed by the client, regardless of success or failure.", }), []string{"grpc_type", "grpc_service", "grpc_method", "grpc_code"}), clientStreamMsgReceived: openmetrics.NewCounterVec( - opts.apply(openmetrics.CounterOpts{ + config.counterOpts.apply(openmetrics.CounterOpts{ Name: "grpc_client_msg_received_total", Help: "Total number of RPC stream messages received by the client.", }), []string{"grpc_type", "grpc_service", "grpc_method"}), clientStreamMsgSent: openmetrics.NewCounterVec( - opts.apply(openmetrics.CounterOpts{ + config.counterOpts.apply(openmetrics.CounterOpts{ Name: "grpc_client_msg_sent_total", Help: "Total number of gRPC stream messages sent by the client.", }), []string{"grpc_type", "grpc_service", "grpc_method"}), - clientHandledHistogramEnabled: false, - clientHandledHistogramOpts: openmetrics.HistogramOpts{ - Name: "grpc_client_handling_seconds", - Help: "Histogram of response latency (seconds) of the gRPC until it is finished by the application.", - Buckets: openmetrics.DefBuckets, - }, - clientHandledHistogram: nil, - clientStreamRecvHistogramEnabled: false, - clientStreamRecvHistogramOpts: openmetrics.HistogramOpts{ - Name: "grpc_client_msg_recv_handling_seconds", - Help: "Histogram of response latency (seconds) of the gRPC single message receive.", - Buckets: openmetrics.DefBuckets, - }, - clientStreamRecvHistogram: nil, - clientStreamSendHistogramEnabled: false, - clientStreamSendHistogramOpts: openmetrics.HistogramOpts{ - Name: "grpc_client_msg_send_handling_seconds", - Help: "Histogram of response latency (seconds) of the gRPC single message send.", - Buckets: openmetrics.DefBuckets, - }, - clientStreamSendHistogram: nil, + clientHandledHistogram: config.clientHandledHistogram, + clientStreamRecvHistogram: config.clientStreamRecvHistogram, + clientStreamSendHistogram: config.clientStreamSendHistogram, } } -// Register registers the provided Collector with the custom register. +// NewRegisteredClientMetrics returns a custom ClientMetrics object registered +// with the user's registry, and registers some common metrics associated +// with every instance. +func NewRegisteredClientMetrics(registry openmetrics.Registerer, opts ...ClientMetricsOption) *ClientMetrics { + customClientMetrics := NewClientMetrics(opts...) + customClientMetrics.MustRegister(registry) + return customClientMetrics +} + +// Register registers the metrics with the registry. // returns error much like DefaultRegisterer of Prometheus. -func (m *ClientMetrics) Register(c openmetrics.Collector) error { - return m.clientRegister.Register(c) +func (m *ClientMetrics) Register(registry openmetrics.Registerer) error { + for _, collector := range m.toRegister() { + if err := registry.Register(collector); err != nil { + return err + } + } + return nil } -// MustRegister registers the provided Collectors with the custom Registerer +// MustRegister registers the metrics with the registry // and panics if any error occurs much like DefaultRegisterer of Prometheus. -func (m *ClientMetrics) MustRegister(c openmetrics.Collector) { - m.clientRegister.MustRegister(c) +func (m *ClientMetrics) MustRegister(registry openmetrics.Registerer) { + registry.MustRegister(m.toRegister()...) +} + +func (m *ClientMetrics) toRegister() []openmetrics.Collector { + res := []openmetrics.Collector{ + m.clientStartedCounter, + m.clientHandledCounter, + m.clientStreamMsgReceived, + m.clientStreamMsgSent, + } + if m.clientHandledHistogram != nil { + res = append(res, m.clientHandledHistogram) + } + if m.clientStreamRecvHistogram != nil { + res = append(res, m.clientStreamRecvHistogram) + } + if m.clientStreamSendHistogram != nil { + res = append(res, m.clientStreamSendHistogram) + } + return res } // Describe sends the super-set of all possible descriptors of metrics @@ -104,13 +108,13 @@ func (m *ClientMetrics) Describe(ch chan<- *openmetrics.Desc) { m.clientHandledCounter.Describe(ch) m.clientStreamMsgReceived.Describe(ch) m.clientStreamMsgSent.Describe(ch) - if m.clientHandledHistogramEnabled { + if m.clientHandledHistogram != nil { m.clientHandledHistogram.Describe(ch) } - if m.clientStreamRecvHistogramEnabled { + if m.clientStreamRecvHistogram != nil { m.clientStreamRecvHistogram.Describe(ch) } - if m.clientStreamSendHistogramEnabled { + if m.clientStreamSendHistogram != nil { m.clientStreamSendHistogram.Describe(ch) } } @@ -123,65 +127,13 @@ func (m *ClientMetrics) Collect(ch chan<- openmetrics.Metric) { m.clientHandledCounter.Collect(ch) m.clientStreamMsgReceived.Collect(ch) m.clientStreamMsgSent.Collect(ch) - if m.clientHandledHistogramEnabled { + if m.clientHandledHistogram != nil { m.clientHandledHistogram.Collect(ch) } - if m.clientStreamRecvHistogramEnabled { + if m.clientStreamRecvHistogram != nil { m.clientStreamRecvHistogram.Collect(ch) } - if m.clientStreamSendHistogramEnabled { + if m.clientStreamSendHistogram != nil { m.clientStreamSendHistogram.Collect(ch) } } - -// EnableClientHandlingTimeHistogram turns on recording of handling time of RPCs. -// Histogram metrics can be very expensive for Prometheus to retain and query. -func (m *ClientMetrics) EnableClientHandlingTimeHistogram(opts ...HistogramOption) error { - for _, o := range opts { - o(&m.clientHandledHistogramOpts) - } - if !m.clientHandledHistogramEnabled { - m.clientHandledHistogram = openmetrics.NewHistogramVec( - m.clientHandledHistogramOpts, - []string{"grpc_type", "grpc_service", "grpc_method"}, - ) - } - m.clientHandledHistogramEnabled = true - return m.clientRegister.Register(m.clientHandledHistogram) -} - -// EnableClientStreamReceiveTimeHistogram turns on recording of single message receive time of streaming RPCs. -// Histogram metrics can be very expensive for Prometheus to retain and query. -func (m *ClientMetrics) EnableClientStreamReceiveTimeHistogram(opts ...HistogramOption) error { - for _, o := range opts { - o(&m.clientStreamRecvHistogramOpts) - } - - if !m.clientStreamRecvHistogramEnabled { - m.clientStreamRecvHistogram = openmetrics.NewHistogramVec( - m.clientStreamRecvHistogramOpts, - []string{"grpc_type", "grpc_service", "grpc_method"}, - ) - } - - m.clientStreamRecvHistogramEnabled = true - return m.clientRegister.Register(m.clientStreamRecvHistogram) -} - -// EnableClientStreamSendTimeHistogram turns on recording of single message send time of streaming RPCs. -// Histogram metrics can be very expensive for Prometheus to retain and query. -func (m *ClientMetrics) EnableClientStreamSendTimeHistogram(opts ...HistogramOption) error { - for _, o := range opts { - o(&m.clientStreamSendHistogramOpts) - } - - if !m.clientStreamSendHistogramEnabled { - m.clientStreamSendHistogram = openmetrics.NewHistogramVec( - m.clientStreamSendHistogramOpts, - []string{"grpc_type", "grpc_service", "grpc_method"}, - ) - } - - m.clientStreamSendHistogramEnabled = true - return m.clientRegister.Register(m.clientStreamSendHistogram) -} diff --git a/providers/openmetrics/client_options.go b/providers/openmetrics/client_options.go new file mode 100644 index 000000000..7175f711c --- /dev/null +++ b/providers/openmetrics/client_options.go @@ -0,0 +1,74 @@ +package metrics + +import ( + openmetrics "github.com/prometheus/client_golang/prometheus" +) + +type clientMetricsConfig struct { + counterOpts counterOptions + // clientHandledHistogram can be nil + clientHandledHistogram *openmetrics.HistogramVec + // clientStreamRecvHistogram can be nil + clientStreamRecvHistogram *openmetrics.HistogramVec + // clientStreamSendHistogram can be nil + clientStreamSendHistogram *openmetrics.HistogramVec +} + +type ClientMetricsOption func(*clientMetricsConfig) + +func (c *clientMetricsConfig) apply(opts []ClientMetricsOption) { + for _, o := range opts { + o(c) + } +} + +func WithClientCounterOptions(opts ...CounterOption) ClientMetricsOption { + return func(o *clientMetricsConfig) { + o.counterOpts = opts + } +} + +// WithClientHandlingTimeHistogram turns on recording of handling time of RPCs. +// Histogram metrics can be very expensive for Prometheus to retain and query. +func WithClientHandlingTimeHistogram(opts ...HistogramOption) ClientMetricsOption { + return func(o *clientMetricsConfig) { + o.clientHandledHistogram = openmetrics.NewHistogramVec( + histogramOptions(opts).apply(openmetrics.HistogramOpts{ + Name: "grpc_client_handling_seconds", + Help: "Histogram of response latency (seconds) of the gRPC until it is finished by the application.", + Buckets: openmetrics.DefBuckets, + }), + []string{"grpc_type", "grpc_service", "grpc_method"}, + ) + } +} + +// WithClientStreamRecvHistogram turns on recording of single message receive time of streaming RPCs. +// Histogram metrics can be very expensive for Prometheus to retain and query. +func WithClientStreamRecvHistogram(opts ...HistogramOption) ClientMetricsOption { + return func(o *clientMetricsConfig) { + o.clientStreamRecvHistogram = openmetrics.NewHistogramVec( + histogramOptions(opts).apply(openmetrics.HistogramOpts{ + Name: "grpc_client_msg_recv_handling_seconds", + Help: "Histogram of response latency (seconds) of the gRPC single message receive.", + Buckets: openmetrics.DefBuckets, + }), + []string{"grpc_type", "grpc_service", "grpc_method"}, + ) + } +} + +// WithClientStreamSendHistogram turns on recording of single message send time of streaming RPCs. +// Histogram metrics can be very expensive for Prometheus to retain and query. +func WithClientStreamSendHistogram(opts ...HistogramOption) ClientMetricsOption { + return func(o *clientMetricsConfig) { + o.clientStreamSendHistogram = openmetrics.NewHistogramVec( + histogramOptions(opts).apply(openmetrics.HistogramOpts{ + Name: "grpc_client_msg_send_handling_seconds", + Help: "Histogram of response latency (seconds) of the gRPC single message send.", + Buckets: openmetrics.DefBuckets, + }), + []string{"grpc_type", "grpc_service", "grpc_method"}, + ) + } +} diff --git a/providers/openmetrics/client_test.go b/providers/openmetrics/client_test.go index c6b0c9602..59830c5a8 100644 --- a/providers/openmetrics/client_test.go +++ b/providers/openmetrics/client_test.go @@ -7,17 +7,13 @@ import ( "testing" "time" - pb_testproto "github.com/grpc-ecosystem/go-grpc-middleware/providers/openmetrics/v2/testproto/v1" - "github.com/prometheus/client_golang/prometheus" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" -) -var ( - DefaultClientMetrics *ClientMetrics = NewClientMetrics(prometheus.DefaultRegisterer) + pb_testproto "github.com/grpc-ecosystem/go-grpc-middleware/providers/openmetrics/v2/testproto/v1" ) func TestClientInterceptorSuite(t *testing.T) { @@ -33,12 +29,13 @@ type ClientInterceptorTestSuite struct { testClient pb_testproto.TestServiceClient ctx context.Context cancel context.CancelFunc + clientMetrics *ClientMetrics } func (s *ClientInterceptorTestSuite) SetupSuite() { var err error - DefaultClientMetrics.EnableClientHandlingTimeHistogram() + s.clientMetrics = NewClientMetrics(WithClientHandlingTimeHistogram()) s.serverListener, err = net.Listen("tcp", "127.0.0.1:0") require.NoError(s.T(), err, "must be able to allocate a port for serverListener") @@ -55,8 +52,8 @@ func (s *ClientInterceptorTestSuite) SetupSuite() { s.serverListener.Addr().String(), grpc.WithInsecure(), grpc.WithBlock(), - grpc.WithUnaryInterceptor(UnaryClientInterceptor(prometheus.DefaultRegisterer)), - grpc.WithStreamInterceptor(StreamClientInterceptor(prometheus.DefaultRegisterer)), + grpc.WithUnaryInterceptor(UnaryClientInterceptor(s.clientMetrics)), + grpc.WithStreamInterceptor(StreamClientInterceptor(s.clientMetrics)), grpc.WithTimeout(2*time.Second)) require.NoError(s.T(), err, "must not error on client Dial") s.testClient = pb_testproto.NewTestServiceClient(s.clientConn) @@ -67,22 +64,21 @@ func (s *ClientInterceptorTestSuite) SetupTest() { s.ctx, s.cancel = context.WithTimeout(context.TODO(), 2*time.Second) // Make sure every test starts with same fresh, intialized metric state. - DefaultClientMetrics.clientStartedCounter.Reset() - DefaultClientMetrics.clientHandledCounter.Reset() - DefaultClientMetrics.clientHandledHistogram.Reset() - DefaultClientMetrics.clientStreamMsgReceived.Reset() - DefaultClientMetrics.clientStreamMsgSent.Reset() + s.clientMetrics.clientStartedCounter.Reset() + s.clientMetrics.clientHandledCounter.Reset() + s.clientMetrics.clientHandledHistogram.Reset() + s.clientMetrics.clientStreamMsgReceived.Reset() + s.clientMetrics.clientStreamMsgSent.Reset() } func (s *ClientInterceptorTestSuite) TearDownSuite() { + if s.clientConn != nil { + s.clientConn.Close() + } if s.serverListener != nil { s.server.Stop() s.T().Logf("stopped grpc.Server at: %v", s.serverListener.Addr().String()) s.serverListener.Close() - - } - if s.clientConn != nil { - s.clientConn.Close() } } @@ -93,33 +89,34 @@ func (s *ClientInterceptorTestSuite) TearDownTest() { func (s *ClientInterceptorTestSuite) TestUnaryIncrementsMetrics() { _, err := s.testClient.PingEmpty(s.ctx, &pb_testproto.PingEmptyRequest{}) // should return with code=OK require.NoError(s.T(), err) - requireValue(s.T(), 1, DefaultClientMetrics.clientStartedCounter.WithLabelValues("unary", "mwitkow.testproto.TestService", "PingEmpty")) - requireValue(s.T(), 1, DefaultClientMetrics.clientHandledCounter.WithLabelValues("unary", "mwitkow.testproto.TestService", "PingEmpty", "OK")) - requireValueHistCount(s.T(), 1, DefaultClientMetrics.clientHandledHistogram.WithLabelValues("unary", "mwitkow.testproto.TestService", "PingEmpty")) + requireValue(s.T(), 1, s.clientMetrics.clientStartedCounter.WithLabelValues("unary", "providers.openmetrics.testproto.v1.TestService", "PingEmpty")) + requireValue(s.T(), 1, s.clientMetrics.clientHandledCounter.WithLabelValues("unary", "providers.openmetrics.testproto.v1.TestService", "PingEmpty", "OK")) + requireValueHistCount(s.T(), 1, s.clientMetrics.clientHandledHistogram.WithLabelValues("unary", "providers.openmetrics.testproto.v1.TestService", "PingEmpty")) _, err = s.testClient.PingError(s.ctx, &pb_testproto.PingErrorRequest{ErrorCodeReturned: uint32(codes.FailedPrecondition)}) // should return with code=FailedPrecondition require.Error(s.T(), err) - requireValue(s.T(), 1, DefaultClientMetrics.clientStartedCounter.WithLabelValues("unary", "mwitkow.testproto.TestService", "PingError")) - requireValue(s.T(), 1, DefaultClientMetrics.clientHandledCounter.WithLabelValues("unary", "mwitkow.testproto.TestService", "PingError", "FailedPrecondition")) - requireValueHistCount(s.T(), 1, DefaultClientMetrics.clientHandledHistogram.WithLabelValues("unary", "mwitkow.testproto.TestService", "PingError")) + requireValue(s.T(), 1, s.clientMetrics.clientStartedCounter.WithLabelValues("unary", "providers.openmetrics.testproto.v1.TestService", "PingError")) + requireValue(s.T(), 1, s.clientMetrics.clientHandledCounter.WithLabelValues("unary", "providers.openmetrics.testproto.v1.TestService", "PingError", "FailedPrecondition")) + requireValueHistCount(s.T(), 1, s.clientMetrics.clientHandledHistogram.WithLabelValues("unary", "providers.openmetrics.testproto.v1.TestService", "PingError")) } func (s *ClientInterceptorTestSuite) TestStartedStreamingIncrementsStarted() { _, err := s.testClient.PingList(s.ctx, &pb_testproto.PingListRequest{}) require.NoError(s.T(), err) - requireValue(s.T(), 1, DefaultClientMetrics.clientStartedCounter.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList")) + requireValue(s.T(), 1, s.clientMetrics.clientStartedCounter.WithLabelValues("server_stream", "providers.openmetrics.testproto.v1.TestService", "PingList")) _, err = s.testClient.PingList(s.ctx, &pb_testproto.PingListRequest{ErrorCodeReturned: uint32(codes.FailedPrecondition)}) // should return with code=FailedPrecondition require.NoError(s.T(), err, "PingList must not fail immediately") - requireValue(s.T(), 2, DefaultClientMetrics.clientStartedCounter.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList")) + requireValue(s.T(), 2, s.clientMetrics.clientStartedCounter.WithLabelValues("server_stream", "providers.openmetrics.testproto.v1.TestService", "PingList")) } func (s *ClientInterceptorTestSuite) TestStreamingIncrementsMetrics() { - ss, _ := s.testClient.PingList(s.ctx, &pb_testproto.PingListRequest{}) // should return with code=OK + ss, err := s.testClient.PingList(s.ctx, &pb_testproto.PingListRequest{}) // should return with code=OK + require.NoError(s.T(), err) // Do a read, just for kicks. count := 0 for { - _, err := ss.Recv() + _, err = ss.Recv() if err == io.EOF { break } @@ -128,13 +125,13 @@ func (s *ClientInterceptorTestSuite) TestStreamingIncrementsMetrics() { } require.EqualValues(s.T(), countListResponses, count, "Number of received msg on the wire must match") - requireValue(s.T(), 1, DefaultClientMetrics.clientStartedCounter.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList")) - requireValue(s.T(), 1, DefaultClientMetrics.clientHandledCounter.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList", "OK")) - requireValue(s.T(), countListResponses, DefaultClientMetrics.clientStreamMsgReceived.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList")) - requireValue(s.T(), 1, DefaultClientMetrics.clientStreamMsgSent.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList")) - requireValueHistCount(s.T(), 1, DefaultClientMetrics.clientHandledHistogram.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList")) + requireValue(s.T(), 1, s.clientMetrics.clientStartedCounter.WithLabelValues("server_stream", "providers.openmetrics.testproto.v1.TestService", "PingList")) + requireValue(s.T(), 1, s.clientMetrics.clientHandledCounter.WithLabelValues("server_stream", "providers.openmetrics.testproto.v1.TestService", "PingList", "OK")) + requireValue(s.T(), countListResponses+1 /* + EOF */, s.clientMetrics.clientStreamMsgReceived.WithLabelValues("server_stream", "providers.openmetrics.testproto.v1.TestService", "PingList")) + requireValue(s.T(), 1, s.clientMetrics.clientStreamMsgSent.WithLabelValues("server_stream", "providers.openmetrics.testproto.v1.TestService", "PingList")) + requireValueHistCount(s.T(), 1, s.clientMetrics.clientHandledHistogram.WithLabelValues("server_stream", "providers.openmetrics.testproto.v1.TestService", "PingList")) - ss, err := s.testClient.PingList(s.ctx, &pb_testproto.PingListRequest{ErrorCodeReturned: uint32(codes.FailedPrecondition)}) // should return with code=FailedPrecondition + ss, err = s.testClient.PingList(s.ctx, &pb_testproto.PingListRequest{ErrorCodeReturned: uint32(codes.FailedPrecondition)}) // should return with code=FailedPrecondition require.NoError(s.T(), err, "PingList must not fail immediately") // Do a read, just to progate errors. @@ -142,7 +139,7 @@ func (s *ClientInterceptorTestSuite) TestStreamingIncrementsMetrics() { st, _ := status.FromError(err) require.Equal(s.T(), codes.FailedPrecondition, st.Code(), "Recv must return FailedPrecondition, otherwise the test is wrong") - requireValue(s.T(), 2, DefaultClientMetrics.clientStartedCounter.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList")) - requireValue(s.T(), 1, DefaultClientMetrics.clientHandledCounter.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList", "FailedPrecondition")) - requireValueHistCount(s.T(), 2, DefaultClientMetrics.clientHandledHistogram.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList")) + requireValue(s.T(), 2, s.clientMetrics.clientStartedCounter.WithLabelValues("server_stream", "providers.openmetrics.testproto.v1.TestService", "PingList")) + requireValue(s.T(), 1, s.clientMetrics.clientHandledCounter.WithLabelValues("server_stream", "providers.openmetrics.testproto.v1.TestService", "PingList", "FailedPrecondition")) + requireValueHistCount(s.T(), 2, s.clientMetrics.clientHandledHistogram.WithLabelValues("server_stream", "providers.openmetrics.testproto.v1.TestService", "PingList")) } diff --git a/providers/openmetrics/go.mod b/providers/openmetrics/go.mod index 81d646e5d..b8b57a4ca 100644 --- a/providers/openmetrics/go.mod +++ b/providers/openmetrics/go.mod @@ -11,3 +11,5 @@ require ( google.golang.org/grpc v1.35.0 google.golang.org/protobuf v1.25.0 ) + +replace github.com/grpc-ecosystem/go-grpc-middleware/v2 => ../.. diff --git a/providers/openmetrics/go.sum b/providers/openmetrics/go.sum index b557e49e6..a1dca24ea 100644 --- a/providers/openmetrics/go.sum +++ b/providers/openmetrics/go.sum @@ -72,7 +72,6 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -111,9 +110,6 @@ github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 h1:z53tR0945TRRQO/fLEVPI6SMv7ZflF0TEaTAoU7tOzg= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20210128111500-3ff779b52992 h1:zQBrssA5h0QjXbr/d560qCC1L48fFjCxx6Ld1r4d+J4= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20210128111500-3ff779b52992/go.mod h1:fG+XdHpfvMfdBQ9GTIRX0nXjb+VHaMWV5o9OCgw6Qi8= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= @@ -271,7 +267,6 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -384,7 +379,6 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200624020401-64a14ca9d1ad h1:uAwc13+y0Y8QZLTYhLCu6lHhnG99ecQU5FYTj8zxAng= google.golang.org/genproto v0.0.0-20200624020401-64a14ca9d1ad/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -432,7 +426,6 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/providers/openmetrics/options.go b/providers/openmetrics/options.go index 3efe38ad6..bac07f849 100644 --- a/providers/openmetrics/options.go +++ b/providers/openmetrics/options.go @@ -36,6 +36,15 @@ func WithConstLabels(labels openmetrics.Labels) CounterOption { // funcs. type HistogramOption func(*openmetrics.HistogramOpts) +type histogramOptions []HistogramOption + +func (ho histogramOptions) apply(o openmetrics.HistogramOpts) openmetrics.HistogramOpts { + for _, f := range ho { + f(&o) + } + return o +} + // WithHistogramBuckets allows you to specify custom bucket ranges for histograms if EnableHandlingTimeHistogram is on. func WithHistogramBuckets(buckets []float64) HistogramOption { return func(o *openmetrics.HistogramOpts) { o.Buckets = buckets } diff --git a/providers/openmetrics/reporter.go b/providers/openmetrics/reporter.go index b526d8c38..9319e18b0 100644 --- a/providers/openmetrics/reporter.go +++ b/providers/openmetrics/reporter.go @@ -28,13 +28,13 @@ func (r *reporter) PostCall(err error, duration time.Duration) { switch r.kind { case KindServer: r.serverMetrics.serverHandledCounter.WithLabelValues(string(r.typ), r.service, r.method, code.String()).Inc() - if r.serverMetrics.serverHandledHistogramEnabled { + if r.serverMetrics.serverHandledHistogram != nil { r.serverMetrics.serverHandledHistogram.WithLabelValues(string(r.typ), r.service, r.method).Observe(time.Since(r.startTime).Seconds()) } case KindClient: r.clientMetrics.clientHandledCounter.WithLabelValues(string(r.typ), r.service, r.method, code.String()).Inc() - if r.clientMetrics.clientHandledHistogramEnabled { + if r.clientMetrics.clientHandledHistogram != nil { r.clientMetrics.clientHandledHistogram.WithLabelValues(string(r.typ), r.service, r.method).Observe(time.Since(r.startTime).Seconds()) } } @@ -61,17 +61,16 @@ func (r *reporter) PostMsgReceive(_ interface{}, _ error, _ time.Duration) { } type reportable struct { - registry openmetrics.Registerer + clientMetrics *ClientMetrics + serverMetrics *ServerMetrics } func (rep *reportable) ServerReporter(ctx context.Context, _ interface{}, typ interceptors.GRPCType, service string, method string) (interceptors.Reporter, context.Context) { - m := NewServerMetrics(rep.registry) - return rep.reporter(m, nil, typ, service, method, KindServer) + return rep.reporter(rep.serverMetrics, nil, typ, service, method, KindServer) } func (rep *reportable) ClientReporter(ctx context.Context, _ interface{}, typ interceptors.GRPCType, service string, method string) (interceptors.Reporter, context.Context) { - m := NewClientMetrics(rep.registry) - return rep.reporter(nil, m, typ, service, method, KindClient) + return rep.reporter(nil, rep.clientMetrics, typ, service, method, KindClient) } func (rep *reportable) reporter(sm *ServerMetrics, cm *ClientMetrics, rpcType interceptors.GRPCType, service, method string, kind Kind) (interceptors.Reporter, context.Context) { @@ -88,22 +87,22 @@ func (rep *reportable) reporter(sm *ServerMetrics, cm *ClientMetrics, rpcType in switch kind { case KindClient: - if r.clientMetrics.clientHandledHistogramEnabled { + if r.clientMetrics.clientHandledHistogram != nil { r.startTime = time.Now() } r.clientMetrics.clientStartedCounter.WithLabelValues(string(r.typ), r.service, r.method).Inc() - if r.clientMetrics.clientStreamSendHistogramEnabled { + if r.clientMetrics.clientStreamSendHistogram != nil { hist := r.clientMetrics.clientStreamSendHistogram.WithLabelValues(string(r.typ), r.service, r.method) r.sendTimer = openmetrics.NewTimer(hist) } - if r.clientMetrics.clientStreamRecvHistogramEnabled { + if r.clientMetrics.clientStreamRecvHistogram != nil { hist := r.clientMetrics.clientStreamRecvHistogram.WithLabelValues(string(r.typ), r.service, r.method) r.receiveTimer = openmetrics.NewTimer(hist) } case KindServer: - if r.serverMetrics.serverHandledHistogramEnabled { + if r.serverMetrics.serverHandledHistogram != nil { r.startTime = time.Now() } r.serverMetrics.serverStartedCounter.WithLabelValues(string(r.typ), r.service, r.method).Inc() diff --git a/providers/openmetrics/server_interceptor.go b/providers/openmetrics/server_interceptor.go index ca3ed3b6c..47778a1f8 100644 --- a/providers/openmetrics/server_interceptor.go +++ b/providers/openmetrics/server_interceptor.go @@ -1,35 +1,21 @@ package metrics import ( - openmetrics "github.com/prometheus/client_golang/prometheus" "google.golang.org/grpc" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors" ) -// RegisterServerMetrics returns a custom ServerMetrics object registered -// with the user's registry, and registers some common metrics associated -// with every instance. -func RegisterServerMetrics(registry openmetrics.Registerer) *ServerMetrics { - customServerMetrics := NewServerMetrics(registry) - customServerMetrics.MustRegister(customServerMetrics.serverStartedCounter) - customServerMetrics.MustRegister(customServerMetrics.serverHandledCounter) - customServerMetrics.MustRegister(customServerMetrics.serverStreamMsgReceived) - customServerMetrics.MustRegister(customServerMetrics.serverStreamMsgSent) - - return customServerMetrics -} - // UnaryServerInterceptor is a gRPC server-side interceptor that provides Prometheus monitoring for Unary RPCs. -func UnaryServerInterceptor(serverRegister openmetrics.Registerer) grpc.UnaryServerInterceptor { +func UnaryServerInterceptor(serverMetrics *ServerMetrics) grpc.UnaryServerInterceptor { return interceptors.UnaryServerInterceptor(&reportable{ - registry: serverRegister, + serverMetrics: serverMetrics, }) } // StreamServerInterceptor is a gRPC server-side interceptor that provides Prometheus monitoring for Streaming RPCs. -func StreamServerInterceptor(serverRegister openmetrics.Registerer) grpc.StreamServerInterceptor { +func StreamServerInterceptor(serverMetrics *ServerMetrics) grpc.StreamServerInterceptor { return interceptors.StreamServerInterceptor(&reportable{ - registry: serverRegister, + serverMetrics: serverMetrics, }) } diff --git a/providers/openmetrics/server_metrics.go b/providers/openmetrics/server_metrics.go index 976338414..18259298d 100644 --- a/providers/openmetrics/server_metrics.go +++ b/providers/openmetrics/server_metrics.go @@ -2,92 +2,88 @@ package metrics import ( openmetrics "github.com/prometheus/client_golang/prometheus" + "google.golang.org/grpc" "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors" - - "google.golang.org/grpc" ) // ServerMetrics represents a collection of metrics to be registered on a // Prometheus metrics registry for a gRPC server. type ServerMetrics struct { - serverRegister openmetrics.Registerer - - serverStartedCounter *openmetrics.CounterVec - serverHandledCounter *openmetrics.CounterVec - serverStreamMsgReceived *openmetrics.CounterVec - serverStreamMsgSent *openmetrics.CounterVec - serverHandledHistogramEnabled bool - serverHandledHistogramOpts openmetrics.HistogramOpts - serverHandledHistogram *openmetrics.HistogramVec + serverStartedCounter *openmetrics.CounterVec + serverHandledCounter *openmetrics.CounterVec + serverStreamMsgReceived *openmetrics.CounterVec + serverStreamMsgSent *openmetrics.CounterVec + // serverHandledHistogram can be nil + serverHandledHistogram *openmetrics.HistogramVec } -// NewServerMetrics returns a ServerMetrics object. Use a new instance of -// ServerMetrics when not using the default Prometheus metrics registry, for -// example when wanting to control which metrics are added to a registry as -// opposed to automatically adding metrics via init functions. -func NewServerMetrics(serverRegistry openmetrics.Registerer, counterOpts ...CounterOption) *ServerMetrics { - opts := counterOptions(counterOpts) +// NewServerMetrics returns a new ServerMetrics object. +func NewServerMetrics(opts ...ServerMetricsOption) *ServerMetrics { + var config serverMetricsConfig + config.apply(opts) return &ServerMetrics{ - serverRegister: serverRegistry, serverStartedCounter: openmetrics.NewCounterVec( - opts.apply(openmetrics.CounterOpts{ + config.counterOpts.apply(openmetrics.CounterOpts{ Name: "grpc_server_started_total", Help: "Total number of RPCs started on the server.", }), []string{"grpc_type", "grpc_service", "grpc_method"}), serverHandledCounter: openmetrics.NewCounterVec( - opts.apply(openmetrics.CounterOpts{ + config.counterOpts.apply(openmetrics.CounterOpts{ Name: "grpc_server_handled_total", Help: "Total number of RPCs completed on the server, regardless of success or failure.", }), []string{"grpc_type", "grpc_service", "grpc_method", "grpc_code"}), serverStreamMsgReceived: openmetrics.NewCounterVec( - opts.apply(openmetrics.CounterOpts{ + config.counterOpts.apply(openmetrics.CounterOpts{ Name: "grpc_server_msg_received_total", Help: "Total number of RPC stream messages received on the server.", }), []string{"grpc_type", "grpc_service", "grpc_method"}), serverStreamMsgSent: openmetrics.NewCounterVec( - opts.apply(openmetrics.CounterOpts{ + config.counterOpts.apply(openmetrics.CounterOpts{ Name: "grpc_server_msg_sent_total", Help: "Total number of gRPC stream messages sent by the server.", }), []string{"grpc_type", "grpc_service", "grpc_method"}), - serverHandledHistogramEnabled: false, - serverHandledHistogramOpts: openmetrics.HistogramOpts{ - Name: "grpc_server_handling_seconds", - Help: "Histogram of response latency (seconds) of gRPC that had been application-level handled by the server.", - Buckets: openmetrics.DefBuckets, - }, - serverHandledHistogram: nil, + serverHandledHistogram: config.serverHandledHistogram, } } -// Register registers the provided Collector with the custom register. +// NewRegisteredServerMetrics returns a custom ServerMetrics object registered +// with the user's registry, and registers some common metrics associated +// with every instance. +func NewRegisteredServerMetrics(registry openmetrics.Registerer, opts ...ServerMetricsOption) *ServerMetrics { + customServerMetrics := NewServerMetrics(opts...) + customServerMetrics.MustRegister(registry) + return customServerMetrics +} + +// Register registers the metrics with the registry. // returns error much like DefaultRegisterer of Prometheus. -func (m *ServerMetrics) Register(c openmetrics.Collector) error { - return m.serverRegister.Register(c) +func (m *ServerMetrics) Register(registry openmetrics.Registerer) error { + for _, collector := range m.toRegister() { + if err := registry.Register(collector); err != nil { + return err + } + } + return nil } -// MustRegister registers the provided Collectors with the custom Registerer +// MustRegister registers the metrics with the registry // and panics if any error occurs much like DefaultRegisterer of Prometheus. -func (m *ServerMetrics) MustRegister(c openmetrics.Collector) { - m.serverRegister.MustRegister(c) +func (m *ServerMetrics) MustRegister(registry openmetrics.Registerer) { + registry.MustRegister(m.toRegister()...) } -// EnableHandlingTimeHistogram turns on recording of handling time -// of RPCs. Histogram metrics can be very expensive for Prometheus -// to retain and query.It takes options to configure histogram -// options such as the defined buckets. -func (m *ServerMetrics) EnableHandlingTimeHistogram(opts ...HistogramOption) error { - for _, o := range opts { - o(&m.serverHandledHistogramOpts) +func (m *ServerMetrics) toRegister() []openmetrics.Collector { + res := []openmetrics.Collector{ + m.serverStartedCounter, + m.serverHandledCounter, + m.serverStreamMsgReceived, + m.serverStreamMsgSent, } - if !m.serverHandledHistogramEnabled { - m.serverHandledHistogram = openmetrics.NewHistogramVec( - m.serverHandledHistogramOpts, - []string{"grpc_type", "grpc_service", "grpc_method"}, - ) + if m.serverHandledHistogram != nil { + res = append(res, m.serverHandledHistogram) } - m.serverHandledHistogramEnabled = true - return m.serverRegister.Register(m.serverHandledHistogram) + return res } // Describe sends the super-set of all possible descriptors of metrics @@ -98,7 +94,7 @@ func (m *ServerMetrics) Describe(ch chan<- *openmetrics.Desc) { m.serverHandledCounter.Describe(ch) m.serverStreamMsgReceived.Describe(ch) m.serverStreamMsgSent.Describe(ch) - if m.serverHandledHistogramEnabled { + if m.serverHandledHistogram != nil { m.serverHandledHistogram.Describe(ch) } } @@ -111,7 +107,7 @@ func (m *ServerMetrics) Collect(ch chan<- openmetrics.Metric) { m.serverHandledCounter.Collect(ch) m.serverStreamMsgReceived.Collect(ch) m.serverStreamMsgSent.Collect(ch) - if m.serverHandledHistogramEnabled { + if m.serverHandledHistogram != nil { m.serverHandledHistogram.Collect(ch) } } @@ -136,7 +132,7 @@ func (m *ServerMetrics) preRegisterMethod(serviceName string, mInfo *grpc.Method m.serverStartedCounter.GetMetricWithLabelValues(methodType, serviceName, methodName) m.serverStreamMsgReceived.GetMetricWithLabelValues(methodType, serviceName, methodName) m.serverStreamMsgSent.GetMetricWithLabelValues(methodType, serviceName, methodName) - if m.serverHandledHistogramEnabled { + if m.serverHandledHistogram != nil { m.serverHandledHistogram.GetMetricWithLabelValues(methodType, serviceName, methodName) } for _, code := range interceptors.AllCodes { diff --git a/providers/openmetrics/server_options.go b/providers/openmetrics/server_options.go new file mode 100644 index 000000000..1b7ca5cc6 --- /dev/null +++ b/providers/openmetrics/server_options.go @@ -0,0 +1,40 @@ +package metrics + +import ( + openmetrics "github.com/prometheus/client_golang/prometheus" +) + +type serverMetricsConfig struct { + counterOpts counterOptions + // serverHandledHistogram can be nil + serverHandledHistogram *openmetrics.HistogramVec +} + +type ServerMetricsOption func(*serverMetricsConfig) + +func (c *serverMetricsConfig) apply(opts []ServerMetricsOption) { + for _, o := range opts { + o(c) + } +} + +func WithServerCounterOptions(opts ...CounterOption) ServerMetricsOption { + return func(o *serverMetricsConfig) { + o.counterOpts = opts + } +} + +// WithServerHandlingTimeHistogram turns on recording of handling time of RPCs. +// Histogram metrics can be very expensive for Prometheus to retain and query. +func WithServerHandlingTimeHistogram(opts ...HistogramOption) ServerMetricsOption { + return func(o *serverMetricsConfig) { + o.serverHandledHistogram = openmetrics.NewHistogramVec( + histogramOptions(opts).apply(openmetrics.HistogramOpts{ + Name: "grpc_server_handling_seconds", + Help: "Histogram of response latency (seconds) of gRPC that had been application-level handled by the server.", + Buckets: openmetrics.DefBuckets, + }), + []string{"grpc_type", "grpc_service", "grpc_method"}, + ) + } +} diff --git a/providers/openmetrics/server_test.go b/providers/openmetrics/server_test.go index 13c8cd26c..38f219211 100644 --- a/providers/openmetrics/server_test.go +++ b/providers/openmetrics/server_test.go @@ -13,11 +13,9 @@ import ( "testing" "time" + "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prometheus/client_golang/prometheus/testutil" - - pb_testproto "github.com/grpc-ecosystem/go-grpc-middleware/providers/openmetrics/v2/testproto/v1" - "github.com/prometheus/client_golang/prometheus" dto "github.com/prometheus/client_model/go" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -25,10 +23,8 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" -) -var ( - DefaultServerMetrics = RegisterServerMetrics(prometheus.DefaultRegisterer) + pb_testproto "github.com/grpc-ecosystem/go-grpc-middleware/providers/openmetrics/v2/testproto/v1" ) const ( @@ -49,20 +45,22 @@ type ServerInterceptorTestSuite struct { testClient pb_testproto.TestServiceClient ctx context.Context cancel context.CancelFunc + + serverMetrics *ServerMetrics } func (s *ServerInterceptorTestSuite) SetupSuite() { var err error - DefaultServerMetrics.EnableHandlingTimeHistogram() + s.serverMetrics = NewServerMetrics(WithServerHandlingTimeHistogram()) s.serverListener, err = net.Listen("tcp", "127.0.0.1:0") require.NoError(s.T(), err, "must be able to allocate a port for serverListener") // This is the point where we hook up the interceptor s.server = grpc.NewServer( - grpc.StreamInterceptor(StreamServerInterceptor(prometheus.DefaultRegisterer)), - grpc.UnaryInterceptor(UnaryServerInterceptor(prometheus.DefaultRegisterer)), + grpc.StreamInterceptor(StreamServerInterceptor(s.serverMetrics)), + grpc.UnaryInterceptor(UnaryServerInterceptor(s.serverMetrics)), ) pb_testproto.RegisterTestServiceServer(s.server, &testService{t: s.T()}) @@ -80,23 +78,22 @@ func (s *ServerInterceptorTestSuite) SetupTest() { s.ctx, s.cancel = context.WithTimeout(context.TODO(), 2*time.Second) // Make sure every test starts with same fresh, intialized metric state. - DefaultServerMetrics.serverStartedCounter.Reset() - DefaultServerMetrics.serverHandledCounter.Reset() - DefaultServerMetrics.serverHandledHistogram.Reset() - DefaultServerMetrics.serverStreamMsgReceived.Reset() - DefaultServerMetrics.serverStreamMsgSent.Reset() - DefaultServerMetrics.InitializeMetrics(s.server) + s.serverMetrics.serverStartedCounter.Reset() + s.serverMetrics.serverHandledCounter.Reset() + s.serverMetrics.serverHandledHistogram.Reset() + s.serverMetrics.serverStreamMsgReceived.Reset() + s.serverMetrics.serverStreamMsgSent.Reset() + s.serverMetrics.InitializeMetrics(s.server) } func (s *ServerInterceptorTestSuite) TearDownSuite() { + if s.clientConn != nil { + s.clientConn.Close() + } if s.serverListener != nil { s.server.Stop() s.T().Logf("stopped grpc.Server at: %v", s.serverListener.Addr().String()) s.serverListener.Close() - - } - if s.clientConn != nil { - s.clientConn.Close() } } @@ -105,51 +102,55 @@ func (s *ServerInterceptorTestSuite) TearDownTest() { } func (s *ServerInterceptorTestSuite) TestRegisterPresetsStuff() { + registry := prometheus.NewPedanticRegistry() + + s.Require().NoError(s.serverMetrics.Register(registry)) + for testID, testCase := range []struct { metricName string existingLabels []string }{ // Order of label is irrelevant. - {"grpc_server_started_total", []string{"mwitkow.testproto.TestService", "PingEmpty", "unary"}}, - {"grpc_server_started_total", []string{"mwitkow.testproto.TestService", "PingList", "server_stream"}}, - {"grpc_server_msg_received_total", []string{"mwitkow.testproto.TestService", "PingList", "server_stream"}}, - {"grpc_server_msg_sent_total", []string{"mwitkow.testproto.TestService", "PingEmpty", "unary"}}, - {"grpc_server_handling_seconds_sum", []string{"mwitkow.testproto.TestService", "PingEmpty", "unary"}}, - {"grpc_server_handling_seconds_count", []string{"mwitkow.testproto.TestService", "PingList", "server_stream"}}, - {"grpc_server_handled_total", []string{"mwitkow.testproto.TestService", "PingList", "server_stream", "OutOfRange"}}, - {"grpc_server_handled_total", []string{"mwitkow.testproto.TestService", "PingList", "server_stream", "Aborted"}}, - {"grpc_server_handled_total", []string{"mwitkow.testproto.TestService", "PingEmpty", "unary", "FailedPrecondition"}}, - {"grpc_server_handled_total", []string{"mwitkow.testproto.TestService", "PingEmpty", "unary", "ResourceExhausted"}}, + {"grpc_server_started_total", []string{"providers.openmetrics.testproto.v1.TestService", "PingEmpty", "unary"}}, + {"grpc_server_started_total", []string{"providers.openmetrics.testproto.v1.TestService", "PingList", "server_stream"}}, + {"grpc_server_msg_received_total", []string{"providers.openmetrics.testproto.v1.TestService", "PingList", "server_stream"}}, + {"grpc_server_msg_sent_total", []string{"providers.openmetrics.testproto.v1.TestService", "PingEmpty", "unary"}}, + {"grpc_server_handling_seconds_sum", []string{"providers.openmetrics.testproto.v1.TestService", "PingEmpty", "unary"}}, + {"grpc_server_handling_seconds_count", []string{"providers.openmetrics.testproto.v1.TestService", "PingList", "server_stream"}}, + {"grpc_server_handled_total", []string{"providers.openmetrics.testproto.v1.TestService", "PingList", "server_stream", "OutOfRange"}}, + {"grpc_server_handled_total", []string{"providers.openmetrics.testproto.v1.TestService", "PingList", "server_stream", "Aborted"}}, + {"grpc_server_handled_total", []string{"providers.openmetrics.testproto.v1.TestService", "PingEmpty", "unary", "FailedPrecondition"}}, + {"grpc_server_handled_total", []string{"providers.openmetrics.testproto.v1.TestService", "PingEmpty", "unary", "ResourceExhausted"}}, } { - lineCount := len(fetchPrometheusLines(s.T(), testCase.metricName, testCase.existingLabels...)) - assert.NotEqual(s.T(), 0, lineCount, "metrics must exist for test case %d", testID) + lineCount := len(fetchPrometheusLines(s.T(), registry, testCase.metricName, testCase.existingLabels...)) + assert.NotZero(s.T(), lineCount, "metrics must exist for test case %d", testID) } } func (s *ServerInterceptorTestSuite) TestUnaryIncrementsMetrics() { _, err := s.testClient.PingEmpty(s.ctx, &pb_testproto.PingEmptyRequest{}) // should return with code=OK require.NoError(s.T(), err) - requireValue(s.T(), 1, DefaultServerMetrics.serverStartedCounter.WithLabelValues("unary", "mwitkow.testproto.TestService", "PingEmpty")) - requireValue(s.T(), 1, DefaultServerMetrics.serverHandledCounter.WithLabelValues("unary", "mwitkow.testproto.TestService", "PingEmpty", "OK")) - requireValueHistCount(s.T(), 1, DefaultServerMetrics.serverHandledHistogram.WithLabelValues("unary", "mwitkow.testproto.TestService", "PingEmpty")) + requireValue(s.T(), 1, s.serverMetrics.serverStartedCounter.WithLabelValues("unary", "providers.openmetrics.testproto.v1.TestService", "PingEmpty")) + requireValue(s.T(), 1, s.serverMetrics.serverHandledCounter.WithLabelValues("unary", "providers.openmetrics.testproto.v1.TestService", "PingEmpty", "OK")) + requireValueHistCount(s.T(), 1, s.serverMetrics.serverHandledHistogram.WithLabelValues("unary", "providers.openmetrics.testproto.v1.TestService", "PingEmpty")) _, err = s.testClient.PingError(s.ctx, &pb_testproto.PingErrorRequest{ErrorCodeReturned: uint32(codes.FailedPrecondition)}) // should return with code=FailedPrecondition require.Error(s.T(), err) - requireValue(s.T(), 1, DefaultServerMetrics.serverStartedCounter.WithLabelValues("unary", "mwitkow.testproto.TestService", "PingError")) - requireValue(s.T(), 1, DefaultServerMetrics.serverHandledCounter.WithLabelValues("unary", "mwitkow.testproto.TestService", "PingError", "FailedPrecondition")) - requireValueHistCount(s.T(), 1, DefaultServerMetrics.serverHandledHistogram.WithLabelValues("unary", "mwitkow.testproto.TestService", "PingError")) + requireValue(s.T(), 1, s.serverMetrics.serverStartedCounter.WithLabelValues("unary", "providers.openmetrics.testproto.v1.TestService", "PingError")) + requireValue(s.T(), 1, s.serverMetrics.serverHandledCounter.WithLabelValues("unary", "providers.openmetrics.testproto.v1.TestService", "PingError", "FailedPrecondition")) + requireValueHistCount(s.T(), 1, s.serverMetrics.serverHandledHistogram.WithLabelValues("unary", "providers.openmetrics.testproto.v1.TestService", "PingError")) } func (s *ServerInterceptorTestSuite) TestStartedStreamingIncrementsStarted() { _, err := s.testClient.PingList(s.ctx, &pb_testproto.PingListRequest{}) require.NoError(s.T(), err) requireValueWithRetry(s.ctx, s.T(), 1, - DefaultServerMetrics.serverStartedCounter.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList")) + s.serverMetrics.serverStartedCounter.WithLabelValues("server_stream", "providers.openmetrics.testproto.v1.TestService", "PingList")) _, err = s.testClient.PingList(s.ctx, &pb_testproto.PingListRequest{ErrorCodeReturned: uint32(codes.FailedPrecondition)}) // should return with code=FailedPrecondition require.NoError(s.T(), err, "PingList must not fail immediately") requireValueWithRetry(s.ctx, s.T(), 2, - DefaultServerMetrics.serverStartedCounter.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList")) + s.serverMetrics.serverStartedCounter.WithLabelValues("server_stream", "providers.openmetrics.testproto.v1.TestService", "PingList")) } func (s *ServerInterceptorTestSuite) TestStreamingIncrementsMetrics() { @@ -167,36 +168,36 @@ func (s *ServerInterceptorTestSuite) TestStreamingIncrementsMetrics() { require.EqualValues(s.T(), countListResponses, count, "Number of received msg on the wire must match") requireValueWithRetry(s.ctx, s.T(), 1, - DefaultServerMetrics.serverStartedCounter.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList")) + s.serverMetrics.serverStartedCounter.WithLabelValues("server_stream", "providers.openmetrics.testproto.v1.TestService", "PingList")) requireValueWithRetry(s.ctx, s.T(), 1, - DefaultServerMetrics.serverHandledCounter.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList", "OK")) + s.serverMetrics.serverHandledCounter.WithLabelValues("server_stream", "providers.openmetrics.testproto.v1.TestService", "PingList", "OK")) requireValueWithRetry(s.ctx, s.T(), countListResponses, - DefaultServerMetrics.serverStreamMsgSent.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList")) + s.serverMetrics.serverStreamMsgSent.WithLabelValues("server_stream", "providers.openmetrics.testproto.v1.TestService", "PingList")) requireValueWithRetry(s.ctx, s.T(), 1, - DefaultServerMetrics.serverStreamMsgReceived.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList")) + s.serverMetrics.serverStreamMsgReceived.WithLabelValues("server_stream", "providers.openmetrics.testproto.v1.TestService", "PingList")) requireValueWithRetryHistCount(s.ctx, s.T(), 1, - DefaultServerMetrics.serverHandledHistogram.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList")) + s.serverMetrics.serverHandledHistogram.WithLabelValues("server_stream", "providers.openmetrics.testproto.v1.TestService", "PingList")) _, err := s.testClient.PingList(s.ctx, &pb_testproto.PingListRequest{ErrorCodeReturned: uint32(codes.FailedPrecondition)}) // should return with code=FailedPrecondition require.NoError(s.T(), err, "PingList must not fail immediately") requireValueWithRetry(s.ctx, s.T(), 2, - DefaultServerMetrics.serverStartedCounter.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList")) + s.serverMetrics.serverStartedCounter.WithLabelValues("server_stream", "providers.openmetrics.testproto.v1.TestService", "PingList")) requireValueWithRetry(s.ctx, s.T(), 1, - DefaultServerMetrics.serverHandledCounter.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList", "FailedPrecondition")) + s.serverMetrics.serverHandledCounter.WithLabelValues("server_stream", "providers.openmetrics.testproto.v1.TestService", "PingList", "FailedPrecondition")) requireValueWithRetryHistCount(s.ctx, s.T(), 2, - DefaultServerMetrics.serverHandledHistogram.WithLabelValues("server_stream", "mwitkow.testproto.TestService", "PingList")) + s.serverMetrics.serverHandledHistogram.WithLabelValues("server_stream", "providers.openmetrics.testproto.v1.TestService", "PingList")) } // fetchPrometheusLines does mocked HTTP GET request against real prometheus handler to get the same view that Prometheus // would have while scraping this endpoint. // Order of matching label vales does not matter. -func fetchPrometheusLines(t *testing.T, metricName string, matchingLabelValues ...string) []string { +func fetchPrometheusLines(t *testing.T, reg prometheus.Gatherer, metricName string, matchingLabelValues ...string) []string { resp := httptest.NewRecorder() req, err := http.NewRequest("GET", "/", nil) require.NoError(t, err, "failed creating request for Prometheus handler") - promhttp.Handler().ServeHTTP(resp, req) + promhttp.HandlerFor(reg, promhttp.HandlerOpts{}).ServeHTTP(resp, req) reader := bufio.NewReader(resp.Body) var ret []string @@ -239,12 +240,12 @@ func (s *testService) Ping(ctx context.Context, ping *pb_testproto.PingRequest) func (s *testService) PingError(ctx context.Context, ping *pb_testproto.PingErrorRequest) (*pb_testproto.PingErrorResponse, error) { code := codes.Code(ping.ErrorCodeReturned) - return nil, status.Errorf(code, "Userspace error.") + return nil, status.Error(code, "Userspace error.") } func (s *testService) PingList(ping *pb_testproto.PingListRequest, stream pb_testproto.TestService_PingListServer) error { if ping.ErrorCodeReturned != 0 { - return status.Errorf(codes.Code(ping.ErrorCodeReturned), "foobar") + return status.Error(codes.Code(ping.ErrorCodeReturned), "foobar") } // Send user trailers and headers. for i := 0; i < countListResponses; i++ { @@ -292,6 +293,7 @@ func toFloat64HistCount(h prometheus.Observer) uint64 { } func requireValue(t *testing.T, expect int, c prometheus.Collector) { + t.Helper() v := int(testutil.ToFloat64(c)) if v == expect { return @@ -303,6 +305,7 @@ func requireValue(t *testing.T, expect int, c prometheus.Collector) { } func requireValueHistCount(t *testing.T, expect int, o prometheus.Observer) { + t.Helper() v := int(toFloat64HistCount(o)) if v == expect { return @@ -314,6 +317,7 @@ func requireValueHistCount(t *testing.T, expect int, o prometheus.Observer) { } func requireValueWithRetry(ctx context.Context, t *testing.T, expect int, c prometheus.Collector) { + t.Helper() for { v := int(testutil.ToFloat64(c)) if v == expect { @@ -332,6 +336,7 @@ func requireValueWithRetry(ctx context.Context, t *testing.T, expect int, c prom } func requireValueWithRetryHistCount(ctx context.Context, t *testing.T, expect int, o prometheus.Observer) { + t.Helper() for { v := int(toFloat64HistCount(o)) if v == expect { From b81999a9cffa9f5d7de65cd3ef5784c49556eab8 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Fri, 23 Apr 2021 11:51:07 -0700 Subject: [PATCH 23/27] Support customization of timestamp format (v2 branch) (#399) This ports #398 to the v2 branch. --- interceptors/logging/interceptors.go | 4 ++-- interceptors/logging/options.go | 11 +++++++++- interceptors/logging/payload.go | 33 ++++++++++++++-------------- interceptors/logging/payload_test.go | 8 +++---- 4 files changed, 33 insertions(+), 23 deletions(-) diff --git a/interceptors/logging/interceptors.go b/interceptors/logging/interceptors.go index 654223f2a..e64148474 100644 --- a/interceptors/logging/interceptors.go +++ b/interceptors/logging/interceptors.go @@ -90,9 +90,9 @@ func (r *reportable) ClientReporter(ctx context.Context, _ interface{}, typ inte func (r *reportable) reporter(ctx context.Context, typ interceptors.GRPCType, service string, method string, kind string) (interceptors.Reporter, context.Context) { fields := commonFields(kind, typ, service, method) - fields = append(fields, "grpc.start_time", time.Now().Format(time.RFC3339)) + fields = append(fields, "grpc.start_time", time.Now().Format(r.opts.timestampFormat)) if d, ok := ctx.Deadline(); ok { - fields = append(fields, "grpc.request.deadline", d.Format(time.RFC3339)) + fields = append(fields, "grpc.request.deadline", d.Format(r.opts.timestampFormat)) } return &reporter{ ctx: ctx, diff --git a/interceptors/logging/options.go b/interceptors/logging/options.go index b1aa328cf..c30878ab6 100644 --- a/interceptors/logging/options.go +++ b/interceptors/logging/options.go @@ -11,7 +11,8 @@ var ( codeFunc: DefaultErrorToCode, durationFieldFunc: DefaultDurationToFields, // levelFunc depends if it's client or server. - levelFunc: nil, + levelFunc: nil, + timestampFormat: time.RFC3339, } ) @@ -20,6 +21,7 @@ type options struct { shouldLog Decider codeFunc ErrorToCode durationFieldFunc DurationToFields + timestampFormat string } type Option func(*options) @@ -92,3 +94,10 @@ func DurationToDurationField(duration time.Duration) Fields { func durationToMilliseconds(duration time.Duration) float32 { return float32(duration.Nanoseconds()/1000) / 1000 } + +// WithTimestampFormat customizes the timestamps emitted in the log fields. +func WithTimestampFormat(format string) Option { + return func(o *options) { + o.timestampFormat = format + } +} diff --git a/interceptors/logging/payload.go b/interceptors/logging/payload.go index 936ea4a45..34c27e883 100644 --- a/interceptors/logging/payload.go +++ b/interceptors/logging/payload.go @@ -89,9 +89,10 @@ func (c *clientPayloadReporter) PostMsgReceive(reply interface{}, err error, dur } type payloadReportable struct { - clientDecider ClientPayloadLoggingDecider - serverDecider ServerPayloadLoggingDecider - logger Logger + clientDecider ClientPayloadLoggingDecider + serverDecider ServerPayloadLoggingDecider + logger Logger + timestampFormat string } func (r *payloadReportable) ServerReporter(ctx context.Context, req interface{}, typ interceptors.GRPCType, service string, method string) (interceptors.Reporter, context.Context) { @@ -99,9 +100,9 @@ func (r *payloadReportable) ServerReporter(ctx context.Context, req interface{}, return interceptors.NoopReporter{}, ctx } fields := commonFields(KindServerFieldValue, typ, service, method) - fields = append(fields, "grpc.start_time", time.Now().Format(time.RFC3339)) + fields = append(fields, "grpc.start_time", time.Now().Format(r.timestampFormat)) if d, ok := ctx.Deadline(); ok { - fields = append(fields, "grpc.request.deadline", d.Format(time.RFC3339)) + fields = append(fields, "grpc.request.deadline", d.Format(r.timestampFormat)) } return &serverPayloadReporter{ ctx: ctx, @@ -113,9 +114,9 @@ func (r *payloadReportable) ClientReporter(ctx context.Context, _ interface{}, t return interceptors.NoopReporter{}, ctx } fields := commonFields(KindClientFieldValue, typ, service, method) - fields = append(fields, "grpc.start_time", time.Now().Format(time.RFC3339)) + fields = append(fields, "grpc.start_time", time.Now().Format(r.timestampFormat)) if d, ok := ctx.Deadline(); ok { - fields = append(fields, "grpc.request.deadline", d.Format(time.RFC3339)) + fields = append(fields, "grpc.request.deadline", d.Format(r.timestampFormat)) } return &clientPayloadReporter{ ctx: ctx, @@ -125,26 +126,26 @@ func (r *payloadReportable) ClientReporter(ctx context.Context, _ interface{}, t // PayloadUnaryServerInterceptor returns a new unary server interceptors that logs the payloads of requests on INFO level. // Logger tags will be used from tags context. -func PayloadUnaryServerInterceptor(logger Logger, decider ServerPayloadLoggingDecider) grpc.UnaryServerInterceptor { - return interceptors.UnaryServerInterceptor(&payloadReportable{logger: logger, serverDecider: decider}) +func PayloadUnaryServerInterceptor(logger Logger, decider ServerPayloadLoggingDecider, timestampFormat string) grpc.UnaryServerInterceptor { + return interceptors.UnaryServerInterceptor(&payloadReportable{logger: logger, serverDecider: decider, timestampFormat: timestampFormat}) } // PayloadStreamServerInterceptor returns a new server server interceptors that logs the payloads of requests on INFO level. // Logger tags will be used from tags context. -func PayloadStreamServerInterceptor(logger Logger, decider ServerPayloadLoggingDecider) grpc.StreamServerInterceptor { - return interceptors.StreamServerInterceptor(&payloadReportable{logger: logger, serverDecider: decider}) +func PayloadStreamServerInterceptor(logger Logger, decider ServerPayloadLoggingDecider, timestampFormat string) grpc.StreamServerInterceptor { + return interceptors.StreamServerInterceptor(&payloadReportable{logger: logger, serverDecider: decider, timestampFormat: timestampFormat}) } -// PayloadUnaryClientInterceptor returns a new unary client interceptor that logs the paylods of requests and responses on INFO level. +// PayloadUnaryClientInterceptor returns a new unary client interceptor that logs the payloads of requests and responses on INFO level. // Logger tags will be used from tags context. -func PayloadUnaryClientInterceptor(logger Logger, decider ClientPayloadLoggingDecider) grpc.UnaryClientInterceptor { - return interceptors.UnaryClientInterceptor(&payloadReportable{logger: logger, clientDecider: decider}) +func PayloadUnaryClientInterceptor(logger Logger, decider ClientPayloadLoggingDecider, timestampFormat string) grpc.UnaryClientInterceptor { + return interceptors.UnaryClientInterceptor(&payloadReportable{logger: logger, clientDecider: decider, timestampFormat: timestampFormat}) } // PayloadStreamClientInterceptor returns a new streaming client interceptor that logs the paylods of requests and responses on INFO level. // Logger tags will be used from tags context. -func PayloadStreamClientInterceptor(logger Logger, decider ClientPayloadLoggingDecider) grpc.StreamClientInterceptor { - return interceptors.StreamClientInterceptor(&payloadReportable{logger: logger, clientDecider: decider}) +func PayloadStreamClientInterceptor(logger Logger, decider ClientPayloadLoggingDecider, timestampFormat string) grpc.StreamClientInterceptor { + return interceptors.StreamClientInterceptor(&payloadReportable{logger: logger, clientDecider: decider, timestampFormat: timestampFormat}) } func logProtoMessageAsJson(logger Logger, pbMsg proto.Message, key string, msg string) { diff --git a/interceptors/logging/payload_test.go b/interceptors/logging/payload_test.go index de95bccc1..c81c07880 100644 --- a/interceptors/logging/payload_test.go +++ b/interceptors/logging/payload_test.go @@ -36,16 +36,16 @@ func TestPayloadSuite(t *testing.T) { }, } s.InterceptorTestSuite.ClientOpts = []grpc.DialOption{ - grpc.WithUnaryInterceptor(logging.PayloadUnaryClientInterceptor(s.logger, alwaysLoggingDeciderClient)), - grpc.WithStreamInterceptor(logging.PayloadStreamClientInterceptor(s.logger, alwaysLoggingDeciderClient)), + grpc.WithUnaryInterceptor(logging.PayloadUnaryClientInterceptor(s.logger, alwaysLoggingDeciderClient, time.RFC3339)), + grpc.WithStreamInterceptor(logging.PayloadStreamClientInterceptor(s.logger, alwaysLoggingDeciderClient, time.RFC3339)), } s.InterceptorTestSuite.ServerOpts = []grpc.ServerOption{ grpc.ChainStreamInterceptor( tags.StreamServerInterceptor(tags.WithFieldExtractor(tags.CodeGenRequestFieldExtractor)), - logging.PayloadStreamServerInterceptor(s.logger, alwaysLoggingDeciderServer)), + logging.PayloadStreamServerInterceptor(s.logger, alwaysLoggingDeciderServer, time.RFC3339)), grpc.ChainUnaryInterceptor( tags.UnaryServerInterceptor(tags.WithFieldExtractor(tags.CodeGenRequestFieldExtractor)), - logging.PayloadUnaryServerInterceptor(s.logger, alwaysLoggingDeciderServer)), + logging.PayloadUnaryServerInterceptor(s.logger, alwaysLoggingDeciderServer, time.RFC3339)), } suite.Run(t, s) } From a171347b4c94a90d4ed69eaa39b2fe30d87aca49 Mon Sep 17 00:00:00 2001 From: Sam Xie Date: Sat, 1 May 2021 15:58:39 +0800 Subject: [PATCH 24/27] Remove old tracing interceptors --- interceptors/tracing/client.go | 100 -------- interceptors/tracing/doc.go | 24 -- interceptors/tracing/id_extract.go | 83 ------- interceptors/tracing/id_extract_test.go | 34 --- interceptors/tracing/interceptors_test.go | 287 ---------------------- interceptors/tracing/metadata.go | 50 ---- interceptors/tracing/options.go | 67 ----- interceptors/tracing/server.go | 95 ------- 8 files changed, 740 deletions(-) delete mode 100644 interceptors/tracing/client.go delete mode 100644 interceptors/tracing/doc.go delete mode 100644 interceptors/tracing/id_extract.go delete mode 100644 interceptors/tracing/id_extract_test.go delete mode 100644 interceptors/tracing/interceptors_test.go delete mode 100644 interceptors/tracing/metadata.go delete mode 100644 interceptors/tracing/options.go delete mode 100644 interceptors/tracing/server.go diff --git a/interceptors/tracing/client.go b/interceptors/tracing/client.go deleted file mode 100644 index ead4931af..000000000 --- a/interceptors/tracing/client.go +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2017 Michal Witkowski. All Rights Reserved. -// See LICENSE for licensing terms. - -package tracing - -import ( - "context" - "io" - "time" - - "github.com/opentracing/opentracing-go" - "github.com/opentracing/opentracing-go/ext" - "github.com/opentracing/opentracing-go/log" - "google.golang.org/grpc" - "google.golang.org/grpc/grpclog" - - "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/util/metautils" -) - -type opentracingClientReporter struct { - typ interceptors.GRPCType - svcName, methodName string - - clientSpan opentracing.Span -} - -func (o *opentracingClientReporter) PostCall(err error, _ time.Duration) { - // Finish span. - if err != nil && err != io.EOF { - ext.Error.Set(o.clientSpan, true) - o.clientSpan.LogFields(log.String("event", "error"), log.String("message", err.Error())) - } - o.clientSpan.Finish() -} - -func (o *opentracingClientReporter) PostMsgSend(interface{}, error, time.Duration) {} - -func (o *opentracingClientReporter) PostMsgReceive(interface{}, error, time.Duration) {} - -type opentracingClientReportable struct { - tracer opentracing.Tracer - filterOutFunc FilterFunc -} - -func (o *opentracingClientReportable) ClientReporter(ctx context.Context, _ interface{}, typ interceptors.GRPCType, service string, method string) (interceptors.Reporter, context.Context) { - if o.filterOutFunc != nil && !o.filterOutFunc(ctx, method) { - return interceptors.NoopReporter{}, ctx - } - - newCtx, clientSpan := newClientSpanFromContext(ctx, o.tracer, interceptors.FullMethod(service, method)) - mock := &opentracingClientReporter{typ: typ, svcName: service, methodName: method, clientSpan: clientSpan} - return mock, newCtx -} - -// UnaryClientInterceptor returns a new unary client interceptor for OpenTracing. -func UnaryClientInterceptor(opts ...Option) grpc.UnaryClientInterceptor { - o := evaluateOptions(opts) - return interceptors.UnaryClientInterceptor(&opentracingClientReportable{tracer: o.tracer, filterOutFunc: o.filterOutFunc}) -} - -// StreamClientInterceptor returns a new streaming client interceptor for OpenTracing. -func StreamClientInterceptor(opts ...Option) grpc.StreamClientInterceptor { - o := evaluateOptions(opts) - return interceptors.StreamClientInterceptor(&opentracingClientReportable{tracer: o.tracer, filterOutFunc: o.filterOutFunc}) -} - -// ClientAddContextTags returns a context with specified opentracing tags, which -// are used by UnaryClientInterceptor/StreamClientInterceptor when creating a -// new span. -func ClientAddContextTags(ctx context.Context, tags opentracing.Tags) context.Context { - return context.WithValue(ctx, clientSpanTagKey{}, tags) -} - -type clientSpanTagKey struct{} - -func newClientSpanFromContext(ctx context.Context, tracer opentracing.Tracer, fullMethodName string) (context.Context, opentracing.Span) { - var parentSpanCtx opentracing.SpanContext - if parent := opentracing.SpanFromContext(ctx); parent != nil { - parentSpanCtx = parent.Context() - } - opts := []opentracing.StartSpanOption{ - opentracing.ChildOf(parentSpanCtx), - ext.SpanKindRPCClient, - grpcTag, - } - if tagx := ctx.Value(clientSpanTagKey{}); tagx != nil { - if opt, ok := tagx.(opentracing.StartSpanOption); ok { - opts = append(opts, opt) - } - } - clientSpan := tracer.StartSpan(fullMethodName, opts...) - // Make sure we add this to the metadata of the call, so it gets propagated: - md := metautils.ExtractOutgoing(ctx).Clone() - if err := tracer.Inject(clientSpan.Context(), opentracing.HTTPHeaders, metadataTextMap(md)); err != nil { - grpclog.Infof("grpc_opentracing: failed serializing trace information: %v", err) - } - ctxWithMetadata := md.ToOutgoing(ctx) - return opentracing.ContextWithSpan(ctxWithMetadata, clientSpan), clientSpan -} diff --git a/interceptors/tracing/doc.go b/interceptors/tracing/doc.go deleted file mode 100644 index aefc57a9b..000000000 --- a/interceptors/tracing/doc.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2017 Michal Witkowski. All Rights Reserved. -// See LICENSE for licensing terms. - -// -/* -tracing is a "parent" package for gRPC logging middlewares. - -This middleware relies on OpenTracing as our tracing interface. - -OpenTracing Interceptors - -These are both client-side and server-side interceptors for OpenTracing. They are a provider-agnostic, with backends -such as Zipkin, or Google Stackdriver Trace. - -For a service that sends out requests and receives requests, you *need* to use both, otherwise downstream requests will -not have the appropriate requests propagated. - -All server-side spans are tagged with grpc_ctxtags information. - -For more information see: -http://opentracing.io/documentation/ -https://github.com/opentracing/specification/blob/master/semantic_conventions.md -*/ -package tracing diff --git a/interceptors/tracing/id_extract.go b/interceptors/tracing/id_extract.go deleted file mode 100644 index a0e482cb0..000000000 --- a/interceptors/tracing/id_extract.go +++ /dev/null @@ -1,83 +0,0 @@ -package tracing - -import ( - "strings" - - "github.com/opentracing/opentracing-go" - "google.golang.org/grpc/grpclog" - - "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tags" -) - -const ( - TagTraceId = "trace.traceid" - TagSpanId = "trace.spanid" - TagSampled = "trace.sampled" - jaegerNotSampledFlag = "0" -) - -// injectOpentracingIdsToTags writes trace data to tags. -// This is done in an incredibly hacky way, because the public-facing interface of opentracing doesn't give access to -// the TraceId and SpanId of the SpanContext. Only the Tracer's Inject/Extract methods know what these are. -// Most tracers have them encoded as keys with 'traceid' and 'spanid': -// https://github.com/openzipkin/zipkin-go-opentracing/blob/594640b9ef7e5c994e8d9499359d693c032d738c/propagation_ot.go#L29 -// https://github.com/opentracing/basictracer-go/blob/1b32af207119a14b1b231d451df3ed04a72efebf/propagation_ot.go#L26 -// Jaeger from Uber use one-key schema with next format '{trace-id}:{span-id}:{parent-span-id}:{flags}' -// https://www.jaegertracing.io/docs/client-libraries/#trace-span-identity -// Datadog uses keys ending with 'trace-id' and 'parent-id' (for span) by default: -// https://github.com/DataDog/dd-trace-go/blob/v1/ddtrace/tracer/textmap.go#L77 -func injectOpentracingIdsToTags(traceHeaderName string, span opentracing.Span, tags tags.Tags) { - if err := span.Tracer().Inject(span.Context(), opentracing.HTTPHeaders, - &tagsCarrier{Tags: tags, traceHeaderName: traceHeaderName}); err != nil { - grpclog.Infof("grpc_opentracing: failed extracting trace info into ctx %v", err) - } -} - -// tagsCarrier is a really hacky way of -type tagsCarrier struct { - tags.Tags - traceHeaderName string -} - -func (t *tagsCarrier) Set(key, val string) { - key = strings.ToLower(key) - - if key == t.traceHeaderName { - parts := strings.Split(val, ":") - if len(parts) == 4 { - t.Tags.Set(TagTraceId, parts[0]) - t.Tags.Set(TagSpanId, parts[1]) - - if parts[3] != jaegerNotSampledFlag { - t.Tags.Set(TagSampled, "true") - } else { - t.Tags.Set(TagSampled, "false") - } - - return - } - } - - if strings.Contains(key, "traceid") { - t.Tags.Set(TagTraceId, val) // this will most likely be base-16 (hex) encoded - } - - if strings.Contains(key, "spanid") && !strings.Contains(strings.ToLower(key), "parent") { - t.Tags.Set(TagSpanId, val) // this will most likely be base-16 (hex) encoded - } - - if strings.Contains(key, "sampled") { - switch val { - case "true", "false": - t.Tags.Set(TagSampled, val) - } - } - - if strings.HasSuffix(key, "trace-id") { - t.Tags.Set(TagTraceId, val) - } - - if strings.HasSuffix(key, "parent-id") { - t.Tags.Set(TagSpanId, val) - } -} diff --git a/interceptors/tracing/id_extract_test.go b/interceptors/tracing/id_extract_test.go deleted file mode 100644 index ce93b6e91..000000000 --- a/interceptors/tracing/id_extract_test.go +++ /dev/null @@ -1,34 +0,0 @@ -package tracing - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tags" -) - -func TestTagsCarrier_Set_JaegerTraceFormat(t *testing.T) { - var ( - fakeTraceSampled = 1 - fakeInboundTraceId = "deadbeef" - fakeInboundSpanId = "c0decafe" - traceHeaderName = "uber-trace-id" - ) - - traceHeaderValue := fmt.Sprintf("%s:%s:%s:%d", fakeInboundTraceId, fakeInboundSpanId, fakeInboundSpanId, fakeTraceSampled) - - c := &tagsCarrier{ - Tags: tags.NewTags(), - traceHeaderName: traceHeaderName, - } - - c.Set(traceHeaderName, traceHeaderValue) - - assert.EqualValues(t, map[string]string{ - TagTraceId: fakeInboundTraceId, - TagSpanId: fakeInboundSpanId, - TagSampled: "true", - }, c.Tags.Values()) -} diff --git a/interceptors/tracing/interceptors_test.go b/interceptors/tracing/interceptors_test.go deleted file mode 100644 index 71d9bdda8..000000000 --- a/interceptors/tracing/interceptors_test.go +++ /dev/null @@ -1,287 +0,0 @@ -// Copyright 2017 Michal Witkowski. All Rights Reserved. -// See LICENSE for licensing terms. - -package tracing_test - -import ( - "context" - "fmt" - "io" - "net/http" - "strconv" - "strings" - "testing" - - "github.com/opentracing/opentracing-go" - "github.com/opentracing/opentracing-go/mocktracer" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "github.com/stretchr/testify/suite" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - - "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tags" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tracing" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/testing/testpb" -) - -var ( - fakeInboundTraceId = 1337 - fakeInboundSpanId = 999 - traceHeaderName = "uber-trace-id" -) - -type tracingAssertService struct { - testpb.TestServiceServer - T *testing.T -} - -func (s *tracingAssertService) Ping(ctx context.Context, ping *testpb.PingRequest) (*testpb.PingResponse, error) { - assert.NotNil(s.T, opentracing.SpanFromContext(ctx), "handlers must have the spancontext in their context, otherwise propagation will fail") - tags := tags.Extract(ctx) - assert.True(s.T, tags.Has(tracing.TagTraceId), "tags must contain traceid") - assert.True(s.T, tags.Has(tracing.TagSpanId), "tags must contain spanid") - assert.True(s.T, tags.Has(tracing.TagSampled), "tags must contain sampled") - assert.Equal(s.T, tags.Values()[tracing.TagSampled], "true", "sampled must be set to true") - return s.TestServiceServer.Ping(ctx, ping) -} - -func (s *tracingAssertService) PingError(ctx context.Context, ping *testpb.PingErrorRequest) (*testpb.PingErrorResponse, error) { - assert.NotNil(s.T, opentracing.SpanFromContext(ctx), "handlers must have the spancontext in their context, otherwise propagation will fail") - return s.TestServiceServer.PingError(ctx, ping) -} - -func (s *tracingAssertService) PingList(ping *testpb.PingListRequest, stream testpb.TestService_PingListServer) error { - assert.NotNil(s.T, opentracing.SpanFromContext(stream.Context()), "handlers must have the spancontext in their context, otherwise propagation will fail") - tags := tags.Extract(stream.Context()) - assert.True(s.T, tags.Has(tracing.TagTraceId), "tags must contain traceid") - assert.True(s.T, tags.Has(tracing.TagSpanId), "tags must contain spanid") - assert.True(s.T, tags.Has(tracing.TagSampled), "tags must contain sampled") - assert.Equal(s.T, tags.Values()[tracing.TagSampled], "true", "sampled must be set to true") - return s.TestServiceServer.PingList(ping, stream) -} - -func (s *tracingAssertService) PingEmpty(ctx context.Context, empty *testpb.PingEmptyRequest) (*testpb.PingEmptyResponse, error) { - assert.NotNil(s.T, opentracing.SpanFromContext(ctx), "handlers must have the spancontext in their context, otherwise propagation will fail") - tags := tags.Extract(ctx) - assert.True(s.T, tags.Has(tracing.TagTraceId), "tags must contain traceid") - assert.True(s.T, tags.Has(tracing.TagSpanId), "tags must contain spanid") - assert.True(s.T, tags.Has(tracing.TagSampled), "tags must contain sampled") - assert.Equal(s.T, tags.Values()[tracing.TagSampled], "false", "sampled must be set to false") - return s.TestServiceServer.PingEmpty(ctx, empty) -} - -func TestTaggingSuite(t *testing.T) { - mockTracer := mocktracer.New() - opts := []tracing.Option{ - tracing.WithTracer(mockTracer), - tracing.WithTraceHeaderName(traceHeaderName), - } - s := &OpentracingSuite{ - mockTracer: mockTracer, - InterceptorTestSuite: makeInterceptorTestSuite(t, opts), - } - suite.Run(t, s) -} - -func TestTaggingSuiteJaeger(t *testing.T) { - mockTracer := mocktracer.New() - mockTracer.RegisterInjector(opentracing.HTTPHeaders, jaegerFormatInjector{}) - mockTracer.RegisterExtractor(opentracing.HTTPHeaders, jaegerFormatExtractor{}) - opts := []tracing.Option{ - tracing.WithTracer(mockTracer), - } - s := &OpentracingSuite{ - mockTracer: mockTracer, - InterceptorTestSuite: makeInterceptorTestSuite(t, opts), - } - suite.Run(t, s) -} - -func makeInterceptorTestSuite(t *testing.T, opts []tracing.Option) *testpb.InterceptorTestSuite { - return &testpb.InterceptorTestSuite{ - TestService: &tracingAssertService{TestServiceServer: &testpb.TestPingService{T: t}, T: t}, - ClientOpts: []grpc.DialOption{ - grpc.WithUnaryInterceptor(tracing.UnaryClientInterceptor(opts...)), - grpc.WithStreamInterceptor(tracing.StreamClientInterceptor(opts...)), - }, - ServerOpts: []grpc.ServerOption{ - grpc.ChainStreamInterceptor( - tags.StreamServerInterceptor(tags.WithFieldExtractor(tags.CodeGenRequestFieldExtractor)), - tracing.StreamServerInterceptor(opts...)), - grpc.ChainUnaryInterceptor( - tags.UnaryServerInterceptor(tags.WithFieldExtractor(tags.CodeGenRequestFieldExtractor)), - tracing.UnaryServerInterceptor(opts...)), - }, - } -} - -type OpentracingSuite struct { - *testpb.InterceptorTestSuite - mockTracer *mocktracer.MockTracer -} - -func (s *OpentracingSuite) SetupTest() { - s.mockTracer.Reset() -} - -func (s *OpentracingSuite) createContextFromFakeHttpRequestParent(ctx context.Context, sampled bool) context.Context { - jFlag := 0 - if sampled { - jFlag = 1 - } - - hdr := http.Header{} - hdr.Set(traceHeaderName, fmt.Sprintf("%d:%d:%d:%d", fakeInboundTraceId, fakeInboundSpanId, fakeInboundSpanId, jFlag)) - hdr.Set("mockpfx-ids-traceid", fmt.Sprint(fakeInboundTraceId)) - hdr.Set("mockpfx-ids-spanid", fmt.Sprint(fakeInboundSpanId)) - hdr.Set("mockpfx-ids-sampled", fmt.Sprint(sampled)) - - parentSpanContext, err := s.mockTracer.Extract(opentracing.HTTPHeaders, opentracing.HTTPHeadersCarrier(hdr)) - require.NoError(s.T(), err, "parsing a fake HTTP request headers shouldn't fail, ever") - fakeSpan := s.mockTracer.StartSpan( - "/fake/parent/http/request", - // this is magical, it attaches the new span to the parent parentSpanContext, and creates an unparented one if empty. - opentracing.ChildOf(parentSpanContext), - ) - fakeSpan.Finish() - return opentracing.ContextWithSpan(ctx, fakeSpan) -} - -func (s *OpentracingSuite) assertTracesCreated(methodName string) (clientSpan *mocktracer.MockSpan, serverSpan *mocktracer.MockSpan) { - spans := s.mockTracer.FinishedSpans() - for _, span := range spans { - s.T().Logf("span: %v, tags: %v", span, span.Tags()) - } - require.Len(s.T(), spans, 3, "should record 3 spans: one fake inbound, one client, one server") - traceIdAssert := fmt.Sprintf("traceId=%d", fakeInboundTraceId) - for _, span := range spans { - assert.Contains(s.T(), span.String(), traceIdAssert, "not part of the fake parent trace: %v", span) - if span.OperationName == methodName { - kind := fmt.Sprintf("%v", span.Tag("span.kind")) - if kind == "client" { - clientSpan = span - } else if kind == "server" { - serverSpan = span - } - assert.EqualValues(s.T(), span.Tag("component"), "gRPC", "span must be tagged with gRPC component") - } - } - require.NotNil(s.T(), clientSpan, "client span must be there") - require.NotNil(s.T(), serverSpan, "server span must be there") - assert.EqualValues(s.T(), serverSpan.Tag("grpc.request.value"), "something", "tags must be propagated, in this case ones from request fields") - return clientSpan, serverSpan -} - -func (s *OpentracingSuite) TestPing_PropagatesTraces() { - ctx := s.createContextFromFakeHttpRequestParent(s.SimpleCtx(), true) - _, err := s.Client.Ping(ctx, testpb.GoodPing) - require.NoError(s.T(), err, "there must be not be an on a successful call") - s.assertTracesCreated("/" + testpb.TestServiceFullName + "/Ping") -} - -func (s *OpentracingSuite) TestPing_ClientContextTags() { - const name = "opentracing.custom" - ctx := tracing.ClientAddContextTags( - s.createContextFromFakeHttpRequestParent(s.SimpleCtx(), true), - opentracing.Tags{name: ""}, - ) - - _, err := s.Client.Ping(ctx, testpb.GoodPing) - require.NoError(s.T(), err, "there must be not be an on a successful call") - - for _, span := range s.mockTracer.FinishedSpans() { - if span.OperationName == "/"+testpb.TestServiceFullName+"/Ping" { - kind := fmt.Sprintf("%v", span.Tag("span.kind")) - if kind == "client" { - assert.Contains(s.T(), span.Tags(), name, "custom opentracing.Tags must be included in context") - } - } - } -} - -func (s *OpentracingSuite) TestPingList_PropagatesTraces() { - ctx := s.createContextFromFakeHttpRequestParent(s.SimpleCtx(), true) - stream, err := s.Client.PingList(ctx, testpb.GoodPingList) - require.NoError(s.T(), err, "should not fail on establishing the stream") - for { - _, err := stream.Recv() - if err == io.EOF { - break - } - require.NoError(s.T(), err, "reading stream should not fail") - } - s.assertTracesCreated("/" + testpb.TestServiceFullName + "/PingList") -} - -func (s *OpentracingSuite) TestPingError_PropagatesTraces() { - ctx := s.createContextFromFakeHttpRequestParent(s.SimpleCtx(), true) - _, err := s.Client.PingError(ctx, &testpb.PingErrorRequest{Value: "something", ErrorCodeReturned: uint32(codes.OutOfRange)}) - require.Error(s.T(), err, "there must be an error returned here") - clientSpan, serverSpan := s.assertTracesCreated("/" + testpb.TestServiceFullName + "/PingError") - assert.Equal(s.T(), true, clientSpan.Tag("error"), "client span needs to be marked as an error") - assert.Equal(s.T(), true, serverSpan.Tag("error"), "server span needs to be marked as an error") -} - -func (s *OpentracingSuite) TestPingEmpty_NotSampleTraces() { - ctx := s.createContextFromFakeHttpRequestParent(s.SimpleCtx(), false) - _, err := s.Client.PingEmpty(ctx, &testpb.PingEmptyRequest{}) - require.NoError(s.T(), err, "there must be not be an on a successful call") -} - -type jaegerFormatInjector struct{} - -func (jaegerFormatInjector) Inject(ctx mocktracer.MockSpanContext, carrier interface{}) error { - w := carrier.(opentracing.TextMapWriter) - flags := 0 - if ctx.Sampled { - flags = 1 - } - w.Set(traceHeaderName, fmt.Sprintf("%d:%d::%d", ctx.TraceID, ctx.SpanID, flags)) - - return nil -} - -type jaegerFormatExtractor struct{} - -func (jaegerFormatExtractor) Extract(carrier interface{}) (mocktracer.MockSpanContext, error) { - rval := mocktracer.MockSpanContext{Sampled: true} - reader, ok := carrier.(opentracing.TextMapReader) - if !ok { - return rval, opentracing.ErrInvalidCarrier - } - err := reader.ForeachKey(func(key, val string) error { - lowerKey := strings.ToLower(key) - switch { - case lowerKey == traceHeaderName: - parts := strings.Split(val, ":") - if len(parts) != 4 { - return errors.New("invalid trace id format") - } - traceId, err := strconv.Atoi(parts[0]) - if err != nil { - return err - } - rval.TraceID = traceId - spanId, err := strconv.Atoi(parts[1]) - if err != nil { - return err - } - rval.SpanID = spanId - flags, err := strconv.Atoi(parts[3]) - if err != nil { - return err - } - rval.Sampled = flags%2 == 1 - } - return nil - }) - if rval.TraceID == 0 || rval.SpanID == 0 { - return rval, opentracing.ErrSpanContextNotFound - } - if err != nil { - return rval, err - } - return rval, nil -} diff --git a/interceptors/tracing/metadata.go b/interceptors/tracing/metadata.go deleted file mode 100644 index 83a16a7c9..000000000 --- a/interceptors/tracing/metadata.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2017 Michal Witkowski. All Rights Reserved. -// See LICENSE for licensing terms. - -package tracing - -import ( - "encoding/base64" - "strings" - - "google.golang.org/grpc/metadata" -) - -const ( - binHdrSuffix = "-bin" -) - -// metadataTextMap extends a metadata.MD to be an opentracing textmap -type metadataTextMap metadata.MD - -// Set is a opentracing.TextMapReader interface that extracts values. -func (m metadataTextMap) Set(key, val string) { - // gRPC allows for complex binary values to be written. - encodedKey, encodedVal := encodeKeyValue(key, val) - // The metadata object is a multimap, and previous values may exist, but for opentracing headers, we do not append - // we just override. - m[encodedKey] = []string{encodedVal} -} - -// ForeachKey is a opentracing.TextMapReader interface that extracts values. -func (m metadataTextMap) ForeachKey(callback func(key, val string) error) error { - for k, vv := range m { - for _, v := range vv { - if err := callback(k, v); err != nil { - return err - } - } - } - return nil -} - -// encodeKeyValue encodes key and value qualified for transmission via gRPC. -// note: copy pasted from private values of grpc.metadata -func encodeKeyValue(k, v string) (string, string) { - k = strings.ToLower(k) - if strings.HasSuffix(k, binHdrSuffix) { - val := base64.StdEncoding.EncodeToString([]byte(v)) - v = string(val) - } - return k, v -} diff --git a/interceptors/tracing/options.go b/interceptors/tracing/options.go deleted file mode 100644 index e8602e12f..000000000 --- a/interceptors/tracing/options.go +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2017 Michal Witkowski. All Rights Reserved. -// See LICENSE for licensing terms. - -package tracing - -import ( - "context" - - "github.com/opentracing/opentracing-go" -) - -var ( - defaultOptions = &options{ - filterOutFunc: nil, - tracer: nil, - } -) - -// FilterFunc allows users to provide a function that filters out certain methods from being traced. -// -// If it returns false, the given request will not be traced. -type FilterFunc func(ctx context.Context, fullMethodName string) bool - -type options struct { - filterOutFunc FilterFunc - tracer opentracing.Tracer - traceHeaderName string -} - -func evaluateOptions(opts []Option) *options { - optCopy := &options{} - *optCopy = *defaultOptions - for _, o := range opts { - o(optCopy) - } - if optCopy.tracer == nil { - optCopy.tracer = opentracing.GlobalTracer() - } - if optCopy.traceHeaderName == "" { - optCopy.traceHeaderName = "uber-trace-id" - } - return optCopy -} - -type Option func(*options) - -// WithFilterFunc customizes the function used for deciding whether a given call is traced or not. -func WithFilterFunc(f FilterFunc) Option { - return func(o *options) { - o.filterOutFunc = f - } -} - -// WithTraceHeaderName customizes the trace header name where trace metadata passed with requests. -// Default one is `uber-trace-id` -func WithTraceHeaderName(name string) Option { - return func(o *options) { - o.traceHeaderName = name - } -} - -// WithTracer sets a custom tracer to be used for this middleware, otherwise the opentracing.GlobalTracer is used. -func WithTracer(tracer opentracing.Tracer) Option { - return func(o *options) { - o.tracer = tracer - } -} diff --git a/interceptors/tracing/server.go b/interceptors/tracing/server.go deleted file mode 100644 index ba05f90b4..000000000 --- a/interceptors/tracing/server.go +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2017 Michal Witkowski. All Rights Reserved. -// See LICENSE for licensing terms. - -package tracing - -import ( - "context" - "time" - - "github.com/opentracing/opentracing-go" - "github.com/opentracing/opentracing-go/ext" - "github.com/opentracing/opentracing-go/log" - "google.golang.org/grpc" - "google.golang.org/grpc/grpclog" - - "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tags" - "github.com/grpc-ecosystem/go-grpc-middleware/v2/util/metautils" -) - -var ( - grpcTag = opentracing.Tag{Key: string(ext.Component), Value: "gRPC"} -) - -type opentracingServerReporter struct { - ctx context.Context - typ interceptors.GRPCType - service, method string - - serverSpan opentracing.Span -} - -func (o *opentracingServerReporter) PostCall(err error, _ time.Duration) { - // Finish span and log context information. - tags := tags.Extract(o.ctx) - for k, v := range tags.Values() { - o.serverSpan.SetTag(k, v) - } - if err != nil { - ext.Error.Set(o.serverSpan, true) - o.serverSpan.LogFields(log.String("event", "error"), log.String("message", err.Error())) - } - o.serverSpan.Finish() -} - -func (o *opentracingServerReporter) PostMsgSend(interface{}, error, time.Duration) {} - -func (o *opentracingServerReporter) PostMsgReceive(interface{}, error, time.Duration) {} - -type opentracingServerReportable struct { - tracer opentracing.Tracer - // This is only used for server. TODO: Investigate if needed in client. - traceHeaderName string - filterOutFunc FilterFunc -} - -func (o *opentracingServerReportable) ServerReporter(ctx context.Context, _ interface{}, typ interceptors.GRPCType, service string, method string) (interceptors.Reporter, context.Context) { - if o.filterOutFunc != nil && !o.filterOutFunc(ctx, interceptors.FullMethod(service, method)) { - return interceptors.NoopReporter{}, ctx - } - - newCtx, serverSpan := newServerSpanFromInbound(ctx, o.tracer, o.traceHeaderName, interceptors.FullMethod(service, method)) - mock := &opentracingServerReporter{ctx: newCtx, typ: typ, service: service, method: method, serverSpan: serverSpan} - return mock, newCtx -} - -// UnaryServerInterceptor returns a new unary server interceptor for OpenTracing. -func UnaryServerInterceptor(opts ...Option) grpc.UnaryServerInterceptor { - o := evaluateOptions(opts) - return interceptors.UnaryServerInterceptor(&opentracingServerReportable{tracer: o.tracer, traceHeaderName: o.traceHeaderName, filterOutFunc: o.filterOutFunc}) -} - -// StreamServerInterceptor returns a new streaming server interceptor for OpenTracing. -func StreamServerInterceptor(opts ...Option) grpc.StreamServerInterceptor { - o := evaluateOptions(opts) - return interceptors.StreamServerInterceptor(&opentracingServerReportable{tracer: o.tracer, traceHeaderName: o.traceHeaderName, filterOutFunc: o.filterOutFunc}) -} - -func newServerSpanFromInbound(ctx context.Context, tracer opentracing.Tracer, traceHeaderName, fullMethodName string) (context.Context, opentracing.Span) { - md := metautils.ExtractIncoming(ctx) - parentSpanContext, err := tracer.Extract(opentracing.HTTPHeaders, metadataTextMap(md)) - if err != nil && err != opentracing.ErrSpanContextNotFound { - grpclog.Infof("grpc_opentracing: failed parsing trace information: %v", err) - } - - serverSpan := tracer.StartSpan( - fullMethodName, - // this is magical, it attaches the new span to the parent parentSpanContext, and creates an unparented one if empty. - ext.RPCServerOption(parentSpanContext), - grpcTag, - ) - - injectOpentracingIdsToTags(traceHeaderName, serverSpan, tags.Extract(ctx)) - return opentracing.ContextWithSpan(ctx, serverSpan), serverSpan -} From 56e8b591af82535c9e799216d85ffebc481e0424 Mon Sep 17 00:00:00 2001 From: Sam Xie Date: Sat, 1 May 2021 21:19:03 +0800 Subject: [PATCH 25/27] Add tracing interceptor --- interceptors/tracing/interceptors.go | 59 ++++ interceptors/tracing/interceptors_test.go | 317 ++++++++++++++++++++++ interceptors/tracing/kv/value.go | 171 ++++++++++++ interceptors/tracing/kv/value_test.go | 56 ++++ interceptors/tracing/reporter.go | 65 +++++ interceptors/tracing/tracing.go | 57 ++++ 6 files changed, 725 insertions(+) create mode 100644 interceptors/tracing/interceptors.go create mode 100644 interceptors/tracing/interceptors_test.go create mode 100644 interceptors/tracing/kv/value.go create mode 100644 interceptors/tracing/kv/value_test.go create mode 100644 interceptors/tracing/reporter.go create mode 100644 interceptors/tracing/tracing.go diff --git a/interceptors/tracing/interceptors.go b/interceptors/tracing/interceptors.go new file mode 100644 index 000000000..681d581ae --- /dev/null +++ b/interceptors/tracing/interceptors.go @@ -0,0 +1,59 @@ +package tracing + +import ( + "context" + + "google.golang.org/grpc" + + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors" +) + +type SpanKind string + +const ( + SpanKindServer SpanKind = "server" + SpanKindClient SpanKind = "client" +) + +type reportable struct { + tracer Tracer +} + +func (r *reportable) ServerReporter(ctx context.Context, _ interface{}, typ interceptors.GRPCType, service string, method string) (interceptors.Reporter, context.Context) { + return r.reporter(ctx, service, method, SpanKindServer) +} + +func (r *reportable) ClientReporter(ctx context.Context, _ interface{}, typ interceptors.GRPCType, service string, method string) (interceptors.Reporter, context.Context) { + return r.reporter(ctx, service, method, SpanKindClient) +} + +func (r *reportable) reporter(ctx context.Context, service string, method string, kind SpanKind) (interceptors.Reporter, context.Context) { + newCtx, span := r.tracer.Start(ctx, interceptors.FullMethod(service, method), kind) + reporter := reporter{ctx: newCtx, span: span} + + return &reporter, newCtx +} + +// UnaryClientInterceptor returns a new unary client interceptor that optionally traces the execution of external gRPC calls. +// Tracer will use tags (from tags package) available in current context as fields. +func UnaryClientInterceptor(tracer Tracer) grpc.UnaryClientInterceptor { + return interceptors.UnaryClientInterceptor(&reportable{tracer: tracer}) +} + +// StreamClientInterceptor returns a new streaming client interceptor that optionally traces the execution of external gRPC calls. +// Tracer will use tags (from tags package) available in current context as fields. +func StreamClientInterceptor(tracer Tracer) grpc.StreamClientInterceptor { + return interceptors.StreamClientInterceptor(&reportable{tracer: tracer}) +} + +// UnaryServerInterceptor returns a new unary server interceptors that optionally traces endpoint handling. +// Tracer will use tags (from tags package) available in current context as fields. +func UnaryServerInterceptor(tracer Tracer) grpc.UnaryServerInterceptor { + return interceptors.UnaryServerInterceptor(&reportable{tracer: tracer}) +} + +// StreamServerInterceptor returns a new stream server interceptors that optionally traces endpoint handling. +// Tracer will use tags (from tags package) available in current context as fields. +func StreamServerInterceptor(tracer Tracer) grpc.StreamServerInterceptor { + return interceptors.StreamServerInterceptor(&reportable{tracer: tracer}) +} diff --git a/interceptors/tracing/interceptors_test.go b/interceptors/tracing/interceptors_test.go new file mode 100644 index 000000000..99d592964 --- /dev/null +++ b/interceptors/tracing/interceptors_test.go @@ -0,0 +1,317 @@ +package tracing_test + +import ( + "context" + "io" + "strconv" + "sync/atomic" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/metadata" + + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tags" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tracing" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tracing/kv" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/testing/testpb" +) + +var ( + id int64 = 0 + traceIDHeaderKey = "traceid" + spanIDHeaderKey = "spanid" +) + +func extractFromContext(ctx context.Context, kind tracing.SpanKind) *mockSpan { + var m metadata.MD + if kind == tracing.SpanKindClient { + m, _ = metadata.FromOutgoingContext(ctx) + } else { + m, _ = metadata.FromIncomingContext(ctx) + } + + traceIDValues := m.Get(traceIDHeaderKey) + if len(traceIDValues) == 0 { + return nil + } + spanIDValues := m.Get(spanIDHeaderKey) + if len(spanIDValues) == 0 { + return nil + } + + return &mockSpan{ + traceID: traceIDValues[0], + spanID: spanIDValues[0], + } +} + +func injectWithContext(ctx context.Context, span *mockSpan, kind tracing.SpanKind) context.Context { + var m metadata.MD + if kind == tracing.SpanKindClient { + m, _ = metadata.FromOutgoingContext(ctx) + } else { + m, _ = metadata.FromIncomingContext(ctx) + } + m = m.Copy() + + m.Set(traceIDHeaderKey, span.traceID) + m.Set(spanIDHeaderKey, span.spanID) + + ctx = metadata.NewOutgoingContext(ctx, m) + return ctx +} + +func genID() string { + return strconv.FormatInt(atomic.AddInt64(&id, 1), 10) +} + +// Implements Tracker +type mockTracer struct { + spanStore map[string]*mockSpan +} + +func (t *mockTracer) ListSpan(kind tracing.SpanKind) []*mockSpan { + var spans []*mockSpan + for _, v := range t.spanStore { + if v.kind == kind { + spans = append(spans, v) + } + } + return spans +} + +func (t *mockTracer) Reset() { + t.spanStore = make(map[string]*mockSpan) +} + +func newMockTracer() *mockTracer { + return &mockTracer{ + spanStore: make(map[string]*mockSpan), + } +} + +func (t *mockTracer) Start(ctx context.Context, spanName string, kind tracing.SpanKind) (context.Context, tracing.Span) { + span := mockSpan{ + spanID: genID(), + name: spanName, + kind: kind, + statusCode: codes.OK, + } + + // parentSpan := spanFromContext(ctx) + parentSpan := extractFromContext(ctx, kind) + if parentSpan != nil { + // Fetch span from context as parent span + span.traceID = parentSpan.traceID + span.parentSpanID = parentSpan.spanID + } else { + span.traceID = genID() + } + + t.spanStore[span.spanID] = &span + + // ctx = contextWithSpan(ctx, &span) + if kind == tracing.SpanKindClient { + ctx = injectWithContext(ctx, &span, kind) + } + return ctx, &span +} + +// Implements Span +type mockSpan struct { + traceID string + spanID string + parentSpanID string + + name string + kind tracing.SpanKind + end bool + + statusCode codes.Code + statusMessage string + + msgSendCounter int + msgReceivedCounter int + eventNameList []string + attributesList [][]kv.KeyValue +} + +func (s *mockSpan) SetAttributes(attrs ...kv.KeyValue) { + s.attributesList = append(s.attributesList, attrs) +} + +func (s *mockSpan) End() { + s.end = true +} + +func (s *mockSpan) SetStatus(code codes.Code, message string) { + s.statusCode = code + s.statusMessage = message +} + +func (s *mockSpan) AddEvent(name string, attrs ...kv.KeyValue) { + s.eventNameList = append(s.eventNameList, name) + + for _, v := range attrs { + switch v { + case tracing.RPCMessageTypeSent: + s.msgSendCounter++ + case tracing.RPCMessageTypeReceived: + s.msgReceivedCounter++ + } + } +} + +type tracingSuite struct { + *testpb.InterceptorTestSuite + tracer *mockTracer +} + +func (s *tracingSuite) BeforeTest(suiteName, testName string) { + s.tracer.Reset() +} + +func (s *tracingSuite) TestPing() { + method := "/testing.testpb.v1.TestService/Ping" + errorMethod := "/testing.testpb.v1.TestService/PingError" + t := s.T() + + testCases := []struct { + name string + error bool + errorMessage string + }{ + { + name: "OK", + error: false, + }, + { + name: "invalid argument error", + error: true, + errorMessage: "Userspace error.", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + s.tracer.Reset() + + var err error + if tc.error { + req := &testpb.PingErrorRequest{ErrorCodeReturned: uint32(codes.InvalidArgument)} + _, err = s.Client.PingError(s.SimpleCtx(), req) + } else { + req := &testpb.PingRequest{Value: "something"} + _, err = s.Client.Ping(s.SimpleCtx(), req) + } + if tc.error { + require.Error(t, err) + } else { + require.NoError(t, err) + } + + clientSpans := s.tracer.ListSpan(tracing.SpanKindClient) + serverSpans := s.tracer.ListSpan(tracing.SpanKindServer) + require.Len(t, clientSpans, 1) + require.Len(t, serverSpans, 1) + + clientSpan := clientSpans[0] + assert.True(t, clientSpan.end) + assert.Equal(t, 1, clientSpan.msgSendCounter) + assert.Equal(t, 1, clientSpan.msgReceivedCounter) + assert.Equal(t, []string{"message", "message"}, clientSpan.eventNameList) + + serverSpan := serverSpans[0] + assert.True(t, serverSpan.end) + assert.Equal(t, 1, serverSpan.msgSendCounter) + assert.Equal(t, 1, serverSpan.msgReceivedCounter) + assert.Equal(t, []string{"message", "message"}, serverSpan.eventNameList) + + assert.Equal(t, clientSpan.traceID, serverSpan.traceID) + assert.Equal(t, clientSpan.spanID, serverSpan.parentSpanID) + + if tc.error { + assert.Equal(t, codes.InvalidArgument, clientSpan.statusCode) + assert.Equal(t, tc.errorMessage, clientSpan.statusMessage) + assert.Equal(t, errorMethod, clientSpan.name) + assert.Equal(t, [][]kv.KeyValue{{kv.Key("rpc.grpc.status_code").Int64(3)}}, clientSpan.attributesList) + + assert.Equal(t, errorMethod, serverSpan.name) + assert.Equal(t, [][]kv.KeyValue{{kv.Key("rpc.grpc.status_code").Int64(3)}}, serverSpan.attributesList) + } else { + assert.Equal(t, codes.OK, clientSpan.statusCode) + assert.Equal(t, method, clientSpan.name) + assert.Equal(t, [][]kv.KeyValue{{kv.Key("rpc.grpc.status_code").Int64(0)}}, clientSpan.attributesList) + + assert.Equal(t, method, serverSpan.name) + assert.Equal(t, [][]kv.KeyValue{{kv.Key("rpc.grpc.status_code").Int64(0)}}, serverSpan.attributesList) + } + }) + } +} + +func (s *tracingSuite) TestPingList() { + t := s.T() + method := "/testing.testpb.v1.TestService/PingList" + + stream, err := s.Client.PingList(s.SimpleCtx(), &testpb.PingListRequest{Value: "something"}) + require.NoError(t, err) + + for { + _, err := stream.Recv() + if err == io.EOF { + break + } + require.NoError(t, err) + } + + clientSpans := s.tracer.ListSpan(tracing.SpanKindClient) + serverSpans := s.tracer.ListSpan(tracing.SpanKindServer) + require.Len(t, clientSpans, 1) + require.Len(t, serverSpans, 1) + + clientSpan := clientSpans[0] + assert.True(t, clientSpan.end) + assert.Equal(t, 1, clientSpan.msgSendCounter) + assert.Equal(t, testpb.ListResponseCount+1, clientSpan.msgReceivedCounter) + assert.Equal(t, codes.OK, clientSpan.statusCode) + assert.Equal(t, method, clientSpan.name) + + serverSpan := serverSpans[0] + assert.True(t, serverSpan.end) + assert.Equal(t, testpb.ListResponseCount, serverSpan.msgSendCounter) + assert.Equal(t, 1, serverSpan.msgReceivedCounter) + assert.Equal(t, codes.OK, serverSpan.statusCode) + assert.Equal(t, method, serverSpan.name) +} + +func TestSuite(t *testing.T) { + tracer := newMockTracer() + + s := tracingSuite{ + InterceptorTestSuite: &testpb.InterceptorTestSuite{ + TestService: &testpb.TestPingService{T: t}, + }, + tracer: tracer, + } + s.InterceptorTestSuite.ClientOpts = []grpc.DialOption{ + grpc.WithUnaryInterceptor(tracing.UnaryClientInterceptor(tracer)), + grpc.WithStreamInterceptor(tracing.StreamClientInterceptor(tracer)), + } + s.InterceptorTestSuite.ServerOpts = []grpc.ServerOption{ + grpc.ChainUnaryInterceptor( + tags.UnaryServerInterceptor(tags.WithFieldExtractor(tags.CodeGenRequestFieldExtractor)), + tracing.UnaryServerInterceptor(tracer), + ), + grpc.ChainStreamInterceptor( + tags.StreamServerInterceptor(tags.WithFieldExtractor(tags.CodeGenRequestFieldExtractor)), + tracing.StreamServerInterceptor(tracer), + ), + } + + suite.Run(t, &s) +} diff --git a/interceptors/tracing/kv/value.go b/interceptors/tracing/kv/value.go new file mode 100644 index 000000000..224f95070 --- /dev/null +++ b/interceptors/tracing/kv/value.go @@ -0,0 +1,171 @@ +package kv + +import ( + "math" +) + +// KeyValue holds a key and value pair. +type KeyValue struct { + Key Key + Value Value +} + +type Key string + +// Bool creates a KeyValue instance with a BOOL Value. +// +// If creating both key and a bool value at the same time, then +// instead of calling kv.Key(name).Bool(value) consider using a +// convenience function provided by the api/key package - +// key.Bool(name, value). +func (k Key) Bool(v bool) KeyValue { + return KeyValue{ + Key: k, + Value: boolValue(v), + } +} + +// Int64 creates a KeyValue instance with an INT64 Value. +// +// If creating both key and an int64 value at the same time, then +// instead of calling kv.Key(name).Int64(value) consider using a +// convenience function provided by the api/key package - +// key.Int64(name, value). +func (k Key) Int64(v int64) KeyValue { + return KeyValue{ + Key: k, + Value: int64Value(v), + } +} + +// Float64 creates a KeyValue instance with a FLOAT64 Value. +// +// If creating both key and a float64 value at the same time, then +// instead of calling kv.Key(name).Float64(value) consider using a +// convenience function provided by the api/key package - +// key.Float64(name, value). +func (k Key) Float64(v float64) KeyValue { + return KeyValue{ + Key: k, + Value: float64Value(v), + } +} + +// String creates a KeyValue instance with a STRING Value. +// +// If creating both key and a string value at the same time, then +// instead of calling kv.Key(name).String(value) consider using a +// convenience function provided by the api/key package - +// key.String(name, value). +func (k Key) String(v string) KeyValue { + return KeyValue{ + Key: k, + Value: stringValue(v), + } +} + +// Int creates a KeyValue instance with either an INT32 or an INT64 +// Value, depending on whether the int type is 32 or 64 bits wide. +// +// If creating both key and an int value at the same time, then +// instead of calling kv.Key(name).Int(value) consider using a +// convenience function provided by the api/key package - +// key.Int(name, value). +func (k Key) Int(v int) KeyValue { + return KeyValue{ + Key: k, + Value: intValue(v), + } +} + +// ValueType describes the type of the data Value holds. +type ValueType int + +const ( + INVALID ValueType = iota // No value. + // BOOL is a boolean Type Value. + BOOL + // INT64 is a 64-bit signed integral Type Value. + INT64 + // FLOAT64 is a 64-bit floating point Type Value. + FLOAT64 + // STRING is a string Type Value. + STRING +) + +type Value struct { + vtype ValueType + numeric uint64 + stringly string +} + +func boolTowRaw(b bool) uint64 { + if b { + return 1 + } + return 0 +} + +func rawToBool(r uint64) bool { + return r != 0 +} + +func boolValue(v bool) Value { + return Value{ + vtype: BOOL, + numeric: boolTowRaw(v), + } +} + +func int64Value(v int64) Value { + return Value{ + vtype: INT64, + numeric: uint64(v), + } +} + +func float64Value(v float64) Value { + return Value{ + vtype: FLOAT64, + numeric: math.Float64bits(v), + } +} + +func stringValue(v string) Value { + return Value{ + vtype: STRING, + stringly: v, + } +} + +// intValue creates an INT64 Value. +func intValue(v int) Value { + return int64Value(int64(v)) +} + +func (v Value) AsBool() bool { + return rawToBool(v.numeric) +} + +// AsInt64 returns the int64 value. Make sure that the Value's type is +// INT64. +func (v Value) AsInt64() int64 { + return int64(v.numeric) +} + +// AsFloat64 returns the float64 value. Make sure that the Value's +// type is FLOAT64. +func (v Value) AsFloat64() float64 { + return math.Float64frombits(v.numeric) +} + +// AsString returns the string value. Make sure that the Value's type +// is STRING. +func (v Value) AsString() string { + return v.stringly +} + +// Type returns a type of the Value. +func (v Value) Type() ValueType { + return v.vtype +} diff --git a/interceptors/tracing/kv/value_test.go b/interceptors/tracing/kv/value_test.go new file mode 100644 index 000000000..34c48687b --- /dev/null +++ b/interceptors/tracing/kv/value_test.go @@ -0,0 +1,56 @@ +package kv + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestKey(t *testing.T) { + testCases := []struct { + name string + keyValue KeyValue + expectedValue interface{} + }{ + { + name: "true", + keyValue: Key("bool").Bool(true), + expectedValue: true, + }, + { + name: "false", + keyValue: Key("bool").Bool(false), + expectedValue: false, + }, + { + name: "int64", + keyValue: Key("int64").Int64(43), + expectedValue: int64(43), + }, + { + name: "float64", + keyValue: Key("float64").Float64(43), + expectedValue: float64(43), + }, + { + name: "string", + keyValue: Key("string").String("foo"), + expectedValue: "foo", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + switch tc.keyValue.Value.Type() { + case BOOL: + assert.Equal(t, tc.expectedValue, tc.keyValue.Value.AsBool()) + case INT64: + assert.Equal(t, tc.expectedValue, tc.keyValue.Value.AsInt64()) + case FLOAT64: + assert.Equal(t, tc.expectedValue, tc.keyValue.Value.AsFloat64()) + case STRING: + assert.Equal(t, tc.expectedValue, tc.keyValue.Value.AsString()) + } + }) + } +} diff --git a/interceptors/tracing/reporter.go b/interceptors/tracing/reporter.go new file mode 100644 index 000000000..d8b5df61d --- /dev/null +++ b/interceptors/tracing/reporter.go @@ -0,0 +1,65 @@ +package tracing + +import ( + "context" + "io" + "time" + + "github.com/golang/protobuf/proto" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tracing/kv" +) + +type reporter struct { + ctx context.Context + span Span + + receivedMessageID int + sentMessageID int +} + +func (o *reporter) PostCall(err error, _ time.Duration) { + // Finish span. + if err != nil && err != io.EOF { + s, _ := status.FromError(err) + o.span.SetStatus(s.Code(), s.Message()) + o.span.SetAttributes(statusCodeAttr(s.Code())) + } else { + o.span.SetAttributes(statusCodeAttr(codes.OK)) + } + o.span.End() +} + +func (o *reporter) PostMsgSend(payload interface{}, err error, d time.Duration) { + o.sentMessageID++ + + addEvent(o.span, RPCMessageTypeSent, o.sentMessageID, payload) +} + +func (o *reporter) PostMsgReceive(payload interface{}, err error, d time.Duration) { + o.receivedMessageID++ + + addEvent(o.span, RPCMessageTypeReceived, o.receivedMessageID, payload) +} + +func addEvent(span Span, messageType kv.KeyValue, messageID int, payload interface{}) { + if p, ok := payload.(proto.Message); ok { + span.AddEvent("message", + messageType, + rpcMessageIDKey.Int(messageID), + rpcMessageUncompressedSizeKey.Int(proto.Size(p)), + ) + } else { + span.AddEvent("message", + messageType, + rpcMessageIDKey.Int(messageID), + ) + } +} + +// statusCodeAttr returns status code attribute based on given gRPC code +func statusCodeAttr(c codes.Code) kv.KeyValue { + return grpcStatusCodeKey.Int64(int64(c)) +} \ No newline at end of file diff --git a/interceptors/tracing/tracing.go b/interceptors/tracing/tracing.go new file mode 100644 index 000000000..3415ecce3 --- /dev/null +++ b/interceptors/tracing/tracing.go @@ -0,0 +1,57 @@ +package tracing + +import ( + "context" + + "google.golang.org/grpc/codes" + + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tracing/kv" +) + +const ( + // Type of message transmitted or received. + rpcMessageTypeKey = kv.Key("message.type") + + // Identifier of message transmitted or received. + rpcMessageIDKey = kv.Key("message.id") + + // The uncompressed size of the message transmitted or received in + // bytes. + rpcMessageUncompressedSizeKey = kv.Key("message.uncompressed_size") + + // grpcStatusCodeKey is convention for numeric status code of a gRPC request. + grpcStatusCodeKey = kv.Key("rpc.grpc.status_code") +) + +var ( + RPCMessageTypeSent = rpcMessageTypeKey.String("SENT") + RPCMessageTypeReceived = rpcMessageTypeKey.String("RECEIVED") +) + +type Tracer interface { + Start(ctx context.Context, spanName string, kind SpanKind) (context.Context, Span) +} + +type Span interface { + // End completes the span. No updates are allowed to span after it + // ends. The only exception is setting status of the span. + End() + + // SetStatus sets the status of the span in the form of a code + // and a message. SetStatus overrides the value of previous + // calls to SetStatus on the Span. + // + // The default span status is OK, so it is not necessary to + // explicitly set an OK status on successful Spans unless it + // is to add an OK message or to override a previous status on the Span. + SetStatus(code codes.Code, msg string) + + // AddEvent adds an event to the span. + // Middleware will call it while receiving or sending messages. + AddEvent(name string, attrs ...kv.KeyValue) + + // SetAttributes sets kv as attributes of the Span. If a key from kv + // already exists for an attribute of the Span it should be overwritten with + // the value contained in kv. + SetAttributes(attrs ...kv.KeyValue) +} From 076b969e36e4f8d977e9423257b7c40d2e9853e7 Mon Sep 17 00:00:00 2001 From: Sam Xie Date: Thu, 6 May 2021 17:06:37 +0800 Subject: [PATCH 26/27] Add opentracing provider --- providers/opentracing/client.go | 49 ++++ providers/opentracing/examples_test.go | 33 +++ providers/opentracing/go.mod | 13 + providers/opentracing/go.sum | 99 +++++++ providers/opentracing/id_extract.go | 80 ++++++ providers/opentracing/interceptors_test.go | 294 +++++++++++++++++++++ providers/opentracing/metadata.go | 49 ++++ providers/opentracing/options.go | 46 ++++ providers/opentracing/server.go | 36 +++ providers/opentracing/span.go | 99 +++++++ providers/opentracing/tracer.go | 36 +++ 11 files changed, 834 insertions(+) create mode 100644 providers/opentracing/client.go create mode 100644 providers/opentracing/examples_test.go create mode 100644 providers/opentracing/go.mod create mode 100644 providers/opentracing/go.sum create mode 100644 providers/opentracing/id_extract.go create mode 100644 providers/opentracing/interceptors_test.go create mode 100644 providers/opentracing/metadata.go create mode 100644 providers/opentracing/options.go create mode 100644 providers/opentracing/server.go create mode 100644 providers/opentracing/span.go create mode 100644 providers/opentracing/tracer.go diff --git a/providers/opentracing/client.go b/providers/opentracing/client.go new file mode 100644 index 000000000..be403bb9d --- /dev/null +++ b/providers/opentracing/client.go @@ -0,0 +1,49 @@ +package opentracing + +import ( + "context" + + "github.com/opentracing/opentracing-go" + "github.com/opentracing/opentracing-go/ext" + "google.golang.org/grpc/grpclog" + + "github.com/grpc-ecosystem/go-grpc-middleware/v2/util/metautils" +) + +var ( + grpcTag = opentracing.Tag{Key: string(ext.Component), Value: "gRPC"} +) + +// ClientAddContextTags returns a context with specified opentracing tags, which +// are used by UnaryClientInterceptor/StreamClientInterceptor when creating a +// new span. +func ClientAddContextTags(ctx context.Context, tags opentracing.Tags) context.Context { + return context.WithValue(ctx, clientSpanTagKey{}, tags) +} + +type clientSpanTagKey struct{} + +func newClientSpanFromContext(ctx context.Context, tracer opentracing.Tracer, fullMethodName string) (context.Context, opentracing.Span) { + var parentSpanCtx opentracing.SpanContext + if parent := opentracing.SpanFromContext(ctx); parent != nil { + parentSpanCtx = parent.Context() + } + opts := []opentracing.StartSpanOption{ + opentracing.ChildOf(parentSpanCtx), + ext.SpanKindRPCClient, + grpcTag, + } + if tagx := ctx.Value(clientSpanTagKey{}); tagx != nil { + if opt, ok := tagx.(opentracing.StartSpanOption); ok { + opts = append(opts, opt) + } + } + clientSpan := tracer.StartSpan(fullMethodName, opts...) + // Make sure we add this to the metadata of the call, so it gets propagated: + md := metautils.ExtractOutgoing(ctx).Clone() + if err := tracer.Inject(clientSpan.Context(), opentracing.HTTPHeaders, metadataTextMap(md)); err != nil { + grpclog.Infof("grpc_opentracing: failed serializing trace information: %v", err) + } + ctxWithMetadata := md.ToOutgoing(ctx) + return opentracing.ContextWithSpan(ctxWithMetadata, clientSpan), clientSpan +} diff --git a/providers/opentracing/examples_test.go b/providers/opentracing/examples_test.go new file mode 100644 index 000000000..84030662d --- /dev/null +++ b/providers/opentracing/examples_test.go @@ -0,0 +1,33 @@ +package opentracing_test + +import ( + "testing" + + "google.golang.org/grpc" + + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tags" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tracing" + grpcopentracing "github.com/grpc-ecosystem/go-grpc-middleware/v2/providers/opentracing" +) + +func Example() { + _ = grpc.NewServer( + grpc.ChainUnaryInterceptor( + tags.UnaryServerInterceptor(tags.WithFieldExtractor(tags.CodeGenRequestFieldExtractor)), + tracing.UnaryServerInterceptor(grpcopentracing.InterceptorTracer()), + ), + grpc.ChainStreamInterceptor( + tags.StreamServerInterceptor(tags.WithFieldExtractor(tags.CodeGenRequestFieldExtractor)), + tracing.StreamServerInterceptor(grpcopentracing.InterceptorTracer()), + ), + ) + + _, _ = grpc.Dial("", + grpc.WithUnaryInterceptor(tracing.UnaryClientInterceptor(grpcopentracing.InterceptorTracer())), + grpc.WithStreamInterceptor(tracing.StreamClientInterceptor(grpcopentracing.InterceptorTracer())), + ) +} + +func TestExamplesBuildable(t *testing.T) { + Example() +} diff --git a/providers/opentracing/go.mod b/providers/opentracing/go.mod new file mode 100644 index 000000000..1512fef44 --- /dev/null +++ b/providers/opentracing/go.mod @@ -0,0 +1,13 @@ +module github.com/grpc-ecosystem/go-grpc-middleware/providers/opentracing/v2 + +go 1.14 + +replace github.com/grpc-ecosystem/go-grpc-middleware/v2 => ../.. + +require ( + github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2 + github.com/opentracing/opentracing-go v1.1.0 + github.com/pkg/errors v0.9.1 + github.com/stretchr/testify v1.7.0 + google.golang.org/grpc v1.30.1 +) diff --git a/providers/opentracing/go.sum b/providers/opentracing/go.sum new file mode 100644 index 000000000..dde461bcc --- /dev/null +++ b/providers/opentracing/go.sum @@ -0,0 +1,99 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +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-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +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/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200624020401-64a14ca9d1ad h1:uAwc13+y0Y8QZLTYhLCu6lHhnG99ecQU5FYTj8zxAng= +google.golang.org/genproto v0.0.0-20200624020401-64a14ca9d1ad/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.30.1 h1:oJTcovwKSu7V3TaBKd0/AXOuJVHjTdGTutbMHIOgVEQ= +google.golang.org/grpc v1.30.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc/examples v0.0.0-20200723182653-9106c3fff523/go.mod h1:5j1uub0jRGhRiSghIlrThmBUgcgLXOVJQ/l1getT4uo= +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= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/providers/opentracing/id_extract.go b/providers/opentracing/id_extract.go new file mode 100644 index 000000000..8216c6641 --- /dev/null +++ b/providers/opentracing/id_extract.go @@ -0,0 +1,80 @@ +package opentracing + +import ( + "strings" + + "github.com/opentracing/opentracing-go" + "google.golang.org/grpc/grpclog" + + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tags" +) + +const ( + TagTraceId = "trace.traceid" + TagSpanId = "trace.spanid" + TagSampled = "trace.sampled" + jaegerNotSampledFlag = "0" +) + +// injectOpentracingIdsToTags writes trace data to tags. +// This is done in an incredibly hacky way, because the public-facing interface of opentracing doesn't give access to +// the TraceId and SpanId of the SpanContext. Only the Tracer's Inject/Extract methods know what these are. +// Most tracers have them encoded as keys with 'traceid' and 'spanid': +// https://github.com/openzipkin/zipkin-go-opentracing/blob/594640b9ef7e5c994e8d9499359d693c032d738c/propagation_ot.go#L29 +// https://github.com/opentracing/basictracer-go/blob/1b32af207119a14b1b231d451df3ed04a72efebf/propagation_ot.go#L26 +// Jaeger from Uber use one-key schema with next format '{trace-id}:{span-id}:{parent-span-id}:{flags}' +// https://www.jaegertracing.io/docs/client-libraries/#trace-span-identity +// Datadog uses keys ending with 'trace-id' and 'parent-id' (for span) by default: +// https://github.com/DataDog/dd-trace-go/blob/v1/ddtrace/tracer/textmap.go#L77 +func injectOpentracingIdsToTags(traceHeaderName string, span opentracing.Span, tags tags.Tags) { + if err := span.Tracer().Inject(span.Context(), opentracing.HTTPHeaders, + &tagsCarrier{Tags: tags, traceHeaderName: traceHeaderName}); err != nil { + grpclog.Infof("grpc_opentracing: failed extracting trace info into ctx %v", err) + } +} + +// tagsCarrier is a really hacky way of +type tagsCarrier struct { + tags.Tags + traceHeaderName string +} + +func (t *tagsCarrier) Set(key, val string) { + key = strings.ToLower(key) + if strings.Contains(key, "traceid") { + t.Tags.Set(TagTraceId, val) // this will most likely be base-16 (hex) encoded + } + + if strings.Contains(key, "spanid") && !strings.Contains(strings.ToLower(key), "parent") { + t.Tags.Set(TagSpanId, val) // this will most likely be base-16 (hex) encoded + } + + if strings.Contains(key, "sampled") { + switch val { + case "true", "false": + t.Tags.Set(TagSampled, val) + } + } + + if key == t.traceHeaderName { + parts := strings.Split(val, ":") + if len(parts) == 4 { + t.Tags.Set(TagTraceId, parts[0]) + t.Tags.Set(TagSpanId, parts[1]) + + if parts[3] != jaegerNotSampledFlag { + t.Tags.Set(TagSampled, "true") + } else { + t.Tags.Set(TagSampled, "false") + } + } + } + + if strings.HasSuffix(key, "trace-id") { + t.Tags.Set(TagTraceId, val) + } + + if strings.HasSuffix(key, "parent-id") { + t.Tags.Set(TagSpanId, val) + } +} diff --git a/providers/opentracing/interceptors_test.go b/providers/opentracing/interceptors_test.go new file mode 100644 index 000000000..8a712b867 --- /dev/null +++ b/providers/opentracing/interceptors_test.go @@ -0,0 +1,294 @@ +// Copyright 2017 Michal Witkowski. All Rights Reserved. +// See LICENSE for licensing terms. + +package opentracing_test + +import ( + "context" + "fmt" + "io" + "net/http" + "strconv" + "strings" + "testing" + + "github.com/opentracing/opentracing-go" + "github.com/opentracing/opentracing-go/mocktracer" + "github.com/pkg/errors" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + + grpcopentracing "github.com/grpc-ecosystem/go-grpc-middleware/providers/opentracing/v2" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tags" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tracing" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/testing/testpb" +) + +var ( + fakeInboundTraceId = 1337 + fakeInboundSpanId = 999 + traceHeaderName = "uber-trace-id" +) + +type tracingAssertService struct { + testpb.TestServiceServer + T *testing.T +} + +func (s *tracingAssertService) Ping(ctx context.Context, ping *testpb.PingRequest) (*testpb.PingResponse, error) { + assert.NotNil(s.T, opentracing.SpanFromContext(ctx), "handlers must have the spancontext in their context, otherwise propagation will fail") + tags := tags.Extract(ctx) + assert.True(s.T, tags.Has(grpcopentracing.TagTraceId), "tags must contain traceid") + assert.True(s.T, tags.Has(grpcopentracing.TagSpanId), "tags must contain spanid") + assert.True(s.T, tags.Has(grpcopentracing.TagSampled), "tags must contain sampled") + assert.Equal(s.T, tags.Values()[grpcopentracing.TagSampled], "true", "sampled must be set to true") + return s.TestServiceServer.Ping(ctx, ping) +} + +func (s *tracingAssertService) PingError(ctx context.Context, ping *testpb.PingErrorRequest) (*testpb.PingErrorResponse, error) { + assert.NotNil(s.T, opentracing.SpanFromContext(ctx), "handlers must have the spancontext in their context, otherwise propagation will fail") + return s.TestServiceServer.PingError(ctx, ping) +} + +func (s *tracingAssertService) PingList(ping *testpb.PingListRequest, stream testpb.TestService_PingListServer) error { + assert.NotNil(s.T, opentracing.SpanFromContext(stream.Context()), "handlers must have the spancontext in their context, otherwise propagation will fail") + tags := tags.Extract(stream.Context()) + assert.True(s.T, tags.Has(grpcopentracing.TagTraceId), "tags must contain traceid") + assert.True(s.T, tags.Has(grpcopentracing.TagSpanId), "tags must contain spanid") + assert.True(s.T, tags.Has(grpcopentracing.TagSampled), "tags must contain sampled") + assert.Equal(s.T, tags.Values()[grpcopentracing.TagSampled], "true", "sampled must be set to true") + return s.TestServiceServer.PingList(ping, stream) +} + +func (s *tracingAssertService) PingEmpty(ctx context.Context, empty *testpb.PingEmptyRequest) (*testpb.PingEmptyResponse, error) { + assert.NotNil(s.T, opentracing.SpanFromContext(ctx), "handlers must have the spancontext in their context, otherwise propagation will fail") + tags := tags.Extract(ctx) + assert.True(s.T, tags.Has(grpcopentracing.TagTraceId), "tags must contain traceid") + assert.True(s.T, tags.Has(grpcopentracing.TagSpanId), "tags must contain spanid") + assert.True(s.T, tags.Has(grpcopentracing.TagSampled), "tags must contain sampled") + assert.Equal(s.T, tags.Values()[grpcopentracing.TagSampled], "false", "sampled must be set to false") + return s.TestServiceServer.PingEmpty(ctx, empty) +} + +func TestTaggingSuite(t *testing.T) { + mockTracer := mocktracer.New() + opts := []grpcopentracing.Option{ + grpcopentracing.WithTracer(mockTracer), + grpcopentracing.WithTraceHeaderName(traceHeaderName), + } + s := &OpentracingSuite{ + mockTracer: mockTracer, + InterceptorTestSuite: makeInterceptorTestSuite(t, opts), + } + suite.Run(t, s) +} + +func TestTaggingSuiteJaeger(t *testing.T) { + mockTracer := mocktracer.New() + mockTracer.RegisterInjector(opentracing.HTTPHeaders, jaegerFormatInjector{}) + mockTracer.RegisterExtractor(opentracing.HTTPHeaders, jaegerFormatExtractor{}) + opts := []grpcopentracing.Option{ + grpcopentracing.WithTracer(mockTracer), + } + s := &OpentracingSuite{ + mockTracer: mockTracer, + InterceptorTestSuite: makeInterceptorTestSuite(t, opts), + } + suite.Run(t, s) +} + +func makeInterceptorTestSuite(t *testing.T, opts []grpcopentracing.Option) *testpb.InterceptorTestSuite { + return &testpb.InterceptorTestSuite{ + TestService: &tracingAssertService{TestServiceServer: &testpb.TestPingService{T: t}, T: t}, + ClientOpts: []grpc.DialOption{ + grpc.WithUnaryInterceptor(tracing.UnaryClientInterceptor(grpcopentracing.InterceptorTracer(opts...))), + grpc.WithStreamInterceptor(tracing.StreamClientInterceptor(grpcopentracing.InterceptorTracer(opts...))), + }, + ServerOpts: []grpc.ServerOption{ + grpc.ChainUnaryInterceptor( + tags.UnaryServerInterceptor(tags.WithFieldExtractor(tags.CodeGenRequestFieldExtractor)), + tracing.UnaryServerInterceptor(grpcopentracing.InterceptorTracer(opts...)), + ), + grpc.ChainStreamInterceptor( + tags.StreamServerInterceptor(tags.WithFieldExtractor(tags.CodeGenRequestFieldExtractor)), + tracing.StreamServerInterceptor(grpcopentracing.InterceptorTracer(opts...)), + ), + }, + } +} + +type OpentracingSuite struct { + *testpb.InterceptorTestSuite + mockTracer *mocktracer.MockTracer +} + +func (s *OpentracingSuite) SetupTest() { + s.mockTracer.Reset() +} + +func (s *OpentracingSuite) createContextFromFakeHttpRequestParent(ctx context.Context, sampled bool) context.Context { + jFlag := 0 + if sampled { + jFlag = 1 + } + + hdr := http.Header{} + hdr.Set(traceHeaderName, fmt.Sprintf("%d:%d:%d:%d", fakeInboundTraceId, fakeInboundSpanId, fakeInboundSpanId, jFlag)) + hdr.Set("mockpfx-ids-traceid", fmt.Sprint(fakeInboundTraceId)) + hdr.Set("mockpfx-ids-spanid", fmt.Sprint(fakeInboundSpanId)) + hdr.Set("mockpfx-ids-sampled", fmt.Sprint(sampled)) + + parentSpanContext, err := s.mockTracer.Extract(opentracing.HTTPHeaders, opentracing.HTTPHeadersCarrier(hdr)) + require.NoError(s.T(), err, "parsing a fake HTTP request headers shouldn't fail, ever") + fakeSpan := s.mockTracer.StartSpan( + "/fake/parent/http/request", + // this is magical, it attaches the new span to the parent parentSpanContext, and creates an unparented one if empty. + opentracing.ChildOf(parentSpanContext), + ) + fakeSpan.Finish() + return opentracing.ContextWithSpan(ctx, fakeSpan) +} + +func (s *OpentracingSuite) assertTracesCreated(methodName string) (clientSpan *mocktracer.MockSpan, serverSpan *mocktracer.MockSpan) { + spans := s.mockTracer.FinishedSpans() + for _, span := range spans { + s.T().Logf("span: %v, tags: %v", span, span.Tags()) + } + require.Len(s.T(), spans, 3, "should record 3 spans: one fake inbound, one client, one server") + traceIdAssert := fmt.Sprintf("traceId=%d", fakeInboundTraceId) + for _, span := range spans { + assert.Contains(s.T(), span.String(), traceIdAssert, "not part of the fake parent trace: %v", span) + if span.OperationName == methodName { + kind := fmt.Sprintf("%v", span.Tag("span.kind")) + if kind == "client" { + clientSpan = span + } else if kind == "server" { + serverSpan = span + } + assert.EqualValues(s.T(), span.Tag("component"), "gRPC", "span must be tagged with gRPC component") + } + } + require.NotNil(s.T(), clientSpan, "client span must be there") + require.NotNil(s.T(), serverSpan, "server span must be there") + assert.EqualValues(s.T(), "something", serverSpan.Tag("grpc.request.value"), "tags must be propagated, in this case ones from request fields") + return clientSpan, serverSpan +} + +func (s *OpentracingSuite) TestPing_PropagatesTraces() { + ctx := s.createContextFromFakeHttpRequestParent(s.SimpleCtx(), true) + goodPing := testpb.PingRequest{Value: "something", SleepTimeMs: 9999} + _, err := s.Client.Ping(ctx, &goodPing) + require.NoError(s.T(), err, "there must be not be an on a successful call") + s.assertTracesCreated("/" + testpb.TestServiceFullName + "/Ping") +} + +func (s *OpentracingSuite) TestPing_ClientContextTags() { + const name = "opentracing.custom" + ctx := grpcopentracing.ClientAddContextTags( + s.createContextFromFakeHttpRequestParent(s.SimpleCtx(), true), + opentracing.Tags{name: ""}, + ) + + goodPing := testpb.PingRequest{Value: "something", SleepTimeMs: 9999} + _, err := s.Client.Ping(ctx, &goodPing) + require.NoError(s.T(), err, "there must be not be an on a successful call") + + for _, span := range s.mockTracer.FinishedSpans() { + if span.OperationName == "/"+testpb.TestServiceFullName+"/Ping" { + kind := fmt.Sprintf("%v", span.Tag("span.kind")) + if kind == "client" { + assert.Contains(s.T(), span.Tags(), name, "custom opentracing.Tags must be included in context") + } + } + } +} + +func (s *OpentracingSuite) TestPingList_PropagatesTraces() { + ctx := s.createContextFromFakeHttpRequestParent(s.SimpleCtx(), true) + goodPing := testpb.PingListRequest{Value: "something", SleepTimeMs: 9999} + stream, err := s.Client.PingList(ctx, &goodPing) + require.NoError(s.T(), err, "should not fail on establishing the stream") + for { + _, err := stream.Recv() + if err == io.EOF { + break + } + require.NoError(s.T(), err, "reading stream should not fail") + } + s.assertTracesCreated("/" + testpb.TestServiceFullName + "/PingList") +} + +func (s *OpentracingSuite) TestPingError_PropagatesTraces() { + ctx := s.createContextFromFakeHttpRequestParent(s.SimpleCtx(), true) + erroringPing := testpb.PingErrorRequest{Value: "something", ErrorCodeReturned: uint32(codes.OutOfRange)} + _, err := s.Client.PingError(ctx, &erroringPing) + require.Error(s.T(), err, "there must be an error returned here") + clientSpan, serverSpan := s.assertTracesCreated("/" + testpb.TestServiceFullName + "/PingError") + assert.Equal(s.T(), true, clientSpan.Tag("error"), "client span needs to be marked as an error") + assert.Equal(s.T(), true, serverSpan.Tag("error"), "server span needs to be marked as an error") +} + +func (s *OpentracingSuite) TestPingEmpty_NotSampleTraces() { + ctx := s.createContextFromFakeHttpRequestParent(s.SimpleCtx(), false) + _, err := s.Client.PingEmpty(ctx, &testpb.PingEmptyRequest{}) + require.NoError(s.T(), err, "there must be not be an on a successful call") +} + +type jaegerFormatInjector struct{} + +func (jaegerFormatInjector) Inject(ctx mocktracer.MockSpanContext, carrier interface{}) error { + w := carrier.(opentracing.TextMapWriter) + flags := 0 + if ctx.Sampled { + flags = 1 + } + w.Set(traceHeaderName, fmt.Sprintf("%d:%d::%d", ctx.TraceID, ctx.SpanID, flags)) + + return nil +} + +type jaegerFormatExtractor struct{} + +func (jaegerFormatExtractor) Extract(carrier interface{}) (mocktracer.MockSpanContext, error) { + rval := mocktracer.MockSpanContext{Sampled: true} + reader, ok := carrier.(opentracing.TextMapReader) + if !ok { + return rval, opentracing.ErrInvalidCarrier + } + err := reader.ForeachKey(func(key, val string) error { + lowerKey := strings.ToLower(key) + switch { + case lowerKey == traceHeaderName: + parts := strings.Split(val, ":") + if len(parts) != 4 { + return errors.New("invalid trace id format") + } + traceId, err := strconv.Atoi(parts[0]) + if err != nil { + return err + } + rval.TraceID = traceId + spanId, err := strconv.Atoi(parts[1]) + if err != nil { + return err + } + rval.SpanID = spanId + flags, err := strconv.Atoi(parts[3]) + if err != nil { + return err + } + rval.Sampled = flags%2 == 1 + } + return nil + }) + if rval.TraceID == 0 || rval.SpanID == 0 { + return rval, opentracing.ErrSpanContextNotFound + } + if err != nil { + return rval, err + } + return rval, nil +} diff --git a/providers/opentracing/metadata.go b/providers/opentracing/metadata.go new file mode 100644 index 000000000..f42c3c370 --- /dev/null +++ b/providers/opentracing/metadata.go @@ -0,0 +1,49 @@ +// Copyright 2017 Michal Witkowski. All Rights Reserved. +// See LICENSE for licensing terms. + +package opentracing + +import ( + "encoding/base64" + "strings" + + "google.golang.org/grpc/metadata" +) + +const ( + binHdrSuffix = "-bin" +) + +// metadataTextMap extends a metadata.MD to be an opentracing textmap +type metadataTextMap metadata.MD + +// Set is a opentracing.TextMapReader interface that extracts values. +func (m metadataTextMap) Set(key, val string) { + // gRPC allows for complex binary values to be written. + encodedKey, encodedVal := encodeKeyValue(key, val) + // The metadata object is a multimap, and previous values may exist, but for opentracing headers, we do not append + // we just override. + m[encodedKey] = []string{encodedVal} +} + +// ForeachKey is a opentracing.TextMapReader interface that extracts values. +func (m metadataTextMap) ForeachKey(callback func(key, val string) error) error { + for k, vv := range m { + for _, v := range vv { + if err := callback(k, v); err != nil { + return err + } + } + } + return nil +} + +// encodeKeyValue encodes key and value qualified for transmission via gRPC. +// note: copy pasted from private values of grpc.metadata +func encodeKeyValue(k, v string) (string, string) { + k = strings.ToLower(k) + if strings.HasSuffix(k, binHdrSuffix) { + v = base64.StdEncoding.EncodeToString([]byte(v)) + } + return k, v +} diff --git a/providers/opentracing/options.go b/providers/opentracing/options.go new file mode 100644 index 000000000..648bf2b9b --- /dev/null +++ b/providers/opentracing/options.go @@ -0,0 +1,46 @@ +package opentracing + +import "github.com/opentracing/opentracing-go" + +var ( + defaultOptions = &options{ + tracer: nil, + } +) + +type options struct { + tracer opentracing.Tracer + traceHeaderName string +} + +func evaluateOptions(opts []Option) *options { + optCopy := &options{} + *optCopy = *defaultOptions + for _, o := range opts { + o(optCopy) + } + if optCopy.tracer == nil { + optCopy.tracer = opentracing.GlobalTracer() + } + if optCopy.traceHeaderName == "" { + optCopy.traceHeaderName = "uber-trace-id" + } + return optCopy +} + +type Option func(*options) + +// WithTraceHeaderName customizes the trace header name where trace metadata passed with requests. +// Default one is `uber-trace-id` +func WithTraceHeaderName(name string) Option { + return func(o *options) { + o.traceHeaderName = name + } +} + +// WithTracer sets a custom tracer to be used for this middleware, otherwise the opentracing.GlobalTracer is used. +func WithTracer(tracer opentracing.Tracer) Option { + return func(o *options) { + o.tracer = tracer + } +} diff --git a/providers/opentracing/server.go b/providers/opentracing/server.go new file mode 100644 index 000000000..09e4cadf1 --- /dev/null +++ b/providers/opentracing/server.go @@ -0,0 +1,36 @@ +package opentracing + +import ( + "context" + + "github.com/opentracing/opentracing-go" + "github.com/opentracing/opentracing-go/ext" + "google.golang.org/grpc/grpclog" + + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tags" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/util/metautils" +) + +func newServerSpanFromInbound(ctx context.Context, tracer opentracing.Tracer, traceHeaderName, fullMethodName string) (context.Context, opentracing.Span) { + md := metautils.ExtractIncoming(ctx) + parentSpanContext, err := tracer.Extract(opentracing.HTTPHeaders, metadataTextMap(md)) + if err != nil && err != opentracing.ErrSpanContextNotFound { + grpclog.Infof("grpc_opentracing: failed parsing trace information: %v", err) + } + + serverSpan := tracer.StartSpan( + fullMethodName, + // this is magical, it attaches the new span to the parent parentSpanContext, and creates an unparented one if empty. + ext.RPCServerOption(parentSpanContext), + grpcTag, + ) + + // Log context information. + t := tags.Extract(ctx) + for k, v := range t.Values() { + serverSpan.SetTag(k, v) + } + + injectOpentracingIdsToTags(traceHeaderName, serverSpan, tags.Extract(ctx)) + return opentracing.ContextWithSpan(ctx, serverSpan), serverSpan +} diff --git a/providers/opentracing/span.go b/providers/opentracing/span.go new file mode 100644 index 000000000..ebceeb4c7 --- /dev/null +++ b/providers/opentracing/span.go @@ -0,0 +1,99 @@ +package opentracing + +import ( + "context" + + "github.com/opentracing/opentracing-go" + "github.com/opentracing/opentracing-go/ext" + "github.com/opentracing/opentracing-go/log" + "google.golang.org/grpc/codes" + + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tags" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tracing" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tracing/kv" +) + +type span struct { + span opentracing.Span + ctx context.Context + + initial bool +} + +// Compatibility check. +var _ tracing.Span = &span{} + +func newSpan(rawSpan opentracing.Span, ctx context.Context) *span { + return &span{ + span: rawSpan, + ctx: ctx, + initial: true, + } +} + +func (s *span) End() { + // Middleware tags only record once + if s.initial { + s.initial = false + t := tags.Extract(s.ctx) + for k, v := range t.Values() { + s.span.SetTag(k, v) + } + } + + s.span.Finish() +} + +func (s *span) SetStatus(code codes.Code, msg string) { + if code != codes.OK { + ext.Error.Set(s.span, true) + s.span.LogFields(log.String("event", "error"), log.String("message", msg)) + } +} + +func (s *span) AddEvent(name string, attrs ...kv.KeyValue) { + fields := make([]log.Field, 0, len(attrs) +1) + + fields = append(fields, log.String("event", name)) + + for _, attr := range attrs { + switch attr.Value.Type() { + case kv.BOOL: + fields = append(fields, log.Bool(string(attr.Key), attr.Value.AsBool())) + case kv.INT64: + fields = append(fields, log.Int64(string(attr.Key), attr.Value.AsInt64())) + case kv.FLOAT64: + fields = append(fields, log.Float64(string(attr.Key), attr.Value.AsFloat64())) + case kv.STRING: + fields = append(fields, log.String(string(attr.Key), attr.Value.AsString())) + default: + continue + } + } + + s.span.LogFields(fields...) +} + + +func (s *span) SetAttributes(attrs ...kv.KeyValue) { + for _, attr := range attrs { + var v interface{} + switch attr.Value.Type() { + case kv.BOOL: + v = attr.Value.AsBool() + case kv.INT64: + v = attr.Value.AsInt64() + case kv.FLOAT64: + v = attr.Value.AsFloat64() + case kv.STRING: + v = attr.Value.AsString() + default: + continue + } + + if v != nil { + s.span.SetTag(string(attr.Key), v) + } + } +} + diff --git a/providers/opentracing/tracer.go b/providers/opentracing/tracer.go new file mode 100644 index 000000000..78fde2544 --- /dev/null +++ b/providers/opentracing/tracer.go @@ -0,0 +1,36 @@ +package opentracing + +import ( + "context" + + "github.com/opentracing/opentracing-go" + + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tracing" +) + +type tracer struct { + tracer opentracing.Tracer + // This is only used for server. + traceHeaderName string +} + +// Compatibility check. +var _ tracing.Tracer = &tracer{} + +// InterceptorTracer converts OpenTracing tracer to Tracer adapter. +func InterceptorTracer(opts ...Option) *tracer { + o := evaluateOptions(opts) + + return &tracer{tracer: o.tracer, traceHeaderName: o.traceHeaderName} +} + +func (t *tracer) Start(ctx context.Context, spanName string, kind tracing.SpanKind) (context.Context, tracing.Span) { + var span opentracing.Span + switch kind { + case tracing.SpanKindClient: + ctx, span = newClientSpanFromContext(ctx, t.tracer, spanName) + case tracing.SpanKindServer: + ctx, span = newServerSpanFromInbound(ctx, t.tracer, t.traceHeaderName, spanName) + } + return ctx, newSpan(span, ctx) +} From 92da0bae57b0d38a46935397236e97aebb8a7746 Mon Sep 17 00:00:00 2001 From: Sam Xie Date: Thu, 6 May 2021 17:07:02 +0800 Subject: [PATCH 27/27] Add opentelemetry provider --- providers/opentelemetry/client.go | 84 ++++++++++++++ providers/opentelemetry/examples_test.go | 33 ++++++ providers/opentelemetry/go.mod | 13 +++ providers/opentelemetry/go.sum | 138 +++++++++++++++++++++++ providers/opentelemetry/options.go | 52 +++++++++ providers/opentelemetry/server.go | 29 +++++ providers/opentelemetry/span.go | 69 ++++++++++++ providers/opentelemetry/tracer.go | 36 ++++++ 8 files changed, 454 insertions(+) create mode 100644 providers/opentelemetry/client.go create mode 100644 providers/opentelemetry/examples_test.go create mode 100644 providers/opentelemetry/go.mod create mode 100644 providers/opentelemetry/go.sum create mode 100644 providers/opentelemetry/options.go create mode 100644 providers/opentelemetry/server.go create mode 100644 providers/opentelemetry/span.go create mode 100644 providers/opentelemetry/tracer.go diff --git a/providers/opentelemetry/client.go b/providers/opentelemetry/client.go new file mode 100644 index 000000000..35ee99372 --- /dev/null +++ b/providers/opentelemetry/client.go @@ -0,0 +1,84 @@ +package opentelemetry + +import ( + "context" + "net" + "strings" + + "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/propagation" + "go.opentelemetry.io/otel/semconv" + "go.opentelemetry.io/otel/trace" + "google.golang.org/grpc/metadata" + + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tags" +) + +func newClientSpanFromContext(ctx context.Context, fullMethod string, tracer trace.Tracer, propagators propagation.TextMapPropagator) (context.Context, trace.Span) { + name, attrs := spanInfo(ctx, fullMethod) + + ctx, span := tracer.Start( + ctx, + name, + trace.WithSpanKind(trace.SpanKindClient), + trace.WithAttributes(attrs...), + ) + + requestMetadata, _ := metadata.FromOutgoingContext(ctx) + metadataCopy := requestMetadata.Copy() + otelgrpc.Inject(ctx, &metadataCopy, otelgrpc.WithPropagators(propagators)) + ctx = metadata.NewOutgoingContext(ctx, metadataCopy) + + return ctx, span +} + +func spanInfo(ctx context.Context, fullMethod string) (string, []attribute.KeyValue) { + t := tags.Extract(ctx) + + attrs := []attribute.KeyValue{semconv.RPCSystemGRPC} + name, mAttrs := parseFullMethod(fullMethod) + attrs = append(attrs, mAttrs...) + attrs = append(attrs, peerAttr(t.Values()["peer.address"])...) + return name, attrs +} + +// peerAttr returns attributes about the peer address. +func peerAttr(addr string) []attribute.KeyValue { + host, port, err := net.SplitHostPort(addr) + if err != nil { + return []attribute.KeyValue(nil) + } + + if host == "" { + host = "127.0.0.1" + } + + return []attribute.KeyValue{ + semconv.NetPeerIPKey.String(host), + semconv.NetPeerPortKey.String(port), + } +} + +// parseFullMethod returns a span name following the OpenTelemetry semantic +// conventions as well as all applicable span kv.KeyValue attributes based +// on a gRPC's FullMethod. +func parseFullMethod(fullMethod string) (string, []attribute.KeyValue) { + // The span name MUST be the full RPC method name formatted as + // `$package.$service/$method`. + name := strings.TrimLeft(fullMethod, "/") + parts := strings.SplitN(name, "/", 2) + if len(parts) != 2 { + // Invalid format, does not follow `$package.$service/$method`. + return name, []attribute.KeyValue(nil) + } + + var attrs []attribute.KeyValue + if service := parts[0]; service != "" { + attrs = append(attrs, semconv.RPCServiceKey.String(service)) + } + if method := parts[1]; method != "" { + attrs = append(attrs, semconv.RPCMethodKey.String(method)) + } + return name, attrs +} diff --git a/providers/opentelemetry/examples_test.go b/providers/opentelemetry/examples_test.go new file mode 100644 index 000000000..c3130ebe2 --- /dev/null +++ b/providers/opentelemetry/examples_test.go @@ -0,0 +1,33 @@ +package opentelemetry_test + +import ( + "testing" + + "google.golang.org/grpc" + + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tags" + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tracing" + grpcopentelemetry "github.com/grpc-ecosystem/go-grpc-middleware/v2/providers/opentelemetry" +) + +func Example() { + _ = grpc.NewServer( + grpc.ChainUnaryInterceptor( + tags.UnaryServerInterceptor(tags.WithFieldExtractor(tags.CodeGenRequestFieldExtractor)), + tracing.UnaryServerInterceptor(grpcopentelemetry.InterceptorTracer()), + ), + grpc.ChainStreamInterceptor( + tags.StreamServerInterceptor(tags.WithFieldExtractor(tags.CodeGenRequestFieldExtractor)), + tracing.StreamServerInterceptor(grpcopentelemetry.InterceptorTracer()), + ), + ) + + _, _ = grpc.Dial("", + grpc.WithUnaryInterceptor(tracing.UnaryClientInterceptor(grpcopentelemetry.InterceptorTracer())), + grpc.WithStreamInterceptor(tracing.StreamClientInterceptor(grpcopentelemetry.InterceptorTracer())), + ) +} + +func TestExamplesBuildable(t *testing.T) { + Example() +} diff --git a/providers/opentelemetry/go.mod b/providers/opentelemetry/go.mod new file mode 100644 index 000000000..ea17550c6 --- /dev/null +++ b/providers/opentelemetry/go.mod @@ -0,0 +1,13 @@ +module github.com/grpc-ecosystem/go-grpc-middleware/providers/opentelemetry/v2 + +go 1.14 + +replace github.com/grpc-ecosystem/go-grpc-middleware/v2 => ../.. + +require ( + github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2 + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0 + go.opentelemetry.io/otel v0.20.0 + go.opentelemetry.io/otel/trace v0.20.0 + google.golang.org/grpc v1.37.0 +) diff --git a/providers/opentelemetry/go.sum b/providers/opentelemetry/go.sum new file mode 100644 index 000000000..2d184a294 --- /dev/null +++ b/providers/opentelemetry/go.sum @@ -0,0 +1,138 @@ +cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ= +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +go.opentelemetry.io/contrib v0.20.0 h1:ubFQUn0VCZ0gPwIoJfBJVpeBlyRMxu8Mm/huKWYd9p0= +go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0 h1:sO4WKdPAudZGKPcpZT4MJn6JaDmpyLrMPDGGyA1SttE= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= +go.opentelemetry.io/otel v0.20.0 h1:eaP0Fqu7SXHwvjiqDq83zImeehOHX8doTvU9AwXON8g= +go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= +go.opentelemetry.io/otel/metric v0.20.0 h1:4kzhXFP+btKm4jwxpjIqjs41A7MakRFUS86bqLHTIw8= +go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= +go.opentelemetry.io/otel/oteltest v0.20.0 h1:HiITxCawalo5vQzdHfKeZurV8x7ljcqAgiWzF6Vaeaw= +go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= +go.opentelemetry.io/otel/trace v0.20.0 h1:1DL6EXUdcg95gukhuRRvLDO/4X5THh/5dIV52lqtnbw= +go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= +go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +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-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11 h1:Yq9t9jnGoR+dBuitxdo9l6Q7xh/zOyNnYUtDKaQ3x0E= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200624020401-64a14ca9d1ad h1:uAwc13+y0Y8QZLTYhLCu6lHhnG99ecQU5FYTj8zxAng= +google.golang.org/genproto v0.0.0-20200624020401-64a14ca9d1ad/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.30.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.37.0 h1:uSZWeQJX5j11bIQ4AJoj+McDBo29cY1MCoC1wO3ts+c= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc/examples v0.0.0-20200723182653-9106c3fff523/go.mod h1:5j1uub0jRGhRiSghIlrThmBUgcgLXOVJQ/l1getT4uo= +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= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/providers/opentelemetry/options.go b/providers/opentelemetry/options.go new file mode 100644 index 000000000..e83036ca4 --- /dev/null +++ b/providers/opentelemetry/options.go @@ -0,0 +1,52 @@ +package opentelemetry + +import ( + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/propagation" + "go.opentelemetry.io/otel/trace" +) + +const ( + instrumentationName = "github.com/grpc-ecosystem/go-grpc-middleware/v2/providers/opentelemetry" +) + +type config struct { + TracerProvider trace.TracerProvider + Propagators propagation.TextMapPropagator + + tracer trace.Tracer +} + +// newConfig returns a config with all Options set. +func newConfig(opts ...Option) config { + cfg := config{ + Propagators: otel.GetTextMapPropagator(), + TracerProvider: otel.GetTracerProvider(), + } + for _, opt := range opts { + opt(&cfg) + } + + cfg.tracer = cfg.TracerProvider.Tracer(instrumentationName) + return cfg +} + +// Option specifies instrumentation configuration options. +type Option func(*config) + +// WithTracerProvider returns an Option to use the TracerProvider when +// creating a Tracer. +func WithTracerProvider(tp trace.TracerProvider) Option { + return func(cfg *config) { + cfg.TracerProvider = tp + } +} + +// WithPropagators specifies propagators to use for extracting +// information from the HTTP requests. If none are specified, global +// ones will be used. +func WithPropagators(propagators propagation.TextMapPropagator) Option { + return func(cfg *config) { + cfg.Propagators = propagators + } +} diff --git a/providers/opentelemetry/server.go b/providers/opentelemetry/server.go new file mode 100644 index 000000000..51f6c5345 --- /dev/null +++ b/providers/opentelemetry/server.go @@ -0,0 +1,29 @@ +package opentelemetry + +import ( + "context" + + "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" + "go.opentelemetry.io/otel/baggage" + "go.opentelemetry.io/otel/propagation" + "go.opentelemetry.io/otel/trace" + "google.golang.org/grpc/metadata" +) + +func newServerSpanFromContext(ctx context.Context, fullMethod string, tracer trace.Tracer, propagators propagation.TextMapPropagator) (context.Context, trace.Span) { + requestMetadata, _ := metadata.FromIncomingContext(ctx) + metadataCopy := requestMetadata.Copy() + + entries, spanCtx := otelgrpc.Extract(ctx, &metadataCopy, otelgrpc.WithPropagators(propagators)) + ctx = baggage.ContextWithValues(ctx, entries...) + + name, attrs := spanInfo(ctx, fullMethod) + ctx, span := tracer.Start( + trace.ContextWithRemoteSpanContext(ctx, spanCtx), + name, + trace.WithSpanKind(trace.SpanKindServer), + trace.WithAttributes(attrs...), + ) + + return ctx, span +} diff --git a/providers/opentelemetry/span.go b/providers/opentelemetry/span.go new file mode 100644 index 000000000..d99ae613e --- /dev/null +++ b/providers/opentelemetry/span.go @@ -0,0 +1,69 @@ +package opentelemetry + +import ( + "context" + + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/codes" + "go.opentelemetry.io/otel/trace" + grpccodes "google.golang.org/grpc/codes" + + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tracing/kv" +) + +type span struct { + span trace.Span + ctx context.Context +} + +func newSpan(ctx context.Context, rawSpan trace.Span) *span { + return &span{ + ctx: ctx, + span: rawSpan, + } +} + +func (s *span) End() { + s.span.End() +} + +func (s *span) SetStatus(code grpccodes.Code, message string) { + if code != grpccodes.OK { + s.span.SetStatus(codes.Error, message) + } else { + s.span.SetStatus(codes.Ok, message) + } +} + +func (s *span) SetAttributes(attrs ...kv.KeyValue) { + s.span.SetAttributes(translateKeyValue(attrs)...) +} + +func (s *span) AddEvent(name string, attrs ...kv.KeyValue) { + kvList := translateKeyValue(attrs) + + s.span.AddEvent(name, trace.WithAttributes(kvList...)) +} + +func translateKeyValue(kvs []kv.KeyValue) []attribute.KeyValue { + kvList := make([]attribute.KeyValue, 0, len(kvs)) + for _, v := range kvs { + var otelKeyValue attribute.KeyValue + otelKey := attribute.Key(v.Key) + + switch v.Value.Type() { + case kv.BOOL: + otelKeyValue = otelKey.Bool(v.Value.AsBool()) + case kv.INT64: + otelKeyValue = otelKey.Int64(v.Value.AsInt64()) + case kv.FLOAT64: + otelKeyValue = otelKey.Float64(v.Value.AsFloat64()) + case kv.STRING: + otelKeyValue = otelKey.String(v.Value.AsString()) + default: + continue + } + kvList = append(kvList, otelKeyValue) + } + return kvList +} diff --git a/providers/opentelemetry/tracer.go b/providers/opentelemetry/tracer.go new file mode 100644 index 000000000..3e851d425 --- /dev/null +++ b/providers/opentelemetry/tracer.go @@ -0,0 +1,36 @@ +package opentelemetry + +import ( + "context" + + "go.opentelemetry.io/otel/propagation" + "go.opentelemetry.io/otel/trace" + + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tracing" +) + +type tracer struct { + tracer trace.Tracer + propagators propagation.TextMapPropagator +} + +// Compatibility check. +var _ tracing.Tracer = &tracer{} + +// InterceptorTracer converts OpenTelemetry tracer to Tracer adapter. +func InterceptorTracer(opts ...Option) *tracer { + o := newConfig(opts...) + + return &tracer{tracer: o.tracer, propagators: o.Propagators} +} + +func (t *tracer) Start(ctx context.Context, spanName string, kind tracing.SpanKind) (context.Context, tracing.Span) { + var span trace.Span + switch kind { + case tracing.SpanKindClient: + ctx, span = newClientSpanFromContext(ctx, spanName, t.tracer, t.propagators) + case tracing.SpanKindServer: + ctx, span = newServerSpanFromContext(ctx, spanName, t.tracer, t.propagators) + } + return ctx, newSpan(ctx, span) +}