/******************************************************************************* * Copyright 2015 IBM Corp. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ 'use strict'; var Probe = require('../lib/probe.js'); var aspect = require('../lib/aspect.js'); var request = require('../lib/request.js'); var util = require('util'); var am = require('../'); /** * Probe to instrument the Oracle-DB npm client */ function OracleDBProbe() { Probe.call(this, 'oracledb'); } util.inherits(OracleDBProbe, Probe); OracleDBProbe.prototype.attach = function(name, target) { var that = this; if (name != 'oracledb') return target; if (target.__probeAttached__) return target; target.__probeAttached__ = true; // After 'getConnection' (single-user connection model) aspect.before(target, 'getConnection', function(target, methodName, args, probeData) { aspect.aroundCallback(args, {}, function(target, callbackArgs, probeData) { var err = callbackArgs[0]; if (!err) { var connection = callbackArgs[1]; // Add monitoring addMonitoring(connection, that); } }); }); // Connection pooling aspect.before(target, 'createPool', function(target, methodName, args, context) { aspect.aroundCallback(args, {}, function(target, callbackArgs, probeData) { var err = callbackArgs[0]; if (!err) { var pool = callbackArgs[1]; aspect.before(pool, 'getConnection', function(target, methodName, args, probeData) { aspect.aroundCallback(args, {}, function(target, callbackArgs, probeData) { var err = callbackArgs[0]; if (!err) { var connection = callbackArgs[1]; // Don't attach to the same connection more than once when connections are pooled if (!connection.__appmetricsProbeAttached__) { connection.__appmetricsProbeAttached__ = true; // Add monitoring addMonitoring(connection, that); } } }); }); } }); }); return target; }; // Monitor the 'execute' method on a connection function addMonitoring(connection, probe) { aspect.around( connection, 'execute', function(target, methodName, args, probeData) { // Start the monitoring for the 'execute' method probe.metricsProbeStart(probeData, methodName, args); probe.requestProbeStart(probeData, methodName, args); // Advise the callback for 'execute'. Will do nothing if no callback is registered aspect.aroundCallback(args, probeData, function(target, callbackArgs, probeData) { // 'execute' has completed and the callback has been called, so end the monitoring probe.metricsProbeEnd(probeData, methodName, args); probe.requestProbeEnd(probeData, methodName, args); }); }, function(target, methodName, args, probeData, rc) { // If no callback used then end the monitoring after returning from the 'execute' method instead if (aspect.findCallbackArg(args) == undefined) { probe.metricsProbeEnd(probeData, methodName, args); probe.requestProbeEnd(probeData, methodName, args); } return rc; } ); } /* * Lightweight metrics probe end for OracleDB queries */ OracleDBProbe.prototype.metricsEnd = function(probeData, method, methodArgs) { if (probeData && probeData.timer) { probeData.timer.stop(); var query = methodArgs[0]; am.emit('oracledb', { time: probeData.timer.startTimeMillis, query: query, duration: probeData.timer.timeDelta, }); } }; /* * Heavyweight request probes for OracleDB queries */ OracleDBProbe.prototype.requestStart = function(probeData, method, methodArgs) { probeData.req = request.startRequest('oracledb', method, false, probeData.timer); }; OracleDBProbe.prototype.requestEnd = function(probeData, method, methodArgs) { if (probeData && probeData.req) { var query = methodArgs[0]; probeData.req.stop({ query: query }); } }; module.exports = OracleDBProbe;