Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
const trackExceptionStub = sinon.stub(AppInsights.defaultClient, "trackException");
const trackTraceStub = sinon.stub(AppInsights.defaultClient, "trackTrace");
disable();
enable(true, AppInsights.defaultClient);
const logEvent: console.IConsoleData = {
message: "test log",
stderr: true // should log as MessageData regardless of this setting
};
const dummyError = new Error("test error");
const errorEvent: console.IConsoleData = {
message: dummyError as any,
stderr: false, // log() should still log as ExceptionData
};
channel.publish("console", logEvent);
assert.ok(trackExceptionStub.notCalled);
assert.ok(trackTraceStub.calledOnce);
assert.deepEqual(trackTraceStub.args[0][0].message, "test log");
trackExceptionStub.reset();
trackTraceStub.reset();
channel.publish("console", errorEvent);
assert.ok(trackExceptionStub.calledOnce);
assert.ok(trackTraceStub.notCalled);
assert.deepEqual(trackExceptionStub.args[0][0].exception, dummyError);
disable();
trackExceptionStub.restore();
trackTraceStub.restore();
});
});
stderr: true // should log as MessageData regardless of this setting
};
const dummyError = new Error("test error");
const errorEvent: console.IConsoleData = {
message: dummyError as any,
stderr: false, // log() should still log as ExceptionData
};
channel.publish("console", logEvent);
assert.ok(trackExceptionStub.notCalled);
assert.ok(trackTraceStub.calledOnce);
assert.deepEqual(trackTraceStub.args[0][0].message, "test log");
trackExceptionStub.reset();
trackTraceStub.reset();
channel.publish("console", errorEvent);
assert.ok(trackExceptionStub.calledOnce);
assert.ok(trackTraceStub.notCalled);
assert.deepEqual(trackExceptionStub.args[0][0].exception, dummyError);
disable();
trackExceptionStub.restore();
trackTraceStub.restore();
});
});
const trackingCallback = channel.bindToContext(function(err: Error, res: IPostgresResult): any {
const end = process.hrtime(start);
data.result = res && { rowCount: res.rowCount, command: res.command };
data.error = err;
data.duration = Math.ceil((end[0] * 1e3) + (end[1] / 1e6));
channel.publish("postgres", data);
// emulate weird internal behavior in pg@6
// on success, the callback is called *before* query events are emitted
// on failure, the callback is called *instead of* the query emitting events
// with no events, that means no promises (since the promise is resolved/rejected in an event handler)
// since we are always inserting ourselves as a callback, we have to restore the original
// behavior if the user didn't provide one themselves
if (err) {
if (cb) {
return cb.apply(this, arguments);
} else if (queryResult && queryResult instanceof EventEmitter) {
queryResult.emit("error", err);
}
} else if (cb) {
cb.apply(this, arguments);
}
cbidx = i;
break;
} else if (typeof arguments[i] !== "undefined") {
break;
}
}
const cb = arguments[cbidx];
const resultContainer = {result: null, startTime: null};
if (typeof cb === "function") {
// Preserve context on the callback.
// If this is one of the functions that we want to track,
// then wrap the callback with the tracking wrapper
if (cbWrapper) {
resultContainer.startTime = process.hrtime();
arguments[cbidx] = channel.bindToContext(cbWrapper(resultContainer, cb));
} else {
arguments[cbidx] = channel.bindToContext(cb);
}
}
const result = originalFunc.apply(this, arguments);
resultContainer.result = result;
return result;
};
}
listener.on("started", function(event) {
if (eventMap[event.requestId]) {
// Note: Mongo can generate 2 completely separate requests
// which share the same requestId, if a certain race condition is triggered.
// For now, we accept that this can happen and potentially miss or mislabel some events.
return;
}
contextMap[event.requestId] = channel.bindToContext((cb) => cb());
eventMap[event.requestId] = event;
});
originalRedis.RedisClient.prototype.internal_send_command = function(commandObj) {
if (commandObj) {
const cb = commandObj.callback;
if (!cb || !cb.pubsubBound) {
const address = this.address;
const startTime = process.hrtime();
// Note: augmenting the callback on internal_send_command is correct for context
// tracking, but may be too low-level for dependency tracking. There are some 'errors'
// which higher levels expect in some cases
// However, the only other option is to intercept every individual command.
commandObj.callback = channel.bindToContext(function(err, result) {
const hrDuration = process.hrtime(startTime);
/* tslint:disable-next-line:no-bitwise */
const duration = (hrDuration[0] * 1e3 + hrDuration[1] / 1e6) | 0;
channel.publish("redis", {duration, address, commandObj, err, result});
if (typeof cb === "function") {
cb.apply(this, arguments);
}
});
commandObj.callback.pubsubBound = true;
}
}
return originalSend.call(this, commandObj);
};
function patchCallback(cb?: PostgresCallback): PostgresCallback {
if (cb && cb[diagnosticOriginalFunc]) {
cb = cb[diagnosticOriginalFunc];
}
const trackingCallback = channel.bindToContext(function(err: Error, res: IPostgresResult): any {
const end = process.hrtime(start);
data.result = res && { rowCount: res.rowCount, command: res.command };
data.error = err;
data.duration = Math.ceil((end[0] * 1e3) + (end[1] / 1e6));
channel.publish("postgres", data);
// emulate weird internal behavior in pg@6
// on success, the callback is called *before* query events are emitted
// on failure, the callback is called *instead of* the query emitting events
// with no events, that means no promises (since the promise is resolved/rejected in an event handler)
// since we are always inserting ourselves as a callback, we have to restore the original
// behavior if the user didn't provide one themselves
if (err) {
if (cb) {
return cb.apply(this, arguments);
} else if (queryResult && queryResult instanceof EventEmitter) {
name: event.data.event.commandName,
data: event.data.event.commandName,
duration: event.data.event.duration,
success: event.data.succeeded,
// TODO: transmit result code from mongo
resultCode: event.data.succeeded ? "0" : "1",
dependencyTypeName: "mongodb"});
if (!event.data.succeeded) {
ApplicationInsights.defaultClient
.trackException({exception: new Error(event.data.event.failure)});
}
}
};
channel.subscribe("mongodb", subscriber);
const connection = queryObj._connection || {};
const connectionConfig = connection.config || {};
const dbName = connectionConfig.socketPath ? connectionConfig.socketPath : `${connectionConfig.host || "localhost"}:${connectionConfig.port}`;
ApplicationInsights.defaultClient.trackDependency({
target: dbName,
name: sqlString,
data: sqlString,
duration: event.data.duration,
success: success,
// TODO: transmit result code from mysql
resultCode: success ? "0" : "1",
dependencyTypeName: "mysql"});
}
};
channel.subscribe("mysql", subscriber);
// We don't want to report 'info', it's irrelevant
return;
}
ApplicationInsights.defaultClient.trackDependency({
target: event.data.address,
name: event.data.commandObj.command,
data: event.data.commandObj.command,
duration: event.data.duration,
success: !event.data.err,
resultCode: event.data.err ? "1" : "0",
dependencyTypeName: "redis"});
}
};
channel.subscribe("redis", subscriber);