apm: go.elastic.co/apm/module/apmgokit Index | Examples | Files

package apmgokit

import "go.elastic.co/apm/module/apmgokit"

Package apmgokit 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 (apmhttp and apmgrpc) are sufficient.

Go kit-based HTTP servers can be traced by instrumenting the kit/transport/http.Server with apmhttp.Wrap, and HTTP clients can be traced by providing a net/http.Client instrumented with apmhttp.WrapClient.

Go kit-based gRPC servers and clients can both be wrapped using the interceptors provided in module/apmgrpc.

Code:

// When dialling the gRPC client connection, use the apmgrpc.NewUnaryClientInterceptor
// function (from module/apmgrpc). This will trace all outgoing requests, as long as
// the context supplied to methods include an apm.Transaction.
conn, err := grpc.Dial("localhost:1234", grpc.WithUnaryInterceptor(apmgrpc.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 := apm.DefaultTracer.StartTransaction("name", "type")
ctx := apm.ContextWithTransaction(context.Background(), tx)
defer tx.End()

_, err = client.Endpoint()(ctx, "world")
if err != nil {
    panic(err)
}

Code:

// 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 apm.StartSpan.
    span, ctx := apm.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 apmgrpc.NewUnaryServerInterceptor
// function (from module/apmgrpc). This will trace all incoming requests.
s := grpc.NewServer(grpc.UnaryInterceptor(apmgrpc.NewUnaryServerInterceptor()))
defer s.GracefulStop()
lis, err := net.Listen("tcp", "localhost:0")
if err != nil {
    panic(err)
}
go s.Serve(lis)
pb.RegisterGreeterServer(s, service)

Code:

// When constructing the kit/transport/http.Client, pass in an http.Client
// instrumented using apmhttp.WrapClient (from module/apmhttp). This will
// trace all outgoing requests, as long as the context supplied to methods
// include an apm.Transaction.
client := kithttp.NewClient(
    "GET", &url.URL{ /*...*/ },
    kithttp.EncodeJSONRequest,
    func(_ context.Context, r *http.Response) (interface{}, error) { return nil, nil },
    kithttp.SetClient(apmhttp.WrapClient(http.DefaultClient)),
)

tx := apm.DefaultTracer.StartTransaction("name", "type")
ctx := apm.ContextWithTransaction(context.Background(), tx)
defer tx.End()

_, err := client.Endpoint()(ctx, struct{}{})
if err != nil {
    panic(err)
}

Code:

// 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 apm.StartSpan.
    span, ctx := apm.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 apmhttp.Wrap (from module/apmhttp) to instrument the
// kit/transport/http.Server. This will trace all incoming requests.
http.ListenAndServe("localhost:1234", apmhttp.Wrap(server))

Index

Examples

Package Files

doc.go

Updated 2019-09-05. Refresh now. Tools for package owners.