apm-agent-nodejs
apm-agent-nodejs copied to clipboard
Support for prisma
Is your feature request related to a problem? Please describe.
I would love to see support for https://www.prisma.io orm in the agent. Right now I am migrating a big project from sequelize to prisma and queries performed by prisma do not show up in the traces:

This can be very misleading. I think because prisma is at this point a very relevant technology the elastic agent should support it.
Thanks and regards
Hannes
@toxsick Thanks for the feature request!
I looked briefly at this. The reason there is tracing of sequelize's queries is because it uses the various database drivers -- some of which we do instrument. It looks like prisma has its own Rust-implemented engine that is doing all the DB queries, so we'd have to instrument prisma directly, if that is possible.
I say "if that is possible" because it looks like -- again from a very brief look -- that the main Prisma query handling (in the @prisma/client package) is deployed as an esbuild-built bundle. That might make instrumenting it effectively "exciting". :) I'm not sure, however. It might be very straightforward.
Hey @trentm,
thanks for looking into this, I wrote my own variant to debug logging for prisma queries, perhaps it helps to get started:
// enable debug logging
// reference: https://github.com/prisma/prisma/issues/5026
const DEBUG = true;
const prisma = new PrismaClient(
DEBUG
? {
log: [
{
emit: 'event',
level: 'query',
},
],
}
: null,
);
if (DEBUG) {
prisma.$on('query', async ({ query, params, duration }) => {
const paramsParsed = JSON.parse(params);
console.log(
[
'==> prisma query:\n',
query
.split('?')
.map((segment, i) => {
if (paramsParsed[i] === undefined) {
return segment;
}
const param = paramsParsed[i];
if (typeof param === 'string') {
return `${segment}"${param}"`;
}
return `${segment}${param}`;
})
.join(''),
`\n==> took ${duration}ms`,
].join('\n'),
);
});
}
It will log the actual sql queries performed by prisma with duration. Perhaps this is a start?
I researched a little bit more and perhaps a prisma middleware would be the right way to go?
- https://www.prisma.io/docs/concepts/components/prisma-client/middleware
- https://www.prisma.io/docs/concepts/components/prisma-client/middleware/logging-middleware
@trentm let me know what u think
@toxsick Thanks! That's very helpful.
Its pretty easy to do something simple yourself.
This is what im rocking right now and it works pretty well:
import apm from "elastic-apm-node";
prisma.$use(async (params, next) => {
const span = apm.startSpan(`prisma.${params.model}.${params.action}`);
if (span) {
span.type = "DB";
span.subtype = "prisma";
span.action = "query";
}
try {
const result = await next(params);
span?.end();
return result;
} catch (e) {
span?.end();
throw e;
}
});
@mikecann Nice.
If you want slightly shorter code you could put the type, subtype, and action in the .startSpan(...) call. E.g.:
const spam = apm.startSpan(`...`, "db", "prisma", "query")
try {
...
Also, I used lower-case "db" like the agent does for other database instrumentation. I'm not actually sure if that case difference makes a difference for some UI in the Kibana APM app. E.g. it might for the icon it uses for database spans.
Nice thanks :)
Hey 👋🏽
Alex here from the Prisma team.
We introduced two preview features a while back that gives insight on how Prisma Client interacts with your database: tracing and metrics.
You can enable the Preview features in your application by updating the generator block with:
generator client {
provider = "prisma-client-js"
previewFeatures = ["metrics", "tracing"]
}
We built an instrumentation package to help with tracing @prisma/instrumentation you could use for tracing (required for the Preview feature to work). It fully supports the OpenTelemetry standard.
Feel free to reach out for any clarifications or create a GH issue in the Prisma repo if you run into any issues. 🙂
Docs:
@ruheni , I tried to activate tracing in my project, while installing the dependencies as stated. but still failed to see traces on elastic APM, Or Actually I am seeing traces now, but does not reflect the same info in the span as provided by other ORMs, most importantly the SQL statement itself.