/// <summary> /// Wait for the given number of metric requests to appear. /// </summary> /// <param name="count">The expected number of metric requests.</param> /// <param name="timeout">The timeout</param> /// <returns>The list of metric requests.</returns> public IImmutableList <ExportMetricsServiceRequest> WaitForMetrics( int count, TimeSpan?timeout = null) { timeout ??= DefaultWaitTimeout; var deadline = DateTime.Now.Add(timeout.Value); IImmutableList <ExportMetricsServiceRequest> relevantMetricRequests = ImmutableList <ExportMetricsServiceRequest> .Empty; while (DateTime.Now < deadline) { relevantMetricRequests = MetricsMessages .Where(m => MetricFilters.All(shouldReturn => shouldReturn(m))) .ToImmutableList(); if (relevantMetricRequests.Count >= count) { break; } Thread.Sleep(500); } return(relevantMetricRequests); }
private void HandleHttpRequests() { while (_listener.IsListening) { try { var ctx = _listener.GetContext(); OnRequestReceived(ctx); if (ctx.Request.RawUrl.Equals("/healthz", StringComparison.OrdinalIgnoreCase)) { CreateHealthResponse(ctx); continue; } if (ctx.Request.RawUrl.Equals("/v1/metrics", StringComparison.OrdinalIgnoreCase)) { if (ShouldDeserializeMetrics) { var metricsMessage = ExportMetricsServiceRequest.Parser.ParseFrom(ctx.Request.InputStream); OnRequestDeserialized(metricsMessage); lock (this) { // we only need to lock when replacing the metric collection, // not when reading it because it is immutable MetricsMessages = MetricsMessages.Add(metricsMessage); RequestHeaders = RequestHeaders.Add(new NameValueCollection(ctx.Request.Headers)); } } // NOTE: HttpStreamRequest doesn't support Transfer-Encoding: Chunked // (Setting content-length avoids that) ctx.Response.ContentType = "application/x-protobuf"; ctx.Response.StatusCode = (int)HttpStatusCode.OK; var responseMessage = new ExportMetricsServiceResponse(); ctx.Response.ContentLength64 = responseMessage.CalculateSize(); responseMessage.WriteTo(ctx.Response.OutputStream); ctx.Response.Close(); continue; } // We received an unsupported request ctx.Response.StatusCode = (int)HttpStatusCode.NotImplemented; ctx.Response.Close(); } catch (HttpListenerException) { // listener was stopped, // ignore to let the loop end and the method return } catch (ObjectDisposedException) { // the response has been already disposed. } catch (InvalidOperationException) { // this can occur when setting Response.ContentLength64, with the framework claiming that the response has already been submitted // for now ignore, and we'll see if this introduces downstream issues } catch (Exception) when(!_listener.IsListening) { // we don't care about any exception when listener is stopped } } }