Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable Tracing in Apollo Studio #4

Open
sbilello opened this issue May 4, 2021 · 8 comments
Open

Enable Tracing in Apollo Studio #4

sbilello opened this issue May 4, 2021 · 8 comments

Comments

@sbilello
Copy link

sbilello commented May 4, 2021

Screen Shot 2021-05-03 at 7 43 11 PM
I was playing with this demo and I noticed that the traces are not available.
Is there some parameter or does need to be implemented the exposure of the fields for the tracing?
Please check the apollo-tracing specification and the relative PR
GraphQL-Java-PR

@paulbakker
Copy link
Contributor

graphql-java comes with an instrumentation class graphql.execution.instrumentation.tracing.TracingInstrumentation for this already as described here.

If you register this class using a @Bean in your own code, the DGS framework will pick it up automatically.

@paulbakker
Copy link
Contributor

I only now realize this issue is on the example app, and not on the framework itself. So yes, we should do exactly what I said in the previous reply for the example :-)

@berngp
Copy link
Contributor

berngp commented May 11, 2021

@sbilello
Copy link
Author

sbilello commented May 11, 2021

Thanks @berngp and @paulbakker !
I added some breakpoint to verify that the extensions are added but maybe there is something missing on the apollo-studio side of things because I don't see the tracing breakdown
Screen Shot 2021-05-11 at 2 12 53 PM

query TracingTest {
  shows {
    id
    reviews {
      __typename
      starRating
    }
  }
}

I was reading more about it in this https://www.apollographql.com/docs/federation/metrics/#gatsby-focus-wrapper and it looks like that it is not enough for apollo studio to make it work.

Accordingly to their documentation they require an ftv1 field

{
  "data": {
    "shows": [
      {
        "title": "Stranger Things"
      },
      {
        "title": "Ozark"
      },
      {
        "title": "The Crown"
      },
      {
        "title": "Dead to Me"
      },
      {
        "title": "Orange is the New Black"
      }
    ]
  },
  "extensions": {
    "tracing": {
      "version": 1,
      "startTime": "2021-05-11T21:40:35.438314Z",
      "endTime": "2021-05-11T21:40:35.443742Z",
      "duration": 5439178,
      "parsing": {
        "startOffset": 3342104,
        "duration": 3316764
      },
      "validation": {
        "startOffset": 3542869,
        "duration": 166042
      },
      "execution": {
        "resolvers": [
          {
            "path": [
              "shows"
            ],
            "parentType": "Query",
            "returnType": "[Show]",
            "fieldName": "shows",
            "startOffset": 3665287,
            "duration": 961267
          },
          {
            "path": [
              "shows",
              0,
              "title"
            ],
            "parentType": "Show",
            "returnType": "String",
            "fieldName": "title",
            "startOffset": 4706215,
            "duration": 252633
          },
          {
            "path": [
              "shows",
              1,
              "title"
            ],
            "parentType": "Show",
            "returnType": "String",
            "fieldName": "title",
            "startOffset": 5052506,
            "duration": 11554
          },
          {
            "path": [
              "shows",
              2,
              "title"
            ],
            "parentType": "Show",
            "returnType": "String",
            "fieldName": "title",
            "startOffset": 5128882,
            "duration": 12249
          },
          {
            "path": [
              "shows",
              3,
              "title"
            ],
            "parentType": "Show",
            "returnType": "String",
            "fieldName": "title",
            "startOffset": 5164359,
            "duration": 7933
          },
          {
            "path": [
              "shows",
              4,
              "title"
            ],
            "parentType": "Show",
            "returnType": "String",
            "fieldName": "title",
            "startOffset": 5195543,
            "duration": 7960
          }
        ]
      }
    }
  }
}

@berngp
Copy link
Contributor

berngp commented May 11, 2021

I think we need to explicitly enable the feature in the Apollo Server. ref. #8

@sbilello
Copy link
Author

I tested this one but it is not enough to make it work. I need to find some time to try this project: https://github.com/braintree/apollo-tracing-uploader-java Thanks @berngp

@sbilello
Copy link
Author

sbilello commented Jun 9, 2021

Finally I found the time to integrate the apollo-tracing-uploader-java

[Disclaimer: Not polished code] I had to add just one simple class like this one:

package us.test.graphql.server.instrumentation;

import com.braintreepayments.apollo_tracing_uploader.TracingUploadInstrumentation;
import com.braintreepayments.apollo_tracing_uploader.VariablesSanitizer;
import com.braintreepayments.apollo_tracing_uploader.impl.HttpTracingUploader;
import com.braintreepayments.apollo_tracing_uploader.impl.ScheduledBatchingTraceProducer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.time.Duration;
import java.util.concurrent.Executors;

@Configuration
public class ApolloTracingUploadInstrumentation {

    @Value("${apollo.secret}")
    private String apolloSecret;

    @Bean
    public TracingUploadInstrumentation tracingUploadInstrumentation(ScheduledBatchingTraceProducer producer) {
        return TracingUploadInstrumentation.newBuilder()
                .sendTracesIf(() -> true)
                .customizeTrace((trace, context) -> trace.setClientName("testClient " + context.toString()))
                .sanitizeVariables(VariablesSanitizer.valuesTo("X"))
                .producer(producer)
                .build();
    }

    @Bean
    public ScheduledBatchingTraceProducer scheduledBatchingTraceProducer(HttpTracingUploader httpTracingUploader) {
        return ScheduledBatchingTraceProducer.newBuilder().batchingWindow(Duration.ofSeconds(1))
                .threadPoolSize(1)
                .customizeHeader(header -> header.setService("test-graphql-server"))
                .uploader(httpTracingUploader)
                .build();
    }

    @Bean
    public HttpTracingUploader httpTracingUploader() {
        return HttpTracingUploader.newBuilder()
                .executor(Executors.newSingleThreadScheduledExecutor())
                .apiKey(apolloSecret)
                .retries(3)
                .retryDelay(Duration.ofSeconds(5))
                .connectTimeout(Duration.ofSeconds(5))
                .readTimeout(Duration.ofSeconds(5))
                .build();
    }

}

There is no documentation on how to integrate it.
I had to read the source code so I hope this snippet can save somebody some time!

CC: @berngp @srinivasankavitha @paulbakker

Screen Shot 2021-06-08 at 7 05 53 PM

Last but not least: I also enabled the tracing: true flag in the apollo-server for the gateway. https://github.com/apollographql/apollo-server/blob/main/packages/apollo-server-core/src/graphqlOptions.ts#L58

Do you think that would it be worth creating a dedicated module to integrate tracing with apollo or document this approach?

@jonckvanderkogel
Copy link

jonckvanderkogel commented Jul 8, 2021

It's a bit easier than that. What you need to do is first import this dependency (I'm using version 0.6.4):

<dependency>
    <groupId>com.apollographql.federation</groupId>
    <artifactId>federation-graphql-java-support</artifactId>
    <version>${graphql.federation.version}</version>
</dependency>

Next, expose a bean of type: com.apollographql.federation.graphqljava.tracing.FederatedTracingInstrumentation

For example as follows:

import com.apollographql.federation.graphqljava.tracing.FederatedTracingInstrumentation;
import graphql.execution.instrumentation.SimpleInstrumentation;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class InstrumentationConfig {
    @Bean
    public SimpleInstrumentation tracingInstrumentation() {
        return new FederatedTracingInstrumentation();
    }
}

Now the DGS framework will pick up this bean and voila, tracing has been enabled in Apollo Studio.

Check out a more complete working example here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants