Skip to content

Commit

Permalink
feat: add logging support to generated clients
Browse files Browse the repository at this point in the history
  • Loading branch information
codyoss committed Nov 1, 2024
1 parent 7e64160 commit cacc368
Show file tree
Hide file tree
Showing 39 changed files with 512 additions and 179 deletions.
22 changes: 14 additions & 8 deletions internal/gengapic/client_init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,7 @@ func TestClientInit(t *testing.T) {
{Name: "iampb", Path: "cloud.google.com/go/iam/apiv1/iampb"}: true,
{Name: "locationpb", Path: "google.golang.org/genproto/googleapis/cloud/location"}: true,
{Name: "mypackagepb", Path: "github.com/googleapis/mypackage"}: true,
{Path: "log/slog"}: true,
},
wantNumSnps: 6,
},
Expand All @@ -436,6 +437,7 @@ func TestClientInit(t *testing.T) {
{Name: "iampb", Path: "cloud.google.com/go/iam/apiv1/iampb"}: true,
{Name: "locationpb", Path: "google.golang.org/genproto/googleapis/cloud/location"}: true,
{Name: "mypackagepb", Path: "github.com/googleapis/mypackage"}: true,
{Path: "log/slog"}: true,
},
wantNumSnps: 6,
},
Expand All @@ -453,6 +455,7 @@ func TestClientInit(t *testing.T) {
{Name: "gtransport", Path: "google.golang.org/api/transport/grpc"}: true,
{Name: "mypackagepb", Path: "github.com/googleapis/mypackage"}: true,
{Name: "httptransport", Path: "google.golang.org/api/transport/http"}: true,
{Path: "log/slog"}: true,
},
wantNumSnps: 1,
},
Expand All @@ -469,9 +472,10 @@ func TestClientInit(t *testing.T) {
{Name: "longrunningpb", Path: "cloud.google.com/go/longrunning/autogen/longrunningpb"}: true,
{Name: "lroauto", Path: "cloud.google.com/go/longrunning/autogen"}: true,
{Name: "mypackagepb", Path: "github.com/googleapis/mypackage"}: true,
{Path: "context"}: true,
{Path: "google.golang.org/api/option"}: true,
{Path: "google.golang.org/grpc"}: true,
{Path: "context"}: true,
{Path: "google.golang.org/api/option"}: true,
{Path: "google.golang.org/grpc"}: true,
{Path: "log/slog"}: true,
},
wantNumSnps: 6,
},
Expand All @@ -484,11 +488,12 @@ func TestClientInit(t *testing.T) {
{Name: "gtransport", Path: "google.golang.org/api/transport/grpc"}: true,
{Name: "httptransport", Path: "google.golang.org/api/transport/http"}: true,
{Name: "mypackagepb", Path: "github.com/googleapis/mypackage"}: true,
{Path: "context"}: true,
{Path: "google.golang.org/api/option"}: true,
{Path: "google.golang.org/api/option/internaloption"}: true,
{Path: "google.golang.org/grpc"}: true,
{Path: "net/http"}: true,
{Path: "context"}: true,
{Path: "google.golang.org/api/option"}: true,
{Path: "google.golang.org/api/option/internaloption"}: true,
{Path: "google.golang.org/grpc"}: true,
{Path: "net/http"}: true,
{Path: "log/slog"}: true,
},
wantNumSnps: 1,
},
Expand All @@ -506,6 +511,7 @@ func TestClientInit(t *testing.T) {
{Path: "net/http"}: true,
{Name: "httptransport", Path: "google.golang.org/api/transport/http"}: true,
{Name: "mypackagepb", Path: "github.com/googleapis/mypackage"}: true,
{Path: "log/slog"}: true,
},
wantNumSnps: 1,
setExt: func() (protoreflect.ExtensionType, interface{}) {
Expand Down
55 changes: 55 additions & 0 deletions internal/gengapic/doc_file.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,19 @@ func (g *generator) genDocFile(year int, scopes []string, serv *descriptorpb.Ser

p("import (")
p("%s%q", "\t", "context")
p("%s%q", "\t", "io")
p("%s%q", "\t", "log/slog")
p("%s%q", "\t", "net/http")
p("")
p("%s%q", "\t", "github.com/googleapis/gax-go/v2/internallog")
p("%s%q", "\t", "github.com/googleapis/gax-go/v2/internallog/grpclog")
p("%s%q", "\t", "google.golang.org/api/googleapi")
p("%s%q", "\t", "google.golang.org/api/option")
p("%s%q", "\t", "google.golang.org/grpc")
p("%s%q", "\t", "google.golang.org/protobuf/proto")
p(")")
p("")
p("const serviceName = %q", g.serviceConfig.GetName())

p("// For more information on implementing a client constructor hook, see")
p("// https://github.com/googleapis/google-cloud-go/wiki/Customizing-constructors.")
Expand All @@ -157,6 +166,52 @@ func (g *generator) genDocFile(year int, scopes []string, serv *descriptorpb.Ser
}
p(" }")
p("}")
p("")

p("func executeHTTPRequest(ctx context.Context, client *http.Client, req *http.Request, logger *slog.Logger, body []byte, rpc string) ([]byte, error) {")
p(` logger.DebugContext(ctx, "api request", "serviceName", serviceName, "rpcName", rpc, "request", internallog.HTTPRequest(req, body))`)
p(" resp, err := client.Do(req)")
p(" if err != nil{")
p(" return nil, err")
p(" }")
p(" defer resp.Body.Close()")
p(" buf, err := io.ReadAll(resp.Body)")
p(" if err != nil {")
p(" return nil, err")
p(" }")
p(` logger.DebugContext(ctx, "api response", "serviceName", serviceName, "rpcName", rpc, "response", internallog.HTTPResponse(resp, buf))`)
p(" if err = googleapi.CheckResponse(resp); err != nil {")
p(" return nil, err")
p(" }")
p(" return buf, nil")
p("}")
p("")

p("func executeStreamingHTTPRequest(ctx context.Context, client *http.Client, req *http.Request, logger *slog.Logger, body []byte, rpc string) (*http.Response, error) {")
p(` logger.DebugContext(ctx, "api request", "serviceName", serviceName, "rpcName", rpc, "request", internallog.HTTPRequest(req, body))`)
p(" resp, err := client.Do(req)")
p(" if err != nil{")
p(" return nil, err")
p(" }")
p(` logger.DebugContext(ctx, "api response", "serviceName", serviceName, "rpcName", rpc, "response", internallog.HTTPResponse(resp, nil))`)
p(" if err = googleapi.CheckResponse(resp); err != nil {")
p(" return nil, err")
p(" }")
p(" return resp, nil")
p("}")
p("")

p("func executeRPC[I proto.Message, O proto.Message](ctx context.Context, fn func(context.Context, I, ...grpc.CallOption) (O, error), req I, opts []grpc.CallOption, logger *slog.Logger, rpc string) (O, error) {")
p(" var zero O")
p(` logger.DebugContext(ctx, "api request", "serviceName", serviceName, "rpcName", rpc, "request", grpclog.ProtoMessageRequest(ctx, req))`)
p(" resp, err := fn(ctx, req, opts...)")
p(" if err != nil {")
p(" return zero, err")
p(" }")
p(` logger.DebugContext(ctx, "api response", "serviceName", serviceName, "rpcName", rpc, "response", grpclog.ProtoMessageResponse(resp))`)
p(" return resp, err")
p("}")
p("")
}

func collectScopes(servs []*descriptorpb.ServiceDescriptorProto) []string {
Expand Down
4 changes: 2 additions & 2 deletions internal/gengapic/gengapic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1127,12 +1127,12 @@ func TestGRPCStubCall(t *testing.T) {
}{
{
name: "foo.FooService.GetFoo",
want: "c.client.GetFoo(ctx, req, settings.GRPC...)",
want: `executeRPC(ctx, c.client.GetFoo, req, settings.GRPC, c.logger, "GetFoo")`,
in: getFoo,
},
{
name: "foo.BarService.GetBar",
want: "c.barClient.GetBar(ctx, req, settings.GRPC...)",
want: `executeRPC(ctx, c.barClient.GetBar, req, settings.GRPC, c.logger, "GetBar")`,
in: getBar,
},
} {
Expand Down
6 changes: 5 additions & 1 deletion internal/gengapic/gengrpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ func (g *generator) emptyUnaryGRPCCall(servName string, m *descriptorpb.MethodDe
func (g *generator) grpcStubCall(method *descriptorpb.MethodDescriptorProto) string {
service := g.descInfo.ParentElement[method]
stub := pbinfo.ReduceServName(service.GetName(), g.opts.pkgName)
return fmt.Sprintf("c.%s.%s(ctx, req, settings.GRPC...)", grpcClientField(stub), method.GetName())
return fmt.Sprintf("executeRPC(ctx, c.%s.%s, req, settings.GRPC, c.logger, %q)", grpcClientField(stub), method.GetName(), method.GetName())
}

func (g *generator) grpcClientOptions(serv *descriptorpb.ServiceDescriptorProto, servName string) error {
Expand Down Expand Up @@ -295,6 +295,8 @@ func (g *generator) grpcClientInit(serv *descriptorpb.ServiceDescriptorProto, se

p("// The x-goog-* metadata to be sent with each request.")
p("xGoogHeaders []string")
p("")
p("logger *slog.Logger")

p("}")
p("")
Expand All @@ -303,6 +305,7 @@ func (g *generator) grpcClientInit(serv *descriptorpb.ServiceDescriptorProto, se
g.imports[imp] = true

g.grpcClientUtilities(serv, servName, imp, hasRPCForLRO)
g.imports[pbinfo.ImportSpec{Path: "log/slog"}] = true
}

func (g *generator) grpcClientUtilities(serv *descriptorpb.ServiceDescriptorProto, servName string, imp pbinfo.ImportSpec, hasRPCForLRO bool) {
Expand Down Expand Up @@ -337,6 +340,7 @@ func (g *generator) grpcClientUtilities(serv *descriptorpb.ServiceDescriptorProt
p(" connPool: connPool,")
p(" %s: %s.New%sClient(connPool),", grpcClientField(servName), imp.Name, serv.GetName())
p(" CallOptions: &client.CallOptions,")
p(" logger: internaloption.GetLogger(opts),")
g.mixinStubsInit()
p("")
p(" }")
Expand Down
Loading

0 comments on commit cacc368

Please sign in to comment.