Exemple #1
0
        /// <summary>
        /// Try to send the given message. On failure, reset and try again.
        /// If that fails, just rethrow the exception.
        /// </summary>
        /// <param name="message">The message to be sent to the Wavefront proxy.</param>
        public async Task WriteAsync(string message)
        {
            var bytes = Encoding.UTF8.GetBytes(message);

            try
            {
                // Might be NPE due to previously failed call to ResetSocket.
                await socketOutputStream.WriteAsync(bytes, 0, bytes.Length);

                writeSuccesses.Inc();
            }
            catch (Exception e)
            {
                try
                {
                    logger.LogWarning(0, e, "Attempting to reset socket connection.");
                    await ResetSocketAsync();

                    await socketOutputStream.WriteAsync(bytes, 0, bytes.Length);

                    writeSuccesses.Inc();
                }
                catch (Exception e2)
                {
                    writeErrors.Inc();
                    throw new IOException(e2.Message, e2);
                }
            }
        }
        /// <see cref="IWavefrontTracingSpanSender.SendSpan"/>
        public void SendSpan(string name, long startMillis, long durationMillis, string source,
                             Guid traceId, Guid spanId, IList <Guid> parents,
                             IList <Guid> followsFrom, IList <KeyValuePair <string, string> > tags,
                             IList <SpanLog> spanLogs)
        {
            if (tracingProxyConnectionHandler == null)
            {
                spansDiscarded.Inc();
                if (spanLogs != null && spanLogs.Count > 0)
                {
                    spanLogsDiscarded.Inc();
                }
                logger.LogWarning("Can't send data to Wavefront. " +
                                  "Please configure histogram distribution port for Wavefront proxy.");
                return;
            }

            string lineData;

            try
            {
                lineData = Utils.TracingSpanToLineData(name, startMillis,
                                                       durationMillis, source, traceId, spanId, parents, followsFrom, tags, spanLogs,
                                                       defaultSource);
                spansValid.Inc();
            }
            catch (ArgumentException e)
            {
                spansInvalid.Inc();
                throw e;
            }

            _ = tracingProxyConnectionHandler.SendDataAsync(lineData).ContinueWith(
                task =>
            {
                if (task.Exception == null)
                {
                    // Send valid span logs only if the span was successfully sent
                    if (spanLogs != null && spanLogs.Count > 0)
                    {
                        SendSpanLogs(traceId, spanId, spanLogs, lineData);
                    }
                }
                else
                {
                    spansDropped.Inc();
                    if (spanLogs != null && spanLogs.Count > 0)
                    {
                        spanLogsDropped.Inc();
                    }
                    tracingProxyConnectionHandler.IncrementFailureCount();
                }
            });
        }
        /// <see cref="IWavefrontHistogramSender.SendDistribution"/>
        public void SendDistribution(string name, IList <KeyValuePair <double, int> > centroids,
                                     ISet <HistogramGranularity> histogramGranularities,
                                     long?timestamp, string source,
                                     IDictionary <string, string> tags)
        {
            if (histogramProxyConnectionHandler == null)
            {
                histogramsDiscarded.Inc();
                logger.LogWarning("Can't send data to Wavefront. " +
                                  "Please configure histogram distribution port for Wavefront proxy.");
                return;
            }

            string lineData;

            try
            {
                lineData = Utils.HistogramToLineData(name, centroids, histogramGranularities,
                                                     timestamp, source, tags, defaultSource);
                histogramsValid.Inc();
            }
            catch (ArgumentException e)
            {
                histogramsInvalid.Inc();
                throw e;
            }

            _ = histogramProxyConnectionHandler.SendDataAsync(lineData).ContinueWith(
                task =>
            {
                histogramsDropped.Inc();
                histogramProxyConnectionHandler.IncrementFailureCount();
            }, TaskContinuationOptions.OnlyOnFaulted);
        }
        /// <see cref="Entities.Metrics.IWavefrontMetricSender.SendMetric"/>
        public void SendMetric(string name, double value, long?timestamp, string source,
                               IDictionary <string, string> tags)
        {
            if (metricsProxyConnectionHandler == null)
            {
                pointsDiscarded.Inc();
                logger.LogWarning("Can't send data to Wavefront. " +
                                  "Please configure metrics port for Wavefront proxy.");
                return;
            }

            string lineData;

            try
            {
                lineData = Utils.MetricToLineData(name, value, timestamp, source, tags,
                                                  defaultSource);
                pointsValid.Inc();
            }
            catch (ArgumentException e)
            {
                pointsInvalid.Inc();
                throw e;
            }

            _ = metricsProxyConnectionHandler.SendDataAsync(lineData).ContinueWith(
                task =>
            {
                pointsDropped.Inc();
                metricsProxyConnectionHandler.IncrementFailureCount();
            }, TaskContinuationOptions.OnlyOnFaulted);
        }
        private void Send(WavefrontSpan span)
        {
            try
            {
                var context          = (WavefrontSpanContext)span.Context;
                var parentReferences = span.GetParents();
                var followReferences = span.GetFollows();

                var parents = parentReferences?
                              .Select(parent => parent.SpanContext.GetSpanId())
                              .ToList();

                var follows = followReferences?
                              .Select(follow => follow.SpanContext.GetSpanId())
                              .ToList();

                WavefrontSender.SendSpan(
                    span.GetOperationName(), span.GetStartTimeMicros() / 1000,
                    span.GetDurationMicros() / 1000, Source, context.GetTraceId(),
                    context.GetSpanId(), parents, follows, span.GetTagsAsList().ToList(),
                    reportSpanLogs ? span.GetSpanLogs().ToList() : null
                    );
            }
            catch (IOException e)
            {
                if (LoggingAllowed())
                {
                    logger.LogWarning(0, e, "Error reporting span: " + span);
                }
                spansDropped?.Inc();
                reportErrors?.Inc();
            }
        }
 /// <inheritdoc />
 public void Report(WavefrontSpan span)
 {
     spansReceived?.Inc();
     if (!spanBuffer.TryAdd(span))
     {
         spansDropped?.Inc();
         if (LoggingAllowed())
         {
             logger.LogWarning("Buffer full, dropping span: " + span);
             if (spansDropped != null)
             {
                 logger.LogWarning("Total spans dropped: " + spansDropped.Count);
             }
         }
     }
 }
        /// <see cref="IWavefrontHistogramSender.SendDistribution"/>
        public void SendDistribution(string name,
                                     IList <KeyValuePair <double, int> > centroids,
                                     ISet <HistogramGranularity> histogramGranularities,
                                     long?timestamp,
                                     string source,
                                     IDictionary <string, string> tags)
        {
            string lineData;

            try
            {
                lineData = Utils.HistogramToLineData(name, centroids, histogramGranularities,
                                                     timestamp, source, tags, DefaultSource);
                histogramsValid.Inc();
            }
            catch (ArgumentException e)
            {
                histogramsInvalid.Inc();
                throw e;
            }

            if (!histogramsBuffer.TryAdd(lineData))
            {
                histogramsDropped.Inc();
                logger.LogWarning("Buffer full, dropping histograms: " + lineData);
            }
        }
        /// <see cref="IWavefrontTracingSpanSender.SendSpan"/>
        public void SendSpan(string name, long startMillis, long durationMillis, string source,
                             Guid traceId, Guid spanId, IList <Guid> parents,
                             IList <Guid> followsFrom, IList <KeyValuePair <string, string> > tags,
                             IList <SpanLog> spanLogs)
        {
            string lineData;

            try
            {
                lineData = Utils.TracingSpanToLineData(name, startMillis,
                                                       durationMillis, source, traceId, spanId, parents, followsFrom, tags, spanLogs,
                                                       DefaultSource);
                spansValid.Inc();
            }
            catch (ArgumentException e)
            {
                spansInvalid.Inc();
                throw e;
            }

            if (tracingSpansBuffer.TryAdd(lineData))
            {
                // Enqueue span logs for sending only if the span was successfully enqueued
                if (spanLogs != null && spanLogs.Count > 0)
                {
                    SendSpanLogs(traceId, spanId, spanLogs, lineData);
                }
            }
            else
            {
                spansDropped.Inc();
                if (spanLogs != null && spanLogs.Count > 0)
                {
                    spanLogsDropped.Inc();
                }
                logger.LogWarning("Buffer full, dropping span: " + lineData);
            }
        }
Exemple #9
0
        /// <summary>
        /// Flushes the outputStream best-effort. If that fails, we reset the connection.
        /// </summary>
        public async Task FlushAsync()
        {
            try
            {
                await socketOutputStream.FlushAsync();

                flushSuccesses.Inc();
            }
            catch (Exception e)
            {
                flushErrors.Inc();
                logger.LogWarning(0, e, "Attempting to reset socket connection.");
                await ResetSocketAsync();
            }
        }
Exemple #10
0
 public void Connect()
 {
     if (reconnectingSocket != null)
     {
         throw new InvalidOperationException("Already connected");
     }
     try
     {
         reconnectingSocket = new ReconnectingSocket(host, port, sdkMetricsRegistry,
                                                     entityPrefix + "socket", loggerFactory);
     }
     catch (Exception e)
     {
         connectErrors.Inc();
         throw new IOException(e.Message, e);
     }
 }
 private void SendSpanLogs(Guid traceId, Guid spanId, IList <SpanLog> spanLogs, string span)
 {
     try
     {
         string lineData = Utils.SpanLogsToLineData(traceId, spanId, spanLogs, span);
         spanLogsValid.Inc();
         if (!spanLogsBuffer.TryAdd(lineData))
         {
             spanLogsDropped.Inc();
             logger.LogWarning("Buffer full, dropping span logs: " + lineData);
         }
     }
     catch (Exception)
     {
         spanLogsInvalid.Inc();
         logger.LogWarning($"Unable to serialize span logs to json: traceId:{traceId}" +
                           $" spanId:{spanId} spanLogs:{spanLogs}");
     }
 }
Exemple #12
0
        /// <summary>
        ///     Flushes the current metrics snapshot in Wavefront data format.
        /// </summary>
        /// <param name="metricsData">The current snapshot of metrics.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>True if metrics were successfully flushed, false otherwise.</returns>
        public async Task <bool> FlushAsync(
            MetricsDataValueSource metricsData,
            CancellationToken cancellationToken = default)
        {
            Logger.Trace("Flushing metrics snapshot");

            try
            {
                await WriteAsync(metricsData, cancellationToken);
            }
            catch (Exception e)
            {
                reporterErrors.Inc();
                Logger.Error(e.Message);
                return(false);
            }

            Logger.Trace("Flushed metrics snapshot");
            return(true);
        }
 private void SendSpanLogs(Guid traceId, Guid spanId, IList <SpanLog> spanLogs, string span)
 {
     try
     {
         string lineData = Utils.SpanLogsToLineData(traceId, spanId, spanLogs, span);
         spanLogsValid.Inc();
         _ = tracingProxyConnectionHandler.SendDataAsync(lineData).ContinueWith(
             task =>
         {
             spanLogsDropped.Inc();
             tracingProxyConnectionHandler.IncrementFailureCount();
         }, TaskContinuationOptions.OnlyOnFaulted);
     }
     catch (Exception)
     {
         spanLogsInvalid.Inc();
         logger.LogWarning($"Unable to serialize span logs to json: traceId:{traceId}" +
                           $" spanId:{spanId} spanLogs:{spanLogs}");
     }
 }
        /// <see cref="Entities.Metrics.IWavefrontMetricSender.SendMetric"/>
        public void SendMetric(string name, double value, long?timestamp, string source,
                               IDictionary <string, string> tags)
        {
            string lineData;

            try
            {
                lineData = Utils.MetricToLineData(name, value, timestamp, source, tags,
                                                  DefaultSource);
                pointsValid.Inc();
            }
            catch (ArgumentException e)
            {
                pointsInvalid.Inc();
                throw e;
            }


            if (!metricsBuffer.TryAdd(lineData))
            {
                pointsDropped.Inc();
                logger.LogWarning("Buffer full, dropping metric point: " + lineData);
            }
        }
        /// <inheritdoc />
        public void Write(string context, string name, IEnumerable <string> columns,
                          IEnumerable <object> values, MetricTags tags, DateTime timestamp)
        {
            // Do not report App Metrics' internal metrics (e.g., report_success counter)
            if (context == InternalMetricsContext)
            {
                return;
            }

            try
            {
                string metricTypeValue =
                    tags.Values[Array.IndexOf(tags.Keys, Pack.MetricTagsTypeKey)];
                var data = columns.Zip(values, (column, value) => new { column, value })
                           .ToDictionary(pair => pair.column, pair => pair.value);

                if (metricTypeValue == Pack.ApdexMetricTypeValue)
                {
                    WriteApdex(context, name, data, tags, timestamp);
                    apdexesReported.Inc();
                }
                else if (metricTypeValue == Pack.CounterMetricTypeValue)
                {
                    WriteCounter(context, name, data, tags, timestamp);
                    if (DeltaCounterOptions.IsDeltaCounter(tags))
                    {
                        deltaCountersReported.Inc();
                    }
                    else
                    {
                        countersReported.Inc();
                    }
                }
                else if (metricTypeValue == Pack.GaugeMetricTypeValue)
                {
                    WriteGauge(context, name, data, tags, timestamp);
                    gaugesReported.Inc();
                }
                else if (metricTypeValue == Pack.HistogramMetricTypeValue)
                {
                    WriteHistogram(context, name, data, tags, timestamp);
                    if (WavefrontHistogramOptions.IsWavefrontHistogram(tags))
                    {
                        wfHistogramsReported.Inc();
                    }
                    else
                    {
                        histogramsReported.Inc();
                    }
                }
                else if (metricTypeValue == Pack.MeterMetricTypeValue)
                {
                    WriteMeter(context, name, data, tags, timestamp);
                    metersReported.Inc();
                }
                else if (metricTypeValue == Pack.TimerMetricTypeValue)
                {
                    WriteMeter(context, name, data, tags, timestamp);
                    WriteHistogram(context, name, data, tags, timestamp);
                    timersReported.Inc();
                }
            }
            catch (Exception e)
            {
                writerErrors.Inc();
                throw e;
            }
        }
        private void InternalFlush(BlockingCollection <string> buffer, string format,
                                   string entityPrefix, WavefrontSdkDeltaCounter dropped, WavefrontSdkDeltaCounter reportErrors)
        {
            var batch = GetBatch(buffer);

            if (batch.Count == 0)
            {
                return;
            }

            try
            {
                using (var stream = BatchToStream(batch))
                {
                    int statusCode = directService.Report(format, stream);
                    sdkMetricsRegistry.DeltaCounter(entityPrefix + ".report." + statusCode).Inc();
                    if ((statusCode >= 400 && statusCode < 600) || statusCode == Constants.HttpNoResponse)
                    {
                        switch (statusCode)
                        {
                        case 401:
                            logger.LogWarning("Error sending " + entityPrefix + " to Wavefront (HTTP " + statusCode + "). " +
                                              "Please verify that your API Token is correct! All " + entityPrefix + " are " +
                                              "discarded.");
                            dropped.Inc(batch.Count);
                            break;

                        case 403:
                            if (format.Equals(Constants.WavefrontMetricFormat))
                            {
                                logger.LogWarning("Error sending " + entityPrefix + " to Wavefront (HTTP " + statusCode + "). " +
                                                  "Please verify that Direct Data Ingestion is enabled for your account! " +
                                                  "All " + entityPrefix + " are discarded.");
                            }
                            else
                            {
                                logger.LogWarning("Error sending " + entityPrefix + " to Wavefront (HTTP " + statusCode + "). " +
                                                  "Please verify that Direct Data Ingestion and " + entityPrefix + " are " +
                                                  "enabled for your account! All " + entityPrefix + " are discarded.");
                            }
                            dropped.Inc(batch.Count);
                            break;

                        default:
                            logger.LogWarning("Error sending " + entityPrefix + " to Wavefront (HTTP " + statusCode + "). Data " +
                                              "will be requeued and resent.");
                            int numAddedBackToBuffer = 0;
                            foreach (var item in batch)
                            {
                                if (buffer.TryAdd(item))
                                {
                                    numAddedBackToBuffer++;
                                }
                                else
                                {
                                    int numDropped = batch.Count - numAddedBackToBuffer;
                                    dropped.Inc(numDropped);
                                    logger.LogWarning("Buffer full, dropping " + numDropped + " " + entityPrefix + ". Consider increasing " +
                                                      "the batch size of your sender to increase throughput.");
                                    break;
                                }
                            }
                            break;
                        }
                    }
                }
            }
            catch (IOException e) {
                dropped.Inc(batch.Count);
                reportErrors.Inc();
                throw e;
            }
        }
Exemple #17
0
        private async Task ConnectAsync(bool isReset)
        {
            if (!await connectSemaphore.WaitAsync(TimeSpan.Zero))
            {
                // skip if another thread is already attempting to connect
                return;
            }

            try
            {
                if (isReset)
                {
                    // Close the outputStream and connection
                    try
                    {
                        socketOutputStream?.Close();
                    }
                    catch (IOException e)
                    {
                        logger.LogInformation(0, e, "Could not flush and close socket.");
                    }
                    client.Close();
                    client = new TcpClient
                    {
                        ReceiveTimeout = serverReadTimeoutMillis
                    };
                }

                // Open a connection and instantiate the outputStream
                try
                {
                    var connectTask   = client.ConnectAsync(host, port);
                    var timeoutTask   = Task.Delay(serverConnectTimeoutMillis);
                    var completedTask = await Task.WhenAny(connectTask, timeoutTask);

                    if (completedTask == connectTask)
                    {
                        socketOutputStream =
                            Stream.Synchronized(new BufferedStream(client.GetStream(), bufferSize));
                        if (isReset)
                        {
                            resetSuccesses.Inc();
                        }
                        logger.LogInformation(
                            string.Format("Successfully connected to {0}:{1}", host, port));
                    }
                    else
                    {
                        logger.LogWarning(string.Format("Unable to connect to {0}:{1}", host, port));
                        client.Close();
                    }
                }
                catch (Exception e)
                {
                    if (isReset)
                    {
                        resetErrors.Inc();
                    }
                    logger.LogWarning(0, e,
                                      string.Format("Unable to connect to {0}:{1}", host, port));
                    client.Close();
                    throw new IOException(e.Message, e);
                }
            }
            finally
            {
                connectSemaphore.Release();
            }
        }
Exemple #18
0
 /// <summary>
 /// Increments the failure count by one.
 /// </summary>
 public void IncrementFailureCount()
 {
     errors.Inc();
 }