public void OnNext(DiagnosticListener value)
        {
            var subscribedAny = false;

            foreach (var listener in _listeners)
            {
                if (value.Name == listener.Name)
                {
                    _sourceSubscription.Add(value.Subscribe(listener));

                    _logger.Debug()
                    ?.Log("Subscribed {DiagnosticListenerType} to `{DiagnosticListenerName}' events source",
                          listener.GetType().FullName, value.Name);
                    subscribedAny = true;
                }
            }

            if (!subscribedAny)
            {
                _logger.Trace()
                ?.Log(
                    "There are no listeners in the current batch ({DiagnosticListeners}) that would like to subscribe to `{DiagnosticListenerName}' events source",
                    string.Join(", ", _listeners.Select(listener => listener.GetType().FullName)),
                    value.Name);
            }
        }
        public void OnNext(KeyValuePair <string, object> kv)
        {
            // We only print the key, we don't print the value, because it can contain a http request object, and its ToString prints
            // the URL, which can contain username and password. See: https://github.com/elastic/apm-agent-dotnet/issues/515
            Logger.Trace()?.Log("Called with key: `{DiagnosticEventKey}'", kv.Key);

            if (string.IsNullOrEmpty(kv.Key))
            {
                Logger.Trace()?.Log($"Key is {(kv.Key == null ? "null" : "an empty string")} - exiting");
                return;
            }

            if (kv.Value == null)
            {
                Logger.Trace()?.Log("Value is null - exiting");
                return;
            }

            var requestObject = kv.Value.GetType().GetTypeInfo().GetDeclaredProperty(EventRequestPropertyName)?.GetValue(kv.Value);

            if (requestObject == null)
            {
                Logger.Trace()?.Log("Event's {EventRequestPropertyName} property is null - exiting", EventRequestPropertyName);
                return;
            }

            if (!(requestObject is TRequest request))
            {
                Logger.Trace()
                ?.Log("Actual type of object ({EventRequestPropertyActualType}) in event's {EventRequestPropertyName} property " +
                      "doesn't match the expected type ({EventRequestPropertyExpectedType}) - exiting",
                      requestObject.GetType().FullName, EventRequestPropertyName, typeof(TRequest).FullName);
                return;
            }

            var requestUrl = RequestGetUri(request);

            if (requestUrl == null)
            {
                Logger.Trace()?.Log("Request URL is null - exiting", EventRequestPropertyName);
                return;
            }

            if (IsRequestFilteredOut(requestUrl))
            {
                Logger.Trace()?.Log("Request URL ({RequestUrl}) is filtered out - exiting", Http.Sanitize(requestUrl));
                return;
            }

            if (kv.Key.Equals(StartEventKey))
            {
                ProcessStartEvent(request, requestUrl);
            }
            else if (kv.Key.Equals(StopEventKey))
            {
                ProcessStopEvent(kv.Value, request, requestUrl);
            }
            else if (kv.Key.Equals(ExceptionEventKey))
            {
                ProcessExceptionEvent(kv.Value, requestUrl);
            }
            else
            {
                Logger.Trace()?.Log("Unrecognized key `{DiagnosticEventKey}'", kv.Key);
            }
        }
        public void OnNext(KeyValuePair <string, object> kv)
        {
            _logger.Trace()?.Log("Called with key: `{DiagnosticEventKey}', value: `{DiagnosticEventValue}'", kv.Key, kv.Value);

            if (string.IsNullOrEmpty(kv.Key))
            {
                _logger.Trace()?.Log($"Key is {(kv.Key == null ? "null" : "an empty string")} - exiting");
                return;
            }

            if (kv.Value == null)
            {
                _logger.Trace()?.Log("Value is null - exiting");
                return;
            }

            var requestObject = kv.Value.GetType().GetTypeInfo().GetDeclaredProperty(EventRequestPropertyName)?.GetValue(kv.Value);

            if (requestObject == null)
            {
                _logger.Trace()?.Log("Event's {EventRequestPropertyName} property is null - exiting", EventRequestPropertyName);
                return;
            }

            var request = requestObject as TRequest;

            if (request == null)
            {
                _logger.Trace()
                ?.Log("Actual type of object ({EventRequestPropertyActualType}) in event's {EventRequestPropertyName} property " +
                      "doesn't match the expected type ({EventRequestPropertyExpectedType}) - exiting",
                      requestObject.GetType().FullName, EventRequestPropertyName, typeof(TRequest).FullName);
                return;
            }

            var requestUrl = RequestGetUri(request);

            if (requestUrl == null)
            {
                _logger.Trace()?.Log("Request URL is null - exiting", EventRequestPropertyName);
                return;
            }

            if (IsRequestFilteredOut(requestUrl))
            {
                _logger.Trace()?.Log("Request URL ({RequestUrl}) is filtered out - exiting", requestUrl);
                return;
            }

            if (kv.Key.Equals(StartEventKey))
            {
                ProcessStartEvent(kv.Value, request, requestUrl);
            }
            else if (kv.Key.Equals(StopEventKey))
            {
                ProcessStopEvent(kv.Value, request, requestUrl);
            }
            else if (kv.Key.Equals(ExceptionEventKey))
            {
                ProcessExceptionEvent(kv.Value, request, requestUrl);
            }
            else
            {
                _logger.Error()?.Log("Unrecognized key `{DiagnosticEventKey}'", kv.Key);
            }
        }