Skip to content

Commit 7ec082c

Browse files
Add gRPC Logging (#5139) (#10721)
Co-authored-by: upodroid <[email protected]> Signed-off-by: Modular Magician <[email protected]> Co-authored-by: upodroid <[email protected]>
1 parent 38b3fe0 commit 7ec082c

File tree

6 files changed

+140
-25
lines changed

6 files changed

+140
-25
lines changed

.changelog/5139.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
provider: gRPC requests and response logging have been enabled
3+
```

go.mod

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ require (
99
github.com/gammazero/deque v0.0.0-20180920172122-f6adf94963e4 // indirect
1010
github.com/gammazero/workerpool v0.0.0-20181230203049-86a96b5d5d92
1111
github.com/golangci/golangci-lint v1.40.1
12+
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
1213
github.com/hashicorp/errwrap v1.0.0
1314
github.com/hashicorp/go-cleanhttp v0.5.2
1415
github.com/hashicorp/go-multierror v1.1.1
@@ -18,6 +19,7 @@ require (
1819
github.com/hashicorp/terraform-plugin-sdk/v2 v2.5.0
1920
github.com/mitchellh/go-homedir v1.1.0
2021
github.com/mitchellh/hashstructure v1.1.0
22+
github.com/sirupsen/logrus v1.8.1 // indirect
2123
github.com/spf13/afero v1.2.2 // indirect
2224
github.com/zclconf/go-cty v1.5.1 // indirect
2325
golang.org/x/mod v0.5.0 // indirect

go.sum

+5
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,7 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
286286
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
287287
github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
288288
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
289+
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
289290
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
290291
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
291292
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -425,6 +426,8 @@ github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:Fecb
425426
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
426427
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
427428
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI=
429+
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw=
430+
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
428431
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
429432
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
430433
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
@@ -547,6 +550,7 @@ github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT
547550
github.com/keybase/go-crypto v0.0.0-20161004153544-93f5b35093ba/go.mod h1:ghbZscTyKdM07+Fw3KSi0hcJm+AlEUWj8QLlPtijN/M=
548551
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
549552
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
553+
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
550554
github.com/kisielk/errcheck v1.6.0 h1:YTDO4pNy7AUN/021p+JGHycQyYNIyMoenM1YDVK6RlY=
551555
github.com/kisielk/errcheck v1.6.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
552556
github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
@@ -1223,6 +1227,7 @@ golang.org/x/tools v0.0.0-20201230224404-63754364767c/go.mod h1:emZCQorbCU4vsT4f
12231227
golang.org/x/tools v0.0.0-20210101214203-2dba1e4ea05c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
12241228
golang.org/x/tools v0.0.0-20210104081019-d8d6ddbec6ee/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
12251229
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
1230+
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
12261231
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
12271232
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
12281233
golang.org/x/tools v0.1.2-0.20210512205948-8287d5da45e4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=

google/bigtable_client_factory.go

+5
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
)
1111

1212
type BigtableClientFactory struct {
13+
gRPCLoggingOptions []option.ClientOption
1314
UserAgent string
1415
TokenSource oauth2.TokenSource
1516
BillingProject string
@@ -27,6 +28,8 @@ func (s BigtableClientFactory) NewInstanceAdminClient(project string) (*bigtable
2728
}
2829

2930
opts = append(opts, option.WithTokenSource(s.TokenSource), option.WithUserAgent(s.UserAgent))
31+
opts = append(opts, s.gRPCLoggingOptions...)
32+
3033
return bigtable.NewInstanceAdminClient(context.Background(), project, opts...)
3134
}
3235

@@ -41,5 +44,7 @@ func (s BigtableClientFactory) NewAdminClient(project, instance string) (*bigtab
4144
}
4245

4346
opts = append(opts, option.WithTokenSource(s.TokenSource), option.WithUserAgent(s.UserAgent))
47+
opts = append(opts, s.gRPCLoggingOptions...)
48+
4449
return bigtable.NewAdminClient(context.Background(), project, instance, opts...)
4550
}

google/config.go

+103-3
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
package google
22

33
import (
4+
"bytes"
45
"context"
6+
"encoding/json"
57
"fmt"
68
"log"
79
"net/http"
810
"regexp"
11+
"strconv"
912
"strings"
1013
"time"
1114

15+
grpc_logrus "github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus"
1216
"github.com/hashicorp/go-cleanhttp"
1317
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/logging"
18+
"github.com/sirupsen/logrus"
1419
"google.golang.org/api/option"
1520

1621
"golang.org/x/oauth2"
@@ -46,12 +51,86 @@ import (
4651
"google.golang.org/api/storage/v1"
4752
"google.golang.org/api/storagetransfer/v1"
4853
"google.golang.org/api/transport"
54+
"google.golang.org/grpc"
4955
)
5056

5157
type providerMeta struct {
5258
ModuleName string `cty:"module_name"`
5359
}
5460

61+
type Formatter struct {
62+
TimestampFormat string
63+
LogFormat string
64+
}
65+
66+
// Borrowed logic from https://github.com/sirupsen/logrus/blob/master/json_formatter.go and https://github.com/t-tomalak/logrus-easy-formatter/blob/master/formatter.go
67+
func (f *Formatter) Format(entry *logrus.Entry) ([]byte, error) {
68+
if !logging.IsDebugOrHigher() {
69+
return nil, nil // Suppress logs if TF_LOG is not DEBUG or TRACE
70+
}
71+
output := f.LogFormat
72+
entry.Level = logrus.DebugLevel // Force Entries to be Debug
73+
74+
timestampFormat := f.TimestampFormat
75+
76+
output = strings.Replace(output, "%time%", entry.Time.Format(timestampFormat), 1)
77+
78+
output = strings.Replace(output, "%msg%", entry.Message, 1)
79+
80+
level := strings.ToUpper(entry.Level.String())
81+
output = strings.Replace(output, "%lvl%", level, 1)
82+
83+
var gRPCMessageFlag bool
84+
for k, val := range entry.Data {
85+
switch v := val.(type) {
86+
case string:
87+
output = strings.Replace(output, "%"+k+"%", v, 1)
88+
case int:
89+
s := strconv.Itoa(v)
90+
output = strings.Replace(output, "%"+k+"%", s, 1)
91+
case bool:
92+
s := strconv.FormatBool(v)
93+
output = strings.Replace(output, "%"+k+"%", s, 1)
94+
}
95+
96+
if k != "system" {
97+
gRPCMessageFlag = true
98+
}
99+
}
100+
101+
if gRPCMessageFlag {
102+
data := make(logrus.Fields, len(entry.Data)+4)
103+
for k, v := range entry.Data {
104+
switch v := v.(type) {
105+
case error:
106+
// Otherwise errors are ignored by `encoding/json`
107+
// https://github.com/sirupsen/logrus/issues/137
108+
data[k] = v.Error()
109+
default:
110+
data[k] = v
111+
}
112+
}
113+
114+
var b *bytes.Buffer
115+
if entry.Buffer != nil {
116+
b = entry.Buffer
117+
} else {
118+
b = &bytes.Buffer{}
119+
}
120+
121+
encoder := json.NewEncoder(b)
122+
encoder.SetIndent("", " ")
123+
if err := encoder.Encode(data); err != nil {
124+
return nil, fmt.Errorf("failed to marshal fields to JSON, %w", err)
125+
}
126+
127+
finalOutput := append([]byte(output), b.Bytes()...)
128+
return finalOutput, nil
129+
}
130+
131+
return []byte(output), nil
132+
}
133+
55134
// Config is the configuration structure used to instantiate the Google
56135
// provider.
57136
type Config struct {
@@ -72,9 +151,10 @@ type Config struct {
72151
// It controls the interval at which we poll for successful operations
73152
PollInterval time.Duration
74153

75-
client *http.Client
76-
context context.Context
77-
userAgent string
154+
client *http.Client
155+
context context.Context
156+
userAgent string
157+
gRPCLoggingOptions []option.ClientOption
78158

79159
tokenSource oauth2.TokenSource
80160

@@ -396,6 +476,25 @@ func (c *Config) LoadAndValidate(ctx context.Context) error {
396476
c.requestBatcherIam = NewRequestBatcher("IAM", ctx, c.BatchingConfig)
397477
c.PollInterval = 10 * time.Second
398478

479+
// gRPC Logging setup
480+
logger := logrus.StandardLogger()
481+
482+
logrus.SetLevel(logrus.DebugLevel)
483+
logrus.SetFormatter(&Formatter{
484+
TimestampFormat: "2006/01/02 15:04:05",
485+
LogFormat: "%time% [%lvl%] %msg% \n",
486+
})
487+
488+
alwaysLoggingDeciderClient := func(ctx context.Context, fullMethodName string) bool { return true }
489+
grpc_logrus.ReplaceGrpcLogger(logrus.NewEntry(logger))
490+
491+
c.gRPCLoggingOptions = append(
492+
c.gRPCLoggingOptions, option.WithGRPCDialOption(grpc.WithUnaryInterceptor(
493+
grpc_logrus.PayloadUnaryClientInterceptor(logrus.NewEntry(logger), alwaysLoggingDeciderClient))),
494+
option.WithGRPCDialOption(grpc.WithStreamInterceptor(
495+
grpc_logrus.PayloadStreamClientInterceptor(logrus.NewEntry(logger), alwaysLoggingDeciderClient))),
496+
)
497+
399498
return nil
400499
}
401500

@@ -939,6 +1038,7 @@ func (c *Config) BigTableClientFactory(userAgent string) *BigtableClientFactory
9391038
bigtableClientFactory := &BigtableClientFactory{
9401039
UserAgent: userAgent,
9411040
TokenSource: c.tokenSource,
1041+
gRPCLoggingOptions: c.gRPCLoggingOptions,
9421042
BillingProject: c.BillingProject,
9431043
UserProjectOverride: c.UserProjectOverride,
9441044
}

website/docs/r/os_config_os_policy_assignment.html.markdown

+22-22
Original file line numberDiff line numberDiff line change
@@ -703,28 +703,6 @@ The `disruption_budget` block supports:
703703
(Optional)
704704
Specifies the relative value defined as a percentage, which will be multiplied by a reference value.
705705

706-
The `validate` block supports:
707-
708-
* `interpreter` -
709-
(Required)
710-
Required. The script interpreter to use. Possible values: INTERPRETER_UNSPECIFIED, NONE, SHELL, POWERSHELL
711-
712-
* `args` -
713-
(Optional)
714-
Optional arguments to pass to the source during execution.
715-
716-
* `file` -
717-
(Optional)
718-
Required. A deb package.
719-
720-
* `output_file_path` -
721-
(Optional)
722-
Only recorded for enforce Exec. Path to an output file (that is created by this Exec) whose content will be recorded in OSPolicyResourceCompliance after a successful run. Absence or failure to read this file will result in this ExecResource being non-compliant. Output file size is limited to 100K bytes.
723-
724-
* `script` -
725-
(Optional)
726-
An inline script. The size of the script is limited to 1024 characters.
727-
728706
- - -
729707

730708
* `description` -
@@ -1016,6 +994,28 @@ The `remote` block supports:
1016994
(Optional)
1017995
SHA256 checksum of the remote file.
1018996

997+
The `enforce` block supports:
998+
999+
* `interpreter` -
1000+
(Required)
1001+
Required. The script interpreter to use. Possible values: INTERPRETER_UNSPECIFIED, NONE, SHELL, POWERSHELL
1002+
1003+
* `args` -
1004+
(Optional)
1005+
Optional arguments to pass to the source during execution.
1006+
1007+
* `file` -
1008+
(Optional)
1009+
Required. A deb package.
1010+
1011+
* `output_file_path` -
1012+
(Optional)
1013+
Only recorded for enforce Exec. Path to an output file (that is created by this Exec) whose content will be recorded in OSPolicyResourceCompliance after a successful run. Absence or failure to read this file will result in this ExecResource being non-compliant. Output file size is limited to 100K bytes.
1014+
1015+
* `script` -
1016+
(Optional)
1017+
An inline script. The size of the script is limited to 1024 characters.
1018+
10191019
## Attributes Reference
10201020

10211021
In addition to the arguments listed above, the following computed attributes are exported:

0 commit comments

Comments
 (0)