@instana/core
Version:
Core library for Instana's Node.js packages
104 lines (84 loc) • 2.92 kB
JavaScript
/*
* (c) Copyright IBM Corp. 2021
* (c) Copyright Instana Inc. and contributors 2018
*/
;
const hook = require('../../../util/hook');
const httpServer = require('../protocols/httpServer');
const cls = require('../../cls');
let logger;
let active = false;
exports.activate = function activate() {
active = true;
};
exports.deactivate = function deactivate() {
active = false;
};
exports.init = function init(config) {
logger = config.logger;
hook.onModuleLoad('fastify', instrument);
};
/**
* Fastify is auto instrumend by our http server instrumention.
*
* In this instrumentation, we want to capture extra data on top.
* We register a custom hook via the framework API and add this data to the
* target http entry span.
*
* See https://www.fastify.io/docs/latest/Hooks
*/
function instrument(build) {
if (typeof build !== 'function') {
return build;
}
// copy further exported properties
Object.keys(build).forEach(k => {
overwrittenBuild[k] = build[k];
});
return overwrittenBuild;
function overwrittenBuild() {
const app = build.apply(this, arguments);
// NOTE: all major versions support `addHook` - this is just a safe protection
if (!app.addHook) {
logger.warn('Instana was not able to instrument Fastify. The instrumention of http requests is still working.');
return app;
}
app.addHook('onRequest', function onRequest(request, reply, done) {
try {
// NOTE: v1 uses _context https://github.com/fastify/fastify/blob/1.x/fastify.js#L276
// v2/v3/v4 uses context https://github.com/fastify/fastify/blob/2.x/test/handler-context.test.js#L41
// v5 uses reply.routeOptions and no longer exposes `.context`
// https://fastify.dev/docs/latest/Guides/Migration-Guide-V5/#streamlined-access-to-route-definition
let url;
if (reply?.routeOptions?.config?.url) {
url = reply.routeOptions.config.url;
} else {
url = reply._context ? reply._context.config.url : reply.context.config.url;
}
annotateHttpEntrySpanWithPathTemplate(app, url);
} catch (err) {
logger.warn(
'Instana was not able to retrieve the path template. The instrumention of http requests is still working.'
);
}
done();
});
return app;
}
}
/**
* A request comes in GET /foo/22
* We want to trace GET /foo/:id
*/
function annotateHttpEntrySpanWithPathTemplate(app, url) {
if (!active) {
return;
}
const span = cls.getCurrentEntrySpan();
if (!span || span.n !== httpServer.spanName || span.pathTplFrozen) {
return;
}
const basePathDescriptor = Object.getOwnPropertyDescriptor(app, 'basePath');
const basePathOrPrefix = basePathDescriptor && basePathDescriptor.get ? app.prefix : app.basePath;
span.data.http.path_tpl = (basePathOrPrefix || '') + (url || '/');
}