opentelemetry-plugin-better-sqlite3
Version:
OpenTelemetry better-sqlite3 automatic instrumentation package
111 lines (110 loc) • 5.03 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.BetterSqlite3Instrumentation = void 0;
const api_1 = require("@opentelemetry/api");
const instrumentation_1 = require("@opentelemetry/instrumentation");
const semantic_conventions_1 = require("@opentelemetry/semantic-conventions");
const supportedVersions = ['^7.0.0', '^8.0.0', '^9.0.0', '^10.0.0', '^11.0.0', '^12.0.0'];
class BetterSqlite3Instrumentation extends instrumentation_1.InstrumentationBase {
static COMPONENT = 'better-sqlite3';
constructor(config) {
super('opentelemetry-instrumentation-better-sqlite3', '1.0.0', config ?? {});
}
init() {
return [
new instrumentation_1.InstrumentationNodeModuleDefinition('better-sqlite3', supportedVersions, (moduleExports, moduleVersion) => {
api_1.diag.debug(`Applying patch for better-sqlite3@${moduleVersion}`);
const proto = 'prototype' in moduleExports
? moduleExports.prototype
: moduleExports.default.prototype;
if (!(0, instrumentation_1.isWrapped)(proto.exec)) {
this._wrap(proto, 'exec', this.patchExec);
this._wrap(proto, 'prepare', this.patchPrepare);
this._wrap(proto, 'pragma', this.patchPragma);
}
return moduleExports;
}, (moduleExports, moduleVersion) => {
if (moduleExports !== undefined) {
api_1.diag.debug(`Removing patch for better-sqlite3@${moduleVersion}`);
const proto = 'prototype' in moduleExports
? moduleExports.prototype
: moduleExports.default.prototype;
this._massUnwrap([proto], ['exec', 'prepare', 'pragma']);
}
}),
];
}
createSpan(query, db, operation) {
const statement = query.trim().split(/\s/u)[0];
const spanName = operation ? `${operation}: ${statement}` : statement;
return this.tracer.startSpan(spanName, {
kind: api_1.SpanKind.CLIENT,
attributes: {
[semantic_conventions_1.ATTR_DB_SYSTEM_NAME]: 'sqlite3',
[semantic_conventions_1.ATTR_DB_QUERY_TEXT]: query,
[semantic_conventions_1.ATTR_DB_NAMESPACE]: db.name,
},
});
}
static defaultRunner(span, original, this_, params) {
try {
const result = original.apply(this_, params);
span.setStatus({ code: api_1.SpanStatusCode.OK });
return result;
}
catch (e) {
span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: e.message });
throw e;
}
finally {
span.end();
}
}
patchExec = (original) => {
const self = this;
return function exec(...params) {
const span = self.createSpan(params[0], this);
return api_1.context.with(api_1.trace.setSpan(api_1.context.active(), span), () => BetterSqlite3Instrumentation.defaultRunner(span, original, this, params));
};
};
patchPrepare = (original) => {
const self = this;
return function prepare(...params) {
const span = self.createSpan(params[0], this, 'prepare');
return api_1.context.with(api_1.trace.setSpan(api_1.context.active(), span), () => {
try {
const result = original.apply(this, params);
span.setStatus({ code: api_1.SpanStatusCode.OK });
self._massWrap([result], ['run', 'get', 'all'], self.patchStatement);
return result;
}
catch (e) {
span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: e.message });
throw e;
}
finally {
span.end();
}
});
};
};
patchPragma = (original) => {
const self = this;
return function pragma(...params) {
const span = self.createSpan(`PRAGMA ${params[0]}`, this);
return api_1.context.with(api_1.trace.setSpan(api_1.context.active(), span), () => BetterSqlite3Instrumentation.defaultRunner(span, original, this, params));
};
};
patchStatement = (original) => {
const self = this;
return function statement_handler(...params) {
if (!self.isEnabled()) {
self._unwrap(this, original.name);
return original.apply(this, params);
}
const span = self.createSpan(this.source, this.database, original.name);
return api_1.context.with(api_1.trace.setSpan(api_1.context.active(), span), () => BetterSqlite3Instrumentation.defaultRunner(span, original, this, params));
};
};
}
exports.BetterSqlite3Instrumentation = BetterSqlite3Instrumentation;