/// <summary>
        /// The cmdlet will call this for every event during the pipeline.
        /// </summary>
        /// <param name="id">a <c>string</c> containing the name of the event being raised (well-known events are in <see cref="Microsoft.Azure.Commands.Common.Events"/></param>
        /// <param name="cancellationToken">a <c>CancellationToken</c> indicating if this request is being cancelled.</param>
        /// <param name="getEventData">a delegate to call to get the event data for this event</param>
        /// <param name="signal">a delegate to signal an event from the handler to the cmdlet.</param>
        /// <param name="invocationInfo">The <see cref="System.Management.Automation.InvocationInfo" /> from the cmdlet</param>
        /// <param name="parameterSetName">The <see cref="string" /> containing the name of the parameter set for this invocation (if available></param>
        /// <param name="correlationId">The <see cref="string" /> containing the correlation id for the cmdlet (if available)</param>
        /// <param name="processRecordId">The <see cref="string" /> containing the correlation id for the individual process record. (if available)</param>
        /// <param name="exception">The <see cref="System.Exception" /> that is being thrown (if available)</param>
        public async Task EventListener(string id, CancellationToken cancellationToken, GetEventData getEventData, SignalDelegate signal, InvocationInfo invocationInfo, string parameterSetName, string correlationId, string processRecordId, System.Exception exception)
        {
            /// Drain the queue of ADAL events whenever an event is fired
            DrainMessages(signal, cancellationToken);
            switch (id)
            {
            case Events.BeforeCall:
            {
                var data    = EventDataConverter.ConvertFrom(getEventData());      // also, we manually use our TypeConverter to return an appropriate type
                var request = data?.RequestMessage as HttpRequestMessage;
                if (request != null)
                {
                    AzurePSQoSEvent qos;
                    if (_telemetryEvents.TryGetValue(processRecordId, out qos))
                    {
                        IEnumerable <string> headers;
                        if (request.Headers != null && request.Headers.TryGetValues("x-ms-client-request-id", out headers))
                        {
                            qos.ClientRequestId = headers.FirstOrDefault();
                            await signal(Events.Debug, cancellationToken,
                                         () => EventHelper.CreateLogEvent($"[{id}]: Amending QosEvent for command '{qos.CommandName}': {qos.ToString()}"));
                        }
                    }

                    /// Print formatted request message
                    await signal(Events.Debug, cancellationToken,
                                 () => EventHelper.CreateLogEvent(GeneralUtilities.GetLog(request)));
                }
            }

            break;

            case Events.CmdletProcessRecordAsyncStart:
            {
                var qos = CreateQosEvent(invocationInfo, parameterSetName, correlationId);
                await signal(Events.Debug, cancellationToken,
                             () => EventHelper.CreateLogEvent($"[{id}]: Created new QosEvent for command '{qos.CommandName}': {qos.ToString()}"));

                _telemetryEvents.Add(processRecordId, qos);
            }
            break;

            case Events.CmdletProcessRecordAsyncEnd:
            {
                AzurePSQoSEvent qos;
                if (_telemetryEvents.TryGetValue(processRecordId, out qos))
                {
                    qos.IsSuccess = qos.Exception == null;
                    await signal(Events.Debug, cancellationToken,
                                 () => EventHelper.CreateLogEvent($"[{id}]: Sending new QosEvent for command '{qos.CommandName}': {qos.ToString()}"));

                    _metricHelper.LogEvent(qos);
                    _telemetryEvents.Remove(processRecordId);
                }
            }
            break;

            case Events.CmdletException:
            {
                var data = EventDataConverter.ConvertFrom(getEventData());
                await signal(Events.Debug, cancellationToken,
                             () => EventHelper.CreateLogEvent($"[{id}]: Received Exception with message '{data?.Message}'"));

                AzurePSQoSEvent qos;
                if (_telemetryEvents.TryGetValue(processRecordId, out qos))
                {
                    await signal(Events.Debug, cancellationToken,
                                 () => EventHelper.CreateLogEvent($"[{id}]: Sending new QosEvent for command '{qos.CommandName}': {qos.ToString()}"));

                    qos.IsSuccess = false;
                    qos.Exception = exception;
                    _metricHelper.LogEvent(qos);
                    _telemetryEvents.Remove(processRecordId);
                }
            }

            break;

            case Events.ResponseCreated:
            {
                var data     = EventDataConverter.ConvertFrom(getEventData());
                var response = data?.ResponseMessage as HttpResponseMessage;
                if (response != null)
                {
                    AzurePSQoSEvent qos;
                    if (_telemetryEvents.TryGetValue(processRecordId, out qos))
                    {
                        qos.ClientRequestId = response?.Headers?.GetValues("x-ms-request-id").FirstOrDefault();
                    }

                    /// Print formatted response message
                    await signal(Events.Debug, cancellationToken,
                                 () => EventHelper.CreateLogEvent(GeneralUtilities.GetLog(response)));
                }
            }

            break;

            default:
                getEventData.Print(signal, cancellationToken, Events.Information, id);
                break;
            }
        }