Documentation ¶
Overview ¶
Package atgokit provides examples and integration tests for tracing services implemented with Go kit.
We do not provide any Go kit specific code, as the other generic modules (athttp and atgrpc) are sufficient.
Go kit-based HTTP servers can be traced by instrumenting the kit/transport/http.Server with athttp.Wrap, and HTTP clients can be traced by providing a net/http.Client instrumented with athttp.WrapClient.
Go kit-based gRPC servers and clients can both be wrapped using the interceptors provided in module/atgrpc.
Example (GrpcClient) ¶
package main import ( "context" kitgrpc "github.com/go-kit/kit/transport/grpc" "google.golang.org/grpc" pb "google.golang.org/grpc/examples/helloworld/helloworld" atatus "go.atatus.com/agent" "go.atatus.com/agent/module/atgrpc" ) func main() { // When dialling the gRPC client connection, use the atgrpc.NewUnaryClientInterceptor // function (from module/atgrpc). This will trace all outgoing requests, as long as // the context supplied to methods include an atatus.Transaction. conn, err := grpc.Dial("localhost:1234", grpc.WithUnaryInterceptor(atgrpc.NewUnaryClientInterceptor())) if err != nil { panic(err) } defer conn.Close() // Create your go-kit/kit/transport/grpc.Client as usual, without any tracing middleware. client := kitgrpc.NewClient( conn, "helloworld.Greeter", "SayHello", func(ctx context.Context, req interface{}) (interface{}, error) { return &pb.HelloRequest{Name: req.(string)}, nil }, func(ctx context.Context, resp interface{}) (interface{}, error) { return resp, nil }, &pb.HelloReply{}, ) tx := atatus.DefaultTracer.StartTransaction("name", "type") ctx := atatus.ContextWithTransaction(context.Background(), tx) defer tx.End() _, err = client.Endpoint()(ctx, "world") if err != nil { panic(err) } }
Output:
Example (GrpcServer) ¶
package main import ( "context" "net" kitgrpc "github.com/go-kit/kit/transport/grpc" netcontext "golang.org/x/net/context" "google.golang.org/grpc" pb "google.golang.org/grpc/examples/helloworld/helloworld" atatus "go.atatus.com/agent" "go.atatus.com/agent/module/atgrpc" ) func main() { // Create your go-kit/kit/transport/grpc.Server as usual, without any tracing middleware. endpoint := func(ctx context.Context, req interface{}) (interface{}, error) { // The middleware added to the underlying gRPC server will be propagate // a transaction to the context passed to your endpoint. You can then // report endpoint-specific spans using atatus.StartSpan. span, ctx := atatus.StartSpan(ctx, "name", "endpoint") defer span.End() return nil, nil } var encodeRequest func(ctx context.Context, req interface{}) (interface{}, error) var decodeResponse func(ctx context.Context, req interface{}) (interface{}, error) service := &helloWorldService{kitgrpc.NewServer( endpoint, encodeRequest, decodeResponse, )} // When creating the underlying gRPC server, use the atgrpc.NewUnaryServerInterceptor // function (from module/atgrpc). This will trace all incoming requests. s := grpc.NewServer(grpc.UnaryInterceptor(atgrpc.NewUnaryServerInterceptor())) defer s.GracefulStop() lis, err := net.Listen("tcp", "localhost:0") if err != nil { panic(err) } go s.Serve(lis) pb.RegisterGreeterServer(s, service) } type helloWorldService struct { sayHello *kitgrpc.Server } func (s *helloWorldService) SayHello(ctx netcontext.Context, req *pb.HelloRequest) (*pb.HelloReply, error) { _, rep, err := s.sayHello.ServeGRPC(ctx, req) if err != nil { return nil, err } return rep.(*pb.HelloReply), nil }
Output:
Example (HttpClient) ¶
package main import ( "context" "net/http" "net/url" kithttp "github.com/go-kit/kit/transport/http" atatus "go.atatus.com/agent" "go.atatus.com/agent/module/athttp" ) func main() { // When constructing the kit/transport/http.Client, pass in an http.Client // instrumented using athttp.WrapClient (from module/athttp). This will // trace all outgoing requests, as long as the context supplied to methods // include an atatus.Transaction. client := kithttp.NewClient( "GET", &url.URL{ /*...*/ }, kithttp.EncodeJSONRequest, func(_ context.Context, r *http.Response) (interface{}, error) { return nil, nil }, kithttp.SetClient(athttp.WrapClient(http.DefaultClient)), ) tx := atatus.DefaultTracer.StartTransaction("name", "type") ctx := atatus.ContextWithTransaction(context.Background(), tx) defer tx.End() _, err := client.Endpoint()(ctx, struct{}{}) if err != nil { panic(err) } }
Output:
Example (HttpServer) ¶
package main import ( "context" "net/http" kithttp "github.com/go-kit/kit/transport/http" atatus "go.atatus.com/agent" "go.atatus.com/agent/module/athttp" ) func main() { // Create your go-kit/kit/transport/http.Server as usual, without any tracing middleware. endpoint := func(ctx context.Context, req interface{}) (interface{}, error) { // The middleware added to the underlying gRPC server will be propagate // a transaction to the context passed to your endpoint. You can then // report endpoint-specific spans using atatus.StartSpan. span, ctx := atatus.StartSpan(ctx, "name", "endpoint") defer span.End() return nil, nil } server := kithttp.NewServer( endpoint, kithttp.NopRequestDecoder, func(_ context.Context, w http.ResponseWriter, _ interface{}) error { return nil }, ) // Use athttp.Wrap (from module/athttp) to instrument the // kit/transport/http.Server. This will trace all incoming requests. http.ListenAndServe("localhost:1234", athttp.Wrap(server)) }
Output:
Click to show internal directories.
Click to hide internal directories.