@instana/core
Version:
Core library for Instana's Node.js packages
121 lines (107 loc) • 3.37 kB
JavaScript
/*
* (c) Copyright IBM Corp. 2024
*/
;
const shimmer = require('../../../shimmer');
const hook = require('../../../../util/hook');
const tracingUtil = require('../../../tracingUtil');
const constants = require('../../../constants');
const cls = require('../../../cls');
let isActive = false;
exports.spanName = 'azstorage';
exports.init = function init() {
// Starting from v12.28.0, the package has been migrated to ESM.
// To support ESM-based applications, we now utilize the IITM hook.
// Reference: https://github.com/Azure/azure-sdk-for-js/pull/33329
hook.onModuleLoad('@azure/storage-blob', instrumentBlob, { nativeEsm: true });
};
function instrumentBlob(blob) {
instrumentBlockBlob(blob.BlockBlobClient);
instrumentBlobClient(blob.BlobClient);
}
// For the download and delete functionality applicable to block blobs, the BlockBlobClient extends BlobClient
// and uses the 'download' and 'delete' methods respectively. Hence we are instrmenting the BlobClient
function instrumentBlobClient(blobClient) {
shimmer.wrap(blobClient.prototype, 'delete', shimOperation('delete'));
shimmer.wrap(blobClient.prototype, 'download', shimOperation('download'));
}
function instrumentBlockBlob(blockBlobClient) {
shimmer.wrap(blockBlobClient.prototype, 'upload', shimOperation('upload'));
shimmer.wrap(blockBlobClient.prototype, 'stageBlock', shimOperation('upload'));
}
function shimOperation(operation) {
return function instrumentOperation(original) {
return function instrumentedOperation() {
if (cls.skipExitTracing({ isActive })) {
return original.apply(this, arguments);
}
const argsForOriginalQuery = new Array(arguments.length);
for (let i = 0; i < arguments.length; i++) {
argsForOriginalQuery[i] = arguments[i];
}
return instrumentingOperation({
ctx: this,
originalQuery: original,
argsForOriginalQuery: argsForOriginalQuery,
_blobName: this._name,
_container: this._containerName,
accntName: this.accountName,
operation: operation
});
};
};
}
function instrumentingOperation({
ctx,
originalQuery,
argsForOriginalQuery,
_blobName,
_container,
accntName,
operation
}) {
const blobName = _blobName;
const containerName = _container;
const accountName = accntName;
const op = operation;
return cls.ns.runAndReturn(() => {
const span = cls.startSpan({
spanName: exports.spanName,
kind: constants.EXIT
});
span.stack = tracingUtil.getStackTrace(instrumentingOperation);
span.data.azstorage = {
containerName,
blobName,
accountName,
op
};
const promise = originalQuery.apply(ctx, argsForOriginalQuery);
if (promise && typeof promise.then === 'function') {
promise
.then(value => {
finishSpan(null, span);
return value;
})
.catch(error => {
finishSpan(error, span);
return error;
});
}
return promise;
});
}
function finishSpan(error, span) {
if (error) {
span.ec = 1;
tracingUtil.setErrorDetails(span, error, 'azstorage');
}
span.d = Date.now() - span.ts;
span.transmit();
}
exports.activate = function activate() {
isActive = true;
};
exports.deactivate = function deactivate() {
isActive = false;
};