@@ -978,6 +978,136 @@ channels.asyncStart.bindStore(myStore, (data) => {
978978});
979979```
980980
981+ #### ` tracingChannel.traceIterator(fn[, context[, thisArg[, ...args]]]) `
982+
983+ <!-- YAML
984+ added: REPLACEME
985+ -->
986+
987+ * ` fn ` {Function} Iterator or async iterator returning function to wrap a trace
988+ around
989+ * ` context ` {Object} Shared object to correlate trace events through
990+ * ` thisArg ` {any} The receiver to be used for the function call
991+ * ` ...args ` {any} Optional arguments to pass to the function
992+ * Returns: {Iterator|AsyncIterator|Promise} The iterator returned by the given
993+ function, or a {Promise} resolving to it if the function is async
994+
995+ Trace an iterator-returning function call. This will always produce a
996+ [ ` start ` event] [ ] and [ ` end ` event] [ ] around the synchronous portion of the
997+ function execution. If the given function returns a promise (i.e. is an async
998+ function), it will additionally produce an [ ` asyncStart ` event] [ ] and
999+ [ ` asyncEnd ` event] [ ] when the promise resolves to the iterator.
1000+
1001+ Each call to ` next() ` , ` return() ` , or ` throw() ` on the returned iterator is
1002+ also traced via a sub-channel derived from the tracing channel name by appending
1003+ ` :next ` . For example, if the tracing channel is named ` my-channel ` , the
1004+ sub-channel will be ` my-channel:next ` . These calls follow the same event
1005+ pattern as the outer function call: [ ` start ` event] [ ] and [ ` end ` event] [ ] for
1006+ synchronous results, plus [ ` asyncStart ` event] [ ] and [ ` asyncEnd ` event] [ ] if
1007+ the method returns a promise (e.g. when iterating an async iterator). An
1008+ [ ` error ` event] [ ] is produced if ` next() ` throws or the iterator method rejects.
1009+
1010+ To ensure only correct trace graphs are formed, events will only be published
1011+ if subscribers are present prior to starting the trace. Subscriptions which are
1012+ added after the trace begins will not receive future events from that trace,
1013+ only future traces will be seen.
1014+
1015+ ``` mjs
1016+ import diagnostics_channel from ' node:diagnostics_channel' ;
1017+
1018+ const channels = diagnostics_channel .tracingChannel (' my-channel' );
1019+
1020+ // Sync function returning a sync iterator.
1021+ // Fires start/end on 'my-channel'; fires start/end on 'my-channel:next'
1022+ // for each next() call.
1023+ for (const value of channels .traceIterator (function * () {
1024+ yield 1 ;
1025+ yield 2 ;
1026+ }, { some: ' thing' })) {
1027+ // consume values
1028+ }
1029+
1030+ // Sync call to an async generator function, returning an AsyncIterator.
1031+ // Fires start/end on 'my-channel'; fires start/end/asyncStart/asyncEnd on
1032+ // 'my-channel:next' for each next() call because next() returns a Promise.
1033+ for await (const value of channels .traceIterator (async function * () {
1034+ yield 1 ;
1035+ yield 2 ;
1036+ }, { some: ' thing' })) {
1037+ // consume values
1038+ }
1039+
1040+ // Async function returning a sync iterator.
1041+ // Fires start/end/asyncStart/asyncEnd on 'my-channel' when the Promise
1042+ // resolves; fires start/end on 'my-channel:next' for each next() call.
1043+ const iter = await channels .traceIterator (async function () {
1044+ return [1 , 2 ].values ();
1045+ }, { some: ' thing' });
1046+ for (const value of iter) {
1047+ // consume values
1048+ }
1049+
1050+ // Async function returning an async iterator.
1051+ // Fires start/end/asyncStart/asyncEnd on 'my-channel' when the Promise
1052+ // resolves; fires start/end/asyncStart/asyncEnd on 'my-channel:next' for each
1053+ // next() call.
1054+ const asyncIter = await channels .traceIterator (async function () {
1055+ return (async function * () { yield 1 ; yield 2 ; })();
1056+ }, { some: ' thing' });
1057+ for await (const value of asyncIter ) {
1058+ // consume values
1059+ }
1060+ ```
1061+
1062+ ``` cjs
1063+ const diagnostics_channel = require (' node:diagnostics_channel' );
1064+
1065+ const channels = diagnostics_channel .tracingChannel (' my-channel' );
1066+
1067+ // Sync function returning a sync iterator.
1068+ // Fires start/end on 'my-channel'; fires start/end on 'my-channel:next'
1069+ // for each next() call.
1070+ for (const value of channels .traceIterator (function * () {
1071+ yield 1 ;
1072+ yield 2 ;
1073+ }, { some: ' thing' })) {
1074+ // consume values
1075+ }
1076+
1077+ (async () => {
1078+ // Sync call to an async generator function, returning an AsyncIterator.
1079+ // Fires start/end on 'my-channel'; fires start/end/asyncStart/asyncEnd on
1080+ // 'my-channel:next' for each next() call because next() returns a Promise.
1081+ for await (const value of channels .traceIterator (async function * () {
1082+ yield 1 ;
1083+ yield 2 ;
1084+ }, { some: ' thing' })) {
1085+ // consume values
1086+ }
1087+
1088+ // Async function returning a sync iterator.
1089+ // Fires start/end/asyncStart/asyncEnd on 'my-channel' when the Promise
1090+ // resolves; fires start/end on 'my-channel:next' for each next() call.
1091+ const iter = await channels .traceIterator (async function () {
1092+ return [1 , 2 ].values ();
1093+ }, { some: ' thing' });
1094+ for (const value of iter) {
1095+ // consume values
1096+ }
1097+
1098+ // Async function returning an async iterator.
1099+ // Fires start/end/asyncStart/asyncEnd on 'my-channel' when the Promise
1100+ // resolves; fires start/end/asyncStart/asyncEnd on 'my-channel:next' for
1101+ // each next() call.
1102+ const asyncIter = await channels .traceIterator (async function () {
1103+ return (async function * () { yield 1 ; yield 2 ; })();
1104+ }, { some: ' thing' });
1105+ for await (const value of asyncIter ) {
1106+ // consume values
1107+ }
1108+ })();
1109+ ```
1110+
9811111#### ` tracingChannel.hasSubscribers `
9821112
9831113<!-- YAML
0 commit comments