Skip to content

feat: MongoDB Tracing Support #3072

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 10 commits into from
Dec 4, 2020
Merged

feat: MongoDB Tracing Support #3072

merged 10 commits into from
Dec 4, 2020

Conversation

kamilogorek
Copy link
Contributor

@kamilogorek kamilogorek commented Nov 24, 2020

MongoDB tracing support.

Usage:

const Sentry = require("@sentry/node");
const Tracing = require("@sentry/tracing");
const mongodb = require("mongodb");

Sentry.init({
  dsn: "__PUBLIC_DSN__",
  integrations: [
    new Tracing.Integrations.Mongo(),
  ],
  tracesSampleRate: 1.0,
});

const client = new mongodb.MongoClient("mongodb://mongo:docker@localhost:27017");

// the rest of the code, for raw-node code we need manual instrumentation, eg.

async function run() {
  const transaction = Sentry.startTransaction({
    op: "transaction",
    name: "My Transaction",
  });

  Sentry.configureScope((scope) => {
    scope.setSpan(transaction);
  });

  try {
    await client.connect();
    
    const database = await client.db("admin");  
    const collection = database.collection("movies");

    await collection.insertOne({ title: "Rick and Morty" });
    await collection.findOne({ title: "Back to the Future" });
    await collection.updateOne(
      { title: "Back to the Future" },
      { $set: { title: "South Park" } }
    );
    await collection.findOne({ title: "South Park" });
  } finally {
    if (transaction) transaction.finish();
    await client.close();
  }
}
run().catch(console.dir);

Works nicely with Express too:

const Sentry = require("@sentry/node");
const Tracing = require("@sentry/tracing");
const mongodb = require("mongodb");
const express = require("express");

Sentry.init({
  dsn: "__PUBLIC_DSN__",
  integrations: [
    new Sentry.Integrations.Http({ tracing: true }),
    new Tracing.Integrations.Express({
      app: express.Router,
      methods: ["get"],
    }),
    new Tracing.Integrations.Mongo(),
  ],
  tracesSampleRate: 1.0,
});

const app = express();
const client = new mongodb.MongoClient("mongodb://mongo:docker@localhost:27017");
client.connect();

app.use(Sentry.Handlers.requestHandler());
app.use(Sentry.Handlers.tracingHandler());
app.use(express.json());

app.get("/hi", async function sayHi(req, res, next) {
  try {
    const database = await client.db("admin");  
    const collection = database.collection("movies");
    await collection.insertOne({ title: "Rick and Morty" });
    const result = await collection.findOne({ title: "Rick and Morty" });
    res.send(result);
  } catch (err) {
    next(err);
  }
});

app.use(Sentry.Handlers.errorHandler());

app.listen(3000);

@github-actions
Copy link
Contributor

github-actions bot commented Nov 24, 2020

size-limit report

Path Size
@sentry/browser - CDN Bundle (gzipped) 19.73 KB (-0.01% 🔽)
@sentry/browser - Webpack 20.6 KB (0%)
@sentry/react - Webpack 20.6 KB (0%)
@sentry/browser + @sentry/tracing - CDN Bundle (gzipped) 26.88 KB (0%)

@kamilogorek kamilogorek force-pushed the node-mongo branch 4 times, most recently from 6efe345 to 8926f90 Compare December 1, 2020 14:05
@kamilogorek kamilogorek marked this pull request as ready for review December 1, 2020 14:05
* Patches original collection methods
*/
private _instrumentOperations(collection: MongoCollection, operations: Operation[], getCurrentHub: () => Hub): void {
operations.forEach((operation: Operation) => this._patchOperation(collection, operation, getCurrentHub));
Copy link
Member

Choose a reason for hiding this comment

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

Why pass in getCurrentHub?

Copy link
Member

Choose a reason for hiding this comment

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

This is how integrations work internally, the function will be injected from outside and we should use that vs. global getCurrentHub.

public name: string = Mongo.id;

private _operations: Operation[];
private _describeOperations?: boolean | Operation[];
Copy link
Member

Choose a reason for hiding this comment

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

Is "describe" your word or theirs? If it's yours, I wonder if we might name this option differently, to a) differentiate it from the description field in a transaction, and b) indicate that what it's really about is recording the operation's inputs.

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 describe is used in database lingo.

@HazAT
Copy link
Member

HazAT commented Dec 4, 2020

Merging this now, has also few other fixes.

@HazAT HazAT merged commit f7fc733 into master Dec 4, 2020
@HazAT HazAT deleted the node-mongo branch December 4, 2020 11:38
@Copdate-Copdate
Copy link

Hi, question about MongoDB support.

I'm currently using Mongoose inside an Express app and when adding new Tracing.Integrations.Mongo() to integrations array in Sentry.init, I got the following error:

UnhandledPromiseRejectionWarning: TypeError: Tracing.Integrations.Mongo is not a constructor

Do I have to pass some config or it just doesn't support Mongoose right now?

@sol-austin
Copy link

I can't seem to get this working with Mongoose. I've added Tracing.Integrations.Mongo() to the integrations array without receiving an error message but it doesn't seem to be tracking database requests at all.

Has anyone successfully got this working with Mongoose yet?

@KevinEdry
Copy link

Same here, would love to see mongoose support for this.

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

Successfully merging this pull request may close these issues.

6 participants