private int CreatePerfCounterProxies(string processInstanceName)
        {
            var perfCounterProxies = new Dictionary <GCSampleType, IPerformanceCounterProxy>();

            var failedSampleTypes = new List <GCSampleType>();

            foreach (var sampleTypeEnum in _perfCounterNames.Keys)
            {
                try
                {
                    perfCounterProxies[sampleTypeEnum] = _pcProxyFactory.CreatePerformanceCounterProxy(GCPerfCounterCategoryName, _perfCounterNames[sampleTypeEnum], processInstanceName);
                }
                catch (UnauthorizedAccessException)
                {
                    throw;  //Let the caller receive this so that they may shutdown the sampler.
                }
                catch (Exception ex)
                {
                    failedSampleTypes.Add(sampleTypeEnum);
                    LogMessage(LogLevel.Debug, $"Error encountered during the creation of performance counter for '{sampleTypeEnum}' for Performance Counter Instance '{processInstanceName}'.  Metrics of this type will not be captured.  Error : {ex}");
                }
            }

            //Print message indicating which perf counter proxies failed to start.
            if (failedSampleTypes.Count > 0)
            {
                var msgToken = string.Join(", ", failedSampleTypes.Select(x => x.ToString()).ToArray());
                LogMessage(LogLevel.Warn, $"The following Performance Counters for Performance Counter Instance '{processInstanceName}' could not be started: {msgToken}.  Debug Level logs will contain more information.");
            }

            var oldProxies = Interlocked.Exchange(ref _perfCounterProxies, perfCounterProxies);

            if (_perfCounterProxies.Count > 0)
            {
                LogMessage(LogLevel.Debug, $"Sampler is collecting {_perfCounterProxies.Count} performance counter(s) for Performance Counter Instance '{processInstanceName}'.");
            }

            if (oldProxies != null && oldProxies.Count > 0)
            {
                DisposeProxies(oldProxies.Values);
            }

            return(_perfCounterProxies.Count);
        }
Example #2
0
        public void SamplerCalculatesValuesCorrectly()
        {
            const int   expectedSampleCount  = 2;
            const float startVal             = 3f;
            const float deltaVal             = 10f;
            var         lastPerfCounterValue = 0f;
            var         testPerfCounterValue = startVal;

            //Create a mock proxy that allows us to return a specific value and ensure that the proxy factory returns this proxy.
            var mockProxy = Mock.Create <IPerformanceCounterProxy>();

            Mock.Arrange(() => mockProxy.NextValue())
            .Returns(() => { return(testPerfCounterValue); });

            Mock.Arrange(() => _perfCounterProxyFactory.CreatePerformanceCounterProxy(Arg.IsAny <string>(), Arg.IsAny <string>(), Arg.IsAny <string>()))
            .Returns(mockProxy);

            Mock.Arrange(() => _perfCounterProxyFactory.GetCurrentProcessInstanceNameForCategory(Arg.IsAny <string>(), Arg.IsAny <string>()))
            .Returns("Test Value");

            //Holds the results of the perf counter captures so that we may compare them as part of our assertions.
            List <Dictionary <GCSampleType, float> > perfCounterValues = new List <Dictionary <GCSampleType, float> >();


            //Intercept the transform method so that we can collect the values that were sampled from the performance counters
            var gcSampleTransformer = Mock.Create <IGcSampleTransformer>();

            Mock.Arrange(() => gcSampleTransformer.Transform(Arg.IsAny <Dictionary <GCSampleType, float> >()))
            .DoInstead <Dictionary <GCSampleType, float> >((sampleValues) =>
            {
                lastPerfCounterValue = testPerfCounterValue;
                perfCounterValues.Add(sampleValues);
                testPerfCounterValue += deltaVal;
            });

            var sampler = new GcSampler(_scheduler, gcSampleTransformer, _perfCounterProxyFactory);

            //Act
            sampler.Start();
            _sampleAction();    //Collect Sample 1
            _sampleAction();    //Collect Sample 2

            //Assert
            NrAssert.Multiple(
                () => Assert.AreEqual(expectedSampleCount, perfCounterValues.Count, $"There should have been {expectedSampleCount} samples collected"),
                () => Assert.AreEqual(_countSampleTypes, perfCounterValues[0].Count, $"There should be {_countSampleTypes} in the first sample"),
                () => Assert.AreEqual(_countSampleTypes, perfCounterValues[1].Count, $"There should be {_countSampleTypes} in the second sample")
                );

            //Validate the sampled(calculated) value for each counter type.
            foreach (var gcSampleType in perfCounterValues[0].Keys)
            {
                //For the first sample, all should have the same value
                Assert.AreEqual(startVal, perfCounterValues[0][gcSampleType]);

                //For the second sample...
                switch (gcSampleType)
                {
                //...delta values should represent the size of the delta
                case GCSampleType.Gen0CollectionCount:
                case GCSampleType.Gen1CollectionCount:
                case GCSampleType.Gen2CollectionCount:
                case GCSampleType.InducedCount:
                    Assert.AreEqual(deltaVal, perfCounterValues[1][gcSampleType]);
                    break;

                //...other measurements should be passed through with the perf counter value
                default:
                    Assert.AreEqual(lastPerfCounterValue, perfCounterValues[1][gcSampleType]);
                    break;
                }
            }
        }