appdynamics
Version:
Performance Profiler and Monitor
186 lines (158 loc) • 5.73 kB
JavaScript
/*
This is for apollo-server entry probe
*/
let HttpCommon = require("./http-common");
exports.ApolloEntryProbe = ApolloEntryProbe;
function ApolloEntryProbe(agent) {
this.agent = agent;
}
ApolloEntryProbe.prototype.init = function () {};
ApolloEntryProbe.prototype.attach = function (obj, moduleName) {
let self = this;
if(process.env.APPDYNAMICS_APOLLO_PROBE_DISABLE == true || process.env.APPDYNAMICS_APOLLO_PROBE_DISABLE == 'true') {
return;
}
if(moduleName == 'apollo-server') {
self.agent.proxy.before(
obj.ApolloServer.prototype,
"createServerInfo",
(args) => this.addLifeCycleHooks(args)
);
} else if (moduleName === '@apollo/server') {
const originalObject = obj;
const overriddenObject = {};
overriddenObject.ApolloServer = proxyApolloServer(self, originalObject);
return overriddenObject;
} else if(moduleName === '@apollo/server/express4') {
const originalObject = obj;
const overriddenObject = {};
overriddenObject.expressMiddleware = proxyExpressMiddleware(self, originalObject);
overriddenObject.__proto__ = originalObject;
return overriddenObject;
} else if(moduleName === '@apollo/server/standalone'){
const originalObject = obj;
const overriddenObject = {};
overriddenObject.startStandaloneServer = proxyStartStandaloneServer(self, originalObject);
overriddenObject.__proto__ = originalObject;
return overriddenObject;
}
};
ApolloEntryProbe.prototype.addLifeCycleHooks = function (obj) {
let self = this;
let userDefinedContext = obj.context;
obj.context = function ({ req, res }) {
let userCtx;
if (userDefinedContext instanceof Function) {
userCtx = userDefinedContext.call(this, ...arguments);
} else if (userDefinedContext instanceof Object) {
userDefinedContext.gqlReq = req;
userDefinedContext.gqlRes = res;
return userDefinedContext;
}
return Object.assign({ gqlReq: req, gqlRes: res }, userCtx);
};
obj.plugins = [
{
requestDidStart() {
return {
didResolveOperation(response) {
response.context.gqlReq.graphqlop = response.operationName;
response.context.gqlReq.transactionStarted = true;
HttpCommon.startTransactionHandler(
response.context.gqlReq,
response.context.gqlRes,
self.agent
);
},
didEncounterErrors(response) {
response.context.gqlRes.error = response.errors[0];
if(response.context.gqlReq.transactionStarted) {
return;
}
HttpCommon.startTransactionHandler(
response.context.gqlReq,
response.context.gqlRes,
self.agent
);
},
};
},
},
...obj.plugins,
];
};
function appDynamicsApolloServerPlugin(self) {
const plugin = {
async requestDidStart() {
return {
didResolveOperation(requestContext) {
if(!requestContext.contextValue.gqlReq) {
requestContext.contextValue.gqlReq = {};
requestContext.contextValue.gqlRes = {};
}
requestContext.contextValue.gqlReq.graphqlop = requestContext.operationName;
requestContext.contextValue.gqlReq.transactionStarted = true;
HttpCommon.startTransactionHandler(
requestContext.contextValue.gqlReq,
requestContext.contextValue.gqlRes,
self.agent
);
},
didEncounterErrors(requestContext) {
if(!requestContext.contextValue.gqlReq) {
requestContext.contextValue.gqlReq = {};
requestContext.contextValue.gqlRes = {};
}
requestContext.contextValue.gqlRes.error = requestContext.errors[0];
if(requestContext.contextValue.gqlReq.transactionStarted) {
return;
}
HttpCommon.startTransactionHandler(
requestContext.contextValue.gqlReq,
requestContext.contextValue.gqlRes,
self.agent
);
},
};
}
};
return plugin;
}
function appDymanicsApolloServerOverriddenOptions(options) {
const overriddenOptions = options || {};
const context = options ? options.context : undefined;
const overriddenContext = async function (contextParam) {
const contextValue = context ? await context(contextParam) : {};
contextParam.req.url = contextParam.req.baseUrl; // For Apollo Server 4
contextValue.gqlReq = contextParam.req;
contextValue.gqlRes = contextParam.res;
return contextValue;
};
overriddenOptions.context = overriddenContext;
return overriddenOptions;
}
function proxyApolloServer(self, originalObject) {
const ApolloServer = originalObject.ApolloServer;
// Define ApolloServerProxy class
class ApolloServerProxy extends ApolloServer {
constructor(config) {
// Call the ApolloServer constructor
super(config);
// Add the plugin to the plugins array
this.addPlugin(appDynamicsApolloServerPlugin(self));
}
}
return ApolloServerProxy;
}
function proxyStartStandaloneServer(self, originalObject) {
return async function startStandaloneServerProxy(server, options) {
const overriddenOptions = appDymanicsApolloServerOverriddenOptions(options);
return await originalObject.startStandaloneServer(server, overriddenOptions);
};
}
function proxyExpressMiddleware(self, originalObject) {
return function expressMiddlewareProxy(server, options) {
const overriddenOptions = appDymanicsApolloServerOverriddenOptions(options);
return originalObject.expressMiddleware(server, overriddenOptions);
};
}