Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,25 @@ import { V4Connect, V4Session } from './internal-types';
import { PACKAGE_NAME, PACKAGE_VERSION } from './version';
import { UpDownCounter } from '@opentelemetry/api';

// Skipping mongoose-added `non-enumerable` properties
// https://github.com/Automattic/mongoose/blob/b34aba65bd64540e330665477f542eb79c877909/lib/helpers/document/compile.js#L217C11-L228C6
// These properties are added by mongoose and supposed to be non-enumerable
// but they are enumerable in some versions of mongoose.
// These properties have made non-enumerable from [email protected]
// https://github.com/Automattic/mongoose/commit/62b7b9c07ad3c763d5e42714ee149c28412db79e
const KEYS_TO_SKIP_SCRUBBING = [
'isNew',
'$__',
'$errors',
'errors',
'_doc',
'$locals',
'$op',
'__parentArray',
'__index',
'$isDocumentArrayElement',
];

/** mongodb instrumentation plugin for OpenTelemetry */
export class MongoDBInstrumentation extends InstrumentationBase<MongoDBInstrumentationConfig> {
private _connectionsUsage!: UpDownCounter;
Expand Down Expand Up @@ -932,17 +951,29 @@ export class MongoDBInstrumentation extends InstrumentationBase<MongoDBInstrumen
return JSON.stringify(resultObj);
}

private _scrubStatement(value: unknown): unknown {
private _scrubStatement(value: unknown, depth = 0): unknown {
if (depth >= 10) {
return 'Max Depth';
}

if (value instanceof Uint8Array || value instanceof Buffer) {
return 'Binary Data';
}

if (Array.isArray(value)) {
return value.map(element => this._scrubStatement(element));
return value.map(element => this._scrubStatement(element, depth + 1));
}

if (typeof value === 'object' && value !== null) {
return Object.fromEntries(
Object.entries(value).map(([key, element]) => [
key,
this._scrubStatement(element),
])
Object.entries(value)
.filter(([key]) => {
return !KEYS_TO_SKIP_SCRUBBING.includes(key);
})
.map(([key, element]) => [
key,
this._scrubStatement(element, depth + 1),
])
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,81 @@ describe('MongoDBInstrumentation-Tracing-v5', () => {
});
});
});

it('should skip `Buffer` and `Uint8Array` values', done => {
const buffer = Buffer.from('buffer');
const uint8Array = new Uint8Array([1, 2, 3, 4]);
const span = trace.getTracer('default').startSpan('insertRootSpan');
context.with(trace.setSpan(context.active(), span), () => {
collection
.insertOne({ buffer, uint8Array })
.then(() => {
span.end();
const spans = getTestSpans();
const operationName = 'mongodb.insert';
assertSpans(
spans,
operationName,
SpanKind.CLIENT,
'insert',
URL,
false,
false
);
const mongoSpan = spans.find(s => s.name === operationName);
const dbStatement = JSON.parse(
mongoSpan!.attributes[SEMATTRS_DB_STATEMENT] as string
);
assert.strictEqual(dbStatement.buffer, 'Binary Data');
assert.strictEqual(dbStatement.uint8Array, 'Binary Data');
done();
})
.catch(err => {
done(err);
});
});
});

it('should skip nested levels of objects over the limit of 10', done => {
const deeplyNestedObject = {
a: {
b: { c: { d: { e: { f: { g: { h: { i: { j: { k: 1 } } } } } } } } },
},
};

const span = trace.getTracer('default').startSpan('insertRootSpan');
context.with(trace.setSpan(context.active(), span), () => {
collection
.insertOne({ deeplyNestedObject })
.then(() => {
span.end();
const spans = getTestSpans();
const operationName = 'mongodb.insert';
assertSpans(
spans,
operationName,
SpanKind.CLIENT,
'insert',
URL,
false,
false
);
const mongoSpan = spans.find(s => s.name === operationName);
const dbStatement = JSON.parse(
mongoSpan!.attributes[SEMATTRS_DB_STATEMENT] as string
);
assert.deepStrictEqual(dbStatement.deeplyNestedObject, {
a: {
b: { c: { d: { e: { f: { g: { h: { i: 'Max Depth' } } } } } } },
},
});
done();
})
.catch(err => {
done(err);
});
});
});
});

describe('when specifying a dbStatementSerializer configuration', () => {
Expand Down
Loading