Skip to content

Commit 15850de

Browse files
authored
feat: Added support for gRPC error reporting (#233)
1 parent d61be7e commit 15850de

File tree

2 files changed

+44
-6
lines changed

2 files changed

+44
-6
lines changed

lib/instrumentation-security/hooks/grpc-js/nr-grpc.js

+35-6
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const grpcutils = require('../../core/grpc-utils');
1616
const routeManager = require('../../core/route-manager');
1717
let serverAddress;
1818
const ExceptionReporting = require('../../../nr-security-agent/lib/core/ExceptionReporting');
19+
const responseErrorSet = new Set([2, 12, 13, 14, 15])
1920

2021

2122

@@ -58,6 +59,33 @@ module.exports.wrapStartCall = function wrappedClient(shim, callStream) {
5859
shim.wrap(callStream.Http2CallStream.prototype, 'start', wrapStart)
5960
}
6061

62+
/**
63+
* Wrapper for error collection
64+
* @param {*} shim
65+
* @param {*} call
66+
*/
67+
module.exports.wrapCall = function wrappedCall(shim, call) {
68+
shim.wrap(call, 'callErrorFromStatus', function wrapCallErrorFromStatus(shim, fn) {
69+
if (!shim.isFunction(fn)) {
70+
return fn
71+
}
72+
return function wrappedCallErrorFromStatus() {
73+
const errRes = fn.apply(this, arguments);
74+
try {
75+
let error = new Error(errRes.message);
76+
error.stack = errRes.stack;
77+
const request = requestManager.getRequest(shim);
78+
if (request) {
79+
ExceptionReporting.generate5xxReportingEvent(error, request);
80+
}
81+
} catch (error) {
82+
}
83+
84+
return errRes;
85+
}
86+
})
87+
}
88+
6189
module.exports.wrapServer = function wrappedServer(shim, server) {
6290
const grpcVersion = shim.require('./package.json').version
6391
logger.info("Instrumenting @grpc/grpc-js", grpcVersion)
@@ -109,6 +137,7 @@ function wrapStart(shim, original) {
109137
"path": method,
110138
"protocol": protocol,
111139
}
140+
112141
if (request) {
113142
const traceObject = secUtils.getTraceObject(shim);
114143
const secMetadata = securityMetaData.getSecurityMetaData(request, urlObj, traceObject, secUtils.getExecutionId(), EVENT_TYPE.HTTP_REQUEST, EVENT_CATEGORY.HTTP)
@@ -256,11 +285,11 @@ function wrapCallback(shim, mod, method) {
256285
if (arguments[0].details && request) {
257286
ExceptionReporting.generateExceptionReportingEvent(arguments[0].details, request);
258287
}
259-
//TODO GRPC response errors reporting
260-
// if (arguments[0].code && arguments[0].code > 0 && request) {
261-
// let responseCode = arguments[0].code
262-
// ExceptionReporting.generate5xxReportingEvent(null, request, responseCode);
263-
// }
288+
289+
if (arguments[0].code && responseErrorSet.has(arguments[0].code) && request) {
290+
let responseCode = arguments[0].code
291+
ExceptionReporting.generate5xxReportingEvent(null, request, responseCode);
292+
}
264293
}
265294
} catch (error) {
266295

@@ -282,7 +311,7 @@ function wrapCallback(shim, mod, method) {
282311
function addRequestData(shim, type, path, args) {
283312
const data = Object.assign({});
284313
try {
285-
const transaction = shim.tracer.getTransaction();
314+
const transaction = shim.tracer.getTransaction();
286315
if (transaction) {
287316
data.method = path;
288317
data.url = path;

lib/instrumentation-security/index.js

+9
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,15 @@ newrelic.instrument({
235235
}
236236
})
237237

238+
newrelic.instrument({
239+
moduleName: '@grpc/grpc-js/build/src/call',
240+
isEsm: true,
241+
onRequire: require('./hooks/grpc-js/nr-grpc').wrapCall,
242+
onError: function intrumentErrorHandler(err) {
243+
logger.error(err.message, err.stack)
244+
}
245+
})
246+
238247
newrelic.instrument({
239248
moduleName: 'graphql/execution/execute',
240249
isEsm: true,

0 commit comments

Comments
 (0)