opentelemetry-instrumentation-neo4j
Version:
open telemetry instrumentation for the `neo4j` javascript driver
93 lines • 5.12 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Neo4jInstrumentation = void 0;
const api_1 = require("@opentelemetry/api");
const semantic_conventions_1 = require("@opentelemetry/semantic-conventions");
const version_1 = require("./version");
const instrumentation_1 = require("@opentelemetry/instrumentation");
const utils_1 = require("./utils");
class Neo4jInstrumentation extends instrumentation_1.InstrumentationBase {
constructor(config = {}) {
super('opentelemetry-instrumentation-neo4j', version_1.VERSION, Object.assign({}, config));
}
setConfig(config = {}) {
this._config = config;
}
init() {
return [
this.getModuleDefinition('neo4j-driver-core', ['>=4.3.0 <5']),
this.getModuleDefinition('neo4j-driver', ['>=4.0.0 <4.3.0']),
];
}
getModuleDefinition(name, supportedVersions) {
const apiModuleFiles = ['session', 'transaction'].map((file) => new instrumentation_1.InstrumentationNodeModuleFile(`${name}/lib/${file}.js`, supportedVersions, this.patchSessionOrTransaction.bind(this), this.unpatchSessionOrTransaction.bind(this)));
const module = new instrumentation_1.InstrumentationNodeModuleDefinition(name, supportedVersions, undefined, undefined, apiModuleFiles);
return module;
}
patchSessionOrTransaction(fileExport, moduleVersion) {
const self = this;
this._wrap(fileExport.default.prototype, 'run', (originalRun) => {
return function (query) {
var _a;
if (((_a = self._config) === null || _a === void 0 ? void 0 : _a.ignoreOrphanedSpans) && !api_1.trace.getSpan(api_1.context.active())) {
return originalRun.apply(this, arguments);
}
const connectionAttributes = (0, utils_1.getAttributesFromNeo4jSession)(this);
const operation = query.trim().split(/\s+/)[0];
const span = self.tracer.startSpan(`${operation} ${connectionAttributes[semantic_conventions_1.SEMATTRS_DB_NAME]}`, {
attributes: Object.assign(Object.assign({}, connectionAttributes), { [semantic_conventions_1.SEMATTRS_DB_SYSTEM]: 'neo4j', [semantic_conventions_1.SEMATTRS_DB_OPERATION]: operation, [semantic_conventions_1.SEMATTRS_DB_STATEMENT]: query }),
kind: api_1.SpanKind.CLIENT,
});
if (self._config.moduleVersionAttributeName) {
span.setAttribute(self._config.moduleVersionAttributeName, moduleVersion);
}
const response = originalRun.apply(this, arguments);
const originalSubscribe = response.subscribe;
response.subscribe = function (observer) {
const records = [];
return originalSubscribe.call(this, Object.assign(Object.assign({}, observer), { onKeys: function (_keys) {
if (!observer.onKeys)
return;
if (!observer.onCompleted) {
span.end();
}
return observer.onKeys.apply(this, arguments);
}, onNext: function (record) {
if (self._config.responseHook) {
records.push(record);
}
if (observer.onNext)
return observer.onNext.apply(this, arguments);
}, onCompleted: function (summary) {
if (self._config.responseHook) {
(0, instrumentation_1.safeExecuteInTheMiddle)(() => self._config.responseHook(span, { records: records, summary }), (e) => {
if (e) {
api_1.diag.error('neo4j instrumentation: responseHook error', e);
}
}, true);
}
span.end();
if (observer.onCompleted)
return observer.onCompleted.apply(this, arguments);
}, onError: function (err) {
span.recordException(err);
span.setStatus({
code: api_1.SpanStatusCode.ERROR,
message: err.message,
});
span.end();
if (observer.onError)
return observer.onError.apply(this, arguments);
} }));
};
return response;
};
});
return fileExport;
}
unpatchSessionOrTransaction(fileExport) {
this._unwrap(fileExport.default.prototype, 'run');
}
}
exports.Neo4jInstrumentation = Neo4jInstrumentation;
//# sourceMappingURL=neo4j.js.map