{"action":"created","comment":{"url":"https://api.github.com/repos/bloomberg/collectdwin/pulls/comments/51264327","id":51264327,"diff_hunk":"@@ -2,194 +2,487 @@\n using System.Collections.Generic;\r\n using System.Configuration;\r\n using System.Diagnostics;\r\n+using System.Timers;\r\n+using System.Reflection;\r\n+using Microsoft.VisualBasic.Devices;\r\n using NLog;\r\n \r\n namespace BloombergFLP.CollectdWin\r\n {\r\n-    internal struct Metric\r\n+    internal class Helper\r\n     {\r\n-        public string Category;\r\n-        public string CollectdPlugin, CollectdPluginInstance, CollectdType, CollectdTypeInstance;\r\n-        public string CounterName;\r\n-        public IList<PerformanceCounter> Counters;\r\n-        public string Instance;\r\n-        public uint ScaleDownFactor;\r\n-        public uint ScaleUpFactor;\r\n+        public delegate double TransformFunction(double value);\r\n+        public static string DictionaryValue(Dictionary<string, object> dict, string key)\r\n+        {\r\n+            return dict.ContainsKey(key) ? dict[key] as string : null;\r\n+        }\r\n+        public static double TotalPhysicalMemoryInBytes = new ComputerInfo().TotalPhysicalMemory;\r\n+\r\n+        // conversion function group\r\n+        public static double _ConvertFromMegaBytesToBytes(double value) { return value * 1024 * 1024; }\r\n+        public static double _ConvertFromPercentageToRemainingPercentage(double value) { return 100 - value; }\r\n+        public static double _ConvertFromMemoryAvailableBytesToUsedPercentage(double value)\r\n+        {\r\n+            return (TotalPhysicalMemoryInBytes - value) * 100 / TotalPhysicalMemoryInBytes;\r\n+        }\r\n+\r\n+        // generator creatation function group\r\n+        public static PerformanceCounterGenerator _Create()\r\n+        {\r\n+            return new PerformanceCounterMetricGenerator();\r\n+        }\r\n+\r\n+        public static PerformanceCounterGenerator _CreateAverage()\r\n+        {\r\n+            return new AveragesGenerator();\r\n+        }\r\n+\r\n+        public static PerformanceCounterGenerator _CreateCountInstances()\r\n+        {\r\n+            return new PerformanceCounterCategoryInstancesGenerator();\r\n+        }\r\n     }\r\n \r\n-    internal class WindowsPerformanceCounterPlugin : IMetricsReadPlugin\r\n+    internal interface IMetricGenerator\r\n     {\r\n-        private static readonly Logger Logger = LogManager.GetCurrentClassLogger();\r\n-        private readonly IList<Metric> _metrics;\r\n-        private string _hostName;\r\n-        private bool _reloadConfiguration;\r\n-        private DateTime _configurationReloadTime;\r\n-        private int _reloadConfigurationInterval;\r\n+        bool Configure(Dictionary<string, object> config);\r\n+        bool Refresh();\r\n+        List<MetricValue> NextValues();\r\n+    }\r\n \r\n-        public WindowsPerformanceCounterPlugin()\r\n+    internal abstract class PerformanceCounterGenerator : IMetricGenerator\r\n+    {\r\n+        static protected string s_hostName = Util.GetHostName();\r\n+        static protected readonly Logger Logger = LogManager.GetCurrentClassLogger();\r\n+        public string CounterCategory, CounterName, CounterInstance;\r\n+        public string CollectdPlugin, CollectdPluginInstance, CollectdType, CollectdTypeInstance;\r\n+        protected Helper.TransformFunction _transform;\r\n+    \r\n+        public virtual bool Configure(Dictionary<string, object> config)\r\n+        {\r\n+            CounterCategory = Helper.DictionaryValue(config, \"Category\");\r\n+            CounterName = Helper.DictionaryValue(config, \"Name\");\r\n+            CounterInstance = Helper.DictionaryValue(config, \"Instance\");\r\n+            CollectdPlugin = Helper.DictionaryValue(config, \"CollectdPlugin\");\r\n+            CollectdPluginInstance = Helper.DictionaryValue(config, \"CollectdPluginInstance\");\r\n+            CollectdType = Helper.DictionaryValue(config, \"CollectdType\");\r\n+            CollectdTypeInstance = Helper.DictionaryValue(config, \"CollectdTypeInstance\");\r\n+\r\n+            string transformer = Helper.DictionaryValue(config, \"Transformer\");\r\n+            if (transformer != null)\r\n+            {\r\n+                MethodInfo transformMethodInfo = typeof(Helper).GetMethod(\"_ConvertFrom\" + transformer);\r\n+                if (transformMethodInfo != null)\r\n+                {\r\n+                    _transform = (Helper.TransformFunction)Delegate.CreateDelegate(typeof(Helper.TransformFunction), transformMethodInfo);\r\n+                }\r\n+            }\r\n+            return true;\r\n+        }\r\n+\r\n+        public virtual bool Refresh()\r\n         {\r\n-            _metrics = new List<Metric>();\r\n+            return true;\r\n         }\r\n \r\n-        public void Configure()\r\n+        public abstract List<MetricValue> NextValues();\r\n+\r\n+        public MetricValue GetMetricValue(List<double> vals)\r\n         {\r\n-            var config =\r\n-                ConfigurationManager.GetSection(\"WindowsPerformanceCounter\") as WindowsPerformanceCounterPluginConfig;\r\n-            if (config == null)\r\n+            var metricValue = new MetricValue\r\n             {\r\n-                throw new Exception(\"Cannot get configuration section : WindowsPerformanceCounter\");\r\n+                HostName = s_hostName,\r\n+                PluginName = CollectdPlugin,\r\n+                PluginInstanceName = CollectdPluginInstance,\r\n+                TypeName = CollectdType,\r\n+                TypeInstanceName = CollectdTypeInstance,\r\n+                Values = vals.ToArray()\r\n+            };\r\n+\r\n+            TimeSpan t = DateTime.UtcNow - new DateTime(1970, 1, 1);\r\n+            double epoch = t.TotalMilliseconds / 1000;\r\n+            metricValue.Epoch = Math.Round(epoch, 3);\r\n+            return metricValue;\r\n+        }\r\n+    }\r\n+\r\n+    internal class PerformanceCounterCategoryInstancesGenerator : PerformanceCounterGenerator\r\n+    {\r\n+        private PerformanceCounterCategory _performanceCounterCategory;\r\n+\r\n+        public override bool Configure(Dictionary<string, object> config)\r\n+        {\r\n+            if (!base.Configure(config))\r\n+                return false;\r\n+            try\r\n+            {\r\n+                _performanceCounterCategory = new PerformanceCounterCategory(CounterCategory);\r\n+                return true;\r\n             }\r\n+            catch (Exception exp)\r\n+            {\r\n+                Logger.Error(\"Got exception : {0}, while adding performance counter category: {1}\", exp, CounterCategory);\r\n+                return false;\r\n+            }\r\n+        }\r\n \r\n-            _reloadConfiguration = config.ReloadConfiguration.Enable;\r\n-            _reloadConfigurationInterval = config.ReloadConfiguration.Interval;\r\n+        public override List<MetricValue> NextValues()\r\n+        {\r\n+            var metricValueList = new List<MetricValue>();\r\n+            var vals = new List<double>();\r\n+            vals.Add(_performanceCounterCategory.GetInstanceNames().Length);\r\n+            metricValueList.Add(GetMetricValue(vals));\r\n+            return metricValueList;\r\n+        }\r\n+    }\r\n \r\n-            _configurationReloadTime = DateTime.Now;\r\n+    internal class PerformanceCounterMetricGenerator : PerformanceCounterGenerator\r\n+    {\r\n+        internal class MetricRetriever\r\n+        {\r\n+            // indicate the real instance when PerformanceCounterMetricGenerator.CounterInstance='*'\r\n+            public string Instance;\r\n+            public IList<PerformanceCounter> Counters;\r\n+            public List<double> Retrive(Helper.TransformFunction transform)\r\n+            {\r\n+                var vals = new List<double>();\r\n+                foreach (PerformanceCounter counter in Counters)\r\n+                {\r\n+                    double val;\r\n+                    try\r\n+                    {\r\n+                        val = counter.NextValue();\r\n+                        if (transform != null)\r\n+                            val = transform.Invoke(val);\r\n+                    }\r\n+                    catch (InvalidOperationException)\r\n+                    {\r\n+                        return null;\r\n+                    }\r\n+                    vals.Add(val);\r\n+                }\r\n+                return vals;\r\n+            }\r\n+        }\r\n \r\n-            _hostName = Util.GetHostName();\r\n+        public IList<MetricRetriever> MetricRetrievers;\r\n \r\n-            _metrics.Clear();\r\n+        private bool ExistInstance(string instance)\r\n+        {\r\n+            foreach(MetricRetriever retriever in MetricRetrievers)\r\n+                if (instance == null && retriever.Instance == null\r\n+                    || instance == retriever.Instance)\r\n+                    return true;\r\n+            return false;\r\n+        }\r\n \r\n-            foreach (WindowsPerformanceCounterPluginConfig.CounterConfig counter in config.Counters)\r\n+        private MetricRetriever GetMetricRetriever(string category, string names, string instance)\r\n+        {\r\n+            string logstr =\r\n+                string.Format(\r\n+                    \"Category:{0} - Instance:{1} - counter:{2}\",\r\n+                    category, instance, names);\r\n+            try\r\n             {\r\n-                if (counter.Instance == \"*\")\r\n+                var metricRetriver = new MetricRetriever();\r\n+                metricRetriver.Counters = new List<PerformanceCounter>();\r\n+                string[] counterList = names.Split(',');\r\n+                foreach (string ctr in counterList)\r\n+                    metricRetriver.Counters.Add(new PerformanceCounter(category, ctr.Trim(), instance));\r\n+                Logger.Info(\"Added Performance COUNTER : {0}\", logstr);\r\n+                return metricRetriver;\r\n+            }\r\n+            catch (Exception exp)\r\n+            {\r\n+                Logger.Error(\"Got exception : {0}, while adding performance counter: {1}\", exp, logstr);\r\n+                return null;\r\n+            }\r\n+        }\r\n+\r\n+        public override bool Refresh()\r\n+        {\r\n+            if (MetricRetrievers == null)\r\n+                MetricRetrievers = new List<MetricRetriever>();\r\n+            if (CounterInstance != null && CounterInstance == \"*\")\r\n+            {\r\n+                var cat = new PerformanceCounterCategory(CounterCategory);\r\n+                string[] instances = cat.GetInstanceNames();\r\n+                foreach (string instance in instances)\r\n                 {\r\n-                    var cat = new PerformanceCounterCategory(counter.Category);\r\n-                    string[] instances = cat.GetInstanceNames();\r\n-                    foreach (string instance in instances)\r\n+                    if (!ExistInstance(instance))\r\n                     {\r\n+                        MetricRetriever metricRetriver = GetMetricRetriever(CounterCategory, CounterName, instance);\r\n+                        if (metricRetriver == null)\r\n+                            return false;\r\n                         // Replace collectd_plugin_instance with the Instance got from counter\r\n-                        AddPerformanceCounter(counter.Category, counter.Name,\r\n-                            instance, counter.ScaleUpFactor,\r\n-                            counter.ScaleDownFactor, counter.CollectdPlugin,\r\n-                            instance, counter.CollectdType,\r\n-                            counter.CollectdTypeInstance);\r\n+                        metricRetriver.Instance = instance;\r\n+                        MetricRetrievers.Add(metricRetriver);\r\n                     }\r\n                 }\r\n+            }\r\n+            else if (MetricRetrievers.Count == 0)\r\n+            {\r\n+                MetricRetriever metricRetriver = GetMetricRetriever(CounterCategory, CounterName, CounterInstance);\r\n+                if (metricRetriver == null)\r\n+                    return false;\r\n+                MetricRetrievers.Add(metricRetriver);\r\n+            }\r\n+            return true;\r\n+        }\r\n+\r\n+        public override bool Configure(Dictionary<string, object> config)\r\n+        {\r\n+            return base.Configure(config) && Refresh();\r\n+        }\r\n+\r\n+        public override List<MetricValue> NextValues()\r\n+        {\r\n+            var metricValueList = new List<MetricValue>();\r\n+            var missingInstances = new List<MetricRetriever>();\r\n+            foreach (MetricRetriever metricRetriver in MetricRetrievers)\r\n+            {\r\n+                var vals = metricRetriver.Retrive(_transform);\r\n+                if (vals == null)\r\n+                {\r\n+                    // The instance is gone\r\n+                    missingInstances.Add(metricRetriver);\r\n+                }\r\n                 else\r\n                 {\r\n-                    AddPerformanceCounter(counter.Category, counter.Name,\r\n-                        counter.Instance, counter.ScaleUpFactor,\r\n-                        counter.ScaleDownFactor, counter.CollectdPlugin,\r\n-                        counter.CollectdPluginInstance, counter.CollectdType,\r\n-                        counter.CollectdTypeInstance);\r\n+                    var metricValue = GetMetricValue(vals);\r\n+                    if (CollectdPluginInstance == null || CollectdPluginInstance == String.Empty)\r\n+                        metricValue.PluginInstanceName = metricRetriver.Instance;\r\n+                    metricValueList.Add(metricValue);\r\n                 }\r\n             }\r\n-            Logger.Info(\"WindowsPerformanceCounter plugin configured\");\r\n+\r\n+            // remove missing instances before return\r\n+            foreach (MetricRetriever missingInstance in missingInstances)\r\n+            {\r\n+                string logstr =\r\n+                    string.Format(\r\n+                        \"Category:{0} - Instance:{1} - counter:{2} - CollectdPlugin:{4} - CollectdPluginInstance:{5} - CollectdType:{6} - CollectdTypeInstance:{7}\",\r\n+                        CounterCategory, missingInstance.Instance, CounterName, \r\n+                        CollectdPlugin, CollectdPluginInstance, CollectdType, CollectdTypeInstance);\r\n+                Logger.Info(\"Removed Performance COUNTER : {0}\", logstr);\r\n+                MetricRetrievers.Remove(missingInstance);\r\n+            }\r\n+\r\n+            return metricValueList;\r\n         }\r\n+    }\r\n \r\n-        public void Start()\r\n+    internal class AveragesGenerator : PerformanceCounterMetricGenerator\r\n+    {\r\n+        public List<uint> AverageIntervalsInSeconds = new List<uint>();\r\n+        public uint MaxIntervalInSeconds;\r\n+        public List<List<List<double>>> _samples;\r\n+        private System.Threading.Mutex _mutex = new System.Threading.Mutex(); // protect _samples\r\n+        private Timer _timer = new Timer(1000);\r\n+\r\n+        ~AveragesGenerator()\r\n         {\r\n-            Logger.Info(\"WindowsPerformanceCounter plugin started\");\r\n+            _timer.Dispose();\r\n         }\r\n \r\n-        public void Stop()\r\n+        private static void OnTakeSample(object source, ElapsedEventArgs e, AveragesGenerator averagesGenerator)\r\n         {\r\n-            Logger.Info(\"WindowsPerformanceCounter plugin stopped\");\r\n+            averagesGenerator.TakeSample();\r\n         }\r\n \r\n-        public IList<MetricValue> Read()\r\n+        private void TakeSample()\r\n         {\r\n-            if (DateTime.Now > _configurationReloadTime.AddSeconds(_reloadConfigurationInterval))\r\n+            // get a sample for each of MetricRetrievers\r\n+            List<List<double>> sample = new List<List<double>>();\r\n+            foreach (MetricRetriever metricRetriver in MetricRetrievers)\r\n             {\r\n-                Logger.Info(\"WindowsPerformanceCounter reloading configuration\");\r\n-                Configure();\r\n+                var vals = metricRetriver.Retrive(_transform);\r\n+                if (vals != null)\r\n+                    sample.Add(vals);\r\n+            }\r\n+            _mutex.WaitOne();\r\n+            for(int i = 0; i < sample.Count; ++i)\r\n+            {\r\n+                List<List<double>> sampleList = _samples[i];\r\n+                sampleList.Add(sample[i]);\r\n+                if (sampleList.Count > MaxIntervalInSeconds)\r\n+                    sampleList.RemoveAt(0);\r\n+            }\r\n+            _mutex.ReleaseMutex();\r\n+        }\r\n+\r\n+        public override bool Refresh()\r\n+        {\r\n+            if (MetricRetrievers == null || MetricRetrievers.Count == 0)\r\n+                base.Refresh();\r\n+            return true;\r\n+        }\r\n+\r\n+        public override bool Configure(Dictionary<string, object> config)\r\n+        {\r\n+            if (!base.Configure(config))\r\n+                return false;\r\n+            string averageIntervals = Helper.DictionaryValue(config, \"TransformerParameters\");\r\n+            if (averageIntervals == null)\r\n+                return false;\r\n+            string[] averagesInString = averageIntervals.Split(',');\r\n+            foreach (string interval in averagesInString)\r\n+            {\r\n+                uint val;\r\n+                if (!UInt32.TryParse(interval, out val) || val == 0)\r\n+                    return false;\r\n+                AverageIntervalsInSeconds.Add(val);\r\n             }\r\n+            if (AverageIntervalsInSeconds.Count == 0)\r\n+                return false;\r\n+            AverageIntervalsInSeconds.Sort();\r\n+            MaxIntervalInSeconds = AverageIntervalsInSeconds[AverageIntervalsInSeconds.Count-1];\r\n+            // init _samples\r\n+            _samples = new List<List<List<double>>>();\r\n+            foreach (MetricRetriever metricRetriver in MetricRetrievers)\r\n+                _samples.Add(new List<List<double>>());\r\n+                // take the first sample\r\n+            TakeSample();\r\n+            // set up sampling timer\r\n+            _timer.Elapsed += (sender, e) => OnTakeSample(sender, e, this); ;\r\n+            _timer.AutoReset = true;\r\n+            _timer.Enabled = true;\r\n+            return true;\r\n+        }\r\n+\r\n+        public override List<MetricValue> NextValues()\r\n+        {\r\n             var metricValueList = new List<MetricValue>();\r\n-            foreach (Metric metric in _metrics)\r\n+            _mutex.WaitOne();\r\n+            int i = 0;\r\n+            foreach (MetricRetriever metricRetriver in MetricRetrievers)\r\n             {\r\n-                var vals = new List<double>();\r\n-                var missingInstances = new List<PerformanceCounter>();\r\n-                foreach (PerformanceCounter ctr in metric.Counters)\r\n+                List<double> average = new List<double>();\r\n+                List<List<double>> sampleList = _samples[i]; ++i;\r\n+                List<double> sum = new List<double>();\r\n+                for (int n = 0; n < sampleList[0].Count; ++n)\r\n+                    sum.Add(0);\r\n+                uint interval = AverageIntervalsInSeconds[0];\r\n+                int intervalCount = 0;\r\n+                for (int count=0; count < sampleList.Count; ++count)\r\n                 {\r\n-                    double val;\r\n-                    try\r\n-                    {\r\n-                         val = ctr.NextValue();\r\n-                    }\r\n-                    catch (InvalidOperationException)\r\n-                    {\r\n-                        // The instance is gone\r\n-                        missingInstances.Add(ctr);\r\n-                        continue;\r\n-                    }\r\n-                    if (metric.ScaleUpFactor > 0)\r\n-                    {\r\n-                        val = val*metric.ScaleUpFactor;\r\n-                    }\r\n-                    else\r\n+                    List<double> sample = sampleList[i];\r\n+                    for (int n=0; n < sum.Count; ++n)\r\n+                        sum[n] += sample[n];\r\n+                    if (count + 1 == interval)\r\n                     {\r\n-                        if (metric.ScaleDownFactor > 0)\r\n+                        foreach (double s in sum)\r\n+                            average.Add(s / interval);\r\n+                        ++intervalCount;\r\n+                        if (intervalCount < AverageIntervalsInSeconds.Count)\r\n                         {\r\n-                            val = val/metric.ScaleDownFactor;\r\n+                            interval = AverageIntervalsInSeconds[intervalCount];\r\n                         }\r\n                     }\r\n-                    vals.Add(val);\r\n                 }\r\n-\r\n-                foreach (PerformanceCounter missingInstance in missingInstances)\r\n+                for (; intervalCount < AverageIntervalsInSeconds.Count; ++intervalCount)\r\n                 {\r\n-                    string logstr =\r\n-                        string.Format(\r\n-                            \"Category:{0} - Instance:{1} - counter:{2} - ScaleUpFactor:{3} - ScaleDownFactor:{4} -  CollectdPlugin:{5} - CollectdPluginInstance:{6} - CollectdType:{7} - CollectdTypeInstance:{8}\",\r\n-                            metric.Category, metric.Instance, metric.CounterName, metric.ScaleUpFactor, metric.ScaleDownFactor, metric.CollectdPlugin, metric.CollectdPluginInstance,\r\n-                            metric.CollectdType, metric.CollectdTypeInstance);\r\n-                    Logger.Info(\"Removed Performance COUNTER : {0}\", logstr);\r\n-                    metric.Counters.Remove(missingInstance);\r\n+                    foreach (double s in sum)\r\n+                        average.Add(s / sampleList.Count);\r\n                 }\r\n \r\n-                var metricValue = new MetricValue\r\n-                {\r\n-                    HostName = _hostName,\r\n-                    PluginName = metric.CollectdPlugin,\r\n-                    PluginInstanceName = metric.CollectdPluginInstance,\r\n-                    TypeName = metric.CollectdType,\r\n-                    TypeInstanceName = metric.CollectdTypeInstance,\r\n-                    Values = vals.ToArray()\r\n-                };\r\n-\r\n-                TimeSpan t = DateTime.UtcNow - new DateTime(1970, 1, 1);\r\n-                double epoch = t.TotalMilliseconds/1000;\r\n-                metricValue.Epoch = Math.Round(epoch, 3);\r\n+                var metricValue = GetMetricValue(average);\r\n+                if (CollectdPluginInstance == null || CollectdPluginInstance == String.Empty)\r\n+                    metricValue.PluginInstanceName = metricRetriver.Instance;\r\n \r\n                 metricValueList.Add(metricValue);\r\n             }\r\n-            return (metricValueList);\r\n+            _mutex.ReleaseMutex();\r\n+            return metricValueList;\r\n         }\r\n+    }\r\n+\r\n+    internal class WindowsPerformanceCounterPlugin : IMetricsReadPlugin\r\n+    {\r\n+        private static readonly Logger Logger = LogManager.GetCurrentClassLogger();\r\n+        private readonly IList<IMetricGenerator> _metricGenerators;\r\n+        private bool _refreshConfiguration;\r\n+        private DateTime _instanceRefreshTime;\r\n+        private int _refreshConfigurationInterval;\r\n \r\n-        private void AddPerformanceCounter(string category, string names, string instance, uint scaleUpFactor,\r\n-            uint scaleDownFactor, string collectdPlugin, string collectdPluginInstance, string collectdType,\r\n-            string collectdTypeInstance)\r\n+        public WindowsPerformanceCounterPlugin()\r\n         {\r\n-            string logstr =\r\n-                string.Format(\r\n-                    \"Category:{0} - Instance:{1} - counter:{2} - ScaleUpFactor:{3} - ScaleDownFactor:{4} -  CollectdPlugin:{5} - CollectdPluginInstance:{6} - CollectdType:{7} - CollectdTypeInstance:{8}\",\r\n-                    category, instance, names, scaleUpFactor, scaleDownFactor, collectdPlugin, collectdPluginInstance,\r\n-                    collectdType, collectdTypeInstance);\r\n+            _metricGenerators = new List<IMetricGenerator>();\r\n+        }\r\n \r\n-            try\r\n+        public void Configure()\r\n+        {\r\n+            var config =\r\n+                ConfigurationManager.GetSection(\"WindowsPerformanceCounter\") as WindowsPerformanceCounterPluginConfig;\r\n+            if (config == null)\r\n             {\r\n-                var metric = new Metric();\r\n-                string[] counterList = names.Split(',');\r\n-                metric.Counters = new List<PerformanceCounter>();\r\n-                foreach (string ctr in counterList)\r\n-                    metric.Counters.Add(new PerformanceCounter(category, ctr.Trim(), instance));\r\n-                metric.Category = category;\r\n-                metric.Instance = instance;\r\n-                metric.CounterName = names;\r\n-                metric.ScaleUpFactor = scaleUpFactor;\r\n-                metric.ScaleDownFactor = scaleDownFactor;\r\n-                metric.CollectdPlugin = collectdPlugin;\r\n-                metric.CollectdPluginInstance = collectdPluginInstance;\r\n-                metric.CollectdType = collectdType;\r\n-                metric.CollectdTypeInstance = collectdTypeInstance;\r\n-\r\n-                _metrics.Add(metric);\r\n-                Logger.Info(\"Added Performance COUNTER : {0}\", logstr);\r\n+                throw new Exception(\"Cannot get configuration section : WindowsPerformanceCounter\");\r\n             }\r\n-            catch (Exception exp)\r\n+\r\n+            _refreshConfiguration = config.RefreshInstancesConfiguration.Enable;\r\n+            _refreshConfigurationInterval = config.RefreshInstancesConfiguration.Interval;\r\n+\r\n+            _instanceRefreshTime = DateTime.Now;\r\n+\r\n+            _metricGenerators.Clear();\r\n+            foreach (WindowsPerformanceCounterPluginConfig.CounterConfig counter in config.Counters)\r\n             {\r\n-                Logger.Error(\"Got exception : {0}, while adding performance counter: {1}\", exp, logstr);\r\n+                // create the IMetricGenerator object based on GeneratorClass\r\n+                //Get the method information using the method info class\r\n+                MethodInfo createMethodInfo = typeof(Helper).GetMethod(\"_Create\" + counter.Transformer);\r\n+                IMetricGenerator metricGenerator;\r\n+                if (createMethodInfo != null)\r\n+                {\r\n+                    metricGenerator = (IMetricGenerator) createMethodInfo.Invoke(null, null);\r\n+                }\r\n+                else\r\n+                {\r\n+                    // cannot find method for creating metric generator, use the default one\r","path":"src/CollectdWinService/WindowsPerformanceCounterPlugin.cs","position":564,"original_position":564,"commit_id":"74134be6aed665d0056b0037f7744e5e6bbb398b","original_commit_id":"74134be6aed665d0056b0037f7744e5e6bbb398b","user":{"login":"yogeswaran","id":6502513,"avatar_url":"https://avatars.githubusercontent.com/u/6502513?v=3","gravatar_id":"","url":"https://api.github.com/users/yogeswaran","html_url":"https://github.com/yogeswaran","followers_url":"https://api.github.com/users/yogeswaran/followers","following_url":"https://api.github.com/users/yogeswaran/following{/other_user}","gists_url":"https://api.github.com/users/yogeswaran/gists{/gist_id}","starred_url":"https://api.github.com/users/yogeswaran/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yogeswaran/subscriptions","organizations_url":"https://api.github.com/users/yogeswaran/orgs","repos_url":"https://api.github.com/users/yogeswaran/repos","events_url":"https://api.github.com/users/yogeswaran/events{/privacy}","received_events_url":"https://api.github.com/users/yogeswaran/received_events","type":"User","site_admin":false},"body":"log an error here","created_at":"2016-01-29T14:16:00Z","updated_at":"2016-01-29T14:16:00Z","html_url":"https://github.com/bloomberg/collectdwin/pull/25#discussion_r51264327","pull_request_url":"https://api.github.com/repos/bloomberg/collectdwin/pulls/25","_links":{"self":{"href":"https://api.github.com/repos/bloomberg/collectdwin/pulls/comments/51264327"},"html":{"href":"https://github.com/bloomberg/collectdwin/pull/25#discussion_r51264327"},"pull_request":{"href":"https://api.github.com/repos/bloomberg/collectdwin/pulls/25"}}},"pull_request":{"url":"https://api.github.com/repos/bloomberg/collectdwin/pulls/25","id":57107858,"html_url":"https://github.com/bloomberg/collectdwin/pull/25","diff_url":"https://github.com/bloomberg/collectdwin/pull/25.diff","patch_url":"https://github.com/bloomberg/collectdwin/pull/25.patch","issue_url":"https://api.github.com/repos/bloomberg/collectdwin/issues/25","number":25,"state":"open","locked":false,"title":"add more metrics for Windows","user":{"login":"budaqing","id":16548238,"avatar_url":"https://avatars.githubusercontent.com/u/16548238?v=3","gravatar_id":"","url":"https://api.github.com/users/budaqing","html_url":"https://github.com/budaqing","followers_url":"https://api.github.com/users/budaqing/followers","following_url":"https://api.github.com/users/budaqing/following{/other_user}","gists_url":"https://api.github.com/users/budaqing/gists{/gist_id}","starred_url":"https://api.github.com/users/budaqing/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/budaqing/subscriptions","organizations_url":"https://api.github.com/users/budaqing/orgs","repos_url":"https://api.github.com/users/budaqing/repos","events_url":"https://api.github.com/users/budaqing/events{/privacy}","received_events_url":"https://api.github.com/users/budaqing/received_events","type":"User","site_admin":false},"body":"And make Perfornamce Counter plugin easier to add more metrics.","created_at":"2016-01-25T18:08:25Z","updated_at":"2016-01-29T14:16:00Z","closed_at":null,"merged_at":null,"merge_commit_sha":"cabe5b0b88f64ba520a77f6177ac9245bc9d2802","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/bloomberg/collectdwin/pulls/25/commits","review_comments_url":"https://api.github.com/repos/bloomberg/collectdwin/pulls/25/comments","review_comment_url":"https://api.github.com/repos/bloomberg/collectdwin/pulls/comments{/number}","comments_url":"https://api.github.com/repos/bloomberg/collectdwin/issues/25/comments","statuses_url":"https://api.github.com/repos/bloomberg/collectdwin/statuses/74134be6aed665d0056b0037f7744e5e6bbb398b","head":{"label":"budaqing:moreMetrics","ref":"moreMetrics","sha":"74134be6aed665d0056b0037f7744e5e6bbb398b","user":{"login":"budaqing","id":16548238,"avatar_url":"https://avatars.githubusercontent.com/u/16548238?v=3","gravatar_id":"","url":"https://api.github.com/users/budaqing","html_url":"https://github.com/budaqing","followers_url":"https://api.github.com/users/budaqing/followers","following_url":"https://api.github.com/users/budaqing/following{/other_user}","gists_url":"https://api.github.com/users/budaqing/gists{/gist_id}","starred_url":"https://api.github.com/users/budaqing/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/budaqing/subscriptions","organizations_url":"https://api.github.com/users/budaqing/orgs","repos_url":"https://api.github.com/users/budaqing/repos","events_url":"https://api.github.com/users/budaqing/events{/privacy}","received_events_url":"https://api.github.com/users/budaqing/received_events","type":"User","site_admin":false},"repo":{"id":49289136,"name":"collectdwin","full_name":"budaqing/collectdwin","owner":{"login":"budaqing","id":16548238,"avatar_url":"https://avatars.githubusercontent.com/u/16548238?v=3","gravatar_id":"","url":"https://api.github.com/users/budaqing","html_url":"https://github.com/budaqing","followers_url":"https://api.github.com/users/budaqing/followers","following_url":"https://api.github.com/users/budaqing/following{/other_user}","gists_url":"https://api.github.com/users/budaqing/gists{/gist_id}","starred_url":"https://api.github.com/users/budaqing/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/budaqing/subscriptions","organizations_url":"https://api.github.com/users/budaqing/orgs","repos_url":"https://api.github.com/users/budaqing/repos","events_url":"https://api.github.com/users/budaqing/events{/privacy}","received_events_url":"https://api.github.com/users/budaqing/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/budaqing/collectdwin","description":"CollectdWin - a system statistics collection daemon for Windows, inspired by 'collectd'","fork":true,"url":"https://api.github.com/repos/budaqing/collectdwin","forks_url":"https://api.github.com/repos/budaqing/collectdwin/forks","keys_url":"https://api.github.com/repos/budaqing/collectdwin/keys{/key_id}","collaborators_url":"https://api.github.com/repos/budaqing/collectdwin/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/budaqing/collectdwin/teams","hooks_url":"https://api.github.com/repos/budaqing/collectdwin/hooks","issue_events_url":"https://api.github.com/repos/budaqing/collectdwin/issues/events{/number}","events_url":"https://api.github.com/repos/budaqing/collectdwin/events","assignees_url":"https://api.github.com/repos/budaqing/collectdwin/assignees{/user}","branches_url":"https://api.github.com/repos/budaqing/collectdwin/branches{/branch}","tags_url":"https://api.github.com/repos/budaqing/collectdwin/tags","blobs_url":"https://api.github.com/repos/budaqing/collectdwin/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/budaqing/collectdwin/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/budaqing/collectdwin/git/refs{/sha}","trees_url":"https://api.github.com/repos/budaqing/collectdwin/git/trees{/sha}","statuses_url":"https://api.github.com/repos/budaqing/collectdwin/statuses/{sha}","languages_url":"https://api.github.com/repos/budaqing/collectdwin/languages","stargazers_url":"https://api.github.com/repos/budaqing/collectdwin/stargazers","contributors_url":"https://api.github.com/repos/budaqing/collectdwin/contributors","subscribers_url":"https://api.github.com/repos/budaqing/collectdwin/subscribers","subscription_url":"https://api.github.com/repos/budaqing/collectdwin/subscription","commits_url":"https://api.github.com/repos/budaqing/collectdwin/commits{/sha}","git_commits_url":"https://api.github.com/repos/budaqing/collectdwin/git/commits{/sha}","comments_url":"https://api.github.com/repos/budaqing/collectdwin/comments{/number}","issue_comment_url":"https://api.github.com/repos/budaqing/collectdwin/issues/comments{/number}","contents_url":"https://api.github.com/repos/budaqing/collectdwin/contents/{+path}","compare_url":"https://api.github.com/repos/budaqing/collectdwin/compare/{base}...{head}","merges_url":"https://api.github.com/repos/budaqing/collectdwin/merges","archive_url":"https://api.github.com/repos/budaqing/collectdwin/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/budaqing/collectdwin/downloads","issues_url":"https://api.github.com/repos/budaqing/collectdwin/issues{/number}","pulls_url":"https://api.github.com/repos/budaqing/collectdwin/pulls{/number}","milestones_url":"https://api.github.com/repos/budaqing/collectdwin/milestones{/number}","notifications_url":"https://api.github.com/repos/budaqing/collectdwin/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/budaqing/collectdwin/labels{/name}","releases_url":"https://api.github.com/repos/budaqing/collectdwin/releases{/id}","deployments_url":"https://api.github.com/repos/budaqing/collectdwin/deployments","created_at":"2016-01-08T18:29:28Z","updated_at":"2016-01-08T18:29:28Z","pushed_at":"2016-01-28T22:35:22Z","git_url":"git://github.com/budaqing/collectdwin.git","ssh_url":"git@github.com:budaqing/collectdwin.git","clone_url":"https://github.com/budaqing/collectdwin.git","svn_url":"https://github.com/budaqing/collectdwin","homepage":null,"size":435,"stargazers_count":0,"watchers_count":0,"language":"C#","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"bloomberg:master","ref":"master","sha":"a6aad0cc67a43d84d1d701754ecafa35146a6727","user":{"login":"bloomberg","id":1416818,"avatar_url":"https://avatars.githubusercontent.com/u/1416818?v=3","gravatar_id":"","url":"https://api.github.com/users/bloomberg","html_url":"https://github.com/bloomberg","followers_url":"https://api.github.com/users/bloomberg/followers","following_url":"https://api.github.com/users/bloomberg/following{/other_user}","gists_url":"https://api.github.com/users/bloomberg/gists{/gist_id}","starred_url":"https://api.github.com/users/bloomberg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bloomberg/subscriptions","organizations_url":"https://api.github.com/users/bloomberg/orgs","repos_url":"https://api.github.com/users/bloomberg/repos","events_url":"https://api.github.com/users/bloomberg/events{/privacy}","received_events_url":"https://api.github.com/users/bloomberg/received_events","type":"Organization","site_admin":false},"repo":{"id":37088492,"name":"collectdwin","full_name":"bloomberg/collectdwin","owner":{"login":"bloomberg","id":1416818,"avatar_url":"https://avatars.githubusercontent.com/u/1416818?v=3","gravatar_id":"","url":"https://api.github.com/users/bloomberg","html_url":"https://github.com/bloomberg","followers_url":"https://api.github.com/users/bloomberg/followers","following_url":"https://api.github.com/users/bloomberg/following{/other_user}","gists_url":"https://api.github.com/users/bloomberg/gists{/gist_id}","starred_url":"https://api.github.com/users/bloomberg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bloomberg/subscriptions","organizations_url":"https://api.github.com/users/bloomberg/orgs","repos_url":"https://api.github.com/users/bloomberg/repos","events_url":"https://api.github.com/users/bloomberg/events{/privacy}","received_events_url":"https://api.github.com/users/bloomberg/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/bloomberg/collectdwin","description":"CollectdWin - a system statistics collection daemon for Windows, inspired by 'collectd'","fork":false,"url":"https://api.github.com/repos/bloomberg/collectdwin","forks_url":"https://api.github.com/repos/bloomberg/collectdwin/forks","keys_url":"https://api.github.com/repos/bloomberg/collectdwin/keys{/key_id}","collaborators_url":"https://api.github.com/repos/bloomberg/collectdwin/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/bloomberg/collectdwin/teams","hooks_url":"https://api.github.com/repos/bloomberg/collectdwin/hooks","issue_events_url":"https://api.github.com/repos/bloomberg/collectdwin/issues/events{/number}","events_url":"https://api.github.com/repos/bloomberg/collectdwin/events","assignees_url":"https://api.github.com/repos/bloomberg/collectdwin/assignees{/user}","branches_url":"https://api.github.com/repos/bloomberg/collectdwin/branches{/branch}","tags_url":"https://api.github.com/repos/bloomberg/collectdwin/tags","blobs_url":"https://api.github.com/repos/bloomberg/collectdwin/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/bloomberg/collectdwin/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/bloomberg/collectdwin/git/refs{/sha}","trees_url":"https://api.github.com/repos/bloomberg/collectdwin/git/trees{/sha}","statuses_url":"https://api.github.com/repos/bloomberg/collectdwin/statuses/{sha}","languages_url":"https://api.github.com/repos/bloomberg/collectdwin/languages","stargazers_url":"https://api.github.com/repos/bloomberg/collectdwin/stargazers","contributors_url":"https://api.github.com/repos/bloomberg/collectdwin/contributors","subscribers_url":"https://api.github.com/repos/bloomberg/collectdwin/subscribers","subscription_url":"https://api.github.com/repos/bloomberg/collectdwin/subscription","commits_url":"https://api.github.com/repos/bloomberg/collectdwin/commits{/sha}","git_commits_url":"https://api.github.com/repos/bloomberg/collectdwin/git/commits{/sha}","comments_url":"https://api.github.com/repos/bloomberg/collectdwin/comments{/number}","issue_comment_url":"https://api.github.com/repos/bloomberg/collectdwin/issues/comments{/number}","contents_url":"https://api.github.com/repos/bloomberg/collectdwin/contents/{+path}","compare_url":"https://api.github.com/repos/bloomberg/collectdwin/compare/{base}...{head}","merges_url":"https://api.github.com/repos/bloomberg/collectdwin/merges","archive_url":"https://api.github.com/repos/bloomberg/collectdwin/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/bloomberg/collectdwin/downloads","issues_url":"https://api.github.com/repos/bloomberg/collectdwin/issues{/number}","pulls_url":"https://api.github.com/repos/bloomberg/collectdwin/pulls{/number}","milestones_url":"https://api.github.com/repos/bloomberg/collectdwin/milestones{/number}","notifications_url":"https://api.github.com/repos/bloomberg/collectdwin/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/bloomberg/collectdwin/labels{/name}","releases_url":"https://api.github.com/repos/bloomberg/collectdwin/releases{/id}","deployments_url":"https://api.github.com/repos/bloomberg/collectdwin/deployments","created_at":"2015-06-08T19:39:14Z","updated_at":"2016-01-12T17:18:13Z","pushed_at":"2016-01-28T22:35:22Z","git_url":"git://github.com/bloomberg/collectdwin.git","ssh_url":"git@github.com:bloomberg/collectdwin.git","clone_url":"https://github.com/bloomberg/collectdwin.git","svn_url":"https://github.com/bloomberg/collectdwin","homepage":null,"size":406,"stargazers_count":44,"watchers_count":44,"language":"C#","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":12,"mirror_url":null,"open_issues_count":4,"forks":12,"open_issues":4,"watchers":44,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/bloomberg/collectdwin/pulls/25"},"html":{"href":"https://github.com/bloomberg/collectdwin/pull/25"},"issue":{"href":"https://api.github.com/repos/bloomberg/collectdwin/issues/25"},"comments":{"href":"https://api.github.com/repos/bloomberg/collectdwin/issues/25/comments"},"review_comments":{"href":"https://api.github.com/repos/bloomberg/collectdwin/pulls/25/comments"},"review_comment":{"href":"https://api.github.com/repos/bloomberg/collectdwin/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/bloomberg/collectdwin/pulls/25/commits"},"statuses":{"href":"https://api.github.com/repos/bloomberg/collectdwin/statuses/74134be6aed665d0056b0037f7744e5e6bbb398b"}}}}