atgokit

package module
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 1, 2022 License: Apache-2.0 Imports: 0 Imported by: 0

README

atgokit

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 (module/athttp and module/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.

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:

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL