aws / aws-xray-sdk-dotnet

The official AWS X-Ray SDK for .NET.
Apache License 2.0
110 stars 64 forks source link

Support for GRPC services #195

Open Kralizek opened 3 years ago

Kralizek commented 3 years ago

I'm creating a system that is composed by multiple grpc services and I wanted to use x-ray to observe them.

Currently, as far as i noticed, there is no support for GRPC services (besides the one available for asp.net core applications). At the same time, on the client side, when setting up the http client, you can attach the x-ray handler.

This causes the odd behavior that a faulty request to a service is marked successful in the service but faulty in the caller. I suspect this is due to GRPC services always returning 200 but the client detects the fault when deserializing the response.

willarmiros commented 3 years ago

@Kralizek thank you for the feature request. You are correct that we currently do not support instrumenting gRPC clients, and it is not currently on our roadmap to do so. We are always open to pull requests if you'd be willing to contribute. AWS is also working on the AWS Distro for OpenTelemetry, which is a unified set of SDKs to collect all your traces and metrics. The .NET OpenTelemetry SDK supports gRPC instrumentation along with many other libraries. You can get started here if interested: https://aws-otel.github.io/docs/getting-started/dotnet-sdk/trace-manual-instr

Sbolder commented 2 years ago

@Kralizek

I have found the workaround to solve the problem, if you have distributed microservices, you can implement a middleware for each like this:

` public async Task InvokeAsync( HttpContext context, IContextAccessor contextAccessor) {

        var request = context.Request;
        var requestContext = contextAccessor.RequestContext;
        var xRayRecorderEntity = AWSXRayRecorder.Instance.GetEntity();
        if(contextAccessor.RequestContext.OperationId == null)
        {
            contextAccessor.RequestContext.OperationId = xRayRecorderEntity.TraceId;

        }
        if (requestContext != null)
        {
            xRayRecorderEntity.TraceId = contextAccessor.RequestContext.OperationId;
            if(requestContext.CurrentId != null){
                xRayRecorderEntity.ParentId = requestContext.CurrentId;
            }

            var parentId = requestContext.CurrentId;
            requestContext.ParentId = parentId;

            if (requestContext != null)
            {
                requestContext.CurrentId = xRayRecorderEntity.Id;
            }
        }

await Next(context);

    }`

So every microservices dosn't found the header in http request, and recreate a istance of _recorder, but you can manipulate it, and set manually the traceId and parentId, then the result is the same:

image

Off course you can manipulate directly the http header and solve it, but this is a transparent solution.