Example #1
0
 public void AddMetric(StatsdMetric metric)
 {
     string key = metric.Type + "_" + metric.Name;
     lock (_lock)
     {
         StatsdMetric oldMetric;
         if (_metrics.TryGetValue(key, out oldMetric))
         {
             //merge
             double val = metric.Value;
             oldMetric.AddValue(val);
         }
         else
         {
             _metrics[key] = metric;
         }
     }
 }
Example #2
0
        public void AddMetric(StatsdMetric metric)
        {
            string key = metric.Type + "_" + metric.Name;

            lock (_lock)
            {
                StatsdMetric oldMetric;
                if (_metrics.TryGetValue(key, out oldMetric))
                {
                    //merge
                    double val = metric.Value;
                    oldMetric.AddValue(val);
                }
                else
                {
                    _metrics[key] = metric;
                }
            }
        }
Example #3
0
        /*
         * StatsD metric collection protocol
         *   - metrics are separated by newlines
         *   - each line ar generally of the form:
         *     <metric name>:<value>|<type>
         *     ** Gauges     :   <metric name>:<value>|g
         *     ** Counters   :   <metric name>:<value>|c[|@<sample rate>]
         *     ** Timers     :   <metric name>:<value>|ms
         *     ** Sets       :   <metric name>:<value>|s
         */

        public static StatsdMetric ParseLine(string line)
        {
            const string pattern = @"^(?<name>.*):(?<value>.*)\|(?<type>.*)(\|\@(?<rate>.*))?$";
            var regex = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.RightToLeft);
            Match match = regex.Match(line);

            if (!match.Success)
            {
                Logger.Debug("Parser: Invalid statsd format [{0}]", line);
                return (null);
            }
            GroupCollection groups = match.Groups;

            string name = groups["name"].Value;
            string valstr = groups["value"].Value;
            string typestr = groups["type"].Value;
            string ratestr = groups["rate"].Value;

            if (String.IsNullOrEmpty(name) || String.IsNullOrEmpty(valstr) || String.IsNullOrEmpty(typestr))
            {
                Logger.Debug("Parser: name/value/type are not optional [{0}]", line);
                return (null);
            }
            StatsdMetric.StatsdType type;

            if (String.Compare(typestr, "g", StringComparison.OrdinalIgnoreCase) == 0)
                type = StatsdMetric.StatsdType.StatsdGauge;
            else if (String.Compare(typestr, "c", StringComparison.OrdinalIgnoreCase) == 0)
                type = StatsdMetric.StatsdType.StatsdCounter;
            else if (String.Compare(typestr, "s", StringComparison.OrdinalIgnoreCase) == 0)
                type = StatsdMetric.StatsdType.StatsdSet;
            else if (String.Compare(typestr, "ms", StringComparison.OrdinalIgnoreCase) == 0)
                type = StatsdMetric.StatsdType.StatsdTimer;
            else
            {
                Logger.Debug("Parser: invalid type [{0}]", line);
                return (null);
            }
            double value;
            try
            {
                value = Convert.ToDouble(valstr);
            }
            catch (Exception)
            {
                Logger.Debug("Parser: invalid value [{0}]", line);
                return (null);
            }

            double rate = 0;
            try
            {
                if (!String.IsNullOrEmpty(ratestr))
                    rate = Convert.ToDouble(ratestr);
            }
            catch (Exception)
            {
                Logger.Debug("Parser: invalid rate [{0}]", line);
                return (null);
            }

            if (!string.IsNullOrEmpty(ratestr) && (rate <= 0 || rate > 1))
            {
                Logger.Debug("Parser: invalid rate range [{0}]", line);
                return (null);
            }

            if (!string.IsNullOrEmpty(ratestr) && type != StatsdMetric.StatsdType.StatsdCounter)
            {
                Logger.Debug("Parser: rate is supported only for Counters [{0}]", line);
                return (null);
            }

            if (!string.IsNullOrEmpty(ratestr))
            {
                value = value/rate;
            }

            var metric = new StatsdMetric(name, type, value);
            return (metric);
        }
Example #4
0
        public IList <MetricValue> Read()
        {
            lock (_lock)
            {
                var res        = new List <MetricValue>();
                var removeList = new List <string>();
                foreach (var pair in _metrics)
                {
                    StatsdMetric metric = pair.Value;
                    if (metric.NumUpdates <= 0 &&
                        ((_delCounter && metric.Type == StatsdMetric.StatsdType.StatsdCounter) ||
                         (_delTimer && metric.Type == StatsdMetric.StatsdType.StatsdTimer) ||
                         (_delGauge && metric.Type == StatsdMetric.StatsdType.StatsdGauge) ||
                         (_delSet && metric.Type == StatsdMetric.StatsdType.StatsdSet)))
                    {
                        removeList.Add(pair.Key);
                        continue;
                    }
                    var metricVal = new MetricValue
                    {
                        HostName           = _hostName,
                        PluginName         = "statsd",
                        PluginInstanceName = "",
                        TypeInstanceName   = metric.Name,
                        Values             = new[] { metric.GetMetric() }
                    };
                    switch (metric.Type)
                    {
                    case StatsdMetric.StatsdType.StatsdGauge:
                        metricVal.TypeName = "gauge";
                        break;

                    case StatsdMetric.StatsdType.StatsdTimer:
                        metricVal.TypeName          = "latency";
                        metricVal.TypeInstanceName += "-average";
                        break;

                    case StatsdMetric.StatsdType.StatsdSet:
                        metricVal.TypeName = "objects";
                        break;

                    default:
                        metricVal.TypeName = "derive";
                        break;
                    }
                    TimeSpan t     = DateTime.UtcNow - new DateTime(1970, 1, 1);
                    double   epoch = t.TotalMilliseconds / 1000;
                    metricVal.Epoch = Math.Round(epoch, 3);

                    res.Add(metricVal);

                    if (metric.Type == StatsdMetric.StatsdType.StatsdTimer)
                    {
                        if (_timerLower)
                        {
                            MetricValue lowerValue = metricVal.DeepCopy();
                            lowerValue.TypeInstanceName = metric.Name + "-lower";
                            lowerValue.Values[0]        = metric.Lat.Min;
                            res.Add(lowerValue);
                        }
                        if (_timerUpper)
                        {
                            MetricValue upperValue = metricVal.DeepCopy();
                            upperValue.TypeInstanceName = metric.Name + "-upper";
                            upperValue.Values[0]        = metric.Lat.Max;
                            res.Add(upperValue);
                        }

                        if (_timerSum)
                        {
                            MetricValue upperSum = metricVal.DeepCopy();
                            upperSum.TypeInstanceName = metric.Name + "-Sum";
                            upperSum.Values[0]        = metric.Lat.Sum;
                            res.Add(upperSum);
                        }
                        if (_timerCount)
                        {
                            MetricValue upperCount = metricVal.DeepCopy();
                            upperCount.TypeInstanceName = metric.Name + "-count";
                            upperCount.Values[0]        = metric.Lat.Num;
                            res.Add(upperCount);
                        }
                        Histogram histogram = metric.Lat.Histogram;
                        if (_percentiles != null && _percentiles.Length > 0 && histogram != null)
                        {
                            foreach (float percentile in _percentiles)
                            {
                                double val = histogram.GetPercentile(percentile);

                                MetricValue mv = metricVal.DeepCopy();
                                mv.TypeInstanceName = metric.Name + "-percentile-" + percentile;
                                mv.Values[0]        = val;
                                res.Add(mv);
                            }
                        }
                    }
                    metric.Reset();
                }
                Logger.Debug("Removing entries that were not updated:{0}", removeList.Count);
                foreach (string key in removeList)
                {
                    _metrics.Remove(key);
                }
                return(res);
            }
        }
Example #5
0
        /*
         * StatsD metric collection protocol
         *   - metrics are separated by newlines
         *   - each line ar generally of the form:
         *     <metric name>:<value>|<type>
         *     ** Gauges     :   <metric name>:<value>|g
         *     ** Counters   :   <metric name>:<value>|c[|@<sample rate>]
         *     ** Timers     :   <metric name>:<value>|ms
         *     ** Sets       :   <metric name>:<value>|s
         */

        public static StatsdMetric ParseLine(string line)
        {
            const string pattern = @"^(?<name>.*):(?<value>.*)\|(?<type>.*)(\|\@(?<rate>.*))?$";
            var          regex   = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.RightToLeft);
            Match        match   = regex.Match(line);

            if (!match.Success)
            {
                Logger.Debug("Parser: Invalid statsd format [{0}]", line);
                return(null);
            }
            GroupCollection groups = match.Groups;

            string name    = groups["name"].Value;
            string valstr  = groups["value"].Value;
            string typestr = groups["type"].Value;
            string ratestr = groups["rate"].Value;

            if (String.IsNullOrEmpty(name) || String.IsNullOrEmpty(valstr) || String.IsNullOrEmpty(typestr))
            {
                Logger.Debug("Parser: name/value/type are not optional [{0}]", line);
                return(null);
            }
            StatsdMetric.StatsdType type;

            if (String.Compare(typestr, "g", StringComparison.OrdinalIgnoreCase) == 0)
            {
                type = StatsdMetric.StatsdType.StatsdGauge;
            }
            else if (String.Compare(typestr, "c", StringComparison.OrdinalIgnoreCase) == 0)
            {
                type = StatsdMetric.StatsdType.StatsdCounter;
            }
            else if (String.Compare(typestr, "s", StringComparison.OrdinalIgnoreCase) == 0)
            {
                type = StatsdMetric.StatsdType.StatsdSet;
            }
            else if (String.Compare(typestr, "ms", StringComparison.OrdinalIgnoreCase) == 0)
            {
                type = StatsdMetric.StatsdType.StatsdTimer;
            }
            else
            {
                Logger.Debug("Parser: invalid type [{0}]", line);
                return(null);
            }
            double value;

            try
            {
                value = Convert.ToDouble(valstr);
            }
            catch (Exception)
            {
                Logger.Debug("Parser: invalid value [{0}]", line);
                return(null);
            }

            double rate = 0;

            try
            {
                if (!String.IsNullOrEmpty(ratestr))
                {
                    rate = Convert.ToDouble(ratestr);
                }
            }
            catch (Exception)
            {
                Logger.Debug("Parser: invalid rate [{0}]", line);
                return(null);
            }

            if (!string.IsNullOrEmpty(ratestr) && (rate <= 0 || rate > 1))
            {
                Logger.Debug("Parser: invalid rate range [{0}]", line);
                return(null);
            }

            if (!string.IsNullOrEmpty(ratestr) && type != StatsdMetric.StatsdType.StatsdCounter)
            {
                Logger.Debug("Parser: rate is supported only for Counters [{0}]", line);
                return(null);
            }

            if (!string.IsNullOrEmpty(ratestr))
            {
                value = value / rate;
            }

            var metric = new StatsdMetric(name, type, value);

            return(metric);
        }