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

feat(remix): Migrate to opentelemetry-instrumentation-remix. #12110

Open
wants to merge 14 commits into
base: develop
Choose a base branch
from

Conversation

onurtemizkan
Copy link
Collaborator

@onurtemizkan onurtemizkan commented May 17, 2024

Ref: #11040

Migrates Remix server-side SDK to opentelemetry-instrumentation-remix.

This PR removes:

  • Performance tracing on action / loader / documentRequest functions. Leaving them to be traced by opentelemetry-instrumentation-remix
  • Request handler instrumentation as they are also traced by opentelemetry-instrumentation-remix
  • Express server adapter (This breakingly changes the DX for the better.)
  • Auto-instrumentation for http as default integration for Remix SDK.

Also:

Migrates Remix integration tests from Jest to Vitest.

Fixes Backlogged Issues:

@onurtemizkan onurtemizkan force-pushed the onur/remix-otel-migration branch 3 times, most recently from 81e86d3 to 8941895 Compare May 20, 2024 11:13
@onurtemizkan onurtemizkan requested review from mydea and Lms24 May 20, 2024 11:46
@onurtemizkan onurtemizkan marked this pull request as ready for review May 20, 2024 11:46
@@ -10,7 +10,7 @@ test('Sends two linked transactions (server & client) to Sentry', async ({ page
const httpServerTransactionPromise = waitForTransaction('create-remix-app-v2', transactionEvent => {
return (
transactionEvent.type === 'transaction' &&
transactionEvent.contexts?.trace?.op === 'http.server' &&
transactionEvent.contexts?.trace?.op === 'http' &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, we should fix this to be http.server - this is important I believe!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Marked requestHandler spans as http.server 👍

*/
export function getDefaultIntegrations(options: RemixOptions): Integration[] {
return [
...getDefaultNodeIntegrations(options).filter(integration => integration.name !== 'Http'),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, do we still instrument outgoing requests without this? Do we really need to remove this? Most otel instrumentation is on top of this...?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Http instrumentation's functionality is covered by requestHandler spans by the opentelemetry-instrumentation-remix.

In this context, HTTP instrumentation also ends up setting an unparameterised route as the root transaction name as I've seen from the tests.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the http span become the parent of the remix request handler spans?

If so, could we just extend the HTTP integration for remix to filter out server spans by default? So we still get instrumentation for outgoing requests?

Otherwise I wonder if we should actually vendor in https://github.com/justindsmith/opentelemetry-instrumentations-js/blob/main/packages/instrumentation-remix/src/instrumentation.ts and change it that way?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, makes sense to me, just extended the Http integration the same way it's done in Next.js. Also marked requestHandler spans as http.server.

@@ -57,7 +57,7 @@ const config: PlaywrightTestConfig = {
port: eventProxyPort,
},
{
command: `PORT=${port} pnpm start`,
command: `PORT=${port} NODE_OPTIONS='--require ./instrument.server.cjs' pnpm start`,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it necessary to run it like this, does it not work with require on top? Just to clarify!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we need to run it like this. esbuild does not bundle the instrumentation inside the entry files correctly.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmmm I wonder if this qualifies as a breaking change 😬 thoughts cc @AbhiPrasad ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this does qualify as a breaking change 😬

I guess we have to opt-in to this mode, we can't break the people who already put the work in to upgrade their sdk to v8.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can make this the default during onboarding though.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that makes sense. So I would say we do:

  1. Expose remixIntegration but do not add it by default
  2. Expose remixHttpIntegration but do not add it by default
  3. Users have to add both of these if they want to opt-in (the latter "overwrites" the default http integration)

Does that sound good? 🤔

Questions that remain:

a. Can we find a way to make 2 obsolete? Can't think of a good way to do it sadly 😬
b. Should we then (eventually) document both paths, or just the "new" path? I guess the "old" way could remain as an alternative installation method...?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we try adding another init option like useOtel to switch to this mode, and initialise the integrations without (or also with) exposing them?

This change also doesn't affect Express servers (or I guess any other custom server), a top-level import on the server file works in those cases. So we can still get rid of the Express adapter instrumentation, and keep the core instrumentation as an alternative for built-in server users (which I also guess is not very popular among Remix users looking at our issue reports)

I have updated the e2e tests using Express custom servers. (0e2f73a)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that sounds good - let's make an option for this and adjust default integrations based on this!

@onurtemizkan onurtemizkan force-pushed the onur/remix-otel-migration branch 2 times, most recently from 3ec1138 to 06a185e Compare May 24, 2024 15:56
@AbhiPrasad
Copy link
Member

@onurtemizkan could you add the new setup instructions to the readme of this PR? and also add a short note about what the migration looks like?

export function getDefaultIntegrations(options: RemixOptions): Integration[] {
return [
...getDefaultNodeIntegrations(options).filter(integration => integration.name !== 'Http'),
httpIntegration(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's refactor this to something like:

function getRemixDefaultIntegrations() {
  return [...]
}

// further down:

if (options.autoInstrumentRemix) {
  options.defaultIntegrations = getRemixDefaultIntegrations(options);
} else {
  instrumentServer();
}

This way users can opt in to the new behavior, but keep the old behavior working if needed?

This also means that wrapExpressCreateRequestHandler should probably remain as it was before, users need to opt-in to not use that anymore...?

name: 'Remix',
setupOnce() {
addOpenTelemetryInstrumentation(
new RemixInstrumentation({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

m: Let's re-write this based on the changes done in #12213, which means extracting this into a instrumentRemix method which is called in setupOnce. You'll have to put the options into module scope so they can be updated later...!

@onurtemizkan onurtemizkan force-pushed the onur/remix-otel-migration branch 2 times, most recently from 615c949 to 14990c4 Compare June 7, 2024 14:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants