(Cls: any, operation: string, operationFunc: any)
| 291 | } |
| 292 | |
| 293 | interceptOperation(Cls: any, operation: string, operationFunc: any): void { |
| 294 | const plugin = this; |
| 295 | const _original = Cls.prototype[operation]; |
| 296 | |
| 297 | if (!_original) return; |
| 298 | |
| 299 | Cls.prototype[operation] = function (...args: any[]) { |
| 300 | let span = ContextManager.currentSpan; |
| 301 | |
| 302 | // XXX: mongodb calls back into itself at this level in several places, for this reason we just do a normal call |
| 303 | // if this is detected instead of opening a new span. This should not affect secondary db calls being recorded |
| 304 | // from a cursor since this span is kept async until the cursor is closed, at which point it is stoppped. |
| 305 | |
| 306 | if ((span as any)?.mongodbInCall) |
| 307 | // mongodb has called into itself internally |
| 308 | return _original.apply(this, args); |
| 309 | |
| 310 | let host = '???'; |
| 311 | |
| 312 | try { |
| 313 | const db = this instanceof plugin.Collection ? this.s.db : this; |
| 314 | host = db.serverConfig.s.options.servers.map((s: any) => `${s.host}:${s.port}`).join(','); // will this work for non-NativeTopology? |
| 315 | } catch { |
| 316 | /* nop */ |
| 317 | } |
| 318 | |
| 319 | span = ContextManager.current.newExitSpan('MongoDB/' + operation, Component.MONGODB); |
| 320 | |
| 321 | span.start(); |
| 322 | |
| 323 | try { |
| 324 | if (span.component === Component.UNKNOWN) |
| 325 | // in case mongoose sitting on top |
| 326 | span.component = Component.MONGODB; |
| 327 | |
| 328 | span.layer = SpanLayer.DATABASE; |
| 329 | span.peer = host; |
| 330 | |
| 331 | span.tag(Tag.dbType('MongoDB')); |
| 332 | span.tag(Tag.dbInstance(`${this.s.namespace.db}`)); |
| 333 | |
| 334 | const hasCB = operationFunc.call(this, operation, span, args); |
| 335 | |
| 336 | (span as any).mongodbInCall = true; |
| 337 | let ret = _original.apply(this, args); |
| 338 | (span as any).mongodbInCall = false; |
| 339 | |
| 340 | if (!hasCB) { |
| 341 | if (plugin.hookCursorMaybe(span, ret)) { |
| 342 | // NOOP |
| 343 | } else if (ret && typeof ret.then === 'function') { |
| 344 | // generic Promise check |
| 345 | ret = wrapPromise(span, ret); |
| 346 | } else { |
| 347 | // no callback passed in and no Promise or Cursor returned, play it safe |
| 348 | span.stop(); |
| 349 | |
| 350 | return ret; |
no test coverage detected