Skip to content

Commit

Permalink
Support gRPC status for versions >=1.40
Browse files Browse the repository at this point in the history
  • Loading branch information
damemi committed Oct 31, 2024
1 parent 77e8de9 commit 424a09f
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ volatile const u64 error_status_pos;
volatile const u64 status_s_pos;
volatile const u64 status_code_pos;

volatile const bool write_status_supported;

// This instrumentation attaches uprobe to the following function:
// func (cc *ClientConn) Invoke(ctx context.Context, method string, args, reply interface{}, opts ...CallOption) error
SEC("uprobe/ClientConn_Invoke")
Expand Down Expand Up @@ -122,6 +124,9 @@ int uprobe_ClientConn_Invoke_Returns(struct pt_regs *ctx) {
return 0;
}

if(!write_status_supported) {
goto done;
}
// Getting the returned response (error)
// The status code is embedded 3 layers deep:
// Invoke() error
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,18 @@ import (
"strings"

"github.com/cilium/ebpf"
"github.com/hashicorp/go-version"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
"go.opentelemetry.io/otel/trace"
"golang.org/x/sys/unix"

"go.opentelemetry.io/auto/internal/pkg/inject"
"go.opentelemetry.io/auto/internal/pkg/instrumentation/context"
"go.opentelemetry.io/auto/internal/pkg/instrumentation/probe"
"go.opentelemetry.io/auto/internal/pkg/instrumentation/utils"
"go.opentelemetry.io/auto/internal/pkg/process"
"go.opentelemetry.io/auto/internal/pkg/structfield"
)

Expand All @@ -29,6 +32,17 @@ const (
pkg = "google.golang.org/grpc"
)

type writeStatusConst struct{}

func (w writeStatusConst) InjectOption(td *process.TargetDetails) (inject.Option, error) {
writeStatusVersion := version.Must(version.NewVersion("1.40.0"))
ver, ok := td.Libraries[pkg]
if !ok {
return nil, fmt.Errorf("unknown module version: %s", pkg)
}
return inject.WithKeyValue("write_status_supported", ver.GreaterThanOrEqual(writeStatusVersion)), nil
}

// New returns a new [probe.Probe].
func New(logger *slog.Logger) probe.Probe {
id := probe.ID{
Expand All @@ -41,6 +55,7 @@ func New(logger *slog.Logger) probe.Probe {
Consts: []probe.Const{
probe.RegistersABIConst{},
probe.AllocationConst{},
writeStatusConst{},
probe.StructFieldConst{
Key: "clientconn_target_ptr_pos",
Val: structfield.NewID("google.golang.org/grpc", "google.golang.org/grpc", "ClientConn", "target"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ volatile const bool is_new_frame_pos;
volatile const u64 status_s_pos;
volatile const u64 status_code_pos;

volatile const bool write_status_supported;

static __always_inline long dummy_extract_span_context_from_headers(void *stream_id, struct span_context *parent_span_context) {
return 0;
}
Expand Down Expand Up @@ -175,6 +177,10 @@ int uprobe_http2Server_operateHeader(struct pt_regs *ctx)
// https://github.com/grpc/grpc-go/blob/bcf9171a20e44ed81a6eb152e3ca9e35b2c02c5d/internal/transport/http2_server.go#L1049
SEC("uprobe/http2Server_WriteStatus")
int uprobe_http2Server_WriteStatus(struct pt_regs *ctx) {
if(!write_status_supported) {
bpf_printk("status probe not supported for this version of gRPC");
return 0;
}
struct go_iface go_context = {0};
get_Go_context(ctx, 2, stream_ctx_pos, true, &go_context);
void *key = get_consistent_key(ctx, go_context.data);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@ const (
pkg = "google.golang.org/grpc"
)

type writeStatusConst struct{}

func (w writeStatusConst) InjectOption(td *process.TargetDetails) (inject.Option, error) {
writeStatusVersion := version.Must(version.NewVersion("1.40.0"))
ver, ok := td.Libraries[pkg]
if !ok {
return nil, fmt.Errorf("unknown module version: %s", pkg)
}
return inject.WithKeyValue("write_status_supported", ver.GreaterThanOrEqual(writeStatusVersion)), nil
}

// New returns a new [probe.Probe].
func New(logger *slog.Logger) probe.Probe {
id := probe.ID{
Expand All @@ -43,6 +54,7 @@ func New(logger *slog.Logger) probe.Probe {
Consts: []probe.Const{
probe.RegistersABIConst{},
probe.AllocationConst{},
writeStatusConst{},
probe.StructFieldConst{
Key: "stream_method_ptr_pos",
Val: structfield.NewID("google.golang.org/grpc", "google.golang.org/grpc/internal/transport", "Stream", "method"),
Expand Down

0 comments on commit 424a09f

Please sign in to comment.