apollographql / apollo-client

:rocket:  A fully-featured, production ready caching GraphQL client for every UI framework and GraphQL server.
https://apollographql.com/client
MIT License
19.34k stars 2.66k forks source link

Initializing ApolloClient before DataDog RUM causes GraphQL calls to not have the correct headers #11801

Closed vacas closed 5 months ago

vacas commented 5 months ago

Original Issue

I believe this issue should have been solved with #8603 and only occur in Apollo Client versions before v3.4.6.

As a result, I'm going to close this issue. If it is still occurring in newer versions, please give this a bump so I'll reopen, or open a new issue :)

Originally posted by @phryneas in https://github.com/apollographql/apollo-client/issues/7130#issuecomment-1867580404

Hello! 👋🏻

I recently came across this issue in my code where we were initializing the Apollo Client before initializing the DataDog RUM package. I was able to fix this by moving the DataDog initialization higher up in the tree (in the same file as where the render(...) function is used), but I thought I would call it out here. I'll add some pseudo-code samples since this is hard to reproduce without a public DataDog account.

Package versions:

Code Sample

ApolloClientProvider.jsx

const createApolloClient = () => {
  const api1Link = new HttpLink({
    uri: 'https://api1.com',
    fetch,
  });

  const api2Link = new HttpLink({
    uri: 'https://api2.com',
    fetch,
  });
  return {
    client: new ApolloClient({
      cache: new InMemoryCache({
        typePolicies: {
          ... // omitted
        },
      }),
      link: from([
        createAuthMiddleware(), // very basic authentication middleware
        createErrorHandlerMiddleware(), // very basic error handling
        specErrorsContextLink, // adding spec errors from GraphQL if present
        ApolloLink.split(api1Link, api2Link),
      ]),
    }),
  };
};

export const ApolloClientProvider = ({
  children,
}) => {
  const { client } = createApolloClient();

  return (
    <ApolloProvider client={client}>{children}</ApolloProvider>
  );
};

DataDogRumProvider.jsx

import { datadogRum } from '@datadog/browser-rum';

export const DataDogRumProvider = ({ children }) => {
  useEffect(() => {
    datadogRum.init({
      applicationId: 'appId123',
      clientToken: 'clientToken123',
      site: 'datadog',
      service: 'service1',
      env: 'production',
      version: '1.0',
      sessionSampleRate: 100,
      sessionReplaySampleRate: 100,
      telemetrySampleRate: 100,
      trackSessionAcrossSubdomains: true,
      trackUserInteractions: true,
      trackResources: true,
      trackLongTasks: true,
      allowedTracingUrls: [
        'https://api1.com',
        'https://api2.com'
      ],
      enableExperimentalFeatures: ['clickmap', 'feature_flags'],
    });
    datadogRum.startSessionReplayRecording();
  }, []);

  return (
    <Provider
      value={{ 
        ... // omitted
      }}
    >
      {children}
    </Provider>
  );
}

Application.jsx

export const Application = () => {
  return (
    <ApolloClientProvider>
      <DataDogRumProvider>
        <Router>
          <Switch>
            <Route path={'/login'} component={Login} />
            <Route path={'/app'} component={App} />
            <Route path={'/logout'} component={Logout} />
          </Switch>
        </Router>
      </DataDogRumProvider>
    </ApolloClientProvider>
  )
}

With this implementation, you should see that none of the x-datadog-* headers are present in the request header of any of the GraphQL requests, and I believe it is very tied to what was highlighted in https://github.com/apollographql/apollo-client/issues/7130.

Let me know if you need any additional details, yes?

Cheers!

phryneas commented 5 months ago

Yes, that's because you manually pass fetch into HttpLink which means "take exactly this fetch" implementation.

This should fix it:

const api1Link = new HttpLink({
    uri: 'https://api1.com/',
-    fetch,
  });
vacas commented 5 months ago

Hey! Thanks for your response, @phryneas 😄

Let me take a closer look into this to confirm if that fixes the problem, and I'll get back to you, yes?

vacas commented 5 months ago

@phryneas, just tested it, and you are absolutely right! That did the trick 🎉

It seems like we were implementing this most likely because we used to have SSR and used to use node-fetch at some point (this was implemented before our time). Since we moved to Vite recently, we don't need this implementation anymore, and this was just an oversight on our part.

Thanks for the quick response! Cheers 🍻

github-actions[bot] commented 5 months ago

Do you have any feedback for the maintainers? Please tell us by taking a one-minute survey. Your responses will help us understand Apollo Client usage and allow us to serve you better.

github-actions[bot] commented 4 months ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. For general questions, we recommend using StackOverflow or our discord server.