diff --git a/lib/session/call-session.js b/lib/session/call-session.js index 1c2907ca..3a2e82bc 100644 --- a/lib/session/call-session.js +++ b/lib/session/call-session.js @@ -828,6 +828,10 @@ class CallSession extends Emitter { const task = this.tasks.shift(); this.logger.info(`CallSession:exec starting task #${stackNum}:${taskNum}: ${task.name}`); this._notifyTaskStatus(task, {event: 'starting'}); + // Register verbhook span wait for end + task.on('VerbHookSpanWaitForEnd', ({span}) => { + this.verbHookSpan = span; + }); try { const resources = await this._evaluatePreconditions(task); let skip = false; @@ -1035,6 +1039,7 @@ class CallSession extends Emitter { /* we started a new app on the child leg, but nothing given for parent so hang him up */ this.currentTask.kill(this); } + this._endVerbHookSpan(); } /** @@ -1306,6 +1311,7 @@ Duration=${duration} ` kill(onBackgroundGatherBargein = false) { if (this.isConfirmCallSession) this.logger.debug('CallSession:kill (ConfirmSession)'); else this.logger.info('CallSession:kill'); + this._endVerbHookSpan(); if (this.currentTask) { this.currentTask.kill(this); this.currentTask = null; @@ -1410,6 +1416,7 @@ Duration=${duration} ` switch (command) { case 'redirect': if (Array.isArray(data)) { + this._endVerbHookSpan(); const t = normalizeJambones(this.logger, data) .map((tdata) => makeTask(this.logger, tdata)); if (!queueCommand) { @@ -2073,6 +2080,13 @@ Duration=${duration} ` stopBackgroundTask(type) { this.backgroundTaskManager.stop(type); } + + _endVerbHookSpan() { + if (this.verbHookSpan) { + this.verbHookSpan.end(); + this.verbHookSpan = null; + } + } } module.exports = CallSession; diff --git a/lib/tasks/task.js b/lib/tasks/task.js index 00f0053a..41073589 100644 --- a/lib/tasks/task.js +++ b/lib/tasks/task.js @@ -162,7 +162,17 @@ class Task extends Emitter { try { const json = await this.cs.requestor.request(type, this.actionHook, params, httpHeaders); span.setAttributes({'http.statusCode': 200}); - span.end(); + const isWsConnection = this.cs.requestor instanceof WsRequestor; + if (!isWsConnection || (expectResponse && json && Array.isArray(json) && json.length)) { + span.end(); + } else { + /** we use this span to measure application response latency, + * and with websocket connections we generally get the application's response + * in a subsequent message from the far end, so we terminate the span when the + * first new set of verbs arrive after sending a transcript + * */ + this.emit('VerbHookSpanWaitForEnd', {span}); + } if (expectResponse && json && Array.isArray(json)) { const makeTask = require('./make_task'); const tasks = normalizeJambones(this.logger, json).map((tdata) => makeTask(this.logger, tdata));