Esempio n. 1
0
    /// <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);
    }
Esempio n. 2
0
    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
            }
        }
    }