UNPKG

newrelic

Version:
135 lines (112 loc) 4.05 kB
/* * Copyright 2020 New Relic Corporation. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ 'use strict' var logger = require('../logger').child({component: 'oracle'}) var shimmer = require('../shimmer') var parseSql = require('../db/parse-sql') var ORACLE = require('../metrics/names').ORACLE module.exports = function initialize(agent, oracle) { var tracer = agent.tracer var wrapped = false logger.trace('wrapping oracle.connect and oracle.connectSync') shimmer.wrapMethod(oracle, 'Oracle', 'connect', function cb_wrapMethod(connect) { return function wrappedConnect(connectData, cb) { return connect.call( this, connectData, tracer.bindFunction(wrapConnection) ) function wrapConnection(err, connection) { if (!err) ensureConnectionWrapped(connection) return cb(err, connection) } } }) shimmer.wrapMethod(oracle, 'Oracle', 'connectSync', function wrapSyncConnect(connect) { return function wrappedSyncConnect() { var connection = connect.apply(this, arguments) ensureConnectionWrapped(connection) return connection } }) function ensureConnectionWrapped(connection) { // return early in case called from an async connect after wrapping if (wrapped) return logger.trace('wrapping oracle connection prototype') wrapped = true oracle.connectSync.__NR_unwrap() oracle.connect.__NR_unwrap() shimmer.wrapMethod(oracle, 'Oracle', 'connect', function wrapMethod(connect) { return tracer.wrapFunctionNoSegment(connect, 'connect') }) var proto = Object.getPrototypeOf(connection) wrapConnectionExecute(proto, tracer) wrapConnectionPrepare(proto, tracer) shimmer.wrapMethod(proto, 'Oracle', 'reader', function wrapMethod(createReader) { return function wrappedConnect(sql) { var reader = createReader.apply(this, arguments) wrapReader(reader, tracer, sql) return reader } }) } } function wrapConnectionExecute(connection, tracer) { shimmer.wrapMethod(connection, 'Oracle.connection', 'execute', wrapExecute) function wrapExecute(execute) { return tracer.wrapFunction(ORACLE.STATEMENT + 'other/', null, execute, wrappedExecute) } function wrappedExecute(segment, args, bind) { var ps = parseSql(ORACLE.PREFIX, args[0]) var collection = ps.collection var operation = ps.operation segment.name = ORACLE.STATEMENT + collection + '/Connection.execute/' + operation logger.trace( 'capturing oracle query. collection: %s, Operation: %s', collection, operation ) segment.transaction.addRecorder(ps.recordMetrics.bind(ps, segment)) args[2] = bind(args[2]) return args } } function wrapReader(reader, tracer, sql) { var ps = parseSql(ORACLE.PREFIX, sql) shimmer.wrapMethod(reader, 'Oracle.Reader', 'nextRow', wrapNextRow) shimmer.wrapMethod(reader, 'Oracle.Reader', 'nextRows', wrapNextRows) function wrapNextRow(nextRow) { return tracer.wrapFunctionLast( ORACLE.STATEMENT + ps.collection + '/Reader.nextRow/' + ps.operation, ps.recordMetrics.bind(ps), nextRow ) } function wrapNextRows(nextRows) { return tracer.wrapFunctionLast( ORACLE.STATEMENT + ps.collection + '/Reader.nextRows/' + ps.operation, ps.recordMetrics.bind(ps), nextRows ) } } function wrapConnectionPrepare(connection, tracer) { shimmer.wrapMethod(connection, 'Oracle.connection', 'prepare', wrapPrepare) function wrapPrepare(prepare) { return function wrappedPrepare(sql) { var ps = parseSql(ORACLE.PREFIX, sql) var prepared = prepare.apply(this, arguments) shimmer.wrapMethod(prepared, 'Oracle', 'execute', wrapExecute) return prepared function wrapExecute(execute) { return tracer.wrapFunctionLast( ORACLE.STATEMENT + ps.collection + '/Statement.execute/' + ps.operation, ps.recordMetrics.bind(ps), execute ) } } } }