Example #1
0
        internal void Update(long number)
        {
            switch (this.aggType)
            {
            case AggregationType.LongSumIncomingDelta:
            {
                Interlocked.Add(ref this.runningValue.AsLong, number);
                break;
            }

            case AggregationType.LongSumIncomingCumulative:
            {
                Interlocked.Exchange(ref this.runningValue.AsLong, number);
                break;
            }

            case AggregationType.LongGauge:
            {
                Interlocked.Exchange(ref this.runningValue.AsLong, number);
                break;
            }

            case AggregationType.Histogram:
            case AggregationType.HistogramSumCount:
            {
                this.Update((double)number);
                break;
            }
            }

            // There is a race with Snapshot:
            // Update() updates the value
            // Snapshot snapshots the value
            // Snapshot sets status to NoCollectPending
            // Update sets status to CollectPending -- this is not right as the Snapshot
            // already included the updated value.
            // In the absence of any new Update call until next Snapshot,
            // this results in exporting an Update even though
            // it had no update.
            // TODO: For Delta, this can be mitigated
            // by ignoring Zero points
            this.MetricPointStatus = MetricPointStatus.CollectPending;
        }
Example #2
0
        internal void TakeSnapshot(bool outputDelta)
        {
            switch (this.aggType)
            {
            case AggregationType.LongSumIncomingDelta:
            case AggregationType.LongSumIncomingCumulative:
            {
                if (outputDelta)
                {
                    long initValue = Interlocked.Read(ref this.runningValue.AsLong);
                    this.snapshotValue.AsLong  = initValue - this.deltaLastValue.AsLong;
                    this.deltaLastValue.AsLong = initValue;
                    this.MetricPointStatus     = MetricPointStatus.NoCollectPending;

                    // Check again if value got updated, if yes reset status.
                    // This ensures no Updates get Lost.
                    if (initValue != Interlocked.Read(ref this.runningValue.AsLong))
                    {
                        this.MetricPointStatus = MetricPointStatus.CollectPending;
                    }
                }
                else
                {
                    this.snapshotValue.AsLong = Interlocked.Read(ref this.runningValue.AsLong);
                }

                break;
            }

            case AggregationType.DoubleSumIncomingDelta:
            case AggregationType.DoubleSumIncomingCumulative:
            {
                if (outputDelta)
                {
                    // TODO:
                    // Is this thread-safe way to read double?
                    // As long as the value is not -ve infinity,
                    // the exchange (to 0.0) will never occur,
                    // but we get the original value atomically.
                    double initValue = Interlocked.CompareExchange(ref this.runningValue.AsDouble, 0.0, double.NegativeInfinity);
                    this.snapshotValue.AsDouble  = initValue - this.deltaLastValue.AsDouble;
                    this.deltaLastValue.AsDouble = initValue;
                    this.MetricPointStatus       = MetricPointStatus.NoCollectPending;

                    // Check again if value got updated, if yes reset status.
                    // This ensures no Updates get Lost.
                    if (initValue != Interlocked.CompareExchange(ref this.runningValue.AsDouble, 0.0, double.NegativeInfinity))
                    {
                        this.MetricPointStatus = MetricPointStatus.CollectPending;
                    }
                }
                else
                {
                    // TODO:
                    // Is this thread-safe way to read double?
                    // As long as the value is not -ve infinity,
                    // the exchange (to 0.0) will never occur,
                    // but we get the original value atomically.
                    this.snapshotValue.AsDouble = Interlocked.CompareExchange(ref this.runningValue.AsDouble, 0.0, double.NegativeInfinity);
                }

                break;
            }

            case AggregationType.LongGauge:
            {
                this.snapshotValue.AsLong = Interlocked.Read(ref this.runningValue.AsLong);
                this.MetricPointStatus    = MetricPointStatus.NoCollectPending;

                // Check again if value got updated, if yes reset status.
                // This ensures no Updates get Lost.
                if (this.snapshotValue.AsLong != Interlocked.Read(ref this.runningValue.AsLong))
                {
                    this.MetricPointStatus = MetricPointStatus.CollectPending;
                }

                break;
            }

            case AggregationType.DoubleGauge:
            {
                // TODO:
                // Is this thread-safe way to read double?
                // As long as the value is not -ve infinity,
                // the exchange (to 0.0) will never occur,
                // but we get the original value atomically.
                this.snapshotValue.AsDouble = Interlocked.CompareExchange(ref this.runningValue.AsDouble, 0.0, double.NegativeInfinity);
                this.MetricPointStatus      = MetricPointStatus.NoCollectPending;

                // Check again if value got updated, if yes reset status.
                // This ensures no Updates get Lost.
                if (this.snapshotValue.AsDouble != Interlocked.CompareExchange(ref this.runningValue.AsDouble, 0.0, double.NegativeInfinity))
                {
                    this.MetricPointStatus = MetricPointStatus.CollectPending;
                }

                break;
            }

            case AggregationType.Histogram:
            {
                lock (this.histogramBuckets.LockObject)
                {
                    this.snapshotValue.AsLong         = this.runningValue.AsLong;
                    this.histogramBuckets.SnapshotSum = this.histogramBuckets.RunningSum;
                    if (outputDelta)
                    {
                        this.runningValue.AsLong         = 0;
                        this.histogramBuckets.RunningSum = 0;
                    }

                    for (int i = 0; i < this.histogramBuckets.RunningBucketCounts.Length; i++)
                    {
                        this.histogramBuckets.SnapshotBucketCounts[i] = this.histogramBuckets.RunningBucketCounts[i];
                        if (outputDelta)
                        {
                            this.histogramBuckets.RunningBucketCounts[i] = 0;
                        }
                    }

                    this.MetricPointStatus = MetricPointStatus.NoCollectPending;
                }

                break;
            }

            case AggregationType.HistogramSumCount:
            {
                lock (this.histogramBuckets.LockObject)
                {
                    this.snapshotValue.AsLong         = this.runningValue.AsLong;
                    this.histogramBuckets.SnapshotSum = this.histogramBuckets.RunningSum;
                    if (outputDelta)
                    {
                        this.runningValue.AsLong         = 0;
                        this.histogramBuckets.RunningSum = 0;
                    }

                    this.MetricPointStatus = MetricPointStatus.NoCollectPending;
                }

                break;
            }
            }
        }
Example #3
0
        internal void Update(double number)
        {
            switch (this.aggType)
            {
            case AggregationType.DoubleSumIncomingDelta:
            {
                double initValue, newValue;
                do
                {
                    initValue = this.runningValue.AsDouble;
                    newValue  = initValue + number;
                }while (initValue != Interlocked.CompareExchange(ref this.runningValue.AsDouble, newValue, initValue));
                break;
            }

            case AggregationType.DoubleSumIncomingCumulative:
            {
                Interlocked.Exchange(ref this.runningValue.AsDouble, number);
                break;
            }

            case AggregationType.DoubleGauge:
            {
                Interlocked.Exchange(ref this.runningValue.AsDouble, number);
                break;
            }

            case AggregationType.Histogram:
            {
                int i;
                for (i = 0; i < this.histogramBuckets.ExplicitBounds.Length; i++)
                {
                    // Upper bound is inclusive
                    if (number <= this.histogramBuckets.ExplicitBounds[i])
                    {
                        break;
                    }
                }

                lock (this.histogramBuckets.LockObject)
                {
                    this.runningValue.AsLong++;
                    this.histogramBuckets.RunningSum += number;
                    this.histogramBuckets.RunningBucketCounts[i]++;
                }

                break;
            }

            case AggregationType.HistogramSumCount:
            {
                lock (this.histogramBuckets.LockObject)
                {
                    this.runningValue.AsLong++;
                    this.histogramBuckets.RunningSum += number;
                }

                break;
            }
            }

            // There is a race with Snapshot:
            // Update() updates the value
            // Snapshot snapshots the value
            // Snapshot sets status to NoCollectPending
            // Update sets status to CollectPending -- this is not right as the Snapshot
            // already included the updated value.
            // In the absence of any new Update call until next Snapshot,
            // this results in exporting an Update even though
            // it had no update.
            // TODO: For Delta, this can be mitigated
            // by ignoring Zero points
            this.MetricPointStatus = MetricPointStatus.CollectPending;
        }