Skip to content

fix(node-experimental): Update auto integration lookup & readme #8690

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

Merged
merged 2 commits into from
Aug 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions packages/node-experimental/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,26 @@ Currently, this SDK:
* Will capture errors (same as @sentry/node)
* Auto-instrument for performance - see below for which performance integrations are available.

### Manual Instrumentation

**Manual instrumentation is not supported!**
This is because the current Sentry-Performance-APIs like `Sentry.startTransaction()` are not compatible with the OpenTelemetry tracing model.
We may add manual tracing capabilities in a later version.

### ESM Support

Due to the way OpenTelemetry handles instrumentation, this only works out of the box for CommonJS (`require`) applications.


There is experimental support for running OpenTelemetry with ESM (`"type": "module"`):

```bash
node --experimental-loader=@opentelemetry/instrumentation/hook.mjs ./app.js
Copy link
Member

Choose a reason for hiding this comment

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

😭

Copy link
Member Author

Choose a reason for hiding this comment

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

yes, so sad 😬 and even that doesn't work with all integrations, e.g. it fails with fastify. 😢

```

See [OpenTelemetry Instrumentation Docs](https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-instrumentation#instrumentation-for-es-modules-in-nodejs-experimental) for details on this -
but note that this is a) experimental, and b) does not work with all integrations.

## Available (Performance) Integrations

* Http
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,39 @@
import type { Instrumentation } from '@opentelemetry/instrumentation';
import { registerInstrumentations } from '@opentelemetry/instrumentation';

/** TODO */
/**
* The base node performance integration.
*/
export abstract class NodePerformanceIntegration<IntegrationOptions> {
protected _options: IntegrationOptions;
protected _unload?: () => void;
protected _instrumentations?: Instrumentation[] | undefined;

public abstract name: string;

public constructor(options: IntegrationOptions) {
this._options = options;
}

/**
* Load the instrumentation(s) for this integration.
* Returns `true` if the instrumentations were loaded, else false.
*/
public loadInstrumentations(): boolean {
try {
this._instrumentations = this.setupInstrumentation(this._options) || undefined;
} catch (error) {
return false;
}

return true;
}

/**
* @inheritDoc
*/
public setupOnce(): void {
const instrumentations = this.setupInstrumentation(this._options);
const instrumentations = this._instrumentations || this.setupInstrumentation(this._options);

if (!instrumentations) {
return;
Expand Down
2 changes: 1 addition & 1 deletion packages/node-experimental/src/integrations/express.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Instrumentation } from '@opentelemetry/instrumentation';
import { ExpressInstrumentation } from '@opentelemetry/instrumentation-express';
import type { Integration } from '@sentry/types';

import { NodePerformanceIntegration } from './lazy';
import { NodePerformanceIntegration } from './NodePerformanceIntegration';

/**
* Express integration
Expand Down
2 changes: 1 addition & 1 deletion packages/node-experimental/src/integrations/fastify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Instrumentation } from '@opentelemetry/instrumentation';
import { FastifyInstrumentation } from '@opentelemetry/instrumentation-fastify';
import type { Integration } from '@sentry/types';

import { NodePerformanceIntegration } from './lazy';
import { NodePerformanceIntegration } from './NodePerformanceIntegration';

/**
* Express integration
Expand Down
Original file line number Diff line number Diff line change
@@ -1,87 +1,67 @@
import type { Integration, IntegrationClass } from '@sentry/types';
import { dynamicRequire } from '@sentry/utils';
import type { Integration } from '@sentry/types';

import type { Express } from './express';
import type { Fastify } from './fastify';
import type { GraphQL } from './graphql';
import type { Mongo } from './mongo';
import type { Mongoose } from './mongoose';
import type { Mysql } from './mysql';
import type { Mysql2 } from './mysql2';
import type { Nest } from './nest';
import type { Postgres } from './postgres';
import type { Prisma } from './prisma';
import { Express } from './express';
import { Fastify } from './fastify';
import { GraphQL } from './graphql';
import { Mongo } from './mongo';
import { Mongoose } from './mongoose';
import { Mysql } from './mysql';
import { Mysql2 } from './mysql2';
import { Nest } from './nest';
import type { NodePerformanceIntegration } from './NodePerformanceIntegration';
import { Postgres } from './postgres';
import { Prisma } from './prisma';

const INTEGRATIONS = [
const INTEGRATIONS: (() => NodePerformanceIntegration<unknown>)[] = [
() => {
const integration = dynamicRequire(module, './express') as {
Express: IntegrationClass<Express>;
};
return new integration.Express();
return new Express();
},
() => {
const integration = dynamicRequire(module, './fastify') as {
Fastify: IntegrationClass<Fastify>;
};
return new integration.Fastify();
return new Fastify();
},
() => {
const integration = dynamicRequire(module, './graphql') as {
GraphQL: IntegrationClass<GraphQL>;
};
return new integration.GraphQL();
return new GraphQL();
},
() => {
const integration = dynamicRequire(module, './mongo') as {
Mongo: IntegrationClass<Mongo>;
};
return new integration.Mongo();
return new Mongo();
},
() => {
const integration = dynamicRequire(module, './mongoose') as {
Mongoose: IntegrationClass<Mongoose>;
};
return new integration.Mongoose();
return new Mongoose();
},
() => {
const integration = dynamicRequire(module, './mysql') as {
Mysql: IntegrationClass<Mysql>;
};
return new integration.Mysql();
return new Mysql();
},
() => {
const integration = dynamicRequire(module, './mysql2') as {
Mysql2: IntegrationClass<Mysql2>;
};
return new integration.Mysql2();
return new Mysql2();
},
() => {
const integration = dynamicRequire(module, './postgres') as {
Postgres: IntegrationClass<Postgres>;
};
return new integration.Postgres();
return new Postgres();
},
() => {
const integration = dynamicRequire(module, './prisma') as {
Prisma: IntegrationClass<Prisma>;
};
return new integration.Prisma();
return new Prisma();
},
() => {
const integration = dynamicRequire(module, './nest') as {
Nest: IntegrationClass<Nest>;
};
return new integration.Nest();
return new Nest();
},
];

/** TODO */
/**
* Get auto-dsicovered performance integrations.
* Note that due to the way OpenTelemetry instrumentation works, this will generally still return Integrations
* for stuff that may not be installed. This is because Otel only instruments when the module is imported/required,
* so if the package is not required at all it will not be patched, and thus not instrumented.
* But the _Sentry_ Integration will still be added.
* This _may_ be a bit confusing because it shows all integrations as being installed in the debug logs, but this is
* technically not wrong because we install it (it just doesn't do anything).
*/
export function getAutoPerformanceIntegrations(): Integration[] {
const loadedIntegrations = INTEGRATIONS.map(tryLoad => {
try {
return tryLoad();
const integration = tryLoad();
const isLoaded = integration.loadInstrumentations();
return isLoaded ? integration : false;
} catch (_) {
return undefined;
return false;
}
}).filter(integration => !!integration) as Integration[];

Expand Down
2 changes: 1 addition & 1 deletion packages/node-experimental/src/integrations/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Instrumentation } from '@opentelemetry/instrumentation';
import { GraphQLInstrumentation } from '@opentelemetry/instrumentation-graphql';
import type { Integration } from '@sentry/types';

import { NodePerformanceIntegration } from './lazy';
import { NodePerformanceIntegration } from './NodePerformanceIntegration';

/**
* GraphQL integration
Expand Down
2 changes: 1 addition & 1 deletion packages/node-experimental/src/integrations/mongo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Instrumentation } from '@opentelemetry/instrumentation';
import { MongoDBInstrumentation } from '@opentelemetry/instrumentation-mongodb';
import type { Integration } from '@sentry/types';

import { NodePerformanceIntegration } from './lazy';
import { NodePerformanceIntegration } from './NodePerformanceIntegration';

/**
* MongoDB integration
Expand Down
2 changes: 1 addition & 1 deletion packages/node-experimental/src/integrations/mongoose.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Instrumentation } from '@opentelemetry/instrumentation';
import { MongooseInstrumentation } from '@opentelemetry/instrumentation-mongoose';
import type { Integration } from '@sentry/types';

import { NodePerformanceIntegration } from './lazy';
import { NodePerformanceIntegration } from './NodePerformanceIntegration';

/**
* Mongoose integration
Expand Down
2 changes: 1 addition & 1 deletion packages/node-experimental/src/integrations/mysql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Instrumentation } from '@opentelemetry/instrumentation';
import { MySQLInstrumentation } from '@opentelemetry/instrumentation-mysql';
import type { Integration } from '@sentry/types';

import { NodePerformanceIntegration } from './lazy';
import { NodePerformanceIntegration } from './NodePerformanceIntegration';

/**
* MySQL integration
Expand Down
2 changes: 1 addition & 1 deletion packages/node-experimental/src/integrations/mysql2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Instrumentation } from '@opentelemetry/instrumentation';
import { MySQL2Instrumentation } from '@opentelemetry/instrumentation-mysql2';
import type { Integration } from '@sentry/types';

import { NodePerformanceIntegration } from './lazy';
import { NodePerformanceIntegration } from './NodePerformanceIntegration';

/**
* MySQL2 integration
Expand Down
2 changes: 1 addition & 1 deletion packages/node-experimental/src/integrations/nest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Instrumentation } from '@opentelemetry/instrumentation';
import { NestInstrumentation } from '@opentelemetry/instrumentation-nestjs-core';
import type { Integration } from '@sentry/types';

import { NodePerformanceIntegration } from './lazy';
import { NodePerformanceIntegration } from './NodePerformanceIntegration';

/**
* Nest framework integration
Expand Down
2 changes: 1 addition & 1 deletion packages/node-experimental/src/integrations/postgres.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Instrumentation } from '@opentelemetry/instrumentation';
import { PgInstrumentation } from '@opentelemetry/instrumentation-pg';
import type { Integration } from '@sentry/types';

import { NodePerformanceIntegration } from './lazy';
import { NodePerformanceIntegration } from './NodePerformanceIntegration';

/**
* Postgres integration
Expand Down
2 changes: 1 addition & 1 deletion packages/node-experimental/src/integrations/prisma.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Instrumentation } from '@opentelemetry/instrumentation';
import { PrismaInstrumentation } from '@prisma/instrumentation';
import type { Integration } from '@sentry/types';

import { NodePerformanceIntegration } from './lazy';
import { NodePerformanceIntegration } from './NodePerformanceIntegration';

/**
* Prisma integration
Expand Down