Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/PerfTap/Configuration/CounterSamplingConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ ReadOnlyCollection<ICounterName> ICounterSamplingConfiguration.CounterNames
get { return new ReadOnlyCollection<ICounterName>(CounterDefinitions.OfType<ICounterName>().ToList() ?? (IList<ICounterName>)new ICounterName[0]); }
}

/// <summary> Add the instance name in the metrics reported. </summary>
/// <value> true or false. </value>
[ConfigurationProperty("addInstanceNameToMetrics", IsRequired = false, DefaultValue = "true")]
public bool AddInstanceNameToMetrics
{
get { return (bool)this["addInstanceNameToMetrics"]; }
set { this["addInstanceNameToMetrics"] = value; }
}
//TODO: 1-9-2012 -- add error handling to ensure that there's always at least a set of definition paths OR counter definitions supplied by the user
}
}
1 change: 1 addition & 0 deletions src/PerfTap/Configuration/ICounterSamplingConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ public interface ICounterSamplingConfiguration
ReadOnlyCollection<ICounterDefinitionsFilePath> DefinitionFilePaths { get; }
ReadOnlyCollection<ICounterName> CounterNames { get; }
TimeSpan SampleInterval { get; }
Boolean AddInstanceNameToMetrics { get; }
}
}
61 changes: 29 additions & 32 deletions src/PerfTap/Counter/PerformanceCounterSamplesExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,29 @@ namespace PerfTap
using System.Text;
using System.Text.RegularExpressions;
using NanoTube.Support;
using NanoTube.Core;
using NanoTube;
using PerfTap.Counter;

/// <summary>
/// TODO: Update summary.
/// </summary>
public static class PerformanceCounterSamplesExtensions
{
private static Regex _validKey = new Regex(@"^[^!\s;:/\.\(\)\\#%\$\^]+$", RegexOptions.Compiled);
private const string _keyValue = "kv",
_timer = "ms",
_performanceCounter = "c",
_separator = "\n",
_badChars = " ;:/.()*";

public static IEnumerable<string> ToGraphiteString(this IEnumerable<PerformanceCounterSample> performanceCounters, string key)
public static IEnumerable<IMetric> ToMetrics(this IEnumerable<PerformanceCounterSample> performanceCounters, bool addInstance)
{
if (null == performanceCounters)
{ throw new ArgumentNullException("performanceCounter"); }
if (!string.IsNullOrEmpty(key) && !_validKey.IsMatch(key))
{ throw new ArgumentException("Key contains invalid characters", "key"); }
{ throw new ArgumentNullException("performanceCounter"); }

var metric = new StringBuilder(150);
string prefix = string.IsNullOrWhiteSpace(key) ? string.Empty : key.Trim() + ".";
string type = _keyValue;

var metricName = new StringBuilder(150);
IMetric metric;
foreach (var counter in performanceCounters)
{
//http://msdn.microsoft.com/en-us/library/system.diagnostics.performancecountertype(v=VS.85).aspx
Expand Down Expand Up @@ -74,49 +72,48 @@ public static IEnumerable<string> ToGraphiteString(this IEnumerable<PerformanceC
case PerformanceCounterType.Timer100Ns:
case PerformanceCounterType.Timer100NsInverse:
default:
type = _keyValue;
var newMetric = new KeyValue();
newMetric.Value = counter.CookedValue;
newMetric.Timestamp = counter.Timestamp;
metric = newMetric;
break;

//timers
case PerformanceCounterType.AverageTimer32:
case PerformanceCounterType.ElapsedTime:
type = _timer;
var newTiming = new Timing();
newTiming.Duration = counter.CookedValue;
metric = newTiming;
break;
}
metricName.Remove(0, metricName.Length); //clear the buffer
var path = counter.Path.ToLower();
if (!addInstance)
{
path = path.Substring(path.IndexOf('\\', 2) + 1);
}
metricName.Append(path);

//https://github.com/kiip/statsite
//key:value|type[|@flag]
metric.Remove(0, metric.Length); //clear the buffer
metric.Append(counter.Path.ToLower());

metric.Replace(@"\\", string.Empty);
metricName.Replace(@"\\", string.Empty);

if (null != counter.InstanceName)
{
string instanceName = counter.InstanceName.ToLower();
metric.Replace(String.Format(@"({0})\", instanceName), String.Format(@"\{0}\", instanceName));
metricName.Replace(String.Format(@"({0})\", instanceName), String.Format(@"\{0}\", instanceName));
}

for (int i = 0; i < metric.Length; ++i)
for (int i = 0; i < metricName.Length; ++i)
{
if (_badChars.Contains(metric[i])) { metric[i] = '_'; }
if (_badChars.Contains(metricName[i])) { metricName[i] = '_'; }
}

metric.Replace('\\', '.');
metric.Replace("#", "num");
metric.Replace("%", "pct");
if (!string.IsNullOrEmpty(prefix)) { metric.Insert(0, prefix); }

metric.AppendFormat(":{0:0.###}|{1}", counter.CookedValue, type);

if (type == _keyValue)
{
metric.AppendFormat("|@{0}", counter.Timestamp.AsUnixTime());
}
metricName.Replace('\\', '.');
metricName.Replace("#", "num");
metricName.Replace("%", "pct");

yield return metric.ToString();
metric.Key = metricName.ToString();
yield return metric;
}
}
//[String]::Join($Separator, $formatted)
}
}
16 changes: 8 additions & 8 deletions src/PerfTap/MonitoringTaskFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace PerfTap
using System.Threading.Tasks;
using NanoTube.Configuration;
using NanoTube.Linq;
using NanoTube.Net;
using NanoTube;
using PerfTap.Configuration;
using PerfTap.Counter;

Expand Down Expand Up @@ -49,31 +49,31 @@ public Task CreateContinuousTask(CancellationToken cancellationToken)
return new Task(() =>
{
var reader = new PerfmonCounterReader();
using (var messenger = new UdpMessenger(_metricPublishingConfig.HostName, _metricPublishingConfig.Port))
using (var messenger = new MetricClient(_metricPublishingConfig))
{
foreach (var metricBatch in reader.StreamCounterSamples(_counterPaths, _counterSamplingConfig.SampleInterval, cancellationToken)
.SelectMany(set => set.CounterSamples.ToGraphiteString(_metricPublishingConfig.PrefixKey))
.SelectMany(set => set.CounterSamples.ToMetrics(_counterSamplingConfig.AddInstanceNameToMetrics))
.Chunk(10))
{
messenger.SendMetrics(metricBatch);
messenger.Send(metricBatch);
}
}
}, cancellationToken);
}

public Task CreateTask(CancellationToken cancellationToken, int maximumSamples)
{
return new Task(() =>
return new Task(() =>
{
var reader = new PerfmonCounterReader();

using (var messenger = new UdpMessenger(_metricPublishingConfig.HostName, _metricPublishingConfig.Port))
using (var messenger = new MetricClient(_metricPublishingConfig))
{
foreach (var metricBatch in reader.GetCounterSamples(_counterPaths, _counterSamplingConfig.SampleInterval, maximumSamples, cancellationToken)
.SelectMany(set => set.CounterSamples.ToGraphiteString(_metricPublishingConfig.PrefixKey))
.SelectMany(set => set.CounterSamples.ToMetrics(_counterSamplingConfig.AddInstanceNameToMetrics))
.Chunk(10))
{
messenger.SendMetrics(metricBatch);
messenger.Send(metricBatch);
}
}
}, cancellationToken);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public class PerformanceCounterSamplesExtensionsTests
public void ToGraphiteString_ThrowsOnInvalidKey(string key)
{
var samples = new [] { new PerformanceCounterSample(@"\\machine-name\memory\% committed bytes in use", null, 36.41245914, 818220, 2247088, 1, PerformanceCounterType.RawFraction, 0, 3579545, DateTime.Now, (ulong)DateTime.Now.ToFileTime(), 0) };
Assert.Throws<ArgumentException>(() => samples.ToGraphiteString(key).ToList());
Assert.Throws<ArgumentException>(() => samples.ToMetrics(true).ToList());
}

public static IEnumerable<object[]> ExpectedMetricConversions
Expand Down Expand Up @@ -81,7 +81,7 @@ public static IEnumerable<object[]> ExpectedMetricConversions
[PropertyData("ExpectedMetricConversions")]
public void ToGraphiteString_GeneratesExpectedMetrics(string key, PerformanceCounterSample sample, string expected)
{
string converted = new [] { sample }.ToGraphiteString(key).First();
string converted = new [] { sample }.ToMetrics(true).First().ToString();
Assert.Equal(expected, converted);
}
}
Expand Down