@@ -90,6 +90,14 @@ interface MongoOptions {
9090  useMongoose ?: boolean ; 
9191} 
9292
93+ interface  MongoCursor  { 
94+   once ( event : 'close' ,  listener : ( )  =>  void ) : void ; 
95+ } 
96+ 
97+ function  isCursor ( maybeCursor : MongoCursor ) : maybeCursor  is MongoCursor  { 
98+   return  maybeCursor  &&  typeof  maybeCursor  ===  'object'  &&  maybeCursor . once  &&  typeof  maybeCursor . once  ===  'function' ; 
99+ } 
100+ 
93101/** Tracing integration for mongo package */ 
94102export  class  Mongo  implements  Integration  { 
95103  /** 
@@ -160,20 +168,38 @@ export class Mongo implements Integration {
160168        // its (non-callback) arguments can also be functions.) 
161169        if  ( typeof  lastArg  !==  'function'  ||  ( operation  ===  'mapReduce'  &&  args . length  ===  2 ) )  { 
162170          const  span  =  parentSpan ?. startChild ( getSpanContext ( this ,  operation ,  args ) ) ; 
163-           const  maybePromise  =  orig . call ( this ,  ...args )   as   Promise < unknown > ; 
171+           const  maybePromiseOrCursor  =  orig . call ( this ,  ...args ) ; 
164172
165-           if  ( isThenable ( maybePromise ) )  { 
166-             return  maybePromise . then ( ( res : unknown )  =>  { 
173+           if  ( isThenable ( maybePromiseOrCursor ) )  { 
174+             return  maybePromiseOrCursor . then ( ( res : unknown )  =>  { 
167175              span ?. finish ( ) ; 
168176              return  res ; 
169177            } ) ; 
178+           } 
179+           // If the operation returns a Cursor 
180+           // we need to attach a listener to it to finish the span when the cursor is closed. 
181+           else  if  ( isCursor ( maybePromiseOrCursor ) )  { 
182+             const  cursor  =  maybePromiseOrCursor  as  MongoCursor ; 
183+ 
184+             try  { 
185+               cursor . once ( 'close' ,  ( )  =>  { 
186+                 span ?. finish ( ) ; 
187+               } ) ; 
188+             }  catch  ( e )  { 
189+               // If the cursor is already closed, `once` will throw an error. In that case, we can 
190+               // finish the span immediately. 
191+               span ?. finish ( ) ; 
192+             } 
193+ 
194+             return  cursor ; 
170195          }  else  { 
171196            span ?. finish ( ) ; 
172-             return  maybePromise ; 
197+             return  maybePromiseOrCursor ; 
173198          } 
174199        } 
175200
176201        const  span  =  parentSpan ?. startChild ( getSpanContext ( this ,  operation ,  args . slice ( 0 ,  - 1 ) ) ) ; 
202+ 
177203        return  orig . call ( this ,  ...args . slice ( 0 ,  - 1 ) ,  function  ( err : Error ,  result : unknown )  { 
178204          span ?. finish ( ) ; 
179205          lastArg ( err ,  result ) ; 
0 commit comments